diff options
Diffstat (limited to 'krita/ui')
210 files changed, 42298 insertions, 0 deletions
diff --git a/krita/ui/Makefile.am b/krita/ui/Makefile.am new file mode 100644 index 000000000..638ae6342 --- /dev/null +++ b/krita/ui/Makefile.am @@ -0,0 +1,75 @@ +INCLUDES = \ + -I$(srcdir) \ + -I$(srcdir)/../sdk \ + -I$(srcdir)/../core \ + -I$(srcdir)/../kritacolor \ + $(KOFFICE_INCLUDES) \ + $(KOPAINTER_INCLUDES) \ + $(KDE_INCLUDES) \ + $(all_includes) + +lib_LTLIBRARIES = libkritaui.la +libkritaui_la_LDFLAGS = -version-info 1:0:0 -no-undefined $(all_libraries) +libkritaui_la_LIBADD = ../sdk/libkritasdk.la ../core/libkritaimage.la ../kritacolor/libkritacolor.la \ + $(LCMS_LIBS) $(LIB_KOFFICEUI) $(LIB_KOPAINTER) $(LIB_KOPALETTE) $(LIB_XINPUTEXT) $(GLLIB) + +libkritaui_la_SOURCES = kis_import_catcher.cc kis_histogram_view.cc imageviewer.cc kcurve.cc \ + kis_autobrush.cc kis_autogradient.cc kis_boundary_painter.cc kis_brush_chooser.cc \ + kis_canvas.cc kis_canvas_painter.cc kis_clipboard.cc kis_cmb_composite.cc \ + kis_cmb_idlist.cc kis_color_cup.cc kis_config.cc kis_controlframe.cc kis_cursor.cc \ + kis_dlg_apply_profile.cc kis_dlg_image_properties.cc kis_dlg_layer_properties.cc \ + kis_dlg_new_layer.cc kis_dlg_preferences.cc kis_doc.cc kis_doc_iface.cc kis_doc_iface.skel \ + kis_double_widget.cc kis_factory.cc kis_filter_manager.cc kis_gradient_chooser.cc \ + kis_gradient_slider_widget.cc kis_icon_item.cc kis_iconwidget.cc kis_int_spinbox.cc \ + kis_itemchooser.cc kis_label_cursor_pos.cc kis_label_progress.cc kis_label_zoom.cc \ + kis_layerbox.cc kis_layerlist.cc kis_multi_bool_filter_widget.cc \ + kis_multi_double_filter_widget.cc kis_multi_integer_filter_widget.cc kis_opengl_canvas.cc \ + kis_opengl_canvas_painter.cc kis_opengl_image_context.cc kis_paintop_box.cc kis_palette_view.cc \ + kis_palette_widget.cc kis_part_layer.cc kis_pattern_chooser.cc kis_previewdialog.cc \ + kis_previewwidget.cc kis_qpaintdevice_canvas.cc kis_qpaintdevice_canvas_painter.cc \ + kis_resource_mediator.cc kis_resourceserver.cc kis_ruler.cc kis_selection_manager.cc \ + kis_selection_options.cc kis_text_brush.cc kis_tool.cc kis_tool_dummy.cc kis_tool_freehand.cc \ + kis_tool_manager.cc kis_tool_non_paint.cc kis_tool_paint.cc kis_tool_registry.cc \ + kis_tool_shape.cc kis_birdeye_box.cc kis_view.cc kis_view_iface.cc kis_custom_brush.cc \ + kis_custom_palette.cc kis_custom_pattern.cc kis_custom_image_widget.cc kis_view_iface.skel \ + kobirdeyepanel.cpp kis_matrix_widget.ui kis_previewwidgetbase.ui layerlist.cpp \ + wdgapplyprofile.ui wdgautobrush.ui wdgautogradient.ui wdgbirdeye.ui wdgcolorsettings.ui \ + wdgdisplaysettings.ui wdggeneralsettings.ui wdglayerproperties.ui wdglayerbox.ui \ + wdgnewimage.ui wdgperformancesettings.ui wdgselectionoptions.ui wdgshapeoptions.ui \ + wdgpressuresettings.ui wdgcustombrush.ui wdgcustompalette.ui wdgcustompattern.ui \ + wdgtextbrush.ui kis_dlg_adjustment_layer.cc kis_filters_listview.cc \ + wdgpalettechooser.ui wdggridsettings.ui kis_grid_manager.cpp wdgtabletdevicesettings.ui \ + wdgtabletsettings.ui kis_input_device.cc kis_part_layer_handler.cc \ + kis_dlg_adj_layer_props.cc squeezedcombobox.cpp kis_perspective_grid_manager.cpp \ + kis_grid_drawer.cpp + +noinst_HEADERS = kis_aboutdata.h imageviewer.h layerlist.h kcurve.h \ + kis_autobrush.h kis_autogradient.h kis_birdeye_box.h kis_brush_chooser.h \ + kis_button_press_event.h kis_canvas.h kis_clipboard.h kis_controlframe.h \ + kis_dlg_apply_profile.h kis_dlg_image_properties.h kis_dlg_layer_properties.h \ + kis_dlg_new_layer.h kis_dlg_preferences.h kis_event.h kis_factory.h \ + kis_label_cursor_pos.h kis_label_progress.h kis_part_layer.h kis_pattern_chooser.h \ + kis_resource_mediator.h kis_resourceserver.h kis_ruler.h kis_selection_manager.h \ + kis_selection_options.h kis_view_iface.h kis_custom_brush.h kis_custom_pattern.h \ + kis_custom_image_widget.h kis_dlg_adjustment_layer.h kis_grid_manager.h \ + kis_dlg_adj_layer_props.h squeezedcombobox.h kis_perspective_grid_manager.h + +include_HEADERS = kis_button_event.h kis_button_release_event.h kis_canvas_painter.h kis_cmb_composite.h kis_cmb_idlist.h kis_color_cup.h kis_config.h \ + kis_cursor.h kis_doc.h kis_doc_iface.h \ + kis_double_click_event.h kis_double_widget.h kis_event.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_int_spinbox.h kis_layerbox.h kis_layerlist.h kis_matrix_widget.ui.h kis_move_event.h \ + kis_multi_bool_filter_widget.h kis_multi_double_filter_widget.h kis_multi_integer_filter_widget.h \ + kis_paintop_box.h kis_palette_widget.h \ + kis_previewdialog.h kis_previewwidget.h \ + kis_tool_controller.h kis_tool.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 kis_tool_registry.h kis_view.h \ + kis_tool_factory.h \ + kobirdeyepanel.h \ + kis_filters_listview.h kis_input_device.h kis_opengl_image_context.h + +METASOURCES = AUTO + +KDE_OPTIONS = nofinal + diff --git a/krita/ui/imageviewer.cc b/krita/ui/imageviewer.cc new file mode 100644 index 000000000..490f34514 --- /dev/null +++ b/krita/ui/imageviewer.cc @@ -0,0 +1,78 @@ +/*************************************************************************** + * Copyright (C) 2005 Eyal Lotem <eyal.lotem@gmail.com> * + * Copyright (C) 2005 Alexandre Oliveira <aleprj@gmail.com> * + * Copyright (C) 2006 Cyrille Berger <cberger@cberger.net> * + * * + * 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 "imageviewer.h" + +#include <qlabel.h> +#include <qpainter.h> +#include <qimage.h> +#include <qcursor.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kis_cursor.h> + +ImageViewer::ImageViewer(QWidget *widget, const char * name) + : QScrollView(widget, name) + , m_isDragging(false) + , m_image(QPixmap()) +{ + m_label = new QLabel( viewport()); + setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding); + setCursor(KisCursor::handCursor()); + addChild(m_label); +} + +void ImageViewer::setImage(QImage & image) +{ + m_image = QPixmap(image); + m_label->setPixmap(m_image); + resizeContents( m_image.width(), m_image.height() ); + repaintContents(false); +} + +void ImageViewer::contentsMousePressEvent(QMouseEvent *event) +{ + if(LeftButton == event->button()) { + setCursor(KisCursor::closedHandCursor()); + m_currentPos = event->globalPos(); + m_isDragging = true; + } +} + +void ImageViewer::contentsMouseReleaseEvent(QMouseEvent *event) +{ + if(LeftButton == event->button()) { + setCursor(KisCursor::handCursor()); + m_currentPos = event->globalPos(); + m_isDragging = false; + } +} + +void ImageViewer::contentsMouseMoveEvent(QMouseEvent *event) +{ + if(m_isDragging) { + QPoint delta = m_currentPos - event->globalPos(); + scrollBy(delta.x(), delta.y()); + m_currentPos = event->globalPos(); + } +} + +#include "imageviewer.moc" diff --git a/krita/ui/imageviewer.h b/krita/ui/imageviewer.h new file mode 100644 index 000000000..17b482c69 --- /dev/null +++ b/krita/ui/imageviewer.h @@ -0,0 +1,52 @@ +/*************************************************************************** + * Copyright (C) 2005 Eyal Lotem <eyal.lotem@gmail.com> * + * * + * 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 PIXMAPVIEWER_H +#define PIXMAPVIEWER_H + +#include <qscrollview.h> +#include <qimage.h> + +class QLabel; + +/** + * A scrollable image view. + * + * XXX: We should add a signal that emits newly eposed rects so the filters + * don't have to filter everything, but just the the new bits. + */ +class ImageViewer : public QScrollView { + Q_OBJECT + +public: + ImageViewer(QWidget *widget, const char * name = 0); + + void setImage(QImage & image); + + void contentsMousePressEvent(QMouseEvent *event); + void contentsMouseReleaseEvent(QMouseEvent *event); + void contentsMouseMoveEvent(QMouseEvent *event); + void wheelEvent(QWheelEvent * event) { event->ignore(); }; +private: + QLabel* m_label; + bool m_isDragging; + QPoint m_currentPos; + QPixmap m_image; +}; + +#endif diff --git a/krita/ui/kcurve.cc b/krita/ui/kcurve.cc new file mode 100644 index 000000000..8e50804fd --- /dev/null +++ b/krita/ui/kcurve.cc @@ -0,0 +1,450 @@ +/* ============================================================ + * Copyright 2004-2005 by Gilles Caulier + * Copyright 2005 by Casper Boemann (reworked to be generic) + * + * 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, 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. + * + * ============================================================ */ + +// C++ includes. + +#include <cmath> +#include <cstdlib> + +// Qt includes. + +#include <qpixmap.h> +#include <qpainter.h> +#include <qpoint.h> +#include <qpen.h> +#include <qevent.h> +#include <qtimer.h> +#include <qrect.h> +#include <qfont.h> +#include <qfontmetrics.h> + +// KDE includes. + +#include <kdebug.h> +#include <kcursor.h> +#include <klocale.h> + +// Local includes. + +#include "kcurve.h" + +KCurve::KCurve(QWidget *parent, const char *name, WFlags f) + : QWidget(parent, name, f) +{ + m_grab_point = NULL; + m_readOnlyMode = false; + m_guideVisible = false; + m_dragging = false; + m_pix = NULL; + + setMouseTracking(true); + setPaletteBackgroundColor(Qt::NoBackground); + setMinimumSize(150, 50); + QPair<double,double> *p = new QPair<double,double>; + p->first = 0.0; p->second=0.0; + m_points.append(p); + p = new QPair<double,double>; + p->first = 1.0; p->second=1.0; + m_points.append(p); + m_points.setAutoDelete(true); + setFocusPolicy(QWidget::StrongFocus); +} + +KCurve::~KCurve() +{ + if (m_pix) delete m_pix; +} + +void KCurve::reset(void) +{ + m_grab_point = NULL; + m_guideVisible = false; + repaint(false); +} + +void KCurve::setCurveGuide(QColor color) +{ + m_guideVisible = true; + m_colorGuide = color; + repaint(false); +} + +void KCurve::setPixmap(QPixmap pix) +{ + if (m_pix) delete m_pix; + m_pix = new QPixmap(pix); + repaint(false); +} + +void KCurve::keyPressEvent(QKeyEvent *e) +{ + if(e->key() == Qt::Key_Delete || e->key() == Qt::Key_Backspace) + { + QPair<double,double> *closest_point=NULL; + if(m_grab_point) + { + //first find closest point to get focus afterwards + QPair<double,double> *p = m_points.first(); + double distance = 1000; // just a big number + while(p) + { + if(p!=m_grab_point) + if (fabs (m_grab_point->first - p->first) < distance) + { + distance = fabs(m_grab_point->first - p->first); + closest_point = p; + } + p = m_points.next(); + } + m_points.remove(m_grab_point); + } + m_grab_point = closest_point; + repaint(false); + } + else + QWidget::keyPressEvent(e); +} + +void KCurve::paintEvent(QPaintEvent *) +{ + int x, y; + int wWidth = width(); + int wHeight = height(); + + x = 0; + y = 0; + + // Drawing selection or all histogram values. + // A QPixmap is used for enable the double buffering. + + QPixmap pm(size()); + QPainter p1; + p1.begin(&pm, this); + + // draw background + if(m_pix) + { + p1.scale(1.0*wWidth/m_pix->width(), 1.0*wHeight/m_pix->height()); + p1.drawPixmap(0, 0, *m_pix); + p1.resetXForm(); + } + else + pm.fill(); + + // Draw grid separators. + p1.setPen(QPen::QPen(Qt::gray, 1, Qt::SolidLine)); + p1.drawLine(wWidth/3, 0, wWidth/3, wHeight); + p1.drawLine(2*wWidth/3, 0, 2*wWidth/3, wHeight); + p1.drawLine(0, wHeight/3, wWidth, wHeight/3); + p1.drawLine(0, 2*wHeight/3, wWidth, 2*wHeight/3); + + // Draw curve. + double curvePrevVal = getCurveValue(0.0); + p1.setPen(QPen::QPen(Qt::black, 1, Qt::SolidLine)); + for (x = 0 ; x < wWidth ; x++) + { + double curveX; + double curveVal; + + curveX = (x + 0.5) / wWidth; + + curveVal = getCurveValue(curveX); + + p1.drawLine(x - 1, wHeight - int(curvePrevVal * wHeight), + x, wHeight - int(curveVal * wHeight)); + + curvePrevVal = curveVal; + } + p1.drawLine(x - 1, wHeight - int(curvePrevVal * wHeight), + x, wHeight - int(getCurveValue(1.0) * wHeight)); + + // Drawing curve handles. + if ( !m_readOnlyMode ) + { + QPair<double,double> *p = m_points.first(); + + while(p) + { + double curveX = p->first; + double curveY = p->second; + + if(p == m_grab_point) + { + p1.setPen(QPen::QPen(Qt::red, 3, Qt::SolidLine)); + p1.drawEllipse( int(curveX * wWidth) - 2, + wHeight - 2 - int(curveY * wHeight), 4, 4 ); + } + else + { + p1.setPen(QPen::QPen(Qt::red, 1, Qt::SolidLine)); + + p1.drawEllipse( int(curveX * wWidth) - 3, + wHeight - 3 - int(curveY * wHeight), 6, 6 ); + } + + p = m_points.next(); + } + } + + p1.end(); + bitBlt(this, 0, 0, &pm); +} + +void KCurve::mousePressEvent ( QMouseEvent * e ) +{ + if (m_readOnlyMode) return; + + QPair<double,double> *closest_point=NULL; + double distance; + + if (e->button() != Qt::LeftButton) + return; + + double x = e->pos().x() / (float)width(); + double y = 1.0 - e->pos().y() / (float)height(); + + distance = 1000; // just a big number + + QPair<double,double> *p = m_points.first(); + int insert_pos,pos=0; + while(p) + { + if (fabs (x - p->first) < distance) + { + distance = fabs(x - p->first); + closest_point = p; + if(x < p->first) + insert_pos = pos; + else + insert_pos = pos + 1; + } + p = m_points.next(); + pos++; + } + + + if(closest_point == NULL) + { + closest_point = new QPair<double,double>; + closest_point->first = x; + closest_point->second = y; + m_points.append(closest_point); + } + else if(distance * width() > 5) + { + closest_point = new QPair<double,double>; + closest_point->first = x; + closest_point->second = y; + m_points.insert(insert_pos, closest_point); + } + else + if(fabs(y - closest_point->second) * width() > 5) + return; + + + m_grab_point = closest_point; + m_grabOffsetX = m_grab_point->first - x; + m_grabOffsetY = m_grab_point->second - y; + m_grab_point->first = x + m_grabOffsetX; + m_grab_point->second = y + m_grabOffsetY; + m_dragging = true; + + setCursor( KCursor::crossCursor() ); + + // Determine the leftmost and rightmost points. + m_leftmost = 0; + m_rightmost = 1; + + p = m_points.first(); + while(p) + { + if (p != m_grab_point) + { + if(p->first> m_leftmost && p->first < x) + m_leftmost = p->first; + if(p->first < m_rightmost && p->first > x) + m_rightmost = p->first; + } + p = m_points.next(); + } + repaint(false); +} + +void KCurve::mouseReleaseEvent ( QMouseEvent * e ) +{ + if (m_readOnlyMode) return; + + if (e->button() != Qt::LeftButton) + return; + + setCursor( KCursor::arrowCursor() ); + m_dragging = false; + repaint(false); + emit modified(); +} + +void KCurve::mouseMoveEvent ( QMouseEvent * e ) +{ + if (m_readOnlyMode) return; + + double x = e->pos().x() / (float)width(); + double y = 1.0 - e->pos().y() / (float)height(); + + if (m_dragging == false) // If no point is selected set the the cursor shape if on top + { + double distance = 1000; + double ydistance = 1000; + QPair<double,double> *p = m_points.first(); + while(p) + { + if (fabs (x - p->first) < distance) + { + distance = fabs(x - p->first); + ydistance = fabs(y - p->second); + } + p = m_points.next(); + } + + if (distance * width() > 5 || ydistance * height() > 5) + setCursor( KCursor::arrowCursor() ); + else + setCursor( KCursor::crossCursor() ); + } + else // Else, drag the selected point + { + setCursor( KCursor::crossCursor() ); + + x += m_grabOffsetX; + y += m_grabOffsetY; + + if (x <= m_leftmost) + x = m_leftmost + 1E-4; // the addition so we can grab the dot later. + + if(x >= m_rightmost) + x = m_rightmost - 1E-4; + + if(y > 1.0) + y = 1.0; + + if(y < 0.0) + y = 0.0; + + m_grab_point->first = x; + m_grab_point->second = y; + + emit modified(); + } + + repaint(false); +} + +double KCurve::getCurveValue(double x) +{ + return getCurveValue(m_points, x); +} + +double KCurve::getCurveValue(QPtrList<QPair<double,double> > &curve, double x) +{ + double t; + QPair<double,double> *p; + QPair<double,double> *p0,*p1,*p2,*p3; + double c0,c1,c2,c3; + double val; + + if(curve.count() == 0) + return 0.5; + + // First find curve segment + p = curve.first(); + if(x < p->first) + return p->second; + + p = curve.last(); + if(x >= p->first) + return p->second; + + // Find the four control points (two on each side of x) + p = curve.first(); + while(x >= p->first) + { + p = curve.next(); + } + curve.prev(); + + if((p0 = curve.prev()) == NULL) + p1 = p0 = curve.first(); + else + p1 = curve.next(); + + p2 = curve.next(); + if( (p = curve.next()) ) + p3 = p; + else + p3 = p2; + + // Calculate the value + t = (x - p1->first) / (p2->first - p1->first); + c2 = (p2->second - p0->second) * (p2->first-p1->first) / (p2->first-p0->first); + c3 = p1->second; + c0 = -2*p2->second + 2*c3 + c2 + (p3->second - p1->second) * (p2->first - p1->first) / (p3->first - p1->first); + c1 = p2->second - c3 - c2 - c0; + val = ((c0*t + c1)*t + c2)*t + c3; + + if(val < 0.0) + val = 0.0; + if(val > 1.0) + val = 1.0; + return val; +} + +QPtrList<QPair<double,double> > KCurve::getCurve() +{ + QPtrList<QPair<double,double> > outlist; + QPair<double,double> *p; + QPair<double,double> *outpoint; + + p = m_points.first(); + while(p) + { + outpoint = new QPair<double,double>(p->first, p->second); + outlist.append(outpoint); + p = m_points.next(); + } + return outlist; +} + +void KCurve::setCurve(QPtrList<QPair<double,double> >inlist) +{ + QPair<double,double> *p; + QPair<double,double> *inpoint; + + m_points.clear(); + + inpoint = inlist.first(); + while(inpoint) + { + p = new QPair<double,double>(inpoint->first, inpoint->second); + m_points.append(p); + inpoint = inlist.next(); + } +} + +void KCurve::leaveEvent( QEvent * ) +{ +} + +#include "kcurve.moc" diff --git a/krita/ui/kcurve.h b/krita/ui/kcurve.h new file mode 100644 index 000000000..412efe5b9 --- /dev/null +++ b/krita/ui/kcurve.h @@ -0,0 +1,79 @@ +/* ============================================================ + * + * Copyright 2004-2005 by Gilles Caulier (original work as digikam curveswidget) + * Copyright 2005 by Casper Boemann (reworked to be generic) + * + * 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, 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. + * + * ============================================================ */ + +#ifndef KCURVE_H +#define KCURVE_H + +// Qt includes. + +#include <qwidget.h> +#include <qcolor.h> +#include <qpair.h> +#include <qsortedlist.h> +#include <koffice_export.h> +class KRITAUI_EXPORT KCurve : public QWidget +{ +Q_OBJECT + +public: + KCurve(QWidget *parent = 0, const char *name = 0, WFlags f = 0); + + virtual ~KCurve(); + + void reset(void); + void setCurveGuide(QColor color); + void setPixmap(QPixmap pix); + + +signals: + + void modified(void); + +protected: + + void keyPressEvent(QKeyEvent *); + void paintEvent(QPaintEvent *); + void mousePressEvent (QMouseEvent * e); + void mouseReleaseEvent ( QMouseEvent * e ); + void mouseMoveEvent ( QMouseEvent * e ); + void leaveEvent ( QEvent * ); + +public: + static double getCurveValue(QPtrList<QPair<double,double> > &curve, double x); + double getCurveValue(double x); + + QPtrList<QPair<double,double> > getCurve(); + void setCurve(QPtrList<QPair<double,double> >inlist); + +private: + double m_leftmost; + double m_rightmost; + QPair<double,double> *m_grab_point; + bool m_dragging; + double m_grabOffsetX; + double m_grabOffsetY; + + bool m_readOnlyMode; + bool m_guideVisible; + QColor m_colorGuide; + QPtrList<QPair<double,double> > m_points; + QPixmap *m_pix; +}; + + +#endif /* KCURVE_H */ diff --git a/krita/ui/kis_aboutdata.h b/krita/ui/kis_aboutdata.h new file mode 100644 index 000000000..385cb4b22 --- /dev/null +++ b/krita/ui/kis_aboutdata.h @@ -0,0 +1,68 @@ +/* + * kis_aboutdata.h - part of Krayon + * + * Copyright (c) 1999-2000 Matthias Elter <me@kde.org> + * + * 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_ABOUT_DATA_H_ +#define KIS_ABOUT_DATA_H_ + +#include <kaboutdata.h> +#include <klocale.h> +#include <kofficeversion.h> +#include <config.h> + +KAboutData * newKritaAboutData() +{ + KAboutData * aboutData = new KAboutData( "krita", + I18N_NOOP("Krita"), + KOFFICE_VERSION_STRING, + I18N_NOOP("KOffice image manipulation application"), + KAboutData::License_GPL, + I18N_NOOP("(c) 1999-2006 The Krita team.\n"), + "", + "http://www.koffice.org/krita", + "submit@bugs.kde.org"); + aboutData->addAuthor("Adrian Page", 0, "Adrian.Page@tesco.net"); + aboutData->addAuthor("Alan Horkan", 0, "", "http://www.openclipart.org"); + aboutData->addAuthor("Bart Coppens", 0, "kde@bartcoppens.be"); + aboutData->addAuthor("Boudewijn Rempt", 0, "boud@valdyas.org", "http://www.valdyas.org/fading/index.cgi"); + aboutData->addAuthor("Carsten Pfeiffer", 0, "carpdjih@cetus.zrz.tu-berlin.de"); + aboutData->addAuthor("Casper Boemann", 0, "cbr@boemann.dk"); + aboutData->addAuthor("Clarence Dang", 0, "dang@kde.org"); + aboutData->addAuthor("Cyrille Berger", 0, "cyb@lepi.org"); + aboutData->addAuthor("Dirk Schoenberger", 0, "dirk.schoenberger@sz-online.de"); + aboutData->addAuthor("Danny Allen", 0 , "danny@dannyallen.co.uk"); + aboutData->addAuthor("Emanuele Tamponi", 0, "emanuele@valinor.it"); + aboutData->addAuthor("Gábor Lehel", 0, "<illissius@gmail.com>"); + aboutData->addAuthor("John Califf",0, "jcaliff@compuzone.net"); + aboutData->addAuthor("Laurent Montel",0, "lmontel@mandrakesoft.com"); + aboutData->addAuthor("Matthias Elter", 0, "me@kde.org"); + aboutData->addAuthor("Melchior Franz", 0, "mfranz@kde.org"); + aboutData->addAuthor("Michael Koch", 0, "koch@kde.org"); + aboutData->addAuthor("Michael Thaler", 0, "michael.thaler@physik.tu-muenchen.de"); + aboutData->addAuthor("Patrick Julien", 0, "freak@codepimps.org"); + aboutData->addAuthor("Roger Larsson", 0, "roger.larsson@norran.net"); + aboutData->addAuthor("Sven Langkamp", 0, "longamp@reallygood.de"); + aboutData->addAuthor("Toshitaka Fujioka", 0, "fujioka@kde.org"); + aboutData->addAuthor("Thomas Zander", 0, "zander@kde.org"); + aboutData->addAuthor("Sander Koning", 0, "sanderkoning@kde.nl"); + aboutData->addAuthor("Ronan Zeegers",/*"icons"*/ 0,0); + aboutData->addAuthor("Frédéric Coiffier", 0, "frederic.coiffier@free.fr"); + return aboutData; +} + +#endif // KIS_ABOUT_DATA_H_ diff --git a/krita/ui/kis_autobrush.cc b/krita/ui/kis_autobrush.cc new file mode 100644 index 000000000..d1f6dce2e --- /dev/null +++ b/krita/ui/kis_autobrush.cc @@ -0,0 +1,177 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_autobrush.h" +#include <KoImageResource.h> +#include <kdebug.h> +#include <qspinbox.h> +#include <qtoolbutton.h> +#include <qimage.h> +#include <qcombobox.h> +#include <qlabel.h> + + +KisAutobrush::KisAutobrush(QWidget *parent, const char* name, const QString& caption) : KisWdgAutobrush(parent, name) +{ + setCaption(caption); + + m_linkSize = true; + m_linkFade = true; + + linkFadeToggled(m_linkSize); + linkSizeToggled(m_linkFade); + + connect(bnLinkSize, SIGNAL(toggled(bool)), this, SLOT(linkSizeToggled( bool ))); + connect(bnLinkFade, SIGNAL(toggled(bool)), this, SLOT(linkFadeToggled( bool ))); + + connect((QObject*)comboBoxShape, SIGNAL(activated(int)), this, SLOT(paramChanged())); + spinBoxWidth->setMinValue(1); + connect(spinBoxWidth,SIGNAL(valueChanged(int)),this,SLOT(spinBoxWidthChanged(int))); + spinBoxHeigth->setMinValue(1); + connect(spinBoxHeigth,SIGNAL(valueChanged(int)),this,SLOT(spinBoxHeigthChanged(int))); + spinBoxHorizontal->setMinValue(0); + connect(spinBoxHorizontal,SIGNAL(valueChanged(int)),this,SLOT(spinBoxHorizontalChanged(int))); + spinBoxVertical->setMinValue(0); + connect(spinBoxVertical,SIGNAL(valueChanged(int)),this,SLOT(spinBoxVerticalChanged(int))); + + m_brsh = new QImage(1,1,32); + Q_CHECK_PTR(m_brsh); + + paramChanged(); + + + connect(brushPreview, SIGNAL(clicked()), SLOT(paramChanged())); + +} + +void KisAutobrush::resizeEvent ( QResizeEvent * ) +{ + brushPreview->setMinimumHeight(brushPreview->width()); // dirty hack ! + brushPreview->setMaximumHeight(brushPreview->width()); // dirty hack ! +} + +void KisAutobrush::activate() +{ + paramChanged(); +} + +void KisAutobrush::paramChanged() +{ + Q_INT32 fh = QMIN( spinBoxWidth->value()/2, spinBoxHorizontal->value() ) ; + Q_INT32 fv = QMIN( spinBoxHeigth->value()/2, spinBoxVertical->value() ); + KisAutobrushShape* kas; + + if(comboBoxShape->currentItem() == 0) // use index compare instead of comparing a translatable string + { + kas = new KisAutobrushCircleShape(spinBoxWidth->value(), spinBoxHeigth->value(), fh, fv); + Q_CHECK_PTR(kas); + + } else { + kas = new KisAutobrushRectShape(spinBoxWidth->value(), spinBoxHeigth->value(), fh, fv); + Q_CHECK_PTR(kas); + + } + kas->createBrush(m_brsh); + + QPixmap p; + QImage pi(*m_brsh); + double coeff = 1.0; + int bPw = brushPreview->width()-3; + if(pi.width() > bPw) + { + coeff = bPw /(double)pi.width(); + } + int bPh = brushPreview->height()-3; + if(pi.height() > coeff * bPh) + { + coeff = bPh /(double)pi.height(); + } + if( coeff < 1.0) + { + pi = pi.smoothScale( (int)(coeff * pi.width()) , (int)(coeff * pi.height())); + } + + p.convertFromImage(pi); + brushPreview->setPixmap(p); + KisAutobrushResource * resource = new KisAutobrushResource(*m_brsh); + Q_CHECK_PTR(resource); + + emit(activatedResource(resource)); + delete kas; +} +void KisAutobrush::spinBoxWidthChanged(int a) +{ + spinBoxHorizontal->setMaxValue(a/2); + if(m_linkSize) + { + spinBoxHeigth->setValue(a); + spinBoxVertical->setMaxValue(a/2); + } + this->paramChanged(); +} +void KisAutobrush::spinBoxHeigthChanged(int a) +{ + spinBoxVertical->setMaxValue(a/2); + if(m_linkSize) + { + spinBoxWidth->setValue(a); + spinBoxHorizontal->setMaxValue(a/2); + } + this->paramChanged(); +} +void KisAutobrush::spinBoxHorizontalChanged(int a) +{ + if(m_linkFade) + spinBoxVertical->setValue(a); + this->paramChanged(); +} +void KisAutobrush::spinBoxVerticalChanged(int a) +{ + if(m_linkFade) + spinBoxHorizontal->setValue(a); + this->paramChanged(); +} + +void KisAutobrush::linkSizeToggled(bool b) +{ + m_linkSize = b; + + KoImageResource kir; + if (b) { + bnLinkSize->setPixmap(kir.chain()); + } + else { + bnLinkSize->setPixmap(kir.chainBroken()); + } +} + +void KisAutobrush::linkFadeToggled(bool b) +{ + m_linkFade = b; + + KoImageResource kir; + if (b) { + bnLinkFade->setPixmap(kir.chain()); + } + else { + bnLinkFade->setPixmap(kir.chainBroken()); + } +} + + +#include "kis_autobrush.moc" diff --git a/krita/ui/kis_autobrush.h b/krita/ui/kis_autobrush.h new file mode 100644 index 000000000..353923202 --- /dev/null +++ b/krita/ui/kis_autobrush.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_AUTOBRUSH_H_ +#define _KIS_AUTOBRUSH_H_ + +#include <qobject.h> +#include "wdgautobrush.h" +#include <kis_autobrush_resource.h> + +class KisAutobrush : public KisWdgAutobrush +{ + Q_OBJECT +public: + KisAutobrush(QWidget *parent, const char* name, const QString& caption); + void activate(); + +signals: + void activatedResource(KisResource *r); + +private slots: + void paramChanged(); + void spinBoxWidthChanged(int ); + void spinBoxHeigthChanged(int ); + void spinBoxHorizontalChanged(int); + void spinBoxVerticalChanged(int); + void linkSizeToggled(bool); + void linkFadeToggled(bool); + +protected: + virtual void resizeEvent ( QResizeEvent * ); + +private: + QImage* m_brsh; + bool m_linkSize; + bool m_linkFade; +}; + + +#endif diff --git a/krita/ui/kis_autogradient.cc b/krita/ui/kis_autogradient.cc new file mode 100644 index 000000000..79b6bb637 --- /dev/null +++ b/krita/ui/kis_autogradient.cc @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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_autogradient.h" + +#include <qpainter.h> +#include <qcombobox.h> + +#include <kcolorbutton.h> +#include <knuminput.h> +#include "kis_int_spinbox.h" +#include "kis_gradient.h" +#include "kis_autogradient_resource.h" + +#include "kis_gradient_slider_widget.h" + +/****************************** KisAutogradient ******************************/ + +KisAutogradient::KisAutogradient(QWidget *parent, const char* name, const QString& caption) : KisWdgAutogradient(parent, name) +{ + setCaption(caption); + m_autogradientResource = new KisAutogradientResource(); + m_autogradientResource->createSegment( INTERP_LINEAR, COLOR_INTERP_RGB, 0.0, 1.0, 0.5, Qt::black, Qt::white ); + connect(gradientSlider, SIGNAL( sigSelectedSegment( KisGradientSegment* ) ), SLOT( slotSelectedSegment(KisGradientSegment*) )); + connect(gradientSlider, SIGNAL( sigChangedSegment(KisGradientSegment*) ), SLOT( slotChangedSegment(KisGradientSegment*) )); + gradientSlider->setGradientResource( m_autogradientResource ); + connect(comboBoxColorInterpolationType, SIGNAL( activated(int) ), SLOT( slotChangedColorInterpolation(int) )); + connect(comboBoxInterpolationType, SIGNAL( activated(int) ), SLOT( slotChangedInterpolation(int) )); + connect(leftColorButton, SIGNAL( changed(const QColor&) ), SLOT( slotChangedLeftColor(const QColor&) )); + connect(rightColorButton, SIGNAL( changed(const QColor&) ), SLOT( slotChangedRightColor(const QColor&) )); + +// intNumInputLeftOpacity->setRange( 0, 100, false); + connect(intNumInputLeftOpacity, SIGNAL( valueChanged(int) ), SLOT( slotChangedLeftOpacity(int) )); +// intNumInputRightOpacity->setRange( 0, 100, false); + connect(intNumInputRightOpacity, SIGNAL( valueChanged(int) ), SLOT( slotChangedRightOpacity(int) )); + +} + +void KisAutogradient::activate() +{ + paramChanged(); +} + +void KisAutogradient::slotSelectedSegment(KisGradientSegment* segment) +{ + leftColorButton->setColor( segment->startColor().color() ); + rightColorButton->setColor( segment->endColor().color() ); + comboBoxColorInterpolationType->setCurrentItem( segment->colorInterpolation() ); + comboBoxInterpolationType->setCurrentItem( segment->interpolation() ); + + int leftOpacity = qRound(segment->startColor().alpha() * 100); + intNumInputLeftOpacity->setValue( leftOpacity ); + + int rightOpacity = qRound(segment->endColor().alpha() * 100); + intNumInputRightOpacity->setValue( rightOpacity ); + + paramChanged(); +} + +void KisAutogradient::slotChangedSegment(KisGradientSegment*) +{ + paramChanged(); +} + +void KisAutogradient::slotChangedInterpolation(int type) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setInterpolation( type ); + gradientSlider->update(); + + paramChanged(); +} + +void KisAutogradient::slotChangedColorInterpolation(int type) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setColorInterpolation( type ); + gradientSlider->update(); + + paramChanged(); +} + +void KisAutogradient::slotChangedLeftColor( const QColor& color) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setStartColor( Color( color, segment->startColor().alpha() ) ); + gradientSlider->update(); + + paramChanged(); +} + +void KisAutogradient::slotChangedRightColor( const QColor& color) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setEndColor( Color( color, segment->endColor().alpha() ) ); + gradientSlider->repaint(); + + paramChanged(); +} + +void KisAutogradient::slotChangedLeftOpacity( int value ) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setStartColor( Color( segment->startColor().color(), (double)value / 100 ) ); + gradientSlider->repaint(false); + + paramChanged(); +} + +void KisAutogradient::slotChangedRightOpacity( int value ) +{ + KisGradientSegment* segment = gradientSlider->selectedSegment(); + if(segment) + segment->setEndColor( Color( segment->endColor().color(), (double)value / 100 ) ); + gradientSlider->repaint(false); + + paramChanged(); +} + +void KisAutogradient::paramChanged() +{ + m_autogradientResource->updatePreview (); + emit activatedResource( m_autogradientResource ); +} + +#include "kis_autogradient.moc" diff --git a/krita/ui/kis_autogradient.h b/krita/ui/kis_autogradient.h new file mode 100644 index 000000000..a2865d5e5 --- /dev/null +++ b/krita/ui/kis_autogradient.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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_AUTOGRADIENT_H_ +#define _KIS_AUTOGRADIENT_H_ + +#include "wdgautogradient.h" + +class KisResource; +class KisGradientSegment; +class KisAutogradientResource; + +class KisAutogradient : public KisWdgAutogradient +{ + Q_OBJECT + + public: + KisAutogradient(QWidget *parent, const char* name, const QString& caption); + void activate(); + signals: + void activatedResource(KisResource *r); + private: + KisAutogradientResource* m_autogradientResource; + private slots: + void slotSelectedSegment(KisGradientSegment* segment); + void slotChangedSegment(KisGradientSegment* segment); + void slotChangedInterpolation(int type); + void slotChangedColorInterpolation(int type); + void slotChangedLeftColor( const QColor& color); + void slotChangedRightColor( const QColor& color); + void slotChangedLeftOpacity( int value ); + void slotChangedRightOpacity( int value ); + void paramChanged(); +}; + +#endif diff --git a/krita/ui/kis_birdeye_box.cc b/krita/ui/kis_birdeye_box.cc new file mode 100644 index 000000000..54335f9cd --- /dev/null +++ b/krita/ui/kis_birdeye_box.cc @@ -0,0 +1,311 @@ +/* + * Copyright (c) 2004 Kivio Team + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 "qlayout.h" +#include "qlabel.h" +#include "qpixmap.h" +#include "qpainter.h" +#include "qimage.h" +#include "config.h" +#include LCMS_HEADER +#include "klocale.h" +#include "qtooltip.h" + +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_canvas_controller.h" +#include "kis_birdeye_box.h" +#include "kis_double_widget.h" +#include "kis_canvas.h" +#include "kis_image.h" +#include "kis_rect.h" +#include "kis_iterators_pixel.h" + +#include "kobirdeyepanel.h" + +namespace { + + class CanvasAdapter : public KoCanvasAdapter { + + public: + CanvasAdapter(KisCanvasSubject * canvasSubject) : KoCanvasAdapter(), m_canvasSubject(canvasSubject) {} + virtual ~CanvasAdapter() {} + + public: + + virtual KoRect visibleArea() + { + if (!m_canvasSubject->currentImg()) return KoRect(0,0,0,0); + + KisCanvasController * c = m_canvasSubject->canvasController(); + + if (c && c->kiscanvas()) + return c->viewToWindow(KisRect(0, 0, c->kiscanvas()->width(), c->kiscanvas()->height())); + else + return KoRect(0,0,0,0); + } + + virtual double zoomFactor() + { + return m_canvasSubject->zoomFactor(); + } + + virtual QRect size() + { + if (!m_canvasSubject->currentImg()) return QRect(0,0,0,0); + + return QRect(0, 0, m_canvasSubject->currentImg()->width(), m_canvasSubject->currentImg()->height()); + } + + virtual void setViewCenterPoint(double x, double y) + { + m_canvasSubject->canvasController()->zoomAroundPoint(x, y, m_canvasSubject->zoomFactor()); + } + + private: + + KisCanvasSubject * m_canvasSubject; + + }; + + class ZoomListener : public KoZoomAdapter { + + public: + + ZoomListener(KisCanvasController * canvasController) + : KoZoomAdapter() + , m_canvasController(canvasController) {} + virtual ~ZoomListener() {} + + public: + + void zoomTo( double x, double y, double factor ) { m_canvasController->zoomAroundPoint(x, y, factor); } + void zoomIn() { m_canvasController->zoomIn(); } + void zoomOut() { m_canvasController->zoomOut(); } + double getMinZoom() { return (1.0 / 500); } + double getMaxZoom() { return 16.0; } + + private: + + KisCanvasController * m_canvasController; + + }; + + class ThumbnailProvider : public KoThumbnailAdapter { + + public: + ThumbnailProvider(KisImageSP image, KisCanvasSubject* canvasSubject) + : KoThumbnailAdapter() + , m_image(image) + , m_canvasSubject(canvasSubject) {} + + virtual ~ThumbnailProvider() {} + + public: + + virtual QSize pixelSize() + { + if (!m_image) return QSize(0, 0); + return QSize(m_image->width(), m_image->height()); + } + + virtual QImage image(QRect r, QSize thumbnailSize) + { + if (!m_image || r.isEmpty() || thumbnailSize.width() == 0 || thumbnailSize.height() == 0) { + return QImage(); + } + + KisPaintDevice thumbnailRect(m_image->colorSpace(), "thumbnailRect"); + KisPaintDeviceSP mergedImage = m_image->projection(); + + Q_INT32 imageWidth = m_image->width(); + Q_INT32 imageHeight = m_image->height(); + Q_UINT32 pixelSize = m_image->colorSpace()->pixelSize(); + + for (Q_INT32 y = 0; y < r.height(); ++y) { + + KisHLineIteratorPixel it = thumbnailRect.createHLineIterator(0, y, r.width(), true); + Q_INT32 thumbnailY = r.y() + y; + Q_INT32 thumbnailX = r.x(); + Q_INT32 imageY = (thumbnailY * imageHeight) / thumbnailSize.height(); + KisHLineIteratorPixel srcIt = mergedImage -> createHLineIterator(0, imageY, imageWidth, false); + + while (!it.isDone()) { + + Q_INT32 imageX = (thumbnailX * imageWidth) / thumbnailSize.width(); + Q_INT32 dx = imageX - srcIt.x(); + srcIt += dx; + + //KisColor pixelColor = mergedImage->colorAt(imageX, imageY); + memcpy(it.rawData(), srcIt.rawData(), pixelSize); + + ++it; + ++thumbnailX; + } + } + + return thumbnailRect.convertToQImage(m_canvasSubject->monitorProfile(), 0, 0, r.width(), r.height(), + m_canvasSubject->HDRExposure()); + } + + void setImage(KisImageSP image) + { + m_image = image; + } + private: + + KisImageSP m_image; + KisCanvasSubject * m_canvasSubject; + + }; + +} + +KisBirdEyeBox::KisBirdEyeBox(KisView * view, QWidget* parent, const char* name) + : QWidget(parent, name) + , m_view(view) + , m_subject(view->canvasSubject()) +{ + QVBoxLayout * l = new QVBoxLayout(this); + + m_image = m_subject->currentImg(); + + m_zoomAdapter = new ZoomListener(m_subject->canvasController()); // The birdeye panel deletes + KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject); // The birdeye panel deletes + KoCanvasAdapter * kpc = new CanvasAdapter(m_subject); // The birdeye panel deletes + + m_birdEyePanel = new KoBirdEyePanel(m_zoomAdapter, ktp, kpc, this); + + connect(view, SIGNAL(cursorPosition( Q_INT32, Q_INT32 )), m_birdEyePanel, SLOT(cursorPosChanged( Q_INT32, Q_INT32 ))); + connect(view, SIGNAL(viewTransformationsChanged()), m_birdEyePanel, SLOT(slotViewTransformationChanged())); + + l->addWidget(m_birdEyePanel); + + QHBoxLayout * hl = new QHBoxLayout(l); + + m_exposureLabel = new QLabel(i18n("Exposure:"), this); + hl->addWidget(m_exposureLabel); + + m_exposureDoubleWidget = new KisDoubleWidget(-10, 10, this); + m_exposureDoubleWidget->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); + hl->addWidget(m_exposureDoubleWidget); + QToolTip::add(m_exposureDoubleWidget, i18n("Select the exposure (stops) for HDR images")); + l->addItem(new QSpacerItem(0, 1, QSizePolicy::Minimum, QSizePolicy::MinimumExpanding)); + + m_exposureDoubleWidget->setPrecision(1); + m_exposureDoubleWidget->setValue(0); + m_exposureDoubleWidget->setLineStep(0.1); + m_exposureDoubleWidget->setPageStep(1); + + connect(m_exposureDoubleWidget, SIGNAL(valueChanged(double)), SLOT(exposureValueChanged(double))); + connect(m_exposureDoubleWidget, SIGNAL(sliderPressed()), SLOT(exposureSliderPressed())); + connect(m_exposureDoubleWidget, SIGNAL(sliderReleased()), SLOT(exposureSliderReleased())); + + m_draggingExposureSlider = false; + + Q_ASSERT(m_subject->document() != 0); + connect(m_subject->document(), SIGNAL(sigCommandExecuted()), SLOT(slotDocCommandExecuted())); + + if (m_image) { + connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(slotImageUpdated(QRect))); + } +} + +KisBirdEyeBox::~KisBirdEyeBox() +{ + // Huh? Why does this cause a crash? + // delete m_zoomAdapter; +} + +void KisBirdEyeBox::setImage(KisImageSP image) +{ + if (m_image) { + m_image->disconnect(this); + } + + m_image = image; + + KoThumbnailAdapter * ktp = new ThumbnailProvider(m_image, m_subject); + m_birdEyePanel->setThumbnailProvider(ktp); + + if (m_image) { + connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(slotImageUpdated(QRect))); + connect(m_image, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), SLOT(slotImageSizeChanged(Q_INT32, Q_INT32))); + connect(m_image, SIGNAL(sigColorSpaceChanged(KisColorSpace *)), SLOT(slotImageColorSpaceChanged(KisColorSpace *))); + m_birdEyePanel->slotUpdate(m_image->bounds()); + slotImageColorSpaceChanged(m_image->colorSpace()); + } +} + +void KisBirdEyeBox::slotDocCommandExecuted() +{ + if (m_image) { + if (!m_dirtyRect.isEmpty()) { + m_birdEyePanel->slotUpdate(m_dirtyRect); + } + m_dirtyRect = QRect(); + } +} + +void KisBirdEyeBox::slotImageUpdated(QRect r) +{ + m_dirtyRect |= r; +} + +void KisBirdEyeBox::slotImageSizeChanged(Q_INT32 /*w*/, Q_INT32 /*h*/) +{ + if (m_image) { + m_birdEyePanel->slotUpdate(m_image->bounds()); + } +} + +void KisBirdEyeBox::slotImageColorSpaceChanged(KisColorSpace *cs) +{ + if (cs->hasHighDynamicRange()) { + m_exposureDoubleWidget->show(); + m_exposureLabel->show(); + } else { + m_exposureDoubleWidget->hide(); + m_exposureLabel->hide(); + } +} + +void KisBirdEyeBox::exposureValueChanged(double exposure) +{ + if (!m_draggingExposureSlider) { + m_subject->setHDRExposure(exposure); + + if (m_image && m_image->colorSpace()->hasHighDynamicRange()) { + m_birdEyePanel->slotUpdate(m_image->bounds()); + } + } +} + +void KisBirdEyeBox::exposureSliderPressed() +{ + m_draggingExposureSlider = true; +} + +void KisBirdEyeBox::exposureSliderReleased() +{ + m_draggingExposureSlider = false; + exposureValueChanged(m_exposureDoubleWidget->value()); +} + +#include "kis_birdeye_box.moc" diff --git a/krita/ui/kis_birdeye_box.h b/krita/ui/kis_birdeye_box.h new file mode 100644 index 000000000..46b6d72d3 --- /dev/null +++ b/krita/ui/kis_birdeye_box.h @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2004 Kivio Team + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_BIRDEYE_BOX_H +#define KIS_BIRDEYE_BOX_H + +#include "qwidget.h" + +#include "kis_types.h" + +class KoBirdEyePanel; +class KisDoubleWidget; +class KisView; +class KisCanvasSubject; +class KoZoomAdapter; +class KisColorSpace; + +class KisBirdEyeBox : public QWidget +{ + Q_OBJECT + +public: + + KisBirdEyeBox(KisView * view, QWidget * parent = 0, const char* name=0); + ~KisBirdEyeBox(); + + void setImage(KisImageSP image); + +public slots: + void slotDocCommandExecuted(); + void slotImageUpdated(QRect r); + void slotImageSizeChanged(Q_INT32 w, Q_INT32 h); + void slotImageColorSpaceChanged(KisColorSpace *cs); + +protected slots: + void exposureValueChanged(double exposure); + void exposureSliderPressed(); + void exposureSliderReleased(); + +private: + KoBirdEyePanel * m_birdEyePanel; + KisDoubleWidget * m_exposureDoubleWidget; + QLabel *m_exposureLabel; + KisView * m_view; + KisCanvasSubject * m_subject; + bool m_draggingExposureSlider; + KoZoomAdapter * m_zoomAdapter; + KisImageSP m_image; + QRect m_dirtyRect; +}; + +#endif // KIS_BIRDEYE_BOX_H diff --git a/krita/ui/kis_boundary_painter.cc b/krita/ui/kis_boundary_painter.cc new file mode 100644 index 000000000..b8dfc7615 --- /dev/null +++ b/krita/ui/kis_boundary_painter.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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 <qpixmap.h> +#include <qpainter.h> + +#include "kis_boundary.h" +#include "kis_boundary_painter.h" +#include "kis_canvas.h" +#include "kis_canvas_painter.h" + +QPixmap KisBoundaryPainter::createPixmap(const KisBoundary& boundary, int w, int h) +{ + QPixmap target(w, h); + KisCanvasPainter painter(&target); + + painter.eraseRect(0, 0, w, h); + + paint(boundary, painter); + + painter.end(); + return target; +} + +void KisBoundaryPainter::paint(const KisBoundary& boundary, KisCanvasPainter& painter) +{ + KisBoundary::PointPairListList::const_iterator it = boundary.m_horSegments.constBegin(); + KisBoundary::PointPairListList::const_iterator end = boundary.m_horSegments.constEnd(); + + // Horizontal + while (it != end) { + KisBoundary::PointPairList::const_iterator lineIt = (*it).constBegin(); + KisBoundary::PointPairList::const_iterator lineEnd = (*it).constEnd(); + while (lineIt != lineEnd) { + int x1 = (*lineIt).first.floorX(); + int y = (*lineIt).first.floorY(); + int x2 = x1 + (*lineIt).second; + + painter.drawLine(x1, y, x2, y); + painter.drawPoint(x2, y); + + ++lineIt; + } + ++it; + } + + // Vertical + it = boundary.m_vertSegments.constBegin(); + end = boundary.m_vertSegments.constEnd(); + + while (it != end) { + KisBoundary::PointPairList::const_iterator lineIt = (*it).constBegin(); + KisBoundary::PointPairList::const_iterator lineEnd = (*it).constEnd(); + while (lineIt != lineEnd) { + int x = (*lineIt).first.floorX(); + int y1 = (*lineIt).first.floorY(); + int y2 = y1 + (*lineIt).second; + + painter.drawLine(x, y1, x, y2); + painter.drawPoint(x, y2); + + ++lineIt; + } + ++it; + } +} + diff --git a/krita/ui/kis_boundary_painter.h b/krita/ui/kis_boundary_painter.h new file mode 100644 index 000000000..10665ee9a --- /dev/null +++ b/krita/ui/kis_boundary_painter.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_BOUNDARY_PAINTER_H_ +#define _KIS_BOUNDARY_PAINTER_H_ + +#include <koffice_export.h> + +class KisBoundary; +class KisCanvasPainter; + +class KRITACORE_EXPORT KisBoundaryPainter { +public: + static void paint(const KisBoundary& boundary, KisCanvasPainter& painter); + static QPixmap createPixmap(const KisBoundary& boundary, int w, int h); +}; + +#endif // _KIS_BOUNDARY_PAINTER_H_ + diff --git a/krita/ui/kis_brush_chooser.cc b/krita/ui/kis_brush_chooser.cc new file mode 100644 index 000000000..03f6c502c --- /dev/null +++ b/krita/ui/kis_brush_chooser.cc @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> +#include <klocale.h> +#include <koIconChooser.h> + +#include "kis_double_widget.h" +#include "kis_brush_chooser.h" +#include "kis_global.h" +#include "kis_icon_item.h" +#include "kis_brush.h" + +KisBrushChooser::KisBrushChooser(QWidget *parent, const char *name) + : super(parent, name) +{ + m_lbSpacing = new QLabel(i18n("Spacing:"), this); + m_slSpacing = new KisDoubleWidget(0.0, 10, this, "double_widget"); + m_slSpacing->setTickmarks(QSlider::Below); + m_slSpacing->setTickInterval(1); + QObject::connect(m_slSpacing, SIGNAL(valueChanged(double)), this, SLOT(slotSetItemSpacing(double))); + + m_chkColorMask = new QCheckBox(i18n("Use color as mask"), this); + QObject::connect(m_chkColorMask, SIGNAL(toggled(bool)), this, SLOT(slotSetItemUseColorAsMask(bool))); + + m_lbName = new QLabel(this); + + QVBoxLayout *mainLayout = new QVBoxLayout(this, 2, -1, "main layout"); + + mainLayout->addWidget(m_lbName); + mainLayout->addWidget(chooserWidget(), 10); + + QGridLayout *spacingLayout = new QGridLayout( 2, 2); + + mainLayout->addLayout(spacingLayout, 1); + + spacingLayout->addWidget(m_lbSpacing, 0, 0); + spacingLayout->addWidget(m_slSpacing, 0, 1); + + spacingLayout->addMultiCellWidget(m_chkColorMask, 1, 1, 0, 1); +} + +KisBrushChooser::~KisBrushChooser() +{ +} + +void KisBrushChooser::slotSetItemSpacing(double spacingValue) +{ + KisIconItem *item = static_cast<KisIconItem *>(currentItem()); + + if (item) { + KisBrush *brush = static_cast<KisBrush *>(item->resource()); + brush->setSpacing(spacingValue); + } +} + +void KisBrushChooser::slotSetItemUseColorAsMask(bool useColorAsMask) +{ + KisIconItem *item = static_cast<KisIconItem *>(currentItem()); + + if (item) { + KisBrush *brush = static_cast<KisBrush *>(item->resource()); + brush->setUseColorAsMask(useColorAsMask); + item->updatePixmaps(); + emit selected(currentItem()); + } +} + +void KisBrushChooser::update(KoIconItem *item) +{ + KisIconItem *kisItem = static_cast<KisIconItem *>(item); + + if (kisItem) { + KisBrush *brush = static_cast<KisBrush *>(kisItem->resource()); + + QString text = QString("%1 (%2 x %3)").arg(brush->name()).arg(brush->width()).arg(brush->height()); + + m_lbName->setText(text); + m_slSpacing->setValue(brush->spacing()); + m_chkColorMask->setChecked(brush->useColorAsMask()); + m_chkColorMask->setEnabled(brush->hasColor()); + } +} + +#include "kis_brush_chooser.moc" + diff --git a/krita/ui/kis_brush_chooser.h b/krita/ui/kis_brush_chooser.h new file mode 100644 index 000000000..942742d1d --- /dev/null +++ b/krita/ui/kis_brush_chooser.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_CHOOSER_H_ +#define KIS_BRUSH_CHOOSER_H_ + +#include "kis_itemchooser.h" + +class QLabel; +class QCheckBox; + +class KisDoubleWidget; + +class KisBrushChooser : public KisItemChooser { + typedef KisItemChooser super; + Q_OBJECT + +public: + KisBrushChooser(QWidget *parent = 0, const char *name = 0); + virtual ~KisBrushChooser(); + +protected: + virtual void update(KoIconItem *item); + +private slots: + void slotSetItemSpacing(double spacing); + void slotSetItemUseColorAsMask(bool); + +private: + QLabel *m_lbName; + QLabel *m_lbSpacing; + KisDoubleWidget *m_slSpacing; + QCheckBox *m_chkColorMask; +}; + +#endif // KIS_BRUSH_CHOOSER_H_ + diff --git a/krita/ui/kis_button_event.h b/krita/ui/kis_button_event.h new file mode 100644 index 000000000..e8b7fc2b1 --- /dev/null +++ b/krita/ui/kis_button_event.h @@ -0,0 +1,45 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_BUTTON_EVENT_H_ +#define KIS_BUTTON_EVENT_H_ + +#include "kis_event.h" + +class KisButtonEvent : public KisEvent { + typedef KisEvent super; +public: + Qt::ButtonState button() const { return m_button; } + +protected: + KisButtonEvent() {} + KisButtonEvent(enumEventType type, + KisInputDevice device, + const KisPoint& pos, + const KisPoint& globalPos, + double pressure, + double xTilt, double yTilt, + Qt::ButtonState button, + Qt::ButtonState state) + : super(type, device, pos, globalPos, pressure, xTilt, yTilt, state) + , m_button(button) {} + + Qt::ButtonState m_button; +}; + +#endif // KIS_BUTTON_EVENT_H_ + diff --git a/krita/ui/kis_button_press_event.h b/krita/ui/kis_button_press_event.h new file mode 100644 index 000000000..51ad0d664 --- /dev/null +++ b/krita/ui/kis_button_press_event.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_BUTTON_PRESS_EVENT_H_ +#define KIS_BUTTON_PRESS_EVENT_H_ + +#include "kis_button_event.h" + +class KisButtonPressEvent : public KisButtonEvent { + typedef KisButtonEvent super; +public: + KisButtonPressEvent() {} + KisButtonPressEvent(KisInputDevice device, const KisPoint& pos, const KisPoint& globalPos, double pressure, double xTilt, double yTilt, Qt::ButtonState button, Qt::ButtonState state) : super(ButtonPressEvent, device, pos, globalPos, pressure, xTilt, yTilt, button, state) {} +}; + +#endif // KIS_BUTTON_PRESS_EVENT_H_ + diff --git a/krita/ui/kis_button_release_event.h b/krita/ui/kis_button_release_event.h new file mode 100644 index 000000000..3d9234f0e --- /dev/null +++ b/krita/ui/kis_button_release_event.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_BUTTON_RELEASE_EVENT_H_ +#define KIS_BUTTON_RELEASE_EVENT_H_ + +#include "kis_button_event.h" + +class KisButtonReleaseEvent : public KisButtonEvent { + typedef KisButtonEvent super; +public: + KisButtonReleaseEvent() {} + KisButtonReleaseEvent(KisInputDevice device, const KisPoint& pos, const KisPoint& globalPos, double pressure, double xTilt, double yTilt, Qt::ButtonState button, Qt::ButtonState state) : super(ButtonReleaseEvent, device, pos, globalPos, pressure, xTilt, yTilt, button, state) {} +}; + +#endif // KIS_BUTTON_RELEASE_EVENT_H_ + diff --git a/krita/ui/kis_canvas.cc b/krita/ui/kis_canvas.cc new file mode 100644 index 000000000..499f4c29a --- /dev/null +++ b/krita/ui/kis_canvas.cc @@ -0,0 +1,1355 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2004-2006 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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. + * + + Some of the X11-specific event handling code is based upon code from + src/kernel/qapplication_x11.cpp from the Qt GUI Toolkit and is subject + to the following license and copyright: + + **************************************************************************** +** +** +** Implementation of X11 startup routines and event handling +** +** Created : 931029 +** +** Copyright (C) 1992-2003 Trolltech AS. All rights reserved. +** +** This file is part of the kernel module of the Qt GUI Toolkit. +** +** This file may be distributed under the terms of the Q Public License +** as defined by Trolltech AS of Norway and appearing in the file +** LICENSE.QPL included in the packaging of this file. +** +** This file may be distributed and/or modified under the terms of the +** GNU General Public License version 2 as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL included in the +** packaging of this file. +** +** Licensees holding valid Qt Enterprise Edition or Qt Professional Edition +** licenses for Unix/X11 may use this file in accordance with the Qt Commercial +** License Agreement provided with the Software. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** See http://www.trolltech.com/pricing.html or email sales@trolltech.com for +** information about Qt Commercial License Agreements. +** See http://www.trolltech.com/qpl/ for QPL licensing information. +** See http://www.trolltech.com/gpl/ for GPL licensing information. +** +** Contact info@trolltech.com if any conditions of this licensing are +** not clear to you. +** +**********************************************************************/ + +#include <qcursor.h> + +#include "kis_canvas.h" +#include "kis_cursor.h" +#include "kis_move_event.h" +#include "kis_button_press_event.h" +#include "kis_button_release_event.h" +#include "kis_double_click_event.h" +#include "kis_config.h" +#include "kis_qpaintdevice_canvas.h" +#include "kis_opengl_canvas.h" +#include "kis_config.h" +#include "kis_input_device.h" +#include "fixx11h.h" + +#ifdef Q_WS_X11 + +#include <qdesktopwidget.h> +#include <qapplication.h> + +#include <X11/keysym.h> + +bool KisCanvasWidget::X11SupportInitialised = false; +long KisCanvasWidget::X11AltMask = 0; +long KisCanvasWidget::X11MetaMask = 0; + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + +int KisCanvasWidget::X11DeviceMotionNotifyEvent = -1; +int KisCanvasWidget::X11DeviceButtonPressEvent = -1; +int KisCanvasWidget::X11DeviceButtonReleaseEvent = -1; +int KisCanvasWidget::X11ProximityInEvent = -1; +int KisCanvasWidget::X11ProximityOutEvent = -1; + +//X11XIDTabletDeviceMap KisCanvasWidget::X11TabletDeviceMap; +std::map<XID, KisCanvasWidget::X11TabletDevice> KisCanvasWidget::X11TabletDeviceMap; + +#endif // EXTENDED_X11_TABLET_SUPPORT + +#endif // Q_WS_X11 + +KisCanvasWidget::KisCanvasWidget() +{ + m_enableMoveEventCompressionHint = false; + m_lastPressure = 0; + +#ifdef Q_WS_X11 + if (!X11SupportInitialised) { + initX11Support(); + } + + m_lastRootX = -1; + m_lastRootY = -1; +#endif +} + +KisCanvasWidget::~KisCanvasWidget() +{ +} + +void KisCanvasWidget::widgetGotPaintEvent(QPaintEvent *e) +{ + emit sigGotPaintEvent(e); +} + +void KisCanvasWidget::widgetGotMousePressEvent(QMouseEvent *e) +{ + KisButtonPressEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state()); + buttonPressEvent(&ke); +} + +void KisCanvasWidget::widgetGotMouseReleaseEvent(QMouseEvent *e) +{ + KisButtonReleaseEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state()); + buttonReleaseEvent(&ke); +} + +void KisCanvasWidget::widgetGotMouseDoubleClickEvent(QMouseEvent *e) +{ + KisDoubleClickEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->button(), e->state()); + doubleClickEvent(&ke); +} + +void KisCanvasWidget::widgetGotMouseMoveEvent(QMouseEvent *e) +{ + KisMoveEvent ke(KisInputDevice::mouse(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->state()); + moveEvent(&ke); +} + +void KisCanvasWidget::widgetGotTabletEvent(QTabletEvent *e) +{ + KisInputDevice device; + + switch (e->device()) { + default: + case QTabletEvent::NoDevice: + case QTabletEvent::Stylus: + device = KisInputDevice::stylus(); + break; + case QTabletEvent::Puck: + device = KisInputDevice::puck(); + break; + case QTabletEvent::Eraser: + device = KisInputDevice::eraser(); + break; + } + + double pressure = e->pressure() / 255.0; + + if (e->type() == QEvent::TabletPress) { + KisButtonPressEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::LeftButton, Qt::NoButton); + translateTabletEvent(&ke); + } + else + if (e->type() == QEvent::TabletRelease) { + KisButtonReleaseEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::LeftButton, Qt::NoButton); + translateTabletEvent(&ke); + } + else { + KisMoveEvent ke(device, e->pos(), e->globalPos(), pressure, e->xTilt(), e->yTilt(), Qt::NoButton); + translateTabletEvent(&ke); +#ifdef Q_WS_X11 + // Fix the problem that when you change from using a tablet device to the mouse, + // the first mouse button event is not recognised. This is because we handle + // X11 core mouse move events directly so Qt does not get to see them. This breaks + // the tablet event accept/ignore mechanism, causing Qt to consume the first + // mouse button event it sees, instead of a mouse move. 'Ignoring' tablet move events + // stops Qt from stealing the next mouse button event. This does not affect the + // tablet aware tools as they do not care about mouse moves while the tablet device is + // drawing. + e->ignore(); +#endif + } +} + +void KisCanvasWidget::widgetGotEnterEvent(QEvent *e) +{ + emit sigGotEnterEvent(e); +} + +void KisCanvasWidget::widgetGotLeaveEvent(QEvent *e) +{ + emit sigGotLeaveEvent(e); +} + +void KisCanvasWidget::widgetGotWheelEvent(QWheelEvent *e) +{ + emit sigGotMouseWheelEvent(e); +} + +void KisCanvasWidget::widgetGotKeyPressEvent(QKeyEvent *e) +{ + emit sigGotKeyPressEvent(e); +} + +void KisCanvasWidget::widgetGotKeyReleaseEvent(QKeyEvent *e) +{ + emit sigGotKeyReleaseEvent(e); +} + +void KisCanvasWidget::widgetGotDragEnterEvent(QDragEnterEvent *e) +{ + emit sigGotDragEnterEvent(e); +} + +void KisCanvasWidget::widgetGotDropEvent(QDropEvent *e) +{ + emit sigGotDropEvent(e); +} + +void KisCanvasWidget::moveEvent(KisMoveEvent *e) +{ + emit sigGotMoveEvent(e); +} + +void KisCanvasWidget::buttonPressEvent(KisButtonPressEvent *e) +{ + QWidget *widget = dynamic_cast<QWidget *>(this); + Q_ASSERT(widget != 0); + + if (widget) { + widget->setFocus(); + } + + emit sigGotButtonPressEvent(e); +} + +void KisCanvasWidget::buttonReleaseEvent(KisButtonReleaseEvent *e) +{ + emit sigGotButtonReleaseEvent(e); +} + +void KisCanvasWidget::doubleClickEvent(KisDoubleClickEvent *e) +{ + emit sigGotDoubleClickEvent(e); +} + +void KisCanvasWidget::translateTabletEvent(KisEvent *e) +{ + bool checkThresholdOnly = false; + + if (e->type() == KisEvent::ButtonPressEvent || e->type() == KisEvent::ButtonReleaseEvent) { + KisButtonEvent *b = static_cast<KisButtonEvent *>(e); + + if (b->button() == Qt::MidButton || b->button() == Qt::RightButton) { + + if (e->type() == KisEvent::ButtonPressEvent) { + buttonPressEvent(static_cast<KisButtonPressEvent *>(e)); + } else { + buttonReleaseEvent(static_cast<KisButtonReleaseEvent *>(e)); + } + + checkThresholdOnly = true; + } + } + + // Use pressure threshold to detect 'left button' press/release + if (e->pressure() >= PRESSURE_THRESHOLD && m_lastPressure < PRESSURE_THRESHOLD) { + KisButtonPressEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), Qt::LeftButton, e->state()); + buttonPressEvent(&ke); + } else if (e->pressure() < PRESSURE_THRESHOLD && m_lastPressure >= PRESSURE_THRESHOLD) { + KisButtonReleaseEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), Qt::LeftButton, e->state()); + buttonReleaseEvent(&ke); + } else { + if (!checkThresholdOnly) { + KisMoveEvent ke(e->device(), e->pos(), e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->state()); + moveEvent(&ke); + } + } + + m_lastPressure = e->pressure(); +} + +#ifdef Q_WS_X11 + +void KisCanvasWidget::initX11Support() +{ + if (X11SupportInitialised) + { + return; + } + + X11SupportInitialised = true; + + Display *x11Display = QApplication::desktop()->x11Display(); + + // Look at the modifier mapping and get the correct masks for alt/meta + XModifierKeymap *map = XGetModifierMapping(x11Display); + + if (map) { + int mapIndex = 0; + + for (int maskIndex = 0; maskIndex < 8; maskIndex++) { + for (int i = 0; i < map->max_keypermod; i++) { + if (map->modifiermap[mapIndex]) { + + KeySym sym = XKeycodeToKeysym(x11Display, map->modifiermap[mapIndex], 0); + + if (X11AltMask == 0 && (sym == XK_Alt_L || sym == XK_Alt_R)) { + X11AltMask = 1 << maskIndex; + } + if (X11MetaMask == 0 && (sym == XK_Meta_L || sym == XK_Meta_R)) { + X11MetaMask = 1 << maskIndex; + } + } + + mapIndex++; + } + } + + XFreeModifiermap(map); + } + else { + // Assume defaults + X11AltMask = Mod1Mask; + X11MetaMask = Mod4Mask; + } + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + + int numDevices = 0; + const XDeviceInfo *devices = XListInputDevices(x11Display, &numDevices); + + if (devices != NULL) { + XID lastStylusSeen = 0; + XID lastEraserSeen = 0; + bool foundStylus = false; + bool foundEraser = false; + + for (int i = 0; i < numDevices; i++) { + + const XDeviceInfo *device = devices + i; + X11TabletDevice tabletDevice(device); + + if (tabletDevice.mightBeTabletDevice()) { + + tabletDevice.readSettingsFromConfig(); + + QString lowerCaseName = tabletDevice.name().lower(); + + // Find the devices that Qt will use as its stylus and eraser devices. + if (!foundStylus || !foundEraser) { + if (lowerCaseName.startsWith("stylus") || lowerCaseName.startsWith("pen")) { + lastStylusSeen = device->id; + foundStylus = true; + } + else if (lowerCaseName.startsWith("eraser")) { + lastEraserSeen = device->id; + foundEraser = true; + } + } + + X11TabletDeviceMap[device->id] = tabletDevice; + + // Event types are device-independent. Store any + // the device supports. + if (tabletDevice.buttonPressEvent() >= 0) { + X11DeviceButtonPressEvent = tabletDevice.buttonPressEvent(); + } + if (tabletDevice.buttonReleaseEvent() >= 0) { + X11DeviceButtonReleaseEvent = tabletDevice.buttonReleaseEvent(); + } + if (tabletDevice.motionNotifyEvent() >= 0) { + X11DeviceMotionNotifyEvent = tabletDevice.motionNotifyEvent(); + } + if (tabletDevice.proximityInEvent() >= 0) { + X11ProximityInEvent = tabletDevice.proximityInEvent(); + } + if (tabletDevice.proximityOutEvent() >= 0) { + X11ProximityOutEvent = tabletDevice.proximityOutEvent(); + } + } + } + + // Allocate input devices. + for (X11XIDTabletDeviceMap::iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) { + + X11TabletDevice& tabletDevice = (*it).second; + + if (foundStylus && tabletDevice.id() == lastStylusSeen) { + tabletDevice.setInputDevice(KisInputDevice::stylus()); + } else if (foundEraser && tabletDevice.id() == lastEraserSeen) { + tabletDevice.setInputDevice(KisInputDevice::eraser()); + } else { + tabletDevice.setInputDevice(KisInputDevice::allocateInputDevice()); + } + } + + XFreeDeviceList(const_cast<XDeviceInfo *>(devices)); + } +#endif // EXTENDED_X11_TABLET_SUPPORT +} + +Qt::ButtonState KisCanvasWidget::translateX11ButtonState(int state) +{ + int buttonState = 0; + + if (state & Button1Mask) + buttonState |= Qt::LeftButton; + if (state & Button2Mask) + buttonState |= Qt::MidButton; + if (state & Button3Mask) + buttonState |= Qt::RightButton; + if (state & ShiftMask) + buttonState |= Qt::ShiftButton; + if (state & ControlMask) + buttonState |= Qt::ControlButton; + if (state & X11AltMask) + buttonState |= Qt::AltButton; + if (state & X11MetaMask) + buttonState |= Qt::MetaButton; + + return static_cast<Qt::ButtonState>(buttonState); +} + +Qt::ButtonState KisCanvasWidget::translateX11Button(unsigned int X11Button) +{ + Qt::ButtonState qtButton; + + switch (X11Button) { + case Button1: + qtButton = Qt::LeftButton; + break; + case Button2: + qtButton = Qt::MidButton; + break; + case Button3: + qtButton = Qt::RightButton; + break; + default: + qtButton = Qt::NoButton; + } + + return qtButton; +} + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + +KisCanvasWidget::X11TabletDevice::X11TabletDevice() +{ + m_mightBeTabletDevice = false; + m_inputDevice = KisInputDevice::unknown(); + m_enabled = false; + m_xAxis = NoAxis; + m_yAxis = NoAxis; + m_pressureAxis = NoAxis; + m_xTiltAxis = NoAxis; + m_yTiltAxis = NoAxis; + m_wheelAxis = NoAxis; + m_toolIDAxis = NoAxis; + m_serialNumberAxis = NoAxis; + m_buttonPressEvent = -1; + m_buttonReleaseEvent = -1; + m_motionNotifyEvent = -1; + m_proximityInEvent = -1; + m_proximityOutEvent = -1; +} + +KisCanvasWidget::X11TabletDevice::X11TabletDevice(const XDeviceInfo *deviceInfo) +{ + m_mightBeTabletDevice = false; + m_inputDevice = KisInputDevice::unknown(); + m_enabled = false; + m_xAxis = NoAxis; + m_yAxis = NoAxis; + m_pressureAxis = NoAxis; + m_xTiltAxis = NoAxis; + m_yTiltAxis = NoAxis; + m_wheelAxis = NoAxis; + m_toolIDAxis = NoAxis; + m_serialNumberAxis = NoAxis; + + m_deviceId = deviceInfo->id; + m_name = deviceInfo->name; + + // Get the ranges of the valuators + XAnyClassPtr classInfo = const_cast<XAnyClassPtr>(deviceInfo->inputclassinfo); + + for (int i = 0; i < deviceInfo->num_classes; i++) { + + if (classInfo->c_class == ValuatorClass) { + + const XValuatorInfo *valuatorInfo = reinterpret_cast<const XValuatorInfo *>(classInfo); + + // Need at least x, y, and pressure. + + if (valuatorInfo->num_axes >= 3) { + + for (unsigned int axis = 0; axis < valuatorInfo->num_axes; axis++) { + m_axisInfo.append(valuatorInfo->axes[axis]); + } + + m_mightBeTabletDevice = true; + } + } + + classInfo = reinterpret_cast<XAnyClassPtr>(reinterpret_cast<char *>(classInfo) + classInfo->length); + } + + // Determine the event types it supports. We're only interested in + // buttons and motion at the moment. + m_buttonPressEvent = -1; + m_buttonReleaseEvent = -1; + m_motionNotifyEvent = -1; + m_proximityInEvent = -1; + m_proximityOutEvent = -1; + + m_XDevice = XOpenDevice(QApplication::desktop()->x11Display(), m_deviceId); + + if (m_XDevice != NULL) { + for (int i = 0; i < m_XDevice->num_classes; i++) { + + XEventClass eventClass; + + if (m_XDevice->classes[i].input_class == ButtonClass) { + DeviceButtonPress(m_XDevice, m_buttonPressEvent, eventClass); + m_eventClassList.append(eventClass); + + DeviceButtonRelease(m_XDevice, m_buttonReleaseEvent, eventClass); + m_eventClassList.append(eventClass); + } + else + if (m_XDevice->classes[i].input_class == ValuatorClass) { + DeviceMotionNotify(m_XDevice, m_motionNotifyEvent, eventClass); + m_eventClassList.append(eventClass); + } + else + if (m_XDevice->classes[i].input_class == ProximityClass) { + ProximityIn(m_XDevice, m_proximityInEvent, eventClass); + m_eventClassList.append(eventClass); + + ProximityOut(m_XDevice, m_proximityOutEvent, eventClass); + m_eventClassList.append(eventClass); + } + } + + // Note: We don't XCloseXDevice() since Qt will have already opened + // it, and only one XCloseDevice() call closes it for all opens. + } + + if (m_buttonPressEvent == -1 || m_buttonReleaseEvent == -1 || m_motionNotifyEvent == -1) { + m_mightBeTabletDevice = false; + } +} + +void KisCanvasWidget::X11TabletDevice::setEnabled(bool enabled) +{ + m_enabled = enabled; +} + +bool KisCanvasWidget::X11TabletDevice::enabled() const +{ + return m_enabled; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::numAxes() const +{ + return m_axisInfo.count(); +} + +void KisCanvasWidget::X11TabletDevice::setXAxis(Q_INT32 axis) +{ + m_xAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setYAxis(Q_INT32 axis) +{ + m_yAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setPressureAxis(Q_INT32 axis) +{ + m_pressureAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setXTiltAxis(Q_INT32 axis) +{ + m_xTiltAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setYTiltAxis(Q_INT32 axis) +{ + m_yTiltAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setWheelAxis(Q_INT32 axis) +{ + m_wheelAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setToolIDAxis(Q_INT32 axis) +{ + m_toolIDAxis = axis; +} + +void KisCanvasWidget::X11TabletDevice::setSerialNumberAxis(Q_INT32 axis) +{ + m_serialNumberAxis = axis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::xAxis() const +{ + return m_xAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::yAxis() const +{ + return m_yAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::pressureAxis() const +{ + return m_pressureAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::xTiltAxis() const +{ + return m_xTiltAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::yTiltAxis() const +{ + return m_yTiltAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::wheelAxis() const +{ + return m_wheelAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::toolIDAxis() const +{ + return m_toolIDAxis; +} + +Q_INT32 KisCanvasWidget::X11TabletDevice::serialNumberAxis() const +{ + return m_serialNumberAxis; +} + +void KisCanvasWidget::X11TabletDevice::readSettingsFromConfig() +{ + KisConfig cfg; + + m_enabled = cfg.tabletDeviceEnabled(m_name); + + m_xAxis = cfg.tabletDeviceAxis(m_name, "XAxis", DefaultAxis); + m_yAxis = cfg.tabletDeviceAxis(m_name, "YAxis", DefaultAxis); + m_pressureAxis = cfg.tabletDeviceAxis(m_name, "PressureAxis", DefaultAxis); + m_xTiltAxis = cfg.tabletDeviceAxis(m_name, "XTiltAxis", DefaultAxis); + m_yTiltAxis = cfg.tabletDeviceAxis(m_name, "YTiltAxis", DefaultAxis); + m_wheelAxis = cfg.tabletDeviceAxis(m_name, "WheelAxis", DefaultAxis); + m_toolIDAxis = cfg.tabletDeviceAxis(m_name, "ToolIDAxis", DefaultAxis); + m_serialNumberAxis = cfg.tabletDeviceAxis(m_name, "SerialNumberAxis", DefaultAxis); + + if (!m_enabled && m_xAxis == DefaultAxis && m_yAxis == DefaultAxis && m_pressureAxis == DefaultAxis && + m_xTiltAxis == DefaultAxis && m_yTiltAxis == DefaultAxis && m_wheelAxis == DefaultAxis && + m_toolIDAxis == DefaultAxis && m_serialNumberAxis == DefaultAxis) { + // This is the first time this device has been seen. Set up default values, assuming + // it's a Wacom pad. + m_xAxis = 0; + m_yAxis = 1; + m_pressureAxis = 2; + + if (m_axisInfo.count() >= 4) { + m_xTiltAxis = 3; + } else { + m_xTiltAxis = NoAxis; + } + + if (m_axisInfo.count() >= 5) { + m_yTiltAxis = 4; + } else { + m_yTiltAxis = NoAxis; + } + + if (m_axisInfo.count() >= 6) { + m_wheelAxis = 5; + } else { + m_wheelAxis = NoAxis; + } + + // Available since driver version 0.7.2. + if (m_axisInfo.count() >= 7) { + m_toolIDAxis = 6; + } else { + m_toolIDAxis = NoAxis; + } + + if (m_axisInfo.count() >= 8) { + m_serialNumberAxis = 7; + } else { + m_serialNumberAxis = NoAxis; + } + } +} + +void KisCanvasWidget::X11TabletDevice::writeSettingsToConfig() +{ + KisConfig cfg; + + cfg.setTabletDeviceEnabled(m_name, m_enabled); + + cfg.setTabletDeviceAxis(m_name, "XAxis", m_xAxis); + cfg.setTabletDeviceAxis(m_name, "YAxis", m_yAxis); + cfg.setTabletDeviceAxis(m_name, "PressureAxis", m_pressureAxis); + cfg.setTabletDeviceAxis(m_name, "XTiltAxis", m_xTiltAxis); + cfg.setTabletDeviceAxis(m_name, "YTiltAxis", m_yTiltAxis); + cfg.setTabletDeviceAxis(m_name, "WheelAxis", m_wheelAxis); + cfg.setTabletDeviceAxis(m_name, "ToolIDAxis", m_toolIDAxis); + cfg.setTabletDeviceAxis(m_name, "SerialNumberAxis", m_serialNumberAxis); +} + +void KisCanvasWidget::X11TabletDevice::enableEvents(QWidget *widget) const +{ + if (!m_eventClassList.isEmpty()) { + int result = XSelectExtensionEvent(widget->x11AppDisplay(), widget->handle(), + const_cast<XEventClass*>(&m_eventClassList[0]), + m_eventClassList.count()); + + if (result != Success) { + kdDebug(41001) << "Failed to select extension events for " << m_name << endl; + } + } +} + +double KisCanvasWidget::X11TabletDevice::translateAxisValue(int value, const XAxisInfo& axisInfo) const +{ + int axisRange = axisInfo.max_value - axisInfo.min_value; + double translatedValue = 0; + + if (axisRange != 0) { + translatedValue = (static_cast<double>(value) - axisInfo.min_value) / axisRange; + if (axisInfo.min_value < 0) { + translatedValue -= 0.5; + } + } + + return translatedValue; +} + +KisCanvasWidget::X11TabletDevice::State::State(const KisPoint& pos, double pressure, const KisVector2D& tilt, double wheel, + Q_UINT32 toolID, Q_UINT32 serialNumber) + : m_pos(pos), + m_pressure(pressure), + m_tilt(tilt), + m_wheel(wheel), + m_toolID(toolID), + m_serialNumber(serialNumber) +{ +} + +KisCanvasWidget::X11TabletDevice::State KisCanvasWidget::X11TabletDevice::translateAxisData(const int *axisData) const +{ + KisPoint pos(0, 0); + + if (m_xAxis != NoAxis && m_yAxis != NoAxis) { + pos = KisPoint(translateAxisValue(axisData[m_xAxis], m_axisInfo[m_xAxis]), + translateAxisValue(axisData[m_yAxis], m_axisInfo[m_yAxis])); + } + + double pressure = PRESSURE_DEFAULT; + + if (m_pressureAxis != NoAxis) { + pressure = translateAxisValue(axisData[m_pressureAxis], m_axisInfo[m_pressureAxis]); + } + + KisVector2D tilt = KisVector2D(0, 0); + Q_UINT32 toolID = 0; + Q_UINT32 serialNumber = 0; + + if (m_xTiltAxis != NoAxis) { + // Latest wacom driver returns the tool id and serial number in + // the upper 16 bits of the x and y tilts and wheel. + int xTiltAxisValue = (Q_INT16)(axisData[m_xTiltAxis] & 0xffff); + toolID = ((Q_UINT32)axisData[m_xTiltAxis] >> 16) & 0xffff; + + tilt.setX(translateAxisValue(xTiltAxisValue, m_axisInfo[m_xTiltAxis])); + } + + if (m_yTiltAxis != NoAxis) { + int yTiltAxisValue = (Q_INT16)(axisData[m_yTiltAxis] & 0xffff); + serialNumber = (Q_UINT32)axisData[m_yTiltAxis] & 0xffff0000; + + tilt.setY(translateAxisValue(yTiltAxisValue, m_axisInfo[m_yTiltAxis])); + } + + double wheel = 0; + + if (m_wheelAxis != NoAxis) { + int wheelAxisValue = (Q_INT16)(axisData[m_wheelAxis] & 0xffff); + serialNumber |= ((Q_UINT32)axisData[m_wheelAxis] >> 16) & 0xffff; + + wheel = translateAxisValue(wheelAxisValue, m_axisInfo[m_wheelAxis]); + } + + //QString ids; + //ids.sprintf("Tool ID: %8x Serial Number: %8x", toolID, serialNumber); + + return State(pos, pressure, tilt, wheel, toolID, serialNumber); +} + +KisCanvasWidget::X11XIDTabletDeviceMap& KisCanvasWidget::tabletDeviceMap() +{ + return X11TabletDeviceMap; +} + +void KisCanvasWidget::selectTabletDeviceEvents(QWidget *widget) +{ + for (X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) { + + const X11TabletDevice& device = (*it).second; + + if (device.enabled()) { + device.enableEvents(widget); + } + } +} + +#endif // EXTENDED_X11_TABLET_SUPPORT + +bool KisCanvasWidget::x11Event(XEvent *event, Display *x11Display, WId winId, QPoint widgetOriginPos) +{ + if (event->type == MotionNotify) { + // Mouse move + if (!m_enableMoveEventCompressionHint) { + + XMotionEvent motion = event->xmotion; + QPoint globalPos(motion.x_root, motion.y_root); + + if (globalPos.x() != m_lastRootX || globalPos.y() != m_lastRootY) { + + int state = translateX11ButtonState(motion.state); + QPoint pos(motion.x, motion.y); + QMouseEvent e(QEvent::MouseMove, pos, globalPos, Qt::NoButton, state); + + widgetGotMouseMoveEvent(&e); + } + + m_lastRootX = globalPos.x(); + m_lastRootY = globalPos.y(); + + return true; + } + else { + return false; + } + } + else +#if defined(EXTENDED_X11_TABLET_SUPPORT) + if (event->type == X11DeviceMotionNotifyEvent || event->type == X11DeviceButtonPressEvent || event->type == X11DeviceButtonReleaseEvent) { + // Tablet event. + int deviceId; + const int *axisData; + Qt::ButtonState button; + Qt::ButtonState buttonState; + + if (event->type == X11DeviceMotionNotifyEvent) { + // Tablet move + const XDeviceMotionEvent *motion = reinterpret_cast<const XDeviceMotionEvent *>(event); + XEvent mouseEvent; + + // Look for an accompanying core event. + if (XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &mouseEvent)) { + if (motion->time == mouseEvent.xmotion.time) { + // Do nothing + } else { + XPutBackEvent(x11Display, &mouseEvent); + } + } + + if (m_enableMoveEventCompressionHint) { + while (true) { + // Look for another motion notify in the queue and skip + // to that if found. + if (!XCheckTypedWindowEvent(x11Display, winId, X11DeviceMotionNotifyEvent, &mouseEvent)) { + break; + } + + motion = reinterpret_cast<const XDeviceMotionEvent *>(&mouseEvent); + + XEvent coreMotionEvent; + + // Look for an accompanying core event. + if (!XCheckTypedWindowEvent(x11Display, winId, MotionNotify, &coreMotionEvent)) { + // Do nothing + } + } + } + + deviceId = motion->deviceid; + axisData = motion->axis_data; + button = Qt::NoButton; + buttonState = translateX11ButtonState(motion->state); + } + else + if (event->type == X11DeviceButtonPressEvent) { + // Tablet button press + const XDeviceButtonPressedEvent *buttonPressed = reinterpret_cast<const XDeviceButtonPressedEvent *>(event); + deviceId = buttonPressed->deviceid; + axisData = buttonPressed->axis_data; + button = translateX11Button(buttonPressed->button); + buttonState = translateX11ButtonState(buttonPressed->state); + + if (QApplication::activePopupWidget() == 0) { + XEvent mouseEvent; + + // Look for and swallow an accompanying core event, but only if there's + // no active popup, as that needs to see it. + if (XCheckTypedWindowEvent(x11Display, winId, ButtonPress, &mouseEvent)) { + if (buttonPressed->time == mouseEvent.xbutton.time) { + // Do nothing + } + else { + XPutBackEvent(x11Display, &mouseEvent); + } + } + } + } + else { + // Tablet button release + const XDeviceButtonReleasedEvent *buttonReleased = reinterpret_cast<const XDeviceButtonReleasedEvent *>(event); + deviceId = buttonReleased->deviceid; + axisData = buttonReleased->axis_data; + button = translateX11Button(buttonReleased->button); + buttonState = translateX11ButtonState(buttonReleased->state); + + if (QApplication::activePopupWidget() == 0) { + XEvent mouseEvent; + + // Look for and swallow an accompanying core event, but only if there's + // no active popup, as that needs to see it. + if (XCheckTypedWindowEvent(x11Display, winId, ButtonRelease, &mouseEvent)) { + if (buttonReleased->time == mouseEvent.xbutton.time) { + // Do nothing + } + else { + XPutBackEvent(x11Display, &mouseEvent); + } + } + } + } + + X11XIDTabletDeviceMap::const_iterator it = X11TabletDeviceMap.find(deviceId); + + if (it != X11TabletDeviceMap.end()) { + + const X11TabletDevice& tabletDevice = (*it).second; + + if (tabletDevice.enabled()) { + X11TabletDevice::State deviceState = tabletDevice.translateAxisData(axisData); + + // Map normalised position coordinates to screen coordinates + QDesktopWidget *desktop = QApplication::desktop(); + KisPoint globalPos(deviceState.pos().x() * desktop->width(), deviceState.pos().y() * desktop->height()); + // Convert screen coordinates to widget coordinates + KisPoint pos = globalPos - KoPoint( widgetOriginPos ); + + // Map tilt to -60 - +60 degrees + KisVector2D tilt(deviceState.tilt().x() * 60, deviceState.tilt().y() * 60); + + if (event->type == X11DeviceMotionNotifyEvent) { + KisMoveEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), buttonState); + translateTabletEvent(&e); + } + else + if (event->type == X11DeviceButtonPressEvent) { + KisButtonPressEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState); + translateTabletEvent(&e); + } + else { + KisButtonReleaseEvent e(tabletDevice.inputDevice(), pos, globalPos, deviceState.pressure(), tilt.x(), tilt.y(), button, buttonState); + translateTabletEvent(&e); + } + } + + // Consume the event even if the device is disabled otherwise Qt will + // process it and send a QTabletEvent. + return true; + } + else { + return false; + } + } + else +#endif // EXTENDED_X11_TABLET_SUPPORT + { + return false; + } +} + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + +KisInputDevice KisCanvasWidget::findActiveInputDevice() +{ + X11XIDTabletDeviceMap::const_iterator it; + + for (it = X11TabletDeviceMap.begin(); it != X11TabletDeviceMap.end(); ++it) { + const X11TabletDevice& tabletDevice = (*it).second; + + XDeviceState *deviceState = XQueryDeviceState(QApplication::desktop()->x11Display(), + tabletDevice.xDevice()); + + // If your the laptop sleeps, and you remove the mouse from the usb + // port, then on wake-up Krita can crash because the above call will + // return 0. + if (!deviceState) continue; + + const XInputClass *inputClass = deviceState->data; + bool deviceIsInProximity = false; + + for (int i = 0; i < deviceState->num_classes; i++) { + + if (inputClass->c_class == ValuatorClass) { + + const XValuatorState *valuatorState = reinterpret_cast<const XValuatorState *>(inputClass); + + if ((valuatorState->mode & ProximityState) == InProximity) { + deviceIsInProximity = true; + break; + } + } + + inputClass = reinterpret_cast<const XInputClass *>(reinterpret_cast<const char *>(inputClass) + inputClass->length); + } + + XFreeDeviceState(deviceState); + + if (deviceIsInProximity && tabletDevice.enabled()) { + return tabletDevice.inputDevice(); + } + } + + return KisInputDevice::mouse(); +} + +#endif // EXTENDED_X11_TABLET_SUPPORT + + +#endif // Q_WS_X11 + +/*************************************************************************/ + +#define QPAINTDEVICE_CANVAS_WIDGET false +#define OPENGL_CANVAS_WIDGET true + +KisCanvas::KisCanvas(QWidget *parent, const char *name) +{ + m_parent = parent; + m_name = name; + m_enableMoveEventCompressionHint = false; + m_canvasWidget = 0; + m_useOpenGL = false; + createCanvasWidget(QPAINTDEVICE_CANVAS_WIDGET); +} + +KisCanvas::~KisCanvas() +{ + delete m_canvasWidget; +} + +#ifdef HAVE_GL +void KisCanvas::createCanvasWidget(bool useOpenGL, QGLWidget *sharedContextWidget) +#else +void KisCanvas::createCanvasWidget(bool useOpenGL) +#endif +{ + delete m_canvasWidget; + +#ifndef HAVE_GL + useOpenGL = false; +#else + if (useOpenGL && !QGLFormat::hasOpenGL()) { + kdDebug(41001) << "Tried to create OpenGL widget when system doesn't have OpenGL\n"; + useOpenGL = false; + } + + if (useOpenGL) { + m_canvasWidget = new KisOpenGLCanvasWidget(m_parent, m_name.latin1(), sharedContextWidget); + } else +#endif + { + m_canvasWidget = new KisQPaintDeviceCanvasWidget(m_parent, m_name.latin1()); + } + + m_useOpenGL = useOpenGL; + + Q_CHECK_PTR(m_canvasWidget); + QWidget *widget = dynamic_cast<QWidget *>(m_canvasWidget); + + widget->setBackgroundMode(QWidget::NoBackground); + widget->setMouseTracking(true); + widget->setAcceptDrops(true); + m_canvasWidget->enableMoveEventCompressionHint(m_enableMoveEventCompressionHint); + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + selectTabletDeviceEvents(); +#endif + + connect(m_canvasWidget, SIGNAL(sigGotPaintEvent(QPaintEvent *)), SIGNAL(sigGotPaintEvent(QPaintEvent *))); + connect(m_canvasWidget, SIGNAL(sigGotEnterEvent(QEvent*)), SIGNAL(sigGotEnterEvent(QEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotLeaveEvent(QEvent*)), SIGNAL(sigGotLeaveEvent(QEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotMouseWheelEvent(QWheelEvent*)), SIGNAL(sigGotMouseWheelEvent(QWheelEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), SIGNAL(sigGotKeyPressEvent(QKeyEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotKeyReleaseEvent(QKeyEvent*)), SIGNAL(sigGotKeyReleaseEvent(QKeyEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotDragEnterEvent(QDragEnterEvent*)), SIGNAL(sigGotDragEnterEvent(QDragEnterEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotDropEvent(QDropEvent*)), SIGNAL(sigGotDropEvent(QDropEvent*))); + connect(m_canvasWidget, SIGNAL(sigGotMoveEvent(KisMoveEvent *)), SIGNAL(sigGotMoveEvent(KisMoveEvent *))); + connect(m_canvasWidget, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *)), SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent *))); + connect(m_canvasWidget, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *)), SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent *))); + connect(m_canvasWidget, SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *)), SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent *))); +} + +void KisCanvas::createQPaintDeviceCanvas() +{ + createCanvasWidget(QPAINTDEVICE_CANVAS_WIDGET); +} + +#ifdef HAVE_GL +void KisCanvas::createOpenGLCanvas(QGLWidget *sharedContextWidget) +{ + createCanvasWidget(OPENGL_CANVAS_WIDGET, sharedContextWidget); +} +#endif + +bool KisCanvas::isOpenGLCanvas() const +{ + return m_useOpenGL; +} + +void KisCanvas::enableMoveEventCompressionHint(bool enableMoveCompression) +{ + m_enableMoveEventCompressionHint = enableMoveCompression; + if (m_canvasWidget != 0) { + m_canvasWidget->enableMoveEventCompressionHint(enableMoveCompression); + } +} + +QWidget *KisCanvas::QPaintDeviceWidget() const +{ + if (m_useOpenGL) { + return 0; + } else { + return dynamic_cast<QWidget *>(m_canvasWidget); + } +} + +#ifdef HAVE_GL +QGLWidget *KisCanvas::OpenGLWidget() const +{ + if (m_useOpenGL) { + return dynamic_cast<QGLWidget *>(m_canvasWidget); + } else { + return 0; + } +} +#endif + +KisCanvasWidgetPainter *KisCanvas::createPainter() +{ + Q_ASSERT(m_canvasWidget != 0); + return m_canvasWidget->createPainter(); +} + +KisCanvasWidget *KisCanvas::canvasWidget() const +{ + return m_canvasWidget; +} + +void KisCanvas::setGeometry(int x, int y, int width, int height) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->setGeometry(x, y, width, height); +} + +void KisCanvas::show() +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->show(); +} + +void KisCanvas::hide() +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->hide(); +} + +int KisCanvas::width() const +{ + Q_ASSERT(m_canvasWidget); + return dynamic_cast<QWidget *>(m_canvasWidget)->width(); +} + +int KisCanvas::height() const +{ + Q_ASSERT(m_canvasWidget); + return dynamic_cast<QWidget *>(m_canvasWidget)->height(); +} + +void KisCanvas::update() +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->update(); +} + +void KisCanvas::update(const QRect& r) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->update(r); +} + +void KisCanvas::update(int x, int y, int width, int height) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->update(x, y, width, height); +} + +void KisCanvas::repaint() +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->repaint(); +} + +void KisCanvas::repaint(bool erase) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->repaint(erase); +} + +void KisCanvas::repaint(int x, int y, int width, int height, bool erase) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->repaint(x, y, width, height, erase); +} + +void KisCanvas::repaint(const QRect& r, bool erase) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->repaint(r, erase); +} + +void KisCanvas::repaint(const QRegion& r, bool erase) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->repaint(r, erase); +} + +bool KisCanvas::isUpdatesEnabled() const +{ + Q_ASSERT(m_canvasWidget); + return dynamic_cast<QWidget *>(m_canvasWidget)->isUpdatesEnabled(); +} + +void KisCanvas::setUpdatesEnabled(bool updatesEnabled) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->setUpdatesEnabled(updatesEnabled); +} + +void KisCanvas::updateGeometry() +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->updateGeometry(); +} + +void KisCanvas::setFocusPolicy(QWidget::FocusPolicy focusPolicy) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->setFocusPolicy(focusPolicy); +} + +const QCursor& KisCanvas::cursor() const +{ + Q_ASSERT(m_canvasWidget); + return dynamic_cast<QWidget *>(m_canvasWidget)->cursor(); +} + +void KisCanvas::setCursor(const QCursor& cursor) +{ + Q_ASSERT(m_canvasWidget); + dynamic_cast<QWidget *>(m_canvasWidget)->setCursor(cursor); +} + +#if defined(EXTENDED_X11_TABLET_SUPPORT) +void KisCanvas::selectTabletDeviceEvents() +{ + Q_ASSERT(m_canvasWidget); + m_canvasWidget->selectTabletDeviceEvents(); +} +#endif + +bool KisCanvas::cursorIsOverCanvas() const +{ + if (QApplication::activePopupWidget() != 0) { + return false; + } + if (QApplication::activeModalWidget() != 0) { + return false; + } + + QWidget *canvasWidget = dynamic_cast<QWidget *>(m_canvasWidget); + Q_ASSERT(canvasWidget != 0); + + if (canvasWidget) { + if (QApplication::widgetAt(QCursor::pos(), true) == canvasWidget) { + return true; + } + } + return false; +} + +void KisCanvas::handleKeyEvent(QEvent *e) +{ + QKeyEvent *ke = dynamic_cast<QKeyEvent *>(e); + + Q_ASSERT(ke != 0); + + if (ke) { + QWidget *canvasWidget = dynamic_cast<QWidget *>(m_canvasWidget); + Q_ASSERT(canvasWidget != 0); + + if (canvasWidget) { + canvasWidget->setFocus(); + + if (e->type() == QEvent::KeyPress) { + emit sigGotKeyPressEvent(ke); + } else { + emit sigGotKeyReleaseEvent(ke); + } + } + } +} + +#include "kis_canvas.moc" + diff --git a/krita/ui/kis_canvas.h b/krita/ui/kis_canvas.h new file mode 100644 index 000000000..b9e387386 --- /dev/null +++ b/krita/ui/kis_canvas.h @@ -0,0 +1,381 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2004-2006 Adrian Page <adrian@pagenet.plus.com> + * + * 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_CANVAS_H_ +#define KIS_CANVAS_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#ifdef HAVE_GL +#include <qgl.h> +#endif +#include <qpainter.h> + +#include "kis_global.h" +#include "kis_point.h" +#include "kis_vec.h" +#include "kis_input_device.h" + +#ifdef Q_WS_X11 + +// Irix has a different (and better) XInput tablet driver to +// the XFree/xorg driver. Qt needs a separate code path for that +// and so would we. +#if defined(HAVE_XINPUTEXT) && !defined(Q_OS_IRIX) +#define EXTENDED_X11_TABLET_SUPPORT +#endif + +#include <map> +#include <X11/Xlib.h> + +#if defined(EXTENDED_X11_TABLET_SUPPORT) +#include <X11/extensions/XInput.h> +#endif + +#endif // Q_WS_X11 + +class KisEvent; +class KisMoveEvent; +class KisButtonPressEvent; +class KisButtonReleaseEvent; +class KisDoubleClickEvent; +class KisCanvasWidgetPainter; + +class KisCanvasWidget : public QObject { + Q_OBJECT + +public: + KisCanvasWidget(); + virtual ~KisCanvasWidget(); + + // When enabled, the canvas may throw away move events if the application + // is unable to keep up with them, i.e. intermediate move events in the event + // queue are skipped. + void enableMoveEventCompressionHint(bool enableMoveCompression) { m_enableMoveEventCompressionHint = enableMoveCompression; } + + virtual KisCanvasWidgetPainter *createPainter() = 0; + +#ifdef EXTENDED_X11_TABLET_SUPPORT + static KisInputDevice findActiveInputDevice(); + virtual void selectTabletDeviceEvents() = 0; + + static void selectTabletDeviceEvents(QWidget *widget); +#endif + +#ifdef Q_WS_X11 + static void initX11Support(); +#endif + +signals: + void sigGotPaintEvent(QPaintEvent*); + void sigGotEnterEvent(QEvent*); + void sigGotLeaveEvent(QEvent*); + void sigGotMouseWheelEvent(QWheelEvent*); + void sigGotKeyPressEvent(QKeyEvent*); + void sigGotKeyReleaseEvent(QKeyEvent*); + void sigGotDragEnterEvent(QDragEnterEvent*); + void sigGotDropEvent(QDropEvent*); + void sigGotMoveEvent(KisMoveEvent *); + void sigGotButtonPressEvent(KisButtonPressEvent *); + void sigGotButtonReleaseEvent(KisButtonReleaseEvent *); + void sigGotDoubleClickEvent(KisDoubleClickEvent *); + +protected: + void widgetGotPaintEvent(QPaintEvent *event); + void widgetGotMousePressEvent(QMouseEvent *event); + void widgetGotMouseReleaseEvent(QMouseEvent *event); + void widgetGotMouseDoubleClickEvent(QMouseEvent *event); + void widgetGotMouseMoveEvent(QMouseEvent *event); + void widgetGotTabletEvent(QTabletEvent *event); + void widgetGotEnterEvent(QEvent *event ); + void widgetGotLeaveEvent(QEvent *event); + void widgetGotWheelEvent(QWheelEvent *event); + void widgetGotKeyPressEvent(QKeyEvent *event); + void widgetGotKeyReleaseEvent(QKeyEvent *event); + void widgetGotDragEnterEvent(QDragEnterEvent *event); + void widgetGotDropEvent(QDropEvent *event); + void moveEvent(KisMoveEvent *event); + void buttonPressEvent(KisButtonPressEvent *event); + void buttonReleaseEvent(KisButtonReleaseEvent *event); + void doubleClickEvent(KisDoubleClickEvent *event); + void translateTabletEvent(KisEvent *event); + +protected: + + bool m_enableMoveEventCompressionHint; + double m_lastPressure; + +#ifdef Q_WS_X11 + // On X11 systems, Qt throws away mouse move events if the application + // is unable to keep up with them. We override this behaviour so that + // we receive all move events, so that painting follows the mouse's motion + // accurately. + bool x11Event(XEvent *event, Display *x11Display, WId winId, QPoint widgetOriginPos); + static Qt::ButtonState translateX11ButtonState(int state); + static Qt::ButtonState translateX11Button(unsigned int button); + + static bool X11SupportInitialised; + + // Modifier masks for alt/meta - detected at run-time + static long X11AltMask; + static long X11MetaMask; + + int m_lastRootX; + int m_lastRootY; + +#ifdef EXTENDED_X11_TABLET_SUPPORT + +public: + class X11TabletDevice + { + public: + X11TabletDevice(); + X11TabletDevice(const XDeviceInfo *deviceInfo); + + bool mightBeTabletDevice() const { return m_mightBeTabletDevice; } + + XID id() const { return m_deviceId; } + XDevice *xDevice() const { return m_XDevice; } + QString name() const { return m_name; } + + KisInputDevice inputDevice() const { return m_inputDevice; } + void setInputDevice(KisInputDevice inputDevice) { m_inputDevice = inputDevice; } + + void setEnabled(bool enabled); + bool enabled() const; + + Q_INT32 numAxes() const; + + void setXAxis(Q_INT32 axis); + void setYAxis(Q_INT32 axis); + void setPressureAxis(Q_INT32 axis); + void setXTiltAxis(Q_INT32 axis); + void setYTiltAxis(Q_INT32 axis); + void setWheelAxis(Q_INT32 axis); + void setToolIDAxis(Q_INT32 axis); + void setSerialNumberAxis(Q_INT32 axis); + + static const Q_INT32 NoAxis = -1; + static const Q_INT32 DefaultAxis = -2; + + Q_INT32 xAxis() const; + Q_INT32 yAxis() const; + Q_INT32 pressureAxis() const; + Q_INT32 xTiltAxis() const; + Q_INT32 yTiltAxis() const; + Q_INT32 wheelAxis() const; + Q_INT32 toolIDAxis() const; + Q_INT32 serialNumberAxis() const; + + void readSettingsFromConfig(); + void writeSettingsToConfig(); + + // These return -1 if the device does not support the event + int buttonPressEvent() const { return m_buttonPressEvent; } + int buttonReleaseEvent() const { return m_buttonReleaseEvent; } + int motionNotifyEvent() const { return m_motionNotifyEvent; } + int proximityInEvent() const { return m_proximityInEvent; } + int proximityOutEvent() const { return m_proximityOutEvent; } + + void enableEvents(QWidget *widget) const; + + class State + { + public: + State() {} + State(const KisPoint& pos, double pressure, const KisVector2D& tilt, double wheel, + Q_UINT32 toolID, Q_UINT32 serialNumber); + + // Position, pressure and wheel are normalised to 0 - 1 + KisPoint pos() const { return m_pos; } + double pressure() const { return m_pressure; } + // Tilt is normalised to -1->+1 + KisVector2D tilt() const { return m_tilt; } + double wheel() const { return m_wheel; } + // Wacom tool id and serial number of device. + Q_UINT32 toolID() const { return m_toolID; } + Q_UINT32 serialNumber() const { return m_serialNumber; } + + private: + KisPoint m_pos; + double m_pressure; + KisVector2D m_tilt; + double m_wheel; + Q_UINT32 m_toolID; + Q_UINT32 m_serialNumber; + }; + + State translateAxisData(const int *axisData) const; + + private: + double translateAxisValue(int value, const XAxisInfo& axisInfo) const; + + XID m_deviceId; + XDevice *m_XDevice; + + QString m_name; + + bool m_mightBeTabletDevice; + KisInputDevice m_inputDevice; + + bool m_enabled; + + Q_INT32 m_xAxis; + Q_INT32 m_yAxis; + Q_INT32 m_pressureAxis; + Q_INT32 m_xTiltAxis; + Q_INT32 m_yTiltAxis; + Q_INT32 m_wheelAxis; + Q_INT32 m_toolIDAxis; + Q_INT32 m_serialNumberAxis; + + QValueVector<XAxisInfo> m_axisInfo; + + int m_motionNotifyEvent; + int m_buttonPressEvent; + int m_buttonReleaseEvent; + int m_proximityInEvent; + int m_proximityOutEvent; + + QValueVector<XEventClass> m_eventClassList; + }; + + typedef std::map<XID, X11TabletDevice> X11XIDTabletDeviceMap; + static X11XIDTabletDeviceMap& tabletDeviceMap(); + +protected: + static int X11DeviceMotionNotifyEvent; + static int X11DeviceButtonPressEvent; + static int X11DeviceButtonReleaseEvent; + static int X11ProximityInEvent; + static int X11ProximityOutEvent; + + static X11XIDTabletDeviceMap X11TabletDeviceMap; + +#endif // EXTENDED_X11_TABLET_SUPPORT + +#endif // Q_WS_X11 +}; + +class KisCanvas : public QObject { + Q_OBJECT + +public: + KisCanvas(QWidget *parent, const char *name); + virtual ~KisCanvas(); + + // When enabled, the canvas may throw away move events if the application + // is unable to keep up with them, i.e. intermediate move events in the event + // queue are skipped. + void enableMoveEventCompressionHint(bool enableMoveCompression); + + bool isOpenGLCanvas() const; + + /** + * Returns true if the cursor is over the canvas. + */ + bool cursorIsOverCanvas() const; + + /** + * Handle the given event (which must be a key event) as if the canvas + * had received it directly. + */ + void handleKeyEvent(QEvent *e); + + int width() const; + int height() const; + + void update(); + void update(const QRect& r); + void update(int x, int y, int width, int height); + void repaint(); + void repaint(bool erase); + void repaint(int x, int y, int width, int height, bool erase = true); + void repaint(const QRect& r, bool erase = true); + void repaint(const QRegion& r, bool erase = true); + + void updateGeometry(); + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + void selectTabletDeviceEvents(); +#endif + +signals: + void sigGotPaintEvent(QPaintEvent*); + void sigGotEnterEvent(QEvent*); + void sigGotLeaveEvent(QEvent*); + void sigGotMouseWheelEvent(QWheelEvent*); + void sigGotKeyPressEvent(QKeyEvent*); + void sigGotKeyReleaseEvent(QKeyEvent*); + void sigGotDragEnterEvent(QDragEnterEvent*); + void sigGotDropEvent(QDropEvent*); + void sigGotMoveEvent(KisMoveEvent *); + void sigGotButtonPressEvent(KisButtonPressEvent *); + void sigGotButtonReleaseEvent(KisButtonReleaseEvent *); + void sigGotDoubleClickEvent(KisDoubleClickEvent *); + +protected: + // Allow KisView to render on the widget directly, but everything else + // has restricted access. + friend class KisView; + friend class KisCanvasPainter; + + // One of these will be valid, the other null. In Qt3, using a QPainter on + // a QGLWidget is not reliable. + QWidget *QPaintDeviceWidget() const; +#ifdef HAVE_GL + QGLWidget *OpenGLWidget() const; +#endif + void createQPaintDeviceCanvas(); +#ifdef HAVE_GL + void createOpenGLCanvas(QGLWidget *sharedContextWidget); +#endif + void show(); + void hide(); + void setGeometry(int x, int y, int width, int height); + + void setUpdatesEnabled(bool updatesEnabled); + bool isUpdatesEnabled() const; + + void setFocusPolicy(QWidget::FocusPolicy focusPolicy); + + const QCursor& cursor() const; + void setCursor(const QCursor& cursor); + + KisCanvasWidgetPainter *createPainter(); + KisCanvasWidget *canvasWidget() const; + +protected: +#ifdef HAVE_GL + void createCanvasWidget(bool useOpenGL, QGLWidget *sharedContextWidget = 0); +#else + void createCanvasWidget(bool useOpenGL); +#endif + QWidget *m_parent; + QString m_name; + KisCanvasWidget *m_canvasWidget; + bool m_enableMoveEventCompressionHint; + bool m_useOpenGL; +}; + +#endif // KIS_CANVAS_H_ + diff --git a/krita/ui/kis_canvas_painter.cc b/krita/ui/kis_canvas_painter.cc new file mode 100644 index 000000000..f9103e650 --- /dev/null +++ b/krita/ui/kis_canvas_painter.cc @@ -0,0 +1,1440 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_qpaintdevice_canvas_painter.h" + +KisCanvasWidgetPainter::KisCanvasWidgetPainter() +{ +} + +KisCanvasWidgetPainter::~KisCanvasWidgetPainter() +{ +} + +bool KisCanvasWidgetPainter::end() +{ + return true; +} + +void KisCanvasWidgetPainter::save() +{ +} + +void KisCanvasWidgetPainter::restore() +{ +} + +QFontMetrics KisCanvasWidgetPainter::fontMetrics() const +{ + return QFontMetrics(QFont()); +} + +QFontInfo KisCanvasWidgetPainter::fontInfo() const +{ + return QFontInfo(QFont()); +} + +const QFont& KisCanvasWidgetPainter::font() const +{ + return m_defaultFont; +} + +void KisCanvasWidgetPainter::setFont(const QFont& /*font*/) +{ +} + +const QPen& KisCanvasWidgetPainter::pen() const +{ + return m_defaultPen; +} + +void KisCanvasWidgetPainter::setPen(const QPen& /*pen*/) +{ +} + +void KisCanvasWidgetPainter::setPen(Qt::PenStyle /*penStyle*/) +{ +} + +void KisCanvasWidgetPainter::setPen(const QColor& /*color*/) +{ +} + +const QBrush& KisCanvasWidgetPainter::brush() const +{ + return m_defaultBrush; +} + +void KisCanvasWidgetPainter::setBrush(const QBrush& /*brush*/) +{ +} + +void KisCanvasWidgetPainter::setBrush(Qt::BrushStyle /*brushStyle*/) +{ +} + +void KisCanvasWidgetPainter::setBrush(const QColor& /*color*/) +{ +} + +QPoint KisCanvasWidgetPainter::pos() const +{ + return QPoint(); +} + +const QColor& KisCanvasWidgetPainter::backgroundColor() const +{ + return m_defaultColor; +} + +void KisCanvasWidgetPainter::setBackgroundColor(const QColor& /*color*/) +{ +} + +Qt::Qt::BGMode KisCanvasWidgetPainter::backgroundMode() const +{ + return Qt::TransparentMode; +} + +void KisCanvasWidgetPainter::setBackgroundMode(Qt::Qt::BGMode /*bgMode*/) +{ +} + +Qt::Qt::RasterOp KisCanvasWidgetPainter::rasterOp() const +{ + return Qt::CopyROP; +} + +void KisCanvasWidgetPainter::setRasterOp(Qt::RasterOp /*rasterOp*/) +{ +} + +const QPoint& KisCanvasWidgetPainter::brushOrigin() const +{ + return m_defaultBrushOrigin; +} + +void KisCanvasWidgetPainter::setBrushOrigin(int /*x*/, int /*y*/) +{ +} + +void KisCanvasWidgetPainter::setBrushOrigin(const QPoint& /*origin*/) +{ +} + +bool KisCanvasWidgetPainter::hasViewXForm() const +{ + return false; +} + +bool KisCanvasWidgetPainter::hasWorldXForm() const +{ + return false; +} + +void KisCanvasWidgetPainter::setViewXForm(bool /*enable*/) +{ +} + +QRect KisCanvasWidgetPainter::window() const +{ + return QRect(); +} + +void KisCanvasWidgetPainter::setWindow(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::setWindow(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +QRect KisCanvasWidgetPainter::viewport() const +{ + return QRect(); +} + +void KisCanvasWidgetPainter::setViewport(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::setViewport(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + + +void KisCanvasWidgetPainter::setWorldXForm(bool /*enable*/) +{ +} + +const QWMatrix& KisCanvasWidgetPainter::worldMatrix() const +{ + return m_defaultWorldMatrix; +} + +void KisCanvasWidgetPainter::setWorldMatrix(const QWMatrix& /*matrix*/, bool /*combine*/) +{ +} + +void KisCanvasWidgetPainter::saveWorldMatrix() +{ +} + +void KisCanvasWidgetPainter::restoreWorldMatrix() +{ +} + +void KisCanvasWidgetPainter::scale(double /*sx*/, double /*sy*/) +{ +} + +void KisCanvasWidgetPainter::shear(double /*sh*/, double /*sv*/) +{ +} + +void KisCanvasWidgetPainter::rotate(double /*a*/) +{ +} + +void KisCanvasWidgetPainter::translate(double /*dx*/, double /*dy*/) +{ +} + +void KisCanvasWidgetPainter::resetXForm() +{ +} + +double KisCanvasWidgetPainter::translationX() const +{ + return 0; +} + +double KisCanvasWidgetPainter::translationY() const +{ + return 0; +} + +QPoint KisCanvasWidgetPainter::xForm(const QPoint& point) const +{ + return point; +} + +QRect KisCanvasWidgetPainter::xForm(const QRect& r) const +{ + return r; +} + +QPointArray KisCanvasWidgetPainter::xForm(const QPointArray& pointArray) const +{ + return pointArray; +} + +QPointArray KisCanvasWidgetPainter::xForm(const QPointArray& pointArray, int /*index*/, int /*npoints*/) const +{ + return pointArray; +} + +QPoint KisCanvasWidgetPainter::xFormDev(const QPoint& point) const +{ + return point; +} + +QRect KisCanvasWidgetPainter::xFormDev(const QRect& r) const +{ + return r; +} + +QPointArray KisCanvasWidgetPainter::xFormDev(const QPointArray& pointArray) const +{ + return pointArray; +} + +QPointArray KisCanvasWidgetPainter::xFormDev(const QPointArray& pointArray, int /*index*/, int /*npoints*/) const +{ + return pointArray; +} + +void KisCanvasWidgetPainter::setClipping(bool /*enable*/) +{ +} + +bool KisCanvasWidgetPainter::hasClipping() const +{ + return true; +} + +QRegion KisCanvasWidgetPainter::clipRegion(QPainter::CoordinateMode /*mode*/) const +{ + return QRegion(); +} + +void KisCanvasWidgetPainter::setClipRect(const QRect& /*r*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisCanvasWidgetPainter::setClipRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisCanvasWidgetPainter::setClipRegion(const QRegion& /*rgn*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisCanvasWidgetPainter::drawPoint(int /*x*/, int /*y*/) +{ +} + +void KisCanvasWidgetPainter::drawPoint(const QPoint& /*point*/) +{ +} + +void KisCanvasWidgetPainter::drawPoints(const QPointArray& /*pointArray*/, int /*index*/, int /*npoints*/) +{ +} + +void KisCanvasWidgetPainter::moveTo(int /*x*/, int /*y*/) +{ +} + +void KisCanvasWidgetPainter::moveTo(const QPoint& /*point*/) +{ +} + +void KisCanvasWidgetPainter::lineTo(int /*x*/, int /*y*/) +{ +} + +void KisCanvasWidgetPainter::lineTo(const QPoint& /*point*/) +{ +} + +void KisCanvasWidgetPainter::drawLine(int /*x1*/, int /*y1*/, int /*x2*/, int /*y2*/) +{ +} + +void KisCanvasWidgetPainter::drawLine(const QPoint& /*start*/, const QPoint& /*end*/) +{ +} + +void KisCanvasWidgetPainter::drawRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisCanvasWidgetPainter::drawRect(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::drawWinFocusRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisCanvasWidgetPainter::drawWinFocusRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, const QColor& /*bgColor*/) +{ +} + +void KisCanvasWidgetPainter::drawWinFocusRect(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::drawWinFocusRect(const QRect& /*r*/, const QColor& /*bgColor*/) +{ +} + +void KisCanvasWidgetPainter::drawRoundRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*xRnd*/, int /*yRnd*/) +{ +} + +void KisCanvasWidgetPainter::drawRoundRect(const QRect& /*r*/, int /*xRnd*/, int /*yRnd*/) +{ +} + +void KisCanvasWidgetPainter::drawEllipse(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisCanvasWidgetPainter::drawEllipse(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::drawArc(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawArc(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawPie(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawPie(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawChord(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawChord(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisCanvasWidgetPainter::drawLineSegments(const QPointArray& /*pointArray*/, int /*index*/, int /*nlines*/) +{ +} + +void KisCanvasWidgetPainter::drawPolyline(const QPointArray& /*pointArray*/, int /*index*/, int /*npoints*/) +{ +} + +void KisCanvasWidgetPainter::drawPolygon(const QPointArray& /*pointArray*/, bool /*winding*/, int /*index*/, int /*npoints*/) +{ +} + +void KisCanvasWidgetPainter::drawConvexPolygon(const QPointArray& /*pointArray*/, int /*index*/, int /*npoints*/) +{ +} + +void KisCanvasWidgetPainter::drawCubicBezier(const QPointArray& /*pointArray*/, int /*index*/) +{ +} + +void KisCanvasWidgetPainter::drawPixmap(int /*x*/, int /*y*/, const QPixmap& /*pixmap*/, int /*sx*/, int /*sy*/, int /*sw*/, int /*sh*/) +{ +} + +void KisCanvasWidgetPainter::drawPixmap(const QPoint& /*point*/, const QPixmap& /*pixmap*/, const QRect& /*sr*/) +{ +} + +void KisCanvasWidgetPainter::drawPixmap(const QPoint& /*point*/, const QPixmap& /*pixmap*/) +{ +} + +void KisCanvasWidgetPainter::drawPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/) +{ +} + +void KisCanvasWidgetPainter::drawImage(int /*x*/, int /*y*/, const QImage& /*image*/, int /*sx*/, int /*sy*/, int /*sw*/, int /*sh*/, int /*conversionFlags*/) +{ +} + +void KisCanvasWidgetPainter::drawImage(const QPoint& /*point*/, const QImage& /*image*/, const QRect& /*sr*/, int /*conversionFlags*/) +{ +} + +void KisCanvasWidgetPainter::drawImage(const QPoint& /*point*/, const QImage& /*image*/, int /*conversion_flags*/) +{ +} + +void KisCanvasWidgetPainter::drawImage(const QRect& /*r*/, const QImage& /*image*/) +{ +} + +void KisCanvasWidgetPainter::drawTiledPixmap(int /*x*/, int /*y*/, int /*w*/, int /*h*/, const QPixmap& /*pixmap*/, int /*sx*/, int /*sy*/) +{ +} + +void KisCanvasWidgetPainter::drawTiledPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/, const QPoint& /*point*/) +{ +} + +void KisCanvasWidgetPainter::drawTiledPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/) +{ +} + +void KisCanvasWidgetPainter::fillRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, const QBrush& /*brush*/) +{ +} + +void KisCanvasWidgetPainter::fillRect(const QRect& /*r*/, const QBrush& /*brush*/) +{ +} + +void KisCanvasWidgetPainter::eraseRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisCanvasWidgetPainter::eraseRect(const QRect& /*r*/) +{ +} + +void KisCanvasWidgetPainter::drawText(int /*x*/, int /*y*/, const QString& /*text*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisCanvasWidgetPainter::drawText(const QPoint& /*point*/, const QString& /*text*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisCanvasWidgetPainter::drawText(int /*x*/, int /*y*/, const QString& /*text*/, int /*pos*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisCanvasWidgetPainter::drawText(const QPoint& /*point*/, const QString& /*text*/, int /*pos*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisCanvasWidgetPainter::drawText(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*flags*/, const QString& /*text*/, int /*len*/, QRect */*br*/, QTextParag **/*intern*/) +{ +} + +void KisCanvasWidgetPainter::drawText(const QRect& /*r*/, int /*flags*/, const QString& /*text*/, int /*len*/, QRect */*br*/, QTextParag **/*intern*/) +{ +} + +void KisCanvasWidgetPainter::drawTextItem(int /*x*/, int /*y*/, const QTextItem& /*ti*/, int /*textflags*/) +{ +} + +void KisCanvasWidgetPainter::drawTextItem(const QPoint& /*p*/, const QTextItem& /*ti*/, int /*textflags*/) +{ +} + +QRect KisCanvasWidgetPainter::boundingRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*flags*/, const QString& /*text*/, int /*len*/, QTextParag **/*intern*/) +{ + return QRect(); +} + +QRect KisCanvasWidgetPainter::boundingRect(const QRect& /*r*/, int /*flags*/, const QString& /*text*/, int /*len*/, QTextParag **/*intern*/) +{ + return QRect(); +} + +int KisCanvasWidgetPainter::tabStops() const +{ + return 0; +} + +void KisCanvasWidgetPainter::setTabStops(int /*ts*/) +{ +} + +int *KisCanvasWidgetPainter::tabArray() const +{ + return 0; +} + +void KisCanvasWidgetPainter::setTabArray(int */*ts*/) +{ +} + +/*************************************************************************/ + +KisCanvasPainter::KisCanvasPainter() +{ + m_canvasWidgetPainter = 0; +} + +KisCanvasPainter::KisCanvasPainter(KisCanvas *canvas) +{ + m_canvasWidgetPainter = canvas->createPainter(); +} + +KisCanvasPainter::KisCanvasPainter(const QPaintDevice *paintDevice) +{ + m_canvasWidgetPainter = new KisQPaintDeviceCanvasPainter(paintDevice); +} + +KisCanvasPainter::~KisCanvasPainter() +{ + delete m_canvasWidgetPainter; +} + +bool KisCanvasPainter::begin(KisCanvas *canvas, bool unclipped) +{ + delete m_canvasWidgetPainter; + m_canvasWidgetPainter = canvas->createPainter(); + return m_canvasWidgetPainter->begin(canvas->canvasWidget(), unclipped); +} + +bool KisCanvasPainter::begin(const QPaintDevice *paintDevice, bool unclipped) +{ + delete m_canvasWidgetPainter; + m_canvasWidgetPainter = new KisQPaintDeviceCanvasPainter(); + return static_cast<KisQPaintDeviceCanvasPainter *>(m_canvasWidgetPainter)->begin(paintDevice, unclipped); +} + +bool KisCanvasPainter::end() +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->end(); + } + return false; +} + +void KisCanvasPainter::save() +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->save(); + } +} + +void KisCanvasPainter::restore() +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->restore(); + } +} + +QFontMetrics KisCanvasPainter::fontMetrics() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->fontMetrics(); + } + return QFontMetrics(QFont()); +} + +QFontInfo KisCanvasPainter::fontInfo() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->fontInfo(); + } + return QFontInfo(QFont()); +} + +const QFont& KisCanvasPainter::font() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->font(); + } + return m_defaultFont; +} + +void KisCanvasPainter::setFont(const QFont& font) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setFont(font); + } +} + +const QPen& KisCanvasPainter::pen() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->pen(); + } + return m_defaultPen; +} + +void KisCanvasPainter::setPen(const QPen& pen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setPen(pen); + } +} + +void KisCanvasPainter::setPen(Qt::PenStyle penStyle) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setPen(penStyle); + } +} + +void KisCanvasPainter::setPen(const QColor& color) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setPen(color);; + } +} + +const QBrush& KisCanvasPainter::brush() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->brush(); + } + return m_defaultBrush; +} + +void KisCanvasPainter::setBrush(const QBrush& brush) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBrush(brush); + } +} + +void KisCanvasPainter::setBrush(Qt::BrushStyle brushStyle) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBrush(brushStyle); + } +} + +void KisCanvasPainter::setBrush(const QColor& color) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBrush(color); + } +} + +QPoint KisCanvasPainter::pos() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->pos(); + } + return QPoint(); +} + +const QColor& KisCanvasPainter::backgroundColor() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->backgroundColor(); + } + return m_defaultColor; +} + +void KisCanvasPainter::setBackgroundColor(const QColor& color) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBackgroundColor(color); + } +} + +Qt::BGMode KisCanvasPainter::backgroundMode() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->backgroundMode(); + } + return Qt::TransparentMode; +} + +void KisCanvasPainter::setBackgroundMode(Qt::BGMode bgMode) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBackgroundMode(bgMode); + } +} + +Qt::RasterOp KisCanvasPainter::rasterOp() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->rasterOp(); + } + return Qt::CopyROP; +} + +void KisCanvasPainter::setRasterOp(Qt::RasterOp rasterOp) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setRasterOp(rasterOp); + } +} + +const QPoint& KisCanvasPainter::brushOrigin() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->brushOrigin(); + } + return m_defaultBrushOrigin; +} + +void KisCanvasPainter::setBrushOrigin(int x, int y) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBrushOrigin(x, y); + } +} + +void KisCanvasPainter::setBrushOrigin(const QPoint& origin) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setBrushOrigin(origin); + } +} + +bool KisCanvasPainter::hasViewXForm() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->hasViewXForm(); + } + return false; +} + +bool KisCanvasPainter::hasWorldXForm() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->hasWorldXForm(); + } + return false; +} + +void KisCanvasPainter::setViewXForm(bool enable) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setViewXForm(enable); + } +} + +QRect KisCanvasPainter::window() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->window(); + } + return QRect(); +} + +void KisCanvasPainter::setWindow(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setWindow(r); + } +} + +void KisCanvasPainter::setWindow(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setWindow(x, y, w, h); + } +} + +QRect KisCanvasPainter::viewport() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->viewport(); + } + return QRect(); +} + +void KisCanvasPainter::setViewport(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setViewport(r); + } +} + +void KisCanvasPainter::setViewport(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setViewport(x, y, w, h); + } +} + +void KisCanvasPainter::setWorldXForm(bool enable) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setWorldXForm(enable); + } +} + +const QWMatrix& KisCanvasPainter::worldMatrix() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->worldMatrix(); + } + return m_defaultWorldMatrix; +} + +void KisCanvasPainter::setWorldMatrix(const QWMatrix& matrix, bool combine) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setWorldMatrix(matrix, combine); + } +} + +void KisCanvasPainter::saveWorldMatrix() +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->saveWorldMatrix(); + } +} + +void KisCanvasPainter::restoreWorldMatrix() +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->restoreWorldMatrix(); + } +} + +void KisCanvasPainter::scale(double sx, double sy) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->scale(sx, sy); + } +} + +void KisCanvasPainter::shear(double sh, double sv) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->shear(sh, sv); + } +} + +void KisCanvasPainter::rotate(double a) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->rotate(a); + } +} + +void KisCanvasPainter::translate(double dx, double dy) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->translate(dx, dy); + } +} + +void KisCanvasPainter::resetXForm() +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->resetXForm(); + } +} + +double KisCanvasPainter::translationX() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->translationX(); + } + return 0; +} + +double KisCanvasPainter::translationY() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->translationY(); + } + return 0; +} + +QPoint KisCanvasPainter::xForm(const QPoint& point) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xForm(point); + } + return point; +} + +QRect KisCanvasPainter::xForm(const QRect& r) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xForm(r); + } + return r; +} + +QPointArray KisCanvasPainter::xForm(const QPointArray& pointArray) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xForm(pointArray); + } + return pointArray; +} + +QPointArray KisCanvasPainter::xForm(const QPointArray& pointArray, int index, int npoints) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xForm(pointArray, index, npoints); + } + return pointArray; +} + +QPoint KisCanvasPainter::xFormDev(const QPoint& point) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xFormDev(point); + } + return point; +} + +QRect KisCanvasPainter::xFormDev(const QRect& r) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xFormDev(r); + } + return r; +} + +QPointArray KisCanvasPainter::xFormDev(const QPointArray& pointArray) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xFormDev(pointArray); + } + return pointArray; +} + +QPointArray KisCanvasPainter::xFormDev(const QPointArray& pointArray, int index, int npoints) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->xFormDev(pointArray, index, npoints); + } + return pointArray; +} + +void KisCanvasPainter::setClipping(bool enable) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setClipping(enable); + } +} + +bool KisCanvasPainter::hasClipping() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->hasClipping(); + } + return true; +} + +QRegion KisCanvasPainter::clipRegion(QPainter::CoordinateMode mode) const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->clipRegion(mode); + } + return QRegion(); +} + +void KisCanvasPainter::setClipRect(const QRect& r, QPainter::CoordinateMode mode) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setClipRect(r, mode); + } +} + +void KisCanvasPainter::setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode mode) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setClipRect(x, y, w, h, mode); + } +} + +void KisCanvasPainter::setClipRegion(const QRegion& rgn, QPainter::CoordinateMode mode) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setClipRegion(rgn, mode); + } +} + +void KisCanvasPainter::drawPoint(int x, int y) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPoint(x, y); + } +} + +void KisCanvasPainter::drawPoint(const QPoint& point) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPoint(point); + } +} + +void KisCanvasPainter::drawPoints(const QPointArray& pointArray, int index, int npoints) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPoints(pointArray, index, npoints); + } +} + +void KisCanvasPainter::moveTo(int x, int y) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->moveTo(x, y); + } +} + +void KisCanvasPainter::moveTo(const QPoint& point) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->moveTo(point); + } +} + +void KisCanvasPainter::lineTo(int x, int y) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->lineTo(x, y); + } +} + +void KisCanvasPainter::lineTo(const QPoint& point) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->lineTo(point); + } +} + +void KisCanvasPainter::drawLine(int x1, int y1, int x2, int y2) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawLine(x1, y1, x2, y2); + } +} + +void KisCanvasPainter::drawLine(const QPoint& start, const QPoint& end) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawLine(start, end); + } +} + +void KisCanvasPainter::drawRect(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawRect(x, y, w, h); + } +} + +void KisCanvasPainter::drawRect(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawRect(r); + } +} + +void KisCanvasPainter::drawWinFocusRect(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawWinFocusRect(x, y, w, h); + } +} + +void KisCanvasPainter::drawWinFocusRect(int x, int y, int w, int h, const QColor& bgColor) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawWinFocusRect(x, y, w, h, bgColor); + } +} + +void KisCanvasPainter::drawWinFocusRect(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawWinFocusRect(r); + } +} + +void KisCanvasPainter::drawWinFocusRect(const QRect& r, const QColor& bgColor) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawWinFocusRect(r, bgColor); + } +} + +void KisCanvasPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawRoundRect(x, y, w, h, xRnd, yRnd); + } +} + +void KisCanvasPainter::drawRoundRect(const QRect& r, int xRnd, int yRnd) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawRoundRect(r, xRnd, yRnd); + } +} + +void KisCanvasPainter::drawEllipse(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawEllipse(x, y, w, h); + } +} + +void KisCanvasPainter::drawEllipse(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawEllipse(r); + } +} + +void KisCanvasPainter::drawArc(int x, int y, int w, int h, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawArc(x, y, w, h, a, alen); + } +} + +void KisCanvasPainter::drawArc(const QRect& r, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawArc(r, a, alen); + } +} + +void KisCanvasPainter::drawPie(int x, int y, int w, int h, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPie(x, y, w, h, a, alen); + } +} + +void KisCanvasPainter::drawPie(const QRect& r, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPie(r, a, alen); + } +} + +void KisCanvasPainter::drawChord(int x, int y, int w, int h, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawChord(x, y, w, h, a, alen); + } +} + +void KisCanvasPainter::drawChord(const QRect& r, int a, int alen) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawChord(r, a, alen); + } +} + +void KisCanvasPainter::drawLineSegments(const QPointArray& pointArray, int index, int nlines) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawLineSegments(pointArray, index, nlines); + } +} + +void KisCanvasPainter::drawPolyline(const QPointArray& pointArray, int index, int npoints) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPolyline(pointArray, index, npoints); + } +} + +void KisCanvasPainter::drawPolygon(const QPointArray& pointArray, bool winding, int index, int npoints) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPolygon(pointArray, winding, index, npoints); + } +} + +void KisCanvasPainter::drawConvexPolygon(const QPointArray& pointArray, int index, int npoints) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawConvexPolygon(pointArray, index, npoints); + } +} + +void KisCanvasPainter::drawCubicBezier(const QPointArray& pointArray, int index) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawCubicBezier(pointArray, index); + } +} + +void KisCanvasPainter::drawPixmap(int x, int y, const QPixmap& pixmap, int sx, int sy, int sw, int sh) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPixmap(x, y, pixmap, sx, sy, sw, sh); + } +} + +void KisCanvasPainter::drawPixmap(const QPoint& point, const QPixmap& pixmap, const QRect& sr) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPixmap(point, pixmap, sr); + } +} + +void KisCanvasPainter::drawPixmap(const QPoint& point, const QPixmap& pixmap) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPixmap(point, pixmap); + } +} + +void KisCanvasPainter::drawPixmap(const QRect& r, const QPixmap& pixmap) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawPixmap(r, pixmap); + } +} + +void KisCanvasPainter::drawImage(int x, int y, const QImage& image, int sx, int sy, int sw, int sh, int conversionFlags) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawImage(x, y, image, sx, sy, sw, sh, conversionFlags); + } +} + +void KisCanvasPainter::drawImage(const QPoint& point, const QImage& image, const QRect& sr, int conversionFlags) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawImage(point, image, sr, conversionFlags); + } +} + +void KisCanvasPainter::drawImage(const QPoint& point, const QImage& image, int conversion_flags) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawImage(point, image, conversion_flags); + } +} + +void KisCanvasPainter::drawImage(const QRect& r, const QImage& image) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawImage(r, image); + } +} + +void KisCanvasPainter::drawTiledPixmap(int x, int y, int w, int h, const QPixmap& pixmap, int sx, int sy) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawTiledPixmap(x, y, w, h, pixmap, sx, sy); + } +} + +void KisCanvasPainter::drawTiledPixmap(const QRect& r, const QPixmap& pixmap, const QPoint& point) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawTiledPixmap(r, pixmap, point); + } +} + +void KisCanvasPainter::drawTiledPixmap(const QRect& r, const QPixmap& pixmap) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawTiledPixmap(r, pixmap); + } +} + +void KisCanvasPainter::fillRect(int x, int y, int w, int h, const QBrush& brush) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->fillRect(x, y, w, h, brush); + } +} + +void KisCanvasPainter::fillRect(const QRect& r, const QBrush& brush) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->fillRect(r, brush); + } +} + +void KisCanvasPainter::eraseRect(int x, int y, int w, int h) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->eraseRect(x, y, w, h); + } +} + +void KisCanvasPainter::eraseRect(const QRect& r) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->eraseRect(r); + } +} + +void KisCanvasPainter::drawText(int x, int y, const QString& text, int len, QPainter::TextDirection dir) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(x, y, text, len, dir); + } +} + +void KisCanvasPainter::drawText(const QPoint& point, const QString& text, int len, QPainter::TextDirection dir) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(point, text, len, dir); + } +} + +void KisCanvasPainter::drawText(int x, int y, const QString& text, int pos, int len, QPainter::TextDirection dir) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(x, y, text, pos, len, dir); + } +} + +void KisCanvasPainter::drawText(const QPoint& point, const QString& text, int pos, int len, QPainter::TextDirection dir) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(point, text, pos, len, dir); + } +} + +void KisCanvasPainter::drawText(int x, int y, int w, int h, int flags, const QString& text, int len, QRect *br, QTextParag **intern) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(x, y, w, h, flags, text, len, br, intern); + } +} + +void KisCanvasPainter::drawText(const QRect& r, int flags, const QString& text, int len, QRect *br, QTextParag **intern) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawText(r, flags, text, len, br, intern); + } +} + +void KisCanvasPainter::drawTextItem(int x, int y, const QTextItem& ti, int textflags) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawTextItem(x, y, ti, textflags); + } +} + +void KisCanvasPainter::drawTextItem(const QPoint& p, const QTextItem& ti, int textflags) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->drawTextItem(p, ti, textflags); + } +} + +QRect KisCanvasPainter::boundingRect(int x, int y, int w, int h, int flags, const QString& text, int len, QTextParag **intern) +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->boundingRect(x, y, w, h, flags, text, len, intern); + } + return QRect(); +} + +QRect KisCanvasPainter::boundingRect(const QRect& r, int flags, const QString& text, int len, QTextParag **intern) +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->boundingRect(r, flags, text, len, intern); + } + return QRect(); +} + +int KisCanvasPainter::tabStops() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->tabStops(); + } + return 0; +} + +void KisCanvasPainter::setTabStops(int ts) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setTabStops(ts); + } +} + +int *KisCanvasPainter::tabArray() const +{ + if (m_canvasWidgetPainter != 0) { + return m_canvasWidgetPainter->tabArray(); + } + return 0; +} + +void KisCanvasPainter::setTabArray(int *ts) +{ + if (m_canvasWidgetPainter != 0) { + m_canvasWidgetPainter->setTabArray(ts); + } +} + diff --git a/krita/ui/kis_canvas_painter.h b/krita/ui/kis_canvas_painter.h new file mode 100644 index 000000000..5559057d6 --- /dev/null +++ b/krita/ui/kis_canvas_painter.h @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_CANVAS_PAINTER_H_ +#define KIS_CANVAS_PAINTER_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qpainter.h> + +#include "kis_global.h" + +class KisCanvas; +class KisCanvasWidget; + +class KisCanvasWidgetPainter { +public: + KisCanvasWidgetPainter(); + virtual ~KisCanvasWidgetPainter(); + + virtual bool begin(KisCanvasWidget *canvasWidget, bool unclipped = false) = 0; + virtual bool end(); + + virtual void save(); + virtual void restore(); + + virtual QFontMetrics fontMetrics() const; + virtual QFontInfo fontInfo() const; + + virtual const QFont& font() const; + virtual void setFont(const QFont&); + virtual const QPen& pen() const; + virtual void setPen(const QPen&); + virtual void setPen(Qt::PenStyle); + virtual void setPen(const QColor&); + virtual const QBrush&brush() const; + virtual void setBrush(const QBrush&); + virtual void setBrush(Qt::BrushStyle); + virtual void setBrush(const QColor&); + virtual QPoint pos() const; + + virtual const QColor&backgroundColor() const; + virtual void setBackgroundColor(const QColor&); + virtual Qt::BGMode backgroundMode() const; + virtual void setBackgroundMode(Qt::BGMode); + virtual Qt::RasterOp rasterOp() const; + virtual void setRasterOp(Qt::RasterOp); + virtual const QPoint&brushOrigin() const; + virtual void setBrushOrigin(int x, int y); + virtual void setBrushOrigin(const QPoint&); + + virtual bool hasViewXForm() const; + virtual bool hasWorldXForm() const; + + virtual void setViewXForm(bool); + virtual QRect window() const; + virtual void setWindow(const QRect&); + virtual void setWindow(int x, int y, int w, int h); + virtual QRect viewport() const; + virtual void setViewport(const QRect&); + virtual void setViewport(int x, int y, int w, int h); + + virtual void setWorldXForm(bool); + virtual const QWMatrix&worldMatrix() const; + virtual void setWorldMatrix(const QWMatrix&, bool combine=FALSE); + + virtual void saveWorldMatrix(); + virtual void restoreWorldMatrix(); + + virtual void scale(double sx, double sy); + virtual void shear(double sh, double sv); + virtual void rotate(double a); + + virtual void translate(double dx, double dy); + virtual void resetXForm(); + virtual double translationX() const; + virtual double translationY() const; + + virtual QPoint xForm(const QPoint&) const; + virtual QRect xForm(const QRect&) const; + virtual QPointArray xForm(const QPointArray&) const; + virtual QPointArray xForm(const QPointArray&, int index, int npoints) const; + virtual QPoint xFormDev(const QPoint&) const; + virtual QRect xFormDev(const QRect&) const; + virtual QPointArray xFormDev(const QPointArray&) const; + virtual QPointArray xFormDev(const QPointArray&, int index, int npoints) const; + + virtual void setClipping(bool); + virtual bool hasClipping() const; + virtual QRegion clipRegion(QPainter::CoordinateMode = QPainter::CoordDevice) const; + virtual void setClipRect(const QRect&, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRegion(const QRegion&, QPainter::CoordinateMode = QPainter::CoordDevice); + + virtual void drawPoint(int x, int y); + virtual void drawPoint(const QPoint&); + virtual void drawPoints(const QPointArray& a, int index=0, int npoints=-1); + virtual void moveTo(int x, int y); + virtual void moveTo(const QPoint&); + virtual void lineTo(int x, int y); + virtual void lineTo(const QPoint&); + virtual void drawLine(int x1, int y1, int x2, int y2); + virtual void drawLine(const QPoint&, const QPoint&); + virtual void drawRect(int x, int y, int w, int h); + virtual void drawRect(const QRect&); + virtual void drawWinFocusRect(int x, int y, int w, int h); + virtual void drawWinFocusRect(int x, int y, int w, int h, const QColor&bgColor); + virtual void drawWinFocusRect(const QRect&); + virtual void drawWinFocusRect(const QRect&, const QColor&bgColor); + virtual void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25); + virtual void drawRoundRect(const QRect&, int = 25, int = 25); + virtual void drawEllipse(int x, int y, int w, int h); + virtual void drawEllipse(const QRect&); + virtual void drawArc(int x, int y, int w, int h, int a, int alen); + virtual void drawArc(const QRect&, int a, int alen); + virtual void drawPie(int x, int y, int w, int h, int a, int alen); + virtual void drawPie(const QRect&, int a, int alen); + virtual void drawChord(int x, int y, int w, int h, int a, int alen); + virtual void drawChord(const QRect&, int a, int alen); + virtual void drawLineSegments(const QPointArray&, int index=0, int nlines=-1); + virtual void drawPolyline(const QPointArray&, int index=0, int npoints=-1); + virtual void drawPolygon(const QPointArray&, bool winding=FALSE, int index=0, int npoints=-1); + virtual void drawConvexPolygon(const QPointArray&, int index=0, int npoints=-1); + virtual void drawCubicBezier(const QPointArray&, int index=0); + virtual void drawPixmap(int x, int y, const QPixmap&, int sx=0, int sy=0, int sw=-1, int sh=-1); + virtual void drawPixmap(const QPoint&, const QPixmap&, const QRect&sr); + virtual void drawPixmap(const QPoint&, const QPixmap&); + virtual void drawPixmap(const QRect&, const QPixmap&); + virtual void drawImage(int x, int y, const QImage&, int sx = 0, int sy = 0, int sw = -1, int sh = -1, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, const QRect&sr, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, int conversion_flags = 0); + virtual void drawImage(const QRect&, const QImage&); + virtual void drawTiledPixmap(int x, int y, int w, int h, const QPixmap&, int sx=0, int sy=0); + virtual void drawTiledPixmap(const QRect&, const QPixmap&, const QPoint&); + virtual void drawTiledPixmap(const QRect&, const QPixmap&); + //virtual void drawPicture(const QPicture&); + //virtual void drawPicture(int x, int y, const QPicture&); + //virtual void drawPicture(const QPoint&, const QPicture&); + + virtual void fillRect(int x, int y, int w, int h, const QBrush&); + virtual void fillRect(const QRect&, const QBrush&); + virtual void eraseRect(int x, int y, int w, int h); + virtual void eraseRect(const QRect&); + + virtual void drawText(int x, int y, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&p, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, int w, int h, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + virtual void drawText(const QRect&, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + + virtual void drawTextItem(int x, int y, const QTextItem&ti, int textflags = 0); + virtual void drawTextItem(const QPoint& p, const QTextItem&ti, int textflags = 0); + + virtual QRect boundingRect(int x, int y, int w, int h, int flags, const QString&, int len = -1, QTextParag **intern=0); + virtual QRect boundingRect(const QRect&, int flags, const QString&, int len = -1, QTextParag **intern=0); + + virtual int tabStops() const; + virtual void setTabStops(int); + virtual int *tabArray() const; + virtual void setTabArray(int *); + +protected: + QFont m_defaultFont; + QPen m_defaultPen; + QBrush m_defaultBrush; + QColor m_defaultColor; + QPoint m_defaultBrushOrigin; + QWMatrix m_defaultWorldMatrix; +}; + +class KisCanvasPainter { +public: + KisCanvasPainter(); + KisCanvasPainter(KisCanvas *canvas); + KisCanvasPainter(const QPaintDevice *paintDevice); + + ~KisCanvasPainter(); + + bool begin(KisCanvas *canvas, bool unclipped = false); + bool begin(const QPaintDevice *paintDevice, bool unclipped = false); + + bool end(); + + void save(); + void restore(); + + QFontMetrics fontMetrics() const; + QFontInfo fontInfo() const; + + const QFont& font() const; + void setFont(const QFont&); + const QPen& pen() const; + void setPen(const QPen&); + void setPen(Qt::PenStyle); + void setPen(const QColor&); + const QBrush&brush() const; + void setBrush(const QBrush&); + void setBrush(Qt::BrushStyle); + void setBrush(const QColor&); + QPoint pos() const; + + const QColor&backgroundColor() const; + void setBackgroundColor(const QColor&); + Qt::BGMode backgroundMode() const; + void setBackgroundMode(Qt::BGMode); + Qt::RasterOp rasterOp() const; + void setRasterOp(Qt::RasterOp); + const QPoint&brushOrigin() const; + void setBrushOrigin(int x, int y); + void setBrushOrigin(const QPoint&); + + bool hasViewXForm() const; + bool hasWorldXForm() const; + + void setViewXForm(bool); + QRect window() const; + void setWindow(const QRect&); + void setWindow(int x, int y, int w, int h); + QRect viewport() const; + void setViewport(const QRect&); + void setViewport(int x, int y, int w, int h); + + void setWorldXForm(bool); + const QWMatrix&worldMatrix() const; + void setWorldMatrix(const QWMatrix&, bool combine=FALSE); + + void saveWorldMatrix(); + void restoreWorldMatrix(); + + void scale(double sx, double sy); + void shear(double sh, double sv); + void rotate(double a); + + void translate(double dx, double dy); + void resetXForm(); + double translationX() const; + double translationY() const; + + QPoint xForm(const QPoint&) const; + QRect xForm(const QRect&) const; + QPointArray xForm(const QPointArray&) const; + QPointArray xForm(const QPointArray&, int index, int npoints) const; + QPoint xFormDev(const QPoint&) const; + QRect xFormDev(const QRect&) const; + QPointArray xFormDev(const QPointArray&) const; + QPointArray xFormDev(const QPointArray&, int index, int npoints) const; + + void setClipping(bool); + bool hasClipping() const; + QRegion clipRegion(QPainter::CoordinateMode = QPainter::CoordDevice) const; + void setClipRect(const QRect&, QPainter::CoordinateMode = QPainter::CoordDevice); + void setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode = QPainter::CoordDevice); + void setClipRegion(const QRegion&, QPainter::CoordinateMode = QPainter::CoordDevice); + + void drawPoint(int x, int y); + void drawPoint(const QPoint&); + void drawPoints(const QPointArray& a, int index=0, int npoints=-1); + void moveTo(int x, int y); + void moveTo(const QPoint&); + void lineTo(int x, int y); + void lineTo(const QPoint&); + void drawLine(int x1, int y1, int x2, int y2); + void drawLine(const QPoint&, const QPoint&); + void drawRect(int x, int y, int w, int h); + void drawRect(const QRect&); + void drawWinFocusRect(int x, int y, int w, int h); + void drawWinFocusRect(int x, int y, int w, int h, const QColor&bgColor); + void drawWinFocusRect(const QRect&); + void drawWinFocusRect(const QRect&, const QColor&bgColor); + void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25); + void drawRoundRect(const QRect&, int = 25, int = 25); + void drawEllipse(int x, int y, int w, int h); + void drawEllipse(const QRect&); + void drawArc(int x, int y, int w, int h, int a, int alen); + void drawArc(const QRect&, int a, int alen); + void drawPie(int x, int y, int w, int h, int a, int alen); + void drawPie(const QRect&, int a, int alen); + void drawChord(int x, int y, int w, int h, int a, int alen); + void drawChord(const QRect&, int a, int alen); + void drawLineSegments(const QPointArray&, int index=0, int nlines=-1); + void drawPolyline(const QPointArray&, int index=0, int npoints=-1); + void drawPolygon(const QPointArray&, bool winding=FALSE, int index=0, int npoints=-1); + void drawConvexPolygon(const QPointArray&, int index=0, int npoints=-1); + void drawCubicBezier(const QPointArray&, int index=0); + void drawPixmap(int x, int y, const QPixmap&, int sx=0, int sy=0, int sw=-1, int sh=-1); + void drawPixmap(const QPoint&, const QPixmap&, const QRect&sr); + void drawPixmap(const QPoint&, const QPixmap&); + void drawPixmap(const QRect&, const QPixmap&); + void drawImage(int x, int y, const QImage&, int sx = 0, int sy = 0, int sw = -1, int sh = -1, int conversionFlags = 0); + void drawImage(const QPoint&, const QImage&, const QRect&sr, int conversionFlags = 0); + void drawImage(const QPoint&, const QImage&, int conversion_flags = 0); + void drawImage(const QRect&, const QImage&); + void drawTiledPixmap(int x, int y, int w, int h, const QPixmap&, int sx=0, int sy=0); + void drawTiledPixmap(const QRect&, const QPixmap&, const QPoint&); + void drawTiledPixmap(const QRect&, const QPixmap&); + //void drawPicture(const QPicture&); + //void drawPicture(int x, int y, const QPicture&); + //void drawPicture(const QPoint&, const QPicture&); + + void fillRect(int x, int y, int w, int h, const QBrush&); + void fillRect(const QRect&, const QBrush&); + void eraseRect(int x, int y, int w, int h); + void eraseRect(const QRect&); + + void drawText(int x, int y, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + void drawText(const QPoint&, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + + void drawText(int x, int y, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + void drawText(const QPoint&p, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + + void drawText(int x, int y, int w, int h, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + void drawText(const QRect&, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + + void drawTextItem(int x, int y, const QTextItem&ti, int textflags = 0); + void drawTextItem(const QPoint& p, const QTextItem&ti, int textflags = 0); + + QRect boundingRect(int x, int y, int w, int h, int flags, const QString&, int len = -1, QTextParag **intern=0); + QRect boundingRect(const QRect&, int flags, const QString&, int len = -1, QTextParag **intern=0); + + int tabStops() const; + void setTabStops(int); + int *tabArray() const; + void setTabArray(int *); + +protected: + KisCanvasWidgetPainter *m_canvasWidgetPainter; + QFont m_defaultFont; + QPen m_defaultPen; + QBrush m_defaultBrush; + QColor m_defaultColor; + QPoint m_defaultBrushOrigin; + QWMatrix m_defaultWorldMatrix; +}; + +#endif // KIS_CANVAS_PAINTER_H_ + diff --git a/krita/ui/kis_clipboard.cc b/krita/ui/kis_clipboard.cc new file mode 100644 index 000000000..8b6a6cd8d --- /dev/null +++ b/krita/ui/kis_clipboard.cc @@ -0,0 +1,287 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qapplication.h> +#include <qclipboard.h> +#include <qobject.h> +#include <qimage.h> +#include <qmessagebox.h> +#include <qbuffer.h> +#include <kmultipledrag.h> +#include <klocale.h> + +#include "kdebug.h" + +#include "KoStore.h" +#include "KoStoreDrag.h" + +#include "kis_types.h" +#include "kis_paint_device.h" +#include "kis_config.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_factory.h" +#include <kis_meta_registry.h> +#include "kis_clipboard.h" + +KisClipboard *KisClipboard::m_singleton = 0; + +KisClipboard::KisClipboard() +{ + Q_ASSERT(KisClipboard::m_singleton == 0); + KisClipboard::m_singleton = this; + + m_pushedClipboard = false; + m_hasClip = false; + m_clip = 0; + + // Check that we don't already have a clip ready + clipboardDataChanged(); + + // Make sure we are notified when clipboard changes + connect( QApplication::clipboard(), SIGNAL( dataChanged() ), + this, SLOT( clipboardDataChanged() ) ); +} + +KisClipboard::~KisClipboard() +{ +} + +KisClipboard* KisClipboard::instance() +{ + if(KisClipboard::m_singleton == 0) + { + KisClipboard::m_singleton = new KisClipboard(); + Q_CHECK_PTR(KisClipboard::m_singleton); + } + return KisClipboard::m_singleton; +} + +void KisClipboard::setClip(KisPaintDeviceSP selection) +{ + m_clip = selection; + + if (!selection) + return; + + m_hasClip = true; + + // We'll create a store (ZIP format) in memory + QBuffer buffer; + QCString mimeType("application/x-krita-selection"); + KoStore* store = KoStore::createStore( &buffer, KoStore::Write, mimeType ); + Q_ASSERT( store ); + Q_ASSERT( !store->bad() ); + + // Layer data + if (store->open("layerdata")) { + if (!selection->write(store)) { + selection->disconnect(); + store->close(); + return; + } + store->close(); + } + + // ColorSpace id of layer data + if (store->open("colorspace")) { + QString csName = selection->colorSpace()->id().id(); + store->write(csName.ascii(), strlen(csName.ascii())); + store->close(); + } + + if (selection->colorSpace()->getProfile()) { + KisAnnotationSP annotation = selection->colorSpace()->getProfile()->annotation(); + if (annotation) { + // save layer profile + if (store->open("profile.icc")) { + store->write(annotation->annotation()); + store->close(); + } + } + } + + delete store; + + // We also create a QImage so we can interchange with other applications + QImage qimg; + KisConfig cfg; + QString monitorProfileName = cfg.monitorProfile(); + KisProfile * monitorProfile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName); + qimg = selection->convertToQImage(monitorProfile); + + QImageDrag *qimgDrag = new QImageDrag(qimg); + KMultipleDrag *multiDrag = new KMultipleDrag(); + if ( !qimg.isNull() ) + multiDrag->addDragObject( qimgDrag ); + KoStoreDrag* storeDrag = new KoStoreDrag( mimeType, 0 ); + storeDrag->setEncodedData( buffer.buffer() ); + multiDrag->addDragObject( storeDrag ); + + + QClipboard *cb = QApplication::clipboard(); + cb->setData(multiDrag); + m_pushedClipboard = true; +} + +KisPaintDeviceSP KisClipboard::clip() +{ + QClipboard *cb = QApplication::clipboard(); + QCString mimeType("application/x-krita-selection"); + QMimeSource *cbData = cb->data(); + + if(cbData && cbData->provides(mimeType)) + { + QBuffer buffer(cbData->encodedData(mimeType)); + KoStore* store = KoStore::createStore( &buffer, KoStore::Read, mimeType ); + KisProfile *profile=0; + + if (store->hasFile("profile.icc")) { + QByteArray data; + store->open("profile.icc"); + data = store->read(store->size()); + store->close(); + profile = new KisProfile(data); + } + + QString csName; + // ColorSpace id of layer data + if (store->hasFile("colorspace")) { + store->open("colorspace"); + csName = QString(store->read(store->size())); + store->close(); + } + + KisColorSpace *cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName, ""), profile); + + m_clip = new KisPaintDevice(cs, "clip"); + + if (store->hasFile("layerdata")) { + store->open("layerdata"); + m_clip->read(store); + store->close(); + } + delete store; + } + else + { + QImage qimg = cb->image(); + + if (qimg.isNull()) + return 0; + + KisConfig cfg; + + Q_UINT32 behaviour = cfg.pasteBehaviour(); + + if(behaviour==2) + { + // Ask user each time + behaviour = QMessageBox::question(0,i18n("Pasting data from simple source"),i18n("The image data you are trying to paste has no colour profile information.\n\nOn the web and in simple applications the data are supposed to be in sRGB color format.\nImporting as web will show it as it is supposed to look.\nMost monitors are not perfect though so if you made the image yourself\nyou might want to import it as it looked on you monitor.\n\nHow do you want to interpret these data?"),i18n("As &Web"),i18n("As on &Monitor")); + } + + KisColorSpace * cs; + QString profileName(""); + if(behaviour==1) + profileName = cfg.monitorProfile(); + + cs = KisMetaRegistry::instance()->csRegistry() ->getColorSpace(KisID("RGBA",""), profileName); + m_clip = new KisPaintDevice(cs, "from paste"); + Q_CHECK_PTR(m_clip); + m_clip->convertFromQImage(qimg, profileName); + } + + return m_clip; +} + +void KisClipboard::clipboardDataChanged() +{ + if (!m_pushedClipboard) { + m_hasClip = false; + QClipboard *cb = QApplication::clipboard(); + QImage qimg = cb->image(); + QMimeSource *cbData = cb->data(); + QCString mimeType("application/x-krita-selection"); + + if(cbData && cbData->provides(mimeType)) + m_hasClip = true; + + if (!qimg.isNull()) + m_hasClip = true; + } + + m_pushedClipboard = false; +} + + +bool KisClipboard::hasClip() +{ + return m_hasClip; +} + +QSize KisClipboard::clipSize() +{ + + QClipboard *cb = QApplication::clipboard(); + QCString mimeType("application/x-krita-selection"); + QMimeSource *cbData = cb->data(); + + KisPaintDeviceSP clip; + + if(cbData && cbData->provides(mimeType)) { + + QBuffer buffer(cbData->encodedData(mimeType)); + KoStore* store = KoStore::createStore( &buffer, KoStore::Read, mimeType ); + KisProfile *profile=0; + + if (store->hasFile("profile.icc")) { + QByteArray data; + store->open("profile.icc"); + data = store->read(store->size()); + store->close(); + profile = new KisProfile(data); + } + + QString csName; + // ColorSpace id of layer data + if (store->hasFile("colorspace")) { + store->open("colorspace"); + csName = QString(store->read(store->size())); + store->close(); + } + + KisColorSpace *cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID(csName, ""), profile); + + clip = new KisPaintDevice(cs, "clip"); + + if (store->hasFile("layerdata")) { + store->open("layerdata"); + clip->read(store); + store->close(); + } + delete store; + + return clip->exactBounds().size(); + } + else { + QImage qimg = cb->image(); + return qimg.size(); + } +; + +} + +#include "kis_clipboard.moc" diff --git a/krita/ui/kis_clipboard.h b/krita/ui/kis_clipboard.h new file mode 100644 index 000000000..346cc742f --- /dev/null +++ b/krita/ui/kis_clipboard.h @@ -0,0 +1,79 @@ +/* + * kis_clipboard.h - part of Krayon + * + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_CLIPBOARD_H_ +#define __KIS_CLIPBOARD_H_ + + +#include <qsize.h> +#include "kis_types.h" + +class QImage; + +/** + * The Krita clipboard is a clipboard that can store paint devices + * instead of just qimage's. + */ +class KisClipboard : public QObject { + + Q_OBJECT + +public: + + virtual ~KisClipboard(); + + static KisClipboard* instance(); + + /** + * Sets the clipboard to the contents of the specified paint device; also + * set the system clipboard to a QImage representation of the specified + * paint device. + */ + void setClip(KisPaintDeviceSP layer); + + /** + * Get the contents of the clipboard in the form of a paint device. + */ + KisPaintDeviceSP clip(); + + bool hasClip(); + + QSize clipSize(); + +private slots: + + void clipboardDataChanged(); +private: + + KisClipboard(); + KisClipboard(const KisClipboard &); + KisClipboard operator=(const KisClipboard &); + + static KisClipboard * m_singleton; + + KisPaintDeviceSP m_clip; + bool m_hasClip; + + bool m_pushedClipboard; + + +}; + +#endif // __KIS_CLIPBOARD_H_ diff --git a/krita/ui/kis_cmb_composite.cc b/krita/ui/kis_cmb_composite.cc new file mode 100644 index 000000000..03c846c15 --- /dev/null +++ b/krita/ui/kis_cmb_composite.cc @@ -0,0 +1,88 @@ +/* + * kis_cmb_composite.cc - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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 <qcombobox.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "kis_cmb_composite.h" + +KisCmbComposite::KisCmbComposite(QWidget * parent, const char * name) + : super( false, parent, name ) +{ + connect(this, SIGNAL(activated(int)), this, SLOT(slotOpActivated(int))); + connect(this, SIGNAL(highlighted(int)), this, SLOT(slotOpHighlighted(int))); +} + +KisCmbComposite::~KisCmbComposite() +{ +} + +void KisCmbComposite::setCompositeOpList(const KisCompositeOpList & list) +{ + super::clear(); + m_list = list; + KisCompositeOpList::iterator it; + for( it = m_list.begin(); it != m_list.end(); ++it ) + insertItem((*it).id().name()); +} + +KisCompositeOp KisCmbComposite::currentItem() const +{ + Q_UINT32 i = super::currentItem(); + if (i > m_list.count()) return KisCompositeOp(); + + return m_list[i]; +} + +void KisCmbComposite::setCurrentItem(const KisCompositeOp& op) +{ + if (m_list.find(op) != m_list.end()) { + super::setCurrentText(op.id().name()); + } +} + +void KisCmbComposite::setCurrentText(const QString & s) +{ + KisCompositeOpList::iterator it; + for( it = m_list.begin(); it != m_list.end(); ++it ) + if ((*it).id().id() == s) { + super::setCurrentText((*it).id().name()); + } +} + +void KisCmbComposite::slotOpActivated(int i) +{ + if ((Q_UINT32)i > m_list.count()) return; + + emit activated(m_list[i]); +} + +void KisCmbComposite::slotOpHighlighted(int i) +{ + if ((Q_UINT32)i > m_list.count()) return; + + emit highlighted(m_list[i]); +} + + +#include "kis_cmb_composite.moc" + diff --git a/krita/ui/kis_cmb_composite.h b/krita/ui/kis_cmb_composite.h new file mode 100644 index 000000000..fa930301b --- /dev/null +++ b/krita/ui/kis_cmb_composite.h @@ -0,0 +1,70 @@ +/* + * kis_cmb_composite.h - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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_CMB_COMPOSITE_H_ +#define KIS_CMB_COMPOSITE_H_ + +#include <koffice_export.h> +#include "qcombobox.h" +#include "kis_composite_op.h" + +/** + * A combobox filled with the various composition strategies defined in kis_global. + * + * XXX: devise some kind of capabilities database for the various colour strategies + * + * enum constant Description CMYK RGBA GRAYA + * 1 COMPOSITE_OVER Over X - X + * + * But that's for later... + */ + +class KRITAUI_EXPORT KisCmbComposite : public QComboBox +{ + typedef QComboBox super; + + Q_OBJECT + + public: + + KisCmbComposite(QWidget * parent = 0, const char * name = 0 ); + virtual ~KisCmbComposite(); + + KisCompositeOp currentItem() const; + + void setCompositeOpList(const KisCompositeOpList& list); + void setCurrentItem(const KisCompositeOp& op); + void setCurrentText(const QString & s); + +signals: + + void activated(const KisCompositeOp &); + void highlighted(const KisCompositeOp &); + +private slots: + + void slotOpActivated(int i); + void slotOpHighlighted(int i); + +private: + KisCompositeOpList m_list; +}; + +#endif diff --git a/krita/ui/kis_cmb_idlist.cc b/krita/ui/kis_cmb_idlist.cc new file mode 100644 index 000000000..570a1ac0b --- /dev/null +++ b/krita/ui/kis_cmb_idlist.cc @@ -0,0 +1,97 @@ +/* + * kis_cmb_idlist.cc - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org) + * + * 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 <qcombobox.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "kis_id.h" +#include "kis_cmb_idlist.h" + +KisCmbIDList::KisCmbIDList(QWidget * parent, const char * name) + : super( false, parent, name ) +{ + connect(this, SIGNAL(activated(int)), this, SLOT(slotIDActivated(int))); + connect(this, SIGNAL(highlighted(int)), this, SLOT(slotIDHighlighted(int))); +} + +KisCmbIDList::~KisCmbIDList() +{ +} + + +void KisCmbIDList::setIDList(const KisIDList & list) +{ + m_list = list; + KisIDList::iterator it; + for( it = m_list.begin(); it != m_list.end(); ++it ) + insertItem((*it).name()); +} + + +KisID KisCmbIDList::currentItem() const +{ + Q_UINT32 i = super::currentItem(); + if (i > m_list.count()) return KisID(); + + return m_list[i]; +} + +void KisCmbIDList::setCurrent(const KisID id) +{ + if (m_list.find(id) != m_list.end()) + super::setCurrentText(id.name()); + else { + m_list.push_back(id); + insertItem(id.name()); + super::setCurrentText(id.name()); + } +} + +void KisCmbIDList::setCurrentText(const QString & s) +{ + KisIDList::iterator it; + for( it = m_list.begin(); it != m_list.end(); ++it ) + if ((*it).id() == s) { + super::setCurrentText((*it).name()); + } +} + +void KisCmbIDList::slotIDActivated(int i) +{ + if ((uint)i > m_list.count()) return; + + emit activated(m_list[i]); + +} + +void KisCmbIDList::slotIDHighlighted(int i) +{ + if ((uint)i > m_list.count()) return; + + emit highlighted(m_list[i]); + +} + + + +#include "kis_cmb_idlist.moc" + diff --git a/krita/ui/kis_cmb_idlist.h b/krita/ui/kis_cmb_idlist.h new file mode 100644 index 000000000..287797eaf --- /dev/null +++ b/krita/ui/kis_cmb_idlist.h @@ -0,0 +1,67 @@ +/* + * kis_cmb_imagetype.h - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org) + * + * 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_CMB_IDLIST_H_ +#define KIS_CMB_IDLIST_H_ + +#include "qcombobox.h" + +#include "kis_id.h" + +/** + * A combobox that is associated with a list of KisID's. The + * descriptive (i18n'ed) text is displayed, but the various + * signals return a KisID. + */ +class KisCmbIDList : public QComboBox +{ + typedef QComboBox super; + + Q_OBJECT + +public: + + KisCmbIDList(QWidget * parent = 0, const char * name = 0 ); + virtual ~KisCmbIDList(); + + +public: + void setIDList(const KisIDList & list); + void setCurrent(const KisID id); + void setCurrentText(const QString & s); + + KisID currentItem() const; + +signals: + + void activated(const KisID &); + void highlighted(const KisID &); + +private slots: + + void slotIDActivated(int i); + void slotIDHighlighted(int i); + +private: + + KisIDList m_list; + +}; +#endif diff --git a/krita/ui/kis_color_cup.cc b/krita/ui/kis_color_cup.cc new file mode 100644 index 000000000..3342305f1 --- /dev/null +++ b/krita/ui/kis_color_cup.cc @@ -0,0 +1,118 @@ +/* + * This file is part of Krita + * + * Copyright (c) 1999 Matthias Elter (me@kde.org) + * Copyright (c) 2001-2002 Igor Jansen (rm@kde.org) + * + * 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 <qpushbutton.h> +#include <qapplication.h> +#include <qclipboard.h> +#include <qcolor.h> +#include <qdrawutil.h> +#include <qhbox.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qspinbox.h> +#include <qstyle.h> +#include <qtooltip.h> +#include <qwidget.h> +#include <qframe.h> + +#include <kcolordialog.h> +#include <klocale.h> +#include <knuminput.h> +#include <koFrameButton.h> + +#include <kis_canvas_subject.h> +#include <kis_color.h> +#include <kis_color_cup.h> + +KisColorPopup::KisColorPopup(QColor c, QWidget * parent, const char * name) + : QFrame(parent, name, WType_Popup | WStyle_Customize | WStyle_NoBorder) +{ + m_color = c; + setMargin(4); + setFocusPolicy(StrongFocus); + QHBoxLayout * l = new QHBoxLayout(this); + l->add(m_khsSelector = new KHSSelector(this)); + m_khsSelector->setMinimumSize(140, 7); + l->add(m_valueSelector = new KValueSelector(this)); + m_valueSelector->setMinimumSize(26, 70); + m_khsSelector->show(); + m_valueSelector->show(); + +} + +KisColorCup::KisColorCup(QWidget * parent, const char * name) + : QPushButton(parent, name) +{ + m_color = Qt::black; + m_popup = new KisColorPopup(m_color, this, "colorpopup"); + connect(this, SIGNAL(clicked()), this, SLOT(slotClicked())); + connect(m_popup, SIGNAL(changed( const QColor &)), this, SLOT(setColor(const QColor &))); +} + +void KisColorCup::setColor(const QColor & c) +{ + m_color = c; + emit changed(c); +} + +void KisColorCup::slotClicked() +{ +// m_popup->move(this->mapToGlobal( this->rect().topRight() ) ); +// m_popup->show(); + emit changed(m_color); +} + +QSize KisColorCup::sizeHint() const +{ + return style().sizeFromContents(QStyle::CT_PushButton, this, QSize(24, 24)). + expandedTo(QApplication::globalStrut()); +} + +void KisColorCup::drawButtonLabel( QPainter *painter ) +{ + int x, y, w, h; + QRect r = style().subRect( QStyle::SR_PushButtonContents, this ); + r.rect(&x, &y, &w, &h); + + int margin = 2; //style().pixelMetric( QStyle::PM_ButtonMargin, this ); + x += margin; + y += margin; + w -= 2*margin; + h -= 2*margin; + + if (isOn() || isDown()) { + x += style().pixelMetric( QStyle::PM_ButtonShiftHorizontal, this ); + y += style().pixelMetric( QStyle::PM_ButtonShiftVertical, this ); + } + + qDrawShadePanel( painter, x, y, w, h, colorGroup(), true, 1, NULL); + if ( m_color.isValid() ) + painter->fillRect( x+1, y+1, w-2, h-2, m_color ); + + if ( hasFocus() ) { + QRect focusRect = style().subRect( QStyle::SR_PushButtonFocusRect, this ); + style().drawPrimitive( QStyle::PE_FocusRect, painter, focusRect, colorGroup() ); + } + +} + +#include "kis_color_cup.moc" diff --git a/krita/ui/kis_color_cup.h b/krita/ui/kis_color_cup.h new file mode 100644 index 000000000..eb98616f0 --- /dev/null +++ b/krita/ui/kis_color_cup.h @@ -0,0 +1,94 @@ +/* This file is part of the KDE project + * + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +#ifndef KIS_COLOR_CUP_H +#define KIS_COLOR_CUP_H + +#include <qpushbutton.h> +#include <qcolor.h> +#include <qframe.h> + +#include <koffice_export.h> + +class QSize; +class QPainter; +class QWidget; +class KHSSelector; +class KValueSelector; + +class KisColorPopup : public QFrame { + + Q_OBJECT + +public: + + KisColorPopup(QColor color, QWidget * w, const char * name); + virtual ~KisColorPopup() {}; + +signals: + + void changed(const QColor &); + +private: + + KHSSelector * m_khsSelector; + KValueSelector * m_valueSelector; + + QColor m_color; +}; + +class KRITAUI_EXPORT KisColorCup : public QPushButton { + + Q_OBJECT + +public: + + KisColorCup(QWidget * parent, const char * name = 0); + + virtual ~KisColorCup() {}; + + QColor color() { return m_color; }; + +signals: + + void changed(const QColor &); + +public: + + QSize sizeHint() const; + +public slots: + + void setColor(const QColor & c); + + +private slots: + + void slotClicked(); + +protected: + + virtual void drawButtonLabel( QPainter *p ); + +private: + + KisColorPopup * m_popup; + QColor m_color; +}; + +#endif diff --git a/krita/ui/kis_config.cc b/krita/ui/kis_config.cc new file mode 100644 index 000000000..b233a1eb0 --- /dev/null +++ b/krita/ui/kis_config.cc @@ -0,0 +1,442 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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 <limits.h> + +#include <kglobalsettings.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kdebug.h> +#include <config.h> + +#include LCMS_HEADER + +#include "kis_global.h" +#include "kis_config.h" + +namespace { + const double IMG_DEFAULT_RESOLUTION = 100.0; + const Q_INT32 IMG_DEFAULT_WIDTH = 512; + const Q_INT32 IMG_DEFAULT_HEIGHT = 512; + const enumCursorStyle DEFAULT_CURSOR_STYLE = CURSOR_STYLE_OUTLINE; + const Q_INT32 DEFAULT_MAX_THREADS = 4; + const Q_INT32 DEFAULT_MAX_TILES_MEM = 500; // 8192 kilobytes given 64x64 tiles with 32bpp + const Q_INT32 DEFAULT_SWAPPINESS = 100; + const Q_INT32 DEFAULT_PRESSURE_CORRECTION = 50; + const Q_INT32 DEFAULT_DOCKABILITY = 0; + const Q_INT32 DEFAULT_UNDO_LIMIT = 50; +} + +KisConfig::KisConfig() +{ + + m_cfg = KGlobal::config(); + if (!m_cfg) { + // Allow unit tests to test parts of the code without having to run the + // full application. + m_cfg = new KConfig(); + } + m_cfg->setGroup(""); +} + +KisConfig::~KisConfig() +{ + m_cfg->sync(); +} + + +bool KisConfig::fixDockerWidth() const +{ + return m_cfg->readBoolEntry("fixDockerWidth", true); +} + +void KisConfig::setFixedDockerWidth(bool fix) +{ + m_cfg->writeEntry("fixDockerWidth", fix); +} + +bool KisConfig::undoEnabled() const +{ + return m_cfg->readBoolEntry("undoEnabled", true); +} + +void KisConfig::setUndoEnabled(bool undo) +{ + m_cfg->writeEntry("undoEnabled", undo); +} + + +Q_INT32 KisConfig::defUndoLimit() const +{ + return m_cfg->readNumEntry("undolimit", DEFAULT_UNDO_LIMIT); +} + +void KisConfig::defUndoLimit(Q_INT32 limit) +{ + m_cfg->writeEntry("undolimit", limit); +} + +Q_INT32 KisConfig::defImgWidth() const +{ + return m_cfg->readNumEntry("imgWidthDef", IMG_DEFAULT_WIDTH); +} + +Q_INT32 KisConfig::defImgHeight() const +{ + return m_cfg->readNumEntry("imgHeightDef", IMG_DEFAULT_HEIGHT); +} + +double KisConfig::defImgResolution() const +{ + return m_cfg->readDoubleNumEntry("imgResolutionDef", IMG_DEFAULT_RESOLUTION); +} + +void KisConfig::defImgWidth(Q_INT32 width) +{ + m_cfg->writeEntry("imgWidthDef", width); +} + +void KisConfig::defImgHeight(Q_INT32 height) +{ + m_cfg->writeEntry("imgHeightDef", height); +} + +void KisConfig::defImgResolution(double res) +{ + m_cfg->writeEntry("imgResolutionDef", res); +} + +enumCursorStyle KisConfig::cursorStyle() const +{ + return (enumCursorStyle) m_cfg->readNumEntry("cursorStyleDef", DEFAULT_CURSOR_STYLE); +} + +enumCursorStyle KisConfig::getDefaultCursorStyle() const +{ + return DEFAULT_CURSOR_STYLE; +} + +void KisConfig::setCursorStyle(enumCursorStyle style) +{ + m_cfg->writeEntry("cursorStyleDef", style); +} + + +QString KisConfig::monitorProfile() const +{ + return m_cfg->readEntry("monitorProfile", ""); +} + +void KisConfig::setMonitorProfile(QString monitorProfile) +{ + m_cfg->writeEntry("monitorProfile", monitorProfile); +} + + +QString KisConfig::workingColorSpace() const +{ + return m_cfg->readEntry("workingColorSpace", "RGBA"); +} + +void KisConfig::setWorkingColorSpace(QString workingColorSpace) +{ + m_cfg->writeEntry(workingColorSpace, workingColorSpace); +} + + +QString KisConfig::printerColorSpace() const +{ + return m_cfg->readEntry("printerColorSpace", "CMYK"); +} + +void KisConfig::setPrinterColorSpace(QString printerColorSpace) +{ + m_cfg->writeEntry("printerColorSpace", printerColorSpace); +} + + +QString KisConfig::printerProfile() const +{ + return m_cfg->readEntry("printerProfile", ""); +} + +void KisConfig::setPrinterProfile(QString printerProfile) +{ + m_cfg->writeEntry("printerProfile", printerProfile); +} + + +bool KisConfig::useBlackPointCompensation() const +{ + return m_cfg->readBoolEntry("useBlackPointCompensation", false); +} + +void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) +{ + m_cfg->writeEntry("useBlackPointCompensation", useBlackPointCompensation); +} + + +bool KisConfig::showRulers() const +{ + return m_cfg->readBoolEntry("showrulers", false); +} + +void KisConfig::setShowRulers(bool rulers) +{ + m_cfg->writeEntry("showrulers", rulers); +} + + +Q_INT32 KisConfig::pasteBehaviour() const +{ + return m_cfg->readNumEntry("pasteBehaviour", 2); +} + +void KisConfig::setPasteBehaviour(Q_INT32 renderIntent) +{ + m_cfg->writeEntry("pasteBehaviour", renderIntent); +} + + +Q_INT32 KisConfig::renderIntent() const +{ + return m_cfg->readNumEntry("renderIntent", INTENT_PERCEPTUAL); +} + +void KisConfig::setRenderIntent(Q_INT32 renderIntent) +{ + m_cfg->writeEntry("renderIntent", renderIntent); +} + +bool KisConfig::useOpenGL() const +{ + return m_cfg->readBoolEntry("useOpenGL", false); +} + +void KisConfig::setUseOpenGL(bool useOpenGL) +{ + m_cfg->writeEntry("useOpenGL", useOpenGL); +} + +bool KisConfig::useOpenGLShaders() const +{ + return m_cfg->readBoolEntry("useOpenGLShaders", false); +} + +void KisConfig::setUseOpenGLShaders(bool useOpenGLShaders) +{ + m_cfg->writeEntry("useOpenGLShaders", useOpenGLShaders); +} + +Q_INT32 KisConfig::maxNumberOfThreads() +{ + return m_cfg->readNumEntry("maxthreads", DEFAULT_MAX_THREADS); +} + +void KisConfig::setMaxNumberOfThreads(Q_INT32 maxThreads) +{ + m_cfg->writeEntry("maxthreads", maxThreads); +} + +Q_INT32 KisConfig::maxTilesInMem() const +{ + return m_cfg->readNumEntry("maxtilesinmem", DEFAULT_MAX_TILES_MEM); +} + +void KisConfig::setMaxTilesInMem(Q_INT32 tiles) +{ + m_cfg->writeEntry("maxtilesinmem", tiles); +} + +Q_INT32 KisConfig::swappiness() const +{ + return m_cfg->readNumEntry("swappiness", DEFAULT_SWAPPINESS); +} + +void KisConfig::setSwappiness(Q_INT32 swappiness) +{ + m_cfg->writeEntry("swappiness", swappiness); +} + +Q_INT32 KisConfig::getPressureCorrection() +{ + return m_cfg->readNumEntry( "pressurecorrection", DEFAULT_PRESSURE_CORRECTION ); +} + +void KisConfig::setPressureCorrection( Q_INT32 correction ) +{ + m_cfg->writeEntry( "pressurecorrection", correction ); +} + +Q_INT32 KisConfig::getDefaultPressureCorrection() +{ + return DEFAULT_PRESSURE_CORRECTION; +} + +bool KisConfig::tabletDeviceEnabled(const QString& tabletDeviceName) const +{ + return m_cfg->readBoolEntry("TabletDevice" + tabletDeviceName + "Enabled", false); +} + +void KisConfig::setTabletDeviceEnabled(const QString& tabletDeviceName, bool enabled) +{ + m_cfg->writeEntry("TabletDevice" + tabletDeviceName + "Enabled", enabled); +} + +Q_INT32 KisConfig::tabletDeviceAxis(const QString& tabletDeviceName, const QString& axisName, Q_INT32 defaultAxis) const +{ + return m_cfg->readNumEntry("TabletDevice" + tabletDeviceName + axisName, defaultAxis); +} + +void KisConfig::setTabletDeviceAxis(const QString& tabletDeviceName, const QString& axisName, Q_INT32 axis) const +{ + m_cfg->writeEntry("TabletDevice" + tabletDeviceName + axisName, axis); +} + +void KisConfig::setDockability( Q_INT32 dockability ) +{ + m_cfg->writeEntry( "palettesdockability", dockability ); +} + +Q_INT32 KisConfig::dockability() +{ + return m_cfg->readNumEntry("palettesdockability", DEFAULT_DOCKABILITY); +} + +Q_INT32 KisConfig::getDefaultDockability() +{ + return DEFAULT_DOCKABILITY; +} + +float KisConfig::dockerFontSize() +{ + return (float) m_cfg->readNumEntry("palettefontsize", (int)getDefaultDockerFontSize()); +} + +float KisConfig::getDefaultDockerFontSize() +{ + float ps = QMIN(9, KGlobalSettings::generalFont().pointSize() * 0.8); + if (ps < 6) ps = 6; + return ps; +} + +void KisConfig::setDockerFontSize(float size) +{ + m_cfg->writeEntry("palettefontsize", size); +} + +Q_UINT32 KisConfig::getGridMainStyle() +{ + Q_UINT32 v = m_cfg->readNumEntry("gridmainstyle", 0); + if (v > 2) + v = 2; + return v; +} + +void KisConfig::setGridMainStyle(Q_UINT32 v) +{ + m_cfg->writeEntry("gridmainstyle", v); +} + +Q_UINT32 KisConfig::getGridSubdivisionStyle() +{ + Q_UINT32 v = m_cfg->readNumEntry("gridsubdivisionstyle", 1); + if (v > 2) v = 2; + return v; +} + +void KisConfig::setGridSubdivisionStyle(Q_UINT32 v) +{ + m_cfg->writeEntry("gridsubdivisionstyle", v); +} + +QColor KisConfig::getGridMainColor() +{ + return m_cfg->readColorEntry("gridmaincolor", new QColor(99,99,99)); +} + +void KisConfig::setGridMainColor(QColor v) +{ + m_cfg->writeEntry("gridmaincolor", v); +} + +QColor KisConfig::getGridSubdivisionColor() +{ + return m_cfg->readColorEntry("gridsubdivisioncolor", new QColor(150,150,150)); +} + +void KisConfig::setGridSubdivisionColor(QColor v) +{ + m_cfg->writeEntry("gridsubdivisioncolor", v); +} + +Q_UINT32 KisConfig::getGridHSpacing() +{ + Q_INT32 v = m_cfg->readNumEntry("gridhspacing", 10); + return (Q_UINT32)QMAX(1, v ); +} + +void KisConfig::setGridHSpacing(Q_UINT32 v) +{ + m_cfg->writeEntry("gridhspacing", v); +} + +Q_UINT32 KisConfig::getGridVSpacing() +{ + Q_INT32 v = m_cfg->readNumEntry("gridvspacing", 10); + return (Q_UINT32)QMAX(1, v ); +} + +void KisConfig::setGridVSpacing(Q_UINT32 v) +{ + m_cfg->writeEntry("gridvspacing", v); +} + +Q_UINT32 KisConfig::getGridSubdivisions() +{ + Q_INT32 v = m_cfg->readNumEntry("gridsubsivisons", 2); + return (Q_UINT32)QMAX(1, v ); +} + +void KisConfig::setGridSubdivisions(Q_UINT32 v) +{ + return m_cfg->writeEntry("gridsubsivisons", v); +} + +Q_UINT32 KisConfig::getGridOffsetX() +{ + Q_INT32 v = m_cfg->readNumEntry("gridoffsetx", 0); + return (Q_UINT32)QMAX(0, v ); +} + +void KisConfig::setGridOffsetX(Q_UINT32 v) +{ + m_cfg->writeEntry("gridoffsetx", v); +} + +Q_UINT32 KisConfig::getGridOffsetY() +{ + Q_INT32 v = m_cfg->readNumEntry("gridoffsety", 0); + return (Q_UINT32)QMAX(0, v ); +} + +void KisConfig::setGridOffsetY(Q_UINT32 v) +{ + m_cfg->writeEntry("gridoffsety", v); +} + diff --git a/krita/ui/kis_config.h b/krita/ui/kis_config.h new file mode 100644 index 000000000..668240071 --- /dev/null +++ b/krita/ui/kis_config.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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_CONFIG_H_ +#define KIS_CONFIG_H_ + +#include "kis_global.h" +#include "koffice_export.h" + +class KRITACORE_EXPORT KisConfig { +public: + KisConfig(); + ~KisConfig(); + + bool fixDockerWidth() const; + void setFixedDockerWidth(bool fix); + + bool undoEnabled() const; + void setUndoEnabled(bool undo); + + Q_INT32 defUndoLimit() const; + void defUndoLimit(Q_INT32 limit); + + Q_INT32 defImgWidth() const; + void defImgWidth(Q_INT32 width); + + Q_INT32 defImgHeight() const; + void defImgHeight(Q_INT32 height); + + double defImgResolution() const; + void defImgResolution(double res); + + enumCursorStyle cursorStyle() const; + enumCursorStyle getDefaultCursorStyle() const; + void setCursorStyle(enumCursorStyle style); + + QString monitorProfile() const; + void setMonitorProfile(QString monitorProfile); + + QString workingColorSpace() const; + void setWorkingColorSpace(QString workingColorSpace); + + QString importProfile() const; + void setImportProfile(QString importProfile); + + QString printerColorSpace() const; + void setPrinterColorSpace(QString printerColorSpace); + + QString printerProfile() const; + void setPrinterProfile(QString printerProfile); + + bool useBlackPointCompensation() const; + void setUseBlackPointCompensation(bool useBlackPointCompensation); + + bool showRulers() const; + void setShowRulers(bool rulers); + + Q_INT32 pasteBehaviour() const; + void setPasteBehaviour(Q_INT32 behaviour); + + Q_INT32 renderIntent() const; + void setRenderIntent(Q_INT32 renderIntent); + + bool useOpenGL() const; + void setUseOpenGL(bool useOpenGL); + + bool useOpenGLShaders() const; + void setUseOpenGLShaders(bool useOpenGLShaders); + + Q_INT32 maxNumberOfThreads(); + void setMaxNumberOfThreads(Q_INT32 numberOfThreads); + + /// Maximum tiles in memory (this is a guideline, not absolute) + Q_INT32 maxTilesInMem() const; + void setMaxTilesInMem(Q_INT32 tiles); + + /// Number of tiles that will be swapped at once. The higher, the more swapped, but more + /// chance that it will become slow + Q_INT32 swappiness() const; + void setSwappiness(Q_INT32 swappiness); + + Q_INT32 getPressureCorrection(); + void setPressureCorrection( Q_INT32 correction); + Q_INT32 getDefaultPressureCorrection(); + + bool tabletDeviceEnabled(const QString& tabletDeviceName) const; + void setTabletDeviceEnabled(const QString& tabletDeviceName, bool enabled); + + Q_INT32 tabletDeviceAxis(const QString& tabletDeviceName, const QString& axisName, Q_INT32 defaultAxis) const; + void setTabletDeviceAxis(const QString& tabletDeviceName, const QString& axisName, Q_INT32 axis) const; + + Q_INT32 dockability(); + Q_INT32 getDefaultDockability(); + void setDockability( Q_INT32 dockability); + + float dockerFontSize(); + float getDefaultDockerFontSize(); + void setDockerFontSize(float); + + + Q_UINT32 getGridMainStyle(); + void setGridMainStyle(Q_UINT32 v); + Q_UINT32 getGridSubdivisionStyle(); + void setGridSubdivisionStyle(Q_UINT32 v); + QColor getGridMainColor(); + void setGridMainColor(QColor v); + QColor getGridSubdivisionColor(); + void setGridSubdivisionColor(QColor v); + Q_UINT32 getGridHSpacing(); + void setGridHSpacing(Q_UINT32 v); + Q_UINT32 getGridVSpacing(); + void setGridVSpacing(Q_UINT32 v); + Q_UINT32 getGridSubdivisions(); + void setGridSubdivisions(Q_UINT32 v); + Q_UINT32 getGridOffsetX(); + void setGridOffsetX(Q_UINT32 v); + Q_UINT32 getGridOffsetY(); + void setGridOffsetY(Q_UINT32 v); + + +private: + KisConfig(const KisConfig&); + KisConfig& operator=(const KisConfig&); + +private: + mutable KConfig *m_cfg; +}; + +#endif // KIS_CONFIG_H_ diff --git a/krita/ui/kis_controlframe.cc b/krita/ui/kis_controlframe.cc new file mode 100644 index 000000000..d2e5a432c --- /dev/null +++ b/krita/ui/kis_controlframe.cc @@ -0,0 +1,343 @@ +/* + * kis_controlframe.cc - part of Krita + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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.g + * + * 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 <stdlib.h> + +#include <qapplication.h> +#include <qlayout.h> +#include <qtabwidget.h> +#include <qframe.h> +#include <qwidget.h> +#include <qevent.h> + +#include <ktoolbar.h> +#include <kmainwindow.h> +#include <kglobalsettings.h> +#include <kstandarddirs.h> +#include <kdebug.h> +#include <klocale.h> +#include <koFrameButton.h> +#include <kactioncollection.h> + +#include "kis_resourceserver.h" +#include "kis_controlframe.h" +#include "kis_resource_mediator.h" +#include "kis_itemchooser.h" +#include "kis_pattern_chooser.h" +#include "kis_gradient_chooser.h" +#include "kis_icon_item.h" +#include "kis_iconwidget.h" +#include "kis_brush.h" +#include "kis_pattern.h" +#include "kis_gradient.h" +#include "kis_brush_chooser.h" +#include "kis_view.h" +#include "kis_autobrush.h" +#include "kis_autogradient.h" +#include "kis_config.h" +#include "kis_paintop_box.h" +#include "kis_custom_brush.h" +#include "kis_custom_pattern.h" +#ifdef HAVE_TEXT_BRUSH +#include "kis_text_brush.h" +#endif +KisPopupFrame::KisPopupFrame(QWidget * parent, const char* name) + : QPopupMenu(parent, name) +{ + setFocusPolicy(StrongFocus); +} + +void KisPopupFrame::keyPressEvent(QKeyEvent * e) +{ + if (e->key()== Qt::Key_Escape) + { + hide(); + e->accept(); + } + else { + e->ignore(); + } +} + + +KisControlFrame::KisControlFrame( KMainWindow * /*window*/, KisView * view, const char* name ) + : QObject(view, name) + //: KToolBar ( window, Qt::DockTop, false, name, true, true ) + , m_view(view) + , m_brushWidget(0) + , m_patternWidget(0) + , m_gradientWidget(0) + , m_brushChooserPopup(0) + , m_patternChooserPopup(0) + , m_gradientChooserPopup(0) + , m_brushMediator(0) + , m_patternMediator(0) + , m_gradientMediator(0) + , m_paintopBox(0) +{ + + KisConfig cfg; + m_font = KGlobalSettings::generalFont(); + m_font.setPointSize((int)cfg.dockerFontSize()); + + m_brushWidget = new KisIconWidget(view, "brushes"); + m_brushWidget->setTextLabel( i18n("Brush Shapes") ); + // XXX: An action without a slot -- that's silly, what kind of action could we use here? + KAction * action = new KWidgetAction(m_brushWidget, + i18n("&Brush"), + 0, + view, + 0, + view->actionCollection(), + "brushes"); + + + m_patternWidget = new KisIconWidget(view, "patterns"); + m_patternWidget->setTextLabel( i18n("Fill Patterns") ); + action = new KWidgetAction(m_patternWidget, + i18n("&Patterns"), + 0, + view, + 0, + view->actionCollection(), + "patterns"); + + m_gradientWidget = new KisIconWidget(view, "gradients"); + m_gradientWidget->setTextLabel( i18n("Gradients") ); + action = new KWidgetAction(m_gradientWidget, + i18n("&Gradients"), + 0, + view, + 0, + view->actionCollection(), + "gradients"); + + m_paintopBox = new KisPaintopBox( view, view, "paintopbox" ); + action = new KWidgetAction(m_paintopBox, + i18n("&Painter's Tools"), + 0, + view, + 0, + view->actionCollection(), + "paintops"); + + m_brushWidget->setFixedSize( 26, 26 ); + m_patternWidget->setFixedSize( 26, 26 ); + m_gradientWidget->setFixedSize( 26, 26 ); + + createBrushesChooser(m_view); + createPatternsChooser(m_view); + createGradientsChooser(m_view); + + m_brushWidget->setPopup(m_brushChooserPopup); + m_brushWidget->setPopupDelay(1); + m_patternWidget->setPopup(m_patternChooserPopup); + m_patternWidget->setPopupDelay(1); + m_gradientWidget->setPopup(m_gradientChooserPopup); + m_gradientWidget->setPopupDelay(1); +} + + +void KisControlFrame::slotSetBrush(KoIconItem *item) +{ + if (item) + m_brushWidget->slotSetItem(*item); +} + +void KisControlFrame::slotSetPattern(KoIconItem *item) +{ + if (item) + m_patternWidget->slotSetItem(*item); +} + +void KisControlFrame::slotSetGradient(KoIconItem *item) +{ + if (item) + m_gradientWidget->slotSetItem(*item); +} + +void KisControlFrame::slotBrushChanged(KisBrush * brush) +{ + KisIconItem *item; + + if((item = m_brushMediator->itemFor(brush))) + { + slotSetBrush(item); + } else { + slotSetBrush( new KisIconItem(brush) ); + } + +} + +void KisControlFrame::slotPatternChanged(KisPattern * pattern) +{ + KisIconItem *item; + if (!pattern) + return; + + if ( (item = m_patternMediator->itemFor(pattern)) ) + slotSetPattern(item); + else + slotSetPattern( new KisIconItem(pattern) ); +} + + +void KisControlFrame::slotGradientChanged(KisGradient * gradient) +{ + KisIconItem *item; + if (!gradient) + return; + + if ( (item = m_gradientMediator->itemFor(gradient)) ) + slotSetGradient(item); + else + slotSetGradient( new KisIconItem(gradient) ); +} + +void KisControlFrame::createBrushesChooser(KisView * view) +{ + + m_brushChooserPopup = new KisPopupFrame(m_brushWidget, "brush_chooser_popup"); + + QHBoxLayout * l = new QHBoxLayout(m_brushChooserPopup, 2, 2, "brushpopuplayout"); + + QTabWidget * m_brushesTab = new QTabWidget(m_brushChooserPopup, "brushestab"); + m_brushesTab->setTabShape(QTabWidget::Triangular); + m_brushesTab->setFocusPolicy(QWidget::NoFocus); + m_brushesTab->setFont(m_font); + m_brushesTab->setMargin(1); + + l->add(m_brushesTab); + + KisAutobrush * m_autobrush = new KisAutobrush(m_brushesTab, "autobrush", i18n("Autobrush")); + m_brushesTab->addTab( m_autobrush, i18n("Autobrush")); + connect(m_autobrush, SIGNAL(activatedResource(KisResource*)), m_view, SLOT(brushActivated( KisResource* ))); + + KisBrushChooser * m_brushChooser = new KisBrushChooser(m_brushesTab, "brush_chooser"); + m_brushesTab->addTab( m_brushChooser, i18n("Predefined Brushes")); + + KisCustomBrush* customBrushes = new KisCustomBrush(m_brushesTab, "custombrush", + i18n("Custom Brush"), m_view); + m_brushesTab->addTab( customBrushes, i18n("Custom Brush")); + connect(customBrushes, SIGNAL(activatedResource(KisResource*)), + m_view, SLOT(brushActivated(KisResource*))); +#ifdef HAVE_TEXT_BRUSH + KisTextBrush* textBrushes = new KisTextBrush(m_brushesTab, "textbrush", + i18n("Text Brush")/*, m_view*/); + m_brushesTab->addTab( textBrushes, i18n("Text Brush")); + connect(textBrushes, SIGNAL(activatedResource(KisResource*)), + m_view, SLOT(brushActivated(KisResource*))); +#endif + + m_brushChooser->setFont(m_font); + m_brushMediator = new KisResourceMediator( m_brushChooser, this); + connect(m_brushMediator, SIGNAL(activatedResource(KisResource*)), m_view, SLOT(brushActivated(KisResource*))); + + KisResourceServerBase* rServer; + rServer = KisResourceServerRegistry::instance()->get("ImagePipeBrushServer"); + m_brushMediator->connectServer(rServer); + rServer = KisResourceServerRegistry::instance()->get("BrushServer"); + m_brushMediator->connectServer(rServer); + + KisControlFrame::connect(view, SIGNAL(brushChanged(KisBrush *)), this, SLOT(slotBrushChanged( KisBrush *))); + m_brushChooser->setCurrent( 0 ); + m_brushMediator->setActiveItem( m_brushChooser->currentItem() ); + customBrushes->setResourceServer(rServer); + + m_autobrush->activate(); +} + +void KisControlFrame::createPatternsChooser(KisView * view) +{ + m_patternChooserPopup = new KisPopupFrame(m_patternWidget, "pattern_chooser_popup"); + + QHBoxLayout * l2 = new QHBoxLayout(m_patternChooserPopup, 2, 2, "patternpopuplayout"); + + QTabWidget * m_patternsTab = new QTabWidget(m_patternChooserPopup, "patternstab"); + m_patternsTab->setTabShape(QTabWidget::Triangular); + m_patternsTab->setFocusPolicy(QWidget::NoFocus); + m_patternsTab->setFont(m_font); + m_patternsTab->setMargin(1); + l2->add( m_patternsTab ); + + KisPatternChooser * chooser = new KisPatternChooser(m_patternChooserPopup, "pattern_chooser"); + chooser->setFont(m_font); + chooser->setMinimumSize(200, 150); + m_patternsTab->addTab(chooser, i18n("Patterns")); + + KisCustomPattern* customPatterns = new KisCustomPattern(m_patternsTab, "custompatterns", + i18n("Custom Pattern"), m_view); + customPatterns->setFont(m_font); + m_patternsTab->addTab( customPatterns, i18n("Custom Pattern")); + + + m_patternMediator = new KisResourceMediator( chooser, view); + connect( m_patternMediator, SIGNAL(activatedResource(KisResource*)), view, SLOT(patternActivated(KisResource*))); + connect(customPatterns, SIGNAL(activatedResource(KisResource*)), + view, SLOT(patternActivated(KisResource*))); + + KisResourceServerBase* rServer; + rServer = KisResourceServerRegistry::instance()->get("PatternServer"); + m_patternMediator->connectServer(rServer); + + KisControlFrame::connect(view, SIGNAL(patternChanged(KisPattern *)), this, SLOT(slotPatternChanged( KisPattern *))); + chooser->setCurrent( 0 ); + m_patternMediator->setActiveItem( chooser->currentItem() ); + + customPatterns->setResourceServer(rServer); +} + + +void KisControlFrame::createGradientsChooser(KisView * view) +{ + m_gradientChooserPopup = new KisPopupFrame(m_gradientWidget, "gradient_chooser_popup"); + + QHBoxLayout * l2 = new QHBoxLayout(m_gradientChooserPopup, 2, 2, "gradientpopuplayout"); + + QTabWidget * m_gradientTab = new QTabWidget(m_gradientChooserPopup, "gradientstab"); + m_gradientTab->setTabShape(QTabWidget::Triangular); + m_gradientTab->setFocusPolicy(QWidget::NoFocus); + m_gradientTab->setFont(m_font); + m_gradientTab->setMargin(1); + + l2->add( m_gradientTab); + + KisGradientChooser * m_gradientChooser = new KisGradientChooser(m_view, m_gradientChooserPopup, "gradient_chooser"); + m_gradientChooser->setFont(m_font); + m_gradientChooser->setMinimumSize(200, 150); + m_gradientTab->addTab( m_gradientChooser, i18n("Gradients")); + + m_gradientMediator = new KisResourceMediator( m_gradientChooser, view); + connect(m_gradientMediator, SIGNAL(activatedResource(KisResource*)), view, SLOT(gradientActivated(KisResource*))); + + KisResourceServerBase* rServer; + rServer = KisResourceServerRegistry::instance()->get("GradientServer"); + m_gradientMediator->connectServer(rServer); + + connect(view, SIGNAL(gradientChanged(KisGradient *)), this, SLOT(slotGradientChanged( KisGradient *))); + m_gradientChooser->setCurrent( 0 ); + m_gradientMediator->setActiveItem( m_gradientChooser->currentItem() ); +} + + +#include "kis_controlframe.moc" + diff --git a/krita/ui/kis_controlframe.h b/krita/ui/kis_controlframe.h new file mode 100644 index 000000000..2007d5cca --- /dev/null +++ b/krita/ui/kis_controlframe.h @@ -0,0 +1,128 @@ +/* + * kis_controlframe.h - part of Krita + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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_controlframe_h__ +#define __kis_controlframe_h__ + +#include <qpopupmenu.h> + +#include <ktoolbar.h> + +#include <koFrameButton.h> + +class QWidget; +class QTabWidget; + +class KToolBar; + +class KoIconItem; +class KisIconWidget; +class KisGradientWidget; + +class KisAutobrush; +class KisAutogradient; +class KisBrush; +class KisBrushChooser; +class KisGradient; +class KisGradientChooser; +class KisItemChooser; +class KisPattern; +class KisResourceMediator; +class KisPaintopBox; +class KisView; + +class KisPopupFrame : public QPopupMenu { + + Q_OBJECT + +public: + + KisPopupFrame(QWidget * parent, const char * name = 0); + virtual void keyPressEvent(QKeyEvent *); + +public: + + void setChooser(KisItemChooser * chooser) { m_chooser = chooser; }; + KisItemChooser * chooser() { return m_chooser; }; + +private: + KisItemChooser * m_chooser; +}; + + +/** + * Control Frame - status display with access to + * color selector, brushes, patterns, and preview + */ +class KisControlFrame : public QObject //: public KToolBar +{ + Q_OBJECT + +public: + KisControlFrame(KMainWindow * window, KisView * view, const char *name = 0 ); + virtual ~KisControlFrame() {}; + +public slots: + + void slotSetBrush(KoIconItem *item); + void slotSetPattern(KoIconItem *item); + void slotSetGradient(KoIconItem *item); + + void slotBrushChanged(KisBrush * brush); + void slotPatternChanged(KisPattern * pattern); + void slotGradientChanged(KisGradient * gradient); + +private: + + void createBrushesChooser(KisView * view); + void createPatternsChooser(KisView * view); + void createGradientsChooser(KisView * view); + + +private: + QFont m_font; + KisView * m_view; + + QTabWidget * m_brushesTab; + QTabWidget * m_gradientTab; + + KisIconWidget *m_brushWidget; + KisIconWidget *m_patternWidget; + KisIconWidget *m_gradientWidget; + + KisPopupFrame * m_brushChooserPopup; + KisPopupFrame * m_patternChooserPopup; + KisPopupFrame * m_gradientChooserPopup; + + KisResourceMediator *m_brushMediator; + KisResourceMediator *m_patternMediator; + KisResourceMediator *m_gradientMediator; + + + KisAutobrush * m_autobrush; + KisBrushChooser * m_brushChooser; + KisGradientChooser * m_gradientChooser; + + KisPaintopBox * m_paintopBox; +}; + +#endif + diff --git a/krita/ui/kis_cursor.cc b/krita/ui/kis_cursor.cc new file mode 100644 index 000000000..0b0b6ea50 --- /dev/null +++ b/krita/ui/kis_cursor.cc @@ -0,0 +1,374 @@ +/* + * kis_cursor.cc - part of KImageShop + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qbitmap.h> +#include <qcursor.h> +#include <qimage.h> +#include <qpainter.h> + +#include <kcursor.h> +#include <kiconloader.h> +#include <kstandarddirs.h> + +#include "kis_cursor.h" +#include "kis_factory.h" + +KisCursor::KisCursor() {} + +/* + * Predefined Qt cursors + */ +QCursor KisCursor::arrowCursor() +{ + return Qt::arrowCursor; +} + +QCursor KisCursor::upArrowCursor() +{ + return Qt::upArrowCursor; +} + +QCursor KisCursor::crossCursor() +{ + return Qt::crossCursor; +} + +QCursor KisCursor::waitCursor() +{ + return Qt::waitCursor; +} + +QCursor KisCursor::ibeamCursor() +{ + return Qt::ibeamCursor; +} + +QCursor KisCursor::sizeVerCursor() +{ + return Qt::sizeVerCursor; +} + +QCursor KisCursor::sizeHorCursor() +{ + return Qt::sizeHorCursor; +} + +QCursor KisCursor::sizeBDiagCursor() +{ + return Qt::sizeBDiagCursor; +} + +QCursor KisCursor::sizeFDiagCursor() +{ + return Qt::sizeFDiagCursor; +} + +QCursor KisCursor::sizeAllCursor() +{ + return Qt::sizeAllCursor; +} + +QCursor KisCursor::blankCursor() +{ + return Qt::blankCursor; +} + +QCursor KisCursor::splitVCursor() +{ + return Qt::splitVCursor; +} + +QCursor KisCursor::splitHCursor() +{ + return Qt::splitHCursor; +} + +QCursor KisCursor::pointingHandCursor() +{ + return Qt::pointingHandCursor; +} + + +/* + * Existing custom KimageShop cursors. Use the 'load' function for all new cursors. + */ + +QCursor KisCursor::pickerCursor() +{ + static unsigned char picker_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, + 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, + 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, + 0x00, 0x72, 0x01, 0x00, 0x39, 0x00, 0x80, 0x1c, 0x00, 0x40, 0x0e, 0x00, + 0x20, 0x07, 0x00, 0x90, 0x03, 0x00, 0xc8, 0x01, 0x00, 0xe4, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00}; + + QBitmap picker_bitmap(24, 24, picker_bits, true); + QBitmap picker_mask = picker_bitmap.createHeuristicMask( false ); + + return QCursor( picker_bitmap, picker_mask, 1, 22 ); +} + + +QCursor KisCursor::pickerPlusCursor() +{ + static unsigned char pickerplus_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, + 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, + 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, + 0x00, 0x72, 0x01, 0x00, 0x39, 0x0c, 0x80, 0x1c, 0x0c, 0x40, 0x0e, 0x0c, + 0x20, 0x07, 0x0c, 0x90, 0x83, 0x7f, 0xc8, 0x81, 0x7f, 0xe4, 0x00, 0x0c, + 0x74, 0x00, 0x0c, 0x32, 0x00, 0x0c, 0x0a, 0x00, 0x0c, 0x00, 0x00, 0x00}; + + QBitmap picker_bitmap(24, 24, pickerplus_bits, true); + QBitmap picker_mask = picker_bitmap.createHeuristicMask( false ); + + return QCursor( picker_bitmap, picker_mask, 1, 22 ); +} + + +QCursor KisCursor::pickerMinusCursor() +{ + static unsigned char pickerminus_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x34, 0x00, 0x00, 0x7a, + 0x00, 0x00, 0x7d, 0x00, 0x80, 0x7e, 0x00, 0x60, 0x3f, 0x00, 0xd0, 0x1f, + 0x00, 0xa0, 0x0f, 0x00, 0x50, 0x07, 0x00, 0xc8, 0x06, 0x00, 0xe4, 0x02, + 0x00, 0x72, 0x01, 0x00, 0x39, 0x00, 0x80, 0x1c, 0x00, 0x40, 0x0e, 0x00, + 0x20, 0x07, 0x00, 0x90, 0xc3, 0x7f, 0xc8, 0xc1, 0x7f, 0xe4, 0x00, 0x00, + 0x74, 0x00, 0x00, 0x32, 0x00, 0x00, 0x0a, 0x00, 0x00, 0x00, 0x00, 0x00}; + + QBitmap picker_bitmap(24, 24, pickerminus_bits, true); + QBitmap picker_mask = picker_bitmap.createHeuristicMask( false ); + + return QCursor( picker_bitmap, picker_mask, 1, 22 ); +} + + + +QCursor KisCursor::penCursor() +{ + static unsigned char pen_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x1c, 0x00, 0x00, 0x3a, 0x00, 0x00, 0x7d, + 0x00, 0x80, 0x7e, 0x00, 0x40, 0x7f, 0x00, 0xa0, 0x3f, 0x00, 0xd0, 0x1f, + 0x00, 0xe8, 0x0f, 0x00, 0xf4, 0x07, 0x00, 0xfa, 0x03, 0x00, 0xfd, 0x01, + 0x80, 0xfe, 0x00, 0x40, 0x7f, 0x00, 0xa0, 0x3f, 0x00, 0xf0, 0x1f, 0x00, + 0xd0, 0x0f, 0x00, 0x88, 0x07, 0x00, 0x88, 0x03, 0x00, 0xe4, 0x01, 0x00, + 0x7c, 0x00, 0x00, 0x1e, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}; + + QBitmap pen_bitmap( 24, 24, pen_bits, true ); + QBitmap pen_mask = pen_bitmap.createHeuristicMask( false ); + + return QCursor( pen_bitmap, pen_mask, 1, 22 ); +} + +QCursor KisCursor::brushCursor() +{ + static unsigned char brush_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x68, 0x00, + 0x00, 0x00, 0xf4, 0x00, 0x00, 0x00, 0xfa, 0x00, 0x00, 0x00, 0xfd, 0x00, + 0x00, 0x80, 0x7e, 0x00, 0x00, 0x40, 0x3f, 0x00, 0x00, 0xa0, 0x1f, 0x00, + 0x00, 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00, 0xf4, 0x03, 0x00, + 0x00, 0xe4, 0x01, 0x00, 0x00, 0xc2, 0x00, 0x00, 0x80, 0x41, 0x00, 0x00, + 0x40, 0x32, 0x00, 0x00, 0xa0, 0x0f, 0x00, 0x00, 0xd0, 0x0f, 0x00, 0x00, + 0xd0, 0x0f, 0x00, 0x00, 0xe8, 0x07, 0x00, 0x00, 0xf4, 0x01, 0x00, 0x00, + 0x7e, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + QBitmap brush_bitmap( 25, 23, brush_bits, true ); + QBitmap brush_mask = brush_bitmap.createHeuristicMask( false ); + + return QCursor( brush_bitmap, brush_mask, 1, 21 ); +} + +QCursor KisCursor::airbrushCursor() +{ + static unsigned char airbrush_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x68, 0x00, 0x00, 0x74, + 0x00, 0x00, 0x7a, 0xf0, 0x00, 0x3d, 0x08, 0x81, 0x1e, 0xe8, 0x41, 0x0f, + 0xe8, 0xa1, 0x07, 0xe8, 0xd1, 0x03, 0xe8, 0xe9, 0x01, 0xe8, 0xf5, 0x00, + 0xe8, 0x7b, 0x00, 0xf0, 0x33, 0x00, 0xf0, 0x23, 0x1f, 0xa0, 0x9f, 0x3f, + 0xd0, 0xff, 0x31, 0xe8, 0xf7, 0x30, 0xf4, 0x03, 0x18, 0xfc, 0x01, 0x0c, + 0xf8, 0x00, 0x06, 0x76, 0x00, 0x03, 0x36, 0x00, 0x03, 0x00, 0x00, 0x00}; + + QBitmap airbrush_bitmap( 24, 24, airbrush_bits, true ); + QBitmap airbrush_mask = airbrush_bitmap.createHeuristicMask( false ); + + return QCursor( airbrush_bitmap, airbrush_mask, 1, 22 ); +} + +QCursor KisCursor::eraserCursor() +{ + static unsigned char eraser_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x00, 0x00, 0x1d, 0x00, + 0x00, 0x80, 0x3e, 0x00, 0x00, 0x40, 0x7f, 0x00, 0x00, 0xa0, 0xff, 0x00, + 0x00, 0xd0, 0xff, 0x00, 0x00, 0xe8, 0x7f, 0x00, 0x00, 0xf4, 0x3f, 0x00, + 0x00, 0xfe, 0x1f, 0x00, 0x00, 0xf9, 0x0f, 0x00, 0x80, 0xf2, 0x07, 0x00, + 0x40, 0xe7, 0x03, 0x00, 0xa0, 0xcf, 0x01, 0x00, 0xd0, 0x9f, 0x00, 0x00, + 0xe8, 0x7f, 0x00, 0x00, 0xfc, 0x3f, 0x00, 0x00, 0xf2, 0x1f, 0x00, 0x00, + 0xe2, 0x0f, 0x00, 0x00, 0xc4, 0x07, 0x00, 0x00, 0x88, 0x03, 0x00, 0x00, + 0x10, 0x01, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; + + QBitmap eraser_bitmap( 25, 24, eraser_bits, true ); + QBitmap eraser_mask = eraser_bitmap.createHeuristicMask( false ); + + return QCursor( eraser_bitmap, eraser_mask, 7, 22 ); +} + +QCursor KisCursor::fillerCursor() +{ + static unsigned char filler_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x28, 0x00, + 0x00, 0x54, 0x00, 0x00, 0x4e, 0x00, 0x00, 0x85, 0x00, 0x80, 0x0a, 0x01, + 0x40, 0x11, 0x01, 0xe0, 0x00, 0x02, 0x58, 0x01, 0x04, 0x2c, 0x02, 0x04, + 0x44, 0x04, 0x08, 0x0c, 0x08, 0x18, 0x3c, 0x00, 0x14, 0x5c, 0x00, 0x0a, + 0x9c, 0x01, 0x05, 0x1c, 0x82, 0x02, 0x18, 0x4c, 0x01, 0x18, 0xb0, 0x00, + 0x08, 0x60, 0x00, 0x00, 0x00, 0x00}; + + QBitmap filler_bitmap( 22, 22, filler_bits, true ); + QBitmap filler_mask = filler_bitmap.createHeuristicMask( false ); + + return QCursor( filler_bitmap, filler_mask, 3, 20 ); +} + +QCursor KisCursor::colorChangerCursor() +{ + static unsigned char colorChanger_bits[] = { + 0x00, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x10, 0x01, 0x0e, 0x08, 0x02, 0x11, + 0x04, 0x82, 0x20, 0x64, 0x84, 0x20, 0x92, 0x44, 0x46, 0x12, 0x49, 0x5f, + 0x12, 0x31, 0x5f, 0x22, 0x01, 0x5f, 0xc2, 0x00, 0x4e, 0x02, 0x00, 0x40, + 0xc2, 0x00, 0x46, 0xe2, 0x01, 0x4f, 0xe4, 0x19, 0x2f, 0xe4, 0x3d, 0x2f, + 0xe8, 0x3d, 0x17, 0xd0, 0x3c, 0x10, 0x20, 0x38, 0x08, 0x40, 0x00, 0x06, + 0x80, 0x81, 0x01, 0x00, 0x7e, 0x00, 0x00, 0x00, 0x00}; + + QBitmap colorChanger_bitmap( 24, 23, colorChanger_bits, true ); + QBitmap colorChanger_mask = colorChanger_bitmap.createHeuristicMask( false ); + + return QCursor( colorChanger_bitmap, colorChanger_mask, 12, 10 ); +} + +QCursor KisCursor::zoomCursor() +{ + static unsigned char zoom_bits[] = { + 0x00, 0x00, 0x00, 0xc0, 0x0f, 0x00, 0xf0, 0x3f, 0x00, 0x38, 0x70, 0x00, + 0x8c, 0xcf, 0x00, 0x0c, 0xdf, 0x00, 0x36, 0xbf, 0x01, 0xb6, 0xbf, 0x01, + 0xf6, 0xbf, 0x01, 0xf6, 0xbf, 0x01, 0xe6, 0x9f, 0x00, 0xcc, 0xcf, 0x00, + 0x9c, 0xe7, 0x01, 0x38, 0x70, 0x03, 0xf0, 0xbf, 0x05, 0xc0, 0xef, 0x0b, + 0x00, 0xc0, 0x17, 0x00, 0x80, 0x2f, 0x00, 0x00, 0x5f, 0x00, 0x00, 0x7e, + 0x00, 0x00, 0x7c, 0x00, 0x00, 0x38, 0x00, 0x00, 0x00}; + + QBitmap zoom_bitmap( 24, 23, zoom_bits, true ); + QBitmap zoom_mask = zoom_bitmap.createHeuristicMask( false ); + + return QCursor( zoom_bitmap, zoom_mask, 9, 8 ); +} + +QCursor KisCursor::moveCursor() +{ + static unsigned char move_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x7e, 0x00, + 0x00, 0xff, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, + 0x10, 0x18, 0x08, 0x18, 0x18, 0x18, 0x1c, 0x18, 0x38, 0xfe, 0xff, 0x7f, + 0xfe, 0xff, 0x7f, 0x1c, 0x18, 0x38, 0x18, 0x18, 0x18, 0x10, 0x18, 0x08, + 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0x18, 0x00, 0x00, 0xff, 0x00, + 0x00, 0x7e, 0x00, 0x00, 0x3c, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00}; + + QBitmap move_bitmap( 24, 24, move_bits, true ); + QBitmap move_mask = move_bitmap.createHeuristicMask( false ); + + return QCursor( move_bitmap, move_mask, 12, 11 ); +} + +QCursor KisCursor::handCursor() +{ + return KCursor::handCursor(); +} + +QCursor KisCursor::selectCursor() +{ + static unsigned char select_bits[] = { + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0xff, 0xff, 0x7f, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, + 0x00, 0x08, 0x00, 0x00, 0x08, 0x00, 0x00, 0x08, 0x00}; + + QBitmap select_bitmap(23, 23, select_bits, true); + QBitmap select_mask = select_bitmap.createHeuristicMask( false ); + + return QCursor( select_bitmap, select_mask, 11, 11 ); +} + +QCursor KisCursor::openHandCursor() +{ + return load("openhand_cursor.xpm"); +} + +QCursor KisCursor::closedHandCursor() +{ + return load("closedhand_cursor.xpm"); +} + +QCursor KisCursor::rotateCursor() +{ + return load("rotate_cursor.xpm"); +} + +QCursor KisCursor::load(const QString & iconName, int hotspotX, int hotspotY) +{ + QString filename = KisFactory::instance()->dirs()->findResource("kis_pics", iconName); + QImage cursorImage; + + cursorImage.load(filename); + Q_ASSERT(!cursorImage.isNull()); + Q_ASSERT(cursorImage.hasAlphaBuffer()); + + QBitmap bitmap(cursorImage.width(), cursorImage.height()); + QBitmap mask(cursorImage.width(), cursorImage.height()); + + QPainter bitmapPainter(&bitmap); + QPainter maskPainter(&mask); + + for (Q_INT32 x = 0; x < cursorImage.width(); ++x) { + for (Q_INT32 y = 0; y < cursorImage.height(); ++y) { + + QRgb pixel = cursorImage.pixel(x, y); + + if (qAlpha(pixel) < 128) { + bitmapPainter.setPen(Qt::color0); + maskPainter.setPen(Qt::color0); + } else { + maskPainter.setPen(Qt::color1); + + if (qGray(pixel) < 128) { + bitmapPainter.setPen(Qt::color1); + } else { + bitmapPainter.setPen(Qt::color0); + } + } + + bitmapPainter.drawPoint(x, y); + maskPainter.drawPoint(x, y); + } + } + + return QCursor(bitmap, mask, hotspotX, hotspotY); +} + diff --git a/krita/ui/kis_cursor.h b/krita/ui/kis_cursor.h new file mode 100644 index 000000000..b4e7e3447 --- /dev/null +++ b/krita/ui/kis_cursor.h @@ -0,0 +1,73 @@ +/* + * kis_cursor.h - part of KImageShop + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_cursor_h__ +#define __kis_cursor_h__ +#include <koffice_export.h> +class QCursor; + +class KRITACORE_EXPORT KisCursor +{ + +public: + + KisCursor(); + + // Predefined Qt cursors. + static QCursor arrowCursor(); // standard arrow cursor + static QCursor upArrowCursor(); // upwards arrow + static QCursor crossCursor(); // crosshair + static QCursor waitCursor(); // hourglass/watch + static QCursor ibeamCursor(); // ibeam/text entry + static QCursor sizeVerCursor(); // vertical resize + static QCursor sizeHorCursor(); // horizontal resize + static QCursor sizeBDiagCursor(); // diagonal resize (/) + static QCursor sizeFDiagCursor(); // diagonal resize (\) + static QCursor sizeAllCursor(); // all directions resize + static QCursor blankCursor(); // blank/invisible cursor + static QCursor splitVCursor(); // vertical splitting + static QCursor splitHCursor(); // horziontal splitting + static QCursor pointingHandCursor(); // a pointing hand + + // Existing custom KimageShop cursors. Use the 'load' function for all new cursors. + static QCursor moveCursor(); // move tool cursor + static QCursor penCursor(); // pen tool cursor + static QCursor brushCursor(); // brush tool cursor + static QCursor airbrushCursor(); // airbrush tool cursor + static QCursor eraserCursor(); // eraser tool cursor + static QCursor fillerCursor(); // filler tool cursor + static QCursor pickerCursor(); // color picker cursor + static QCursor pickerPlusCursor(); // color picker cursor + static QCursor pickerMinusCursor(); // color picker cursor + static QCursor colorChangerCursor(); // color changer tool cursor + static QCursor selectCursor(); // select cursor + static QCursor zoomCursor(); // zoom tool cursor + static QCursor handCursor(); // hand tool cursor + static QCursor openHandCursor(); // Pan tool cursor + static QCursor closedHandCursor(); // Pan tool cursor + static QCursor rotateCursor(); // Transform tool cursor + + // Load a cursor from an image file. The image should have an alpha channel + // and will be converted to black and white on loading. Any format loadable by + // QImage can be used. + static QCursor load(const QString & imageFilename, int hotspotX = -1, int hotspotY = -1); +}; +#endif // __kis_cursor_h__ diff --git a/krita/ui/kis_custom_brush.cc b/krita/ui/kis_custom_brush.cc new file mode 100644 index 000000000..3e6046e7e --- /dev/null +++ b/krita/ui/kis_custom_brush.cc @@ -0,0 +1,158 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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 <KoImageResource.h> +#include <kdebug.h> +#include <qlabel.h> +#include <qimage.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <qcheckbox.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <ktempfile.h> + +#include "kis_view.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_brush.h" +#include "kis_imagepipe_brush.h" +#include "kis_custom_brush.h" +#include "kis_resource_mediator.h" +#include "kis_resourceserver.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" + +KisCustomBrush::KisCustomBrush(QWidget *parent, const char* name, const QString& caption, KisView* view) + : KisWdgCustomBrush(parent, name), m_view(view) +{ + Q_ASSERT(m_view); + m_mediator = 0; + setCaption(caption); + + m_brush = 0; + + preview->setScaledContents(true); + + connect(addButton, SIGNAL(pressed()), this, SLOT(slotAddPredefined())); + connect(brushButton, SIGNAL(pressed()), this, SLOT(slotUseBrush())); +// connect(exportButton, SIGNAL(pressed()), this, SLOT(slotExport())); + connect(style, SIGNAL(activated(int)), this, SLOT(slotUpdateCurrentBrush(int))); + connect(colorAsMask, SIGNAL(stateChanged(int)), this, SLOT(slotUpdateCurrentBrush(int))); +} + +KisCustomBrush::~KisCustomBrush() { + delete m_brush; +} + +void KisCustomBrush::showEvent(QShowEvent *) { + slotUpdateCurrentBrush(0); +} + +void KisCustomBrush::slotUpdateCurrentBrush(int) { + delete m_brush; + if (m_view->canvasSubject() && m_view->canvasSubject()->currentImg()) { + createBrush(); + preview->setPixmap(QPixmap(m_brush->img())); + } else { + m_brush = 0; + } +} + +void KisCustomBrush::slotExport() { + ; +} + +void KisCustomBrush::slotAddPredefined() { + // Save in the directory that is likely to be: ~/.kde/share/apps/krita/brushes + // a unique file with this brushname + QString dir = KGlobal::dirs()->saveLocation("data", "krita/brushes"); + QString extension; + + if (style->currentItem() == 0) { + extension = ".gbr"; + } else { + extension = ".gih"; + } + KTempFile file(dir, extension); + file.close(); // If we don't, and brush->save first, it might get truncated! + + // Save it to that file + m_brush->setFilename(file.name()); + + // Add it to the brush server, so that it automatically gets to the mediators, and + // so to the other brush choosers can pick it up, if they want to + if (m_server) + m_server->addResource(m_brush->clone()); +} + +void KisCustomBrush::slotUseBrush() { + KisBrush* copy = m_brush->clone(); + + Q_CHECK_PTR(copy); + + emit(activatedResource(copy)); +} + +void KisCustomBrush::createBrush() { + KisImageSP img = m_view->canvasSubject()->currentImg(); + + if (!img) + return; + + if (style->currentItem() == 0) { + m_brush = new KisBrush(img->mergedImage(), 0, 0, img->width(), img->height()); + if (colorAsMask->isChecked()) + m_brush->makeMaskImage(); + return; + } + + // For each layer in the current image, create a new image, and add it to the list + QValueVector< QValueVector<KisPaintDevice*> > devices; + devices.push_back(QValueVector<KisPaintDevice*>()); + int w = img->width(); + int h = img->height(); + + // We only loop over the rootLayer. Since we actually should have a layer selection + // list, no need to elaborate on that here and now + KisLayer* layer = img->rootLayer()->firstChild(); + while (layer) { + KisPaintLayer* paint = 0; + if (layer->visible() && (paint = dynamic_cast<KisPaintLayer*>(layer))) + devices.at(0).push_back(paint->paintDevice()); + layer = layer->nextSibling(); + } + QValueVector<KisPipeBrushParasite::SelectionMode> modes; + + switch(comboBox2->currentItem()) { + case 0: modes.push_back(KisPipeBrushParasite::Constant); break; + case 1: modes.push_back(KisPipeBrushParasite::Random); break; + case 2: modes.push_back(KisPipeBrushParasite::Incremental); break; + case 3: modes.push_back(KisPipeBrushParasite::Pressure); break; + case 4: modes.push_back(KisPipeBrushParasite::Angular); break; + default: modes.push_back(KisPipeBrushParasite::Incremental); + } + + m_brush = new KisImagePipeBrush(img->name(), w, h, devices, modes); + if (colorAsMask->isChecked()) + m_brush->makeMaskImage(); +} + + +#include "kis_custom_brush.moc" diff --git a/krita/ui/kis_custom_brush.h b/krita/ui/kis_custom_brush.h new file mode 100644 index 000000000..8beb52c21 --- /dev/null +++ b/krita/ui/kis_custom_brush.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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_CUSTOM_BRUSH_H_ +#define KIS_CUSTOM_BRUSH_H_ + +#include <qobject.h> + +#include "wdgcustombrush.h" + + +class KisResource; +class KisView; +class KisResourceServerBase; + +class KisCustomBrush : public KisWdgCustomBrush +{ + Q_OBJECT +public: + KisCustomBrush(QWidget *parent, const char* name, const QString& caption, KisView* view); + virtual ~KisCustomBrush(); + void setResourceServer(KisResourceServerBase* server) { m_server = server; } + +public slots: + void slotUseBrush(); + +signals: + void activatedResource(KisResource *); + +protected: + virtual void showEvent(QShowEvent *); + +private slots: + void slotExport(); + void slotAddPredefined(); + void slotUpdateCurrentBrush(int); // To connect with activated(int) + +private: + void createBrush(); + KisView* m_view; + KisBrush* m_brush; + KisResourceMediator* m_mediator; + KisResourceServerBase* m_server; +}; + + +#endif // KIS_CUSTOM_BRUSH_H_ diff --git a/krita/ui/kis_custom_image_widget.cc b/krita/ui/kis_custom_image_widget.cc new file mode 100644 index 000000000..79b9389f7 --- /dev/null +++ b/krita/ui/kis_custom_image_widget.cc @@ -0,0 +1,110 @@ +/* This file is part of the KOffice project + * Copyright (C) 2005 Thomas Zander <zander@kde.org> + * Copyright (C) 2005 Casper Boemann <cbr@boemann.dk> + * + * 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; version 2. + + * 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_custom_image_widget.h> +#include <kis_doc.h> +#include <kis_meta_registry.h> +#include "kis_colorspace_factory_registry.h" +#include "kis_profile.h" +#include "kis_colorspace.h" +#include "kis_id.h" +#include "kis_cmb_idlist.h" +#include "squeezedcombobox.h" +#include "kis_color.h" +#include "kis_image.h" +#include "kis_layer.h" + +#include <kcolorcombo.h> + +#include <kdebug.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtextedit.h> +#include <KoUnitWidgets.h> +#include <qlabel.h> + +KisCustomImageWidget::KisCustomImageWidget(QWidget *parent, KisDoc *doc, Q_INT32 defWidth, Q_INT32 defHeight, double resolution, QString defColorSpaceName, QString imageName) + : WdgNewImage(parent) { + m_doc = doc; + + txtName->setText(imageName); + + intWidth->setValue(defWidth); + intHeight->setValue(defHeight); + doubleResolution->setValue(resolution); + + cmbColorSpaces->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys()); + cmbColorSpaces->setCurrentText(defColorSpaceName); + + connect(cmbColorSpaces, SIGNAL(activated(const KisID &)), + this, SLOT(fillCmbProfiles(const KisID &))); + connect (m_createButton, SIGNAL( clicked() ), this, SLOT (buttonClicked()) ); + m_createButton -> setDefault(true); + + fillCmbProfiles(cmbColorSpaces->currentItem()); + lblResolution->hide(); + doubleResolution->hide(); +} + +void KisCustomImageWidget::buttonClicked() { + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(cmbColorSpaces->currentItem(), cmbProfile->currentText()); + + QColor qc(cmbColor->color()); + + m_doc->newImage(txtName->text(), (Q_INT32)intWidth->value(), (Q_INT32)intHeight->value(), cs, KisColor(qc, cs), txtDescription->text(), doubleResolution->value()); + KisImageSP img = m_doc->currentImage(); + if (img) { + KisLayerSP layer = img->activeLayer(); + if (layer) { + layer->setOpacity(backgroundOpacity()); + } + } + emit documentSelected(); +} + +Q_UINT8 KisCustomImageWidget::backgroundOpacity() const +{ + Q_INT32 opacity = sliderOpacity->value(); + + if (!opacity) + return 0; + + return (opacity * 255) / 100; +} + +void KisCustomImageWidget::fillCmbProfiles(const KisID & s) +{ + cmbProfile->clear(); + + if (!KisMetaRegistry::instance()->csRegistry()->exists(s)) { + return; + } + + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + if (csf == 0) return; + + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + cmbProfile->insertItem((*it)->productName()); + } + cmbProfile->setCurrentText(csf->defaultProfile()); +} + +#include "kis_custom_image_widget.moc" diff --git a/krita/ui/kis_custom_image_widget.h b/krita/ui/kis_custom_image_widget.h new file mode 100644 index 000000000..31455f85c --- /dev/null +++ b/krita/ui/kis_custom_image_widget.h @@ -0,0 +1,57 @@ +/* This file is part of the KOffice project + * Copyright (C) 2005 Thomas Zander <zander@kde.org> + * Copyright (C) 2005 Casper Boemann <cbr@boemann.dk> + * + * 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; version 2. + + * 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_CUSTOM_IMAGE_WIDGET_H +#define KIS_CUSTOM_IMAGE_WIDGET_H + +#include <wdgnewimage.h> +#include "kis_global.h" + +class KisDoc; +class KisID; + +/** + * The 'Custom Document' widget in the Krita startup widget. + * This class embeds the image size and colorspace to allow the user to select the image properties + * for a new empty image document. + */ +class KisCustomImageWidget : public WdgNewImage { + Q_OBJECT +public: + /** + * Constructor. Please note that this class is being used/created by KisDoc. + * @param parent the parent widget + * @param doc the document that wants to be altered + */ + KisCustomImageWidget(QWidget *parent, KisDoc *doc, Q_INT32 defWidth, Q_INT32 defHeight, double resolution, QString defColorSpaceName, QString imageName); + +private slots: + void buttonClicked(); + void fillCmbProfiles(const KisID & s); + +signals: + /// this signal is emitted (as defined by KoDocument) the moment the document is 'ready' + void documentSelected(); + +private: + Q_UINT8 backgroundOpacity() const; + + KisDoc *m_doc; +}; + +#endif diff --git a/krita/ui/kis_custom_palette.cc b/krita/ui/kis_custom_palette.cc new file mode 100644 index 000000000..166311169 --- /dev/null +++ b/krita/ui/kis_custom_palette.cc @@ -0,0 +1,151 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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 <KoImageResource.h> +#include <kdebug.h> +#include <qlineedit.h> +#include <qimage.h> +#include <qpushbutton.h> +#include <qregexp.h> +#include <qvalidator.h> + +#include <kglobal.h> +#include <kstandarddirs.h> +#include <ktempfile.h> +#include <kcolordialog.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "kis_view.h" +#include "kis_palette.h" +#include "kis_palette_view.h" +#include "kis_custom_palette.h" +#include "kis_resource_mediator.h" +#include "kis_resourceserver.h" + +KisCustomPalette::KisCustomPalette(QWidget *parent, const char* name, const QString& caption, KisView* view) + : KisWdgCustomPalette(parent, name), m_view(view) +{ + Q_ASSERT(m_view); + m_mediator = 0; + m_server = 0; + m_editMode = false; + setCaption(caption); + + m_palette = new KisPalette(); + m_ownPalette = true; + this->view->setPalette(m_palette); + + connect(addColor, SIGNAL(pressed()), this, SLOT(slotAddNew())); + connect(removeColor, SIGNAL(pressed()), this, SLOT(slotRemoveCurrent())); + connect(addPalette, SIGNAL(pressed()), this, SLOT(slotAddPredefined())); +} + +KisCustomPalette::~KisCustomPalette() { + if (m_ownPalette) + delete m_palette; +} + +void KisCustomPalette::setPalette(KisPalette* p) { + if (m_ownPalette) + delete m_palette; + m_ownPalette = false; + m_palette = p; + view->setPalette(m_palette); +} + +void KisCustomPalette::setEditMode(bool b) { + m_editMode = b; + + if (m_editMode) { + addPalette->setText(i18n("Save changes")); + } else { + addPalette->setText(i18n("Add to Predefined Palettes")); + } +} + +void KisCustomPalette::slotAddNew() { + // Let the user select a new color + // FIXME also let him add the current paint color to the palette + // or even better, let the color picker have an option 'Add to palette'! + + QColor color; + int result = KColorDialog::getColor(color); + if (result != KColorDialog::Accepted) + return; + + bool ok; + QRegExpValidator validator(QRegExp(".*"), this); + QString name = KInputDialog::getText(i18n("Add Color to Palette"), + i18n("Color name (optional):"), + QString::null, &ok, + 0, 0, &validator); + if (!ok) + return; + + KisPaletteEntry entry; + entry.color = color; + entry.name = name; + + m_palette->add(entry); + + // Just reload the palette completely for the view updating + view->setPalette(m_palette); +} + +void KisCustomPalette::slotRemoveCurrent() { + m_palette->remove(view->currentEntry()); + // Just reload the palette completely for the view updating + view->setPalette(m_palette); +} + +void KisCustomPalette::slotAddPredefined() { + m_palette->setName(palettename->text()); + + if (!m_editMode) { + // Save in the directory that is likely to be: ~/.kde/share/apps/krita/palettes + // a unique file with this palettename + QString dir = KGlobal::dirs()->saveLocation("data", "krita/palettes"); + QString extension; + + extension = ".gpl"; + KTempFile file(dir, extension); + file.close(); // If we don't, and palette->save first, it might get truncated! + + // Save it to that file + m_palette->setFilename(file.name()); + } else { + // The filename is already set + } + + if (!m_palette->save()) { + KMessageBox::error(0, i18n("Cannot write to palette file %1. Maybe it is read-only.") + .arg(m_palette->filename()), i18n("Palette")); + return; + } + + // Add it to the palette server, so that it automatically gets to the mediators, and + // so to the other choosers can pick it up, if they want to + // This probably leaks! + if (m_server) + m_server->addResource(new KisPalette(*m_palette)); +} + + +#include "kis_custom_palette.moc" diff --git a/krita/ui/kis_custom_palette.h b/krita/ui/kis_custom_palette.h new file mode 100644 index 000000000..1a2cfd952 --- /dev/null +++ b/krita/ui/kis_custom_palette.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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_CUSTOM_PALETTE_H_ +#define KIS_CUSTOM_PALETTE_H_ + +#include <qobject.h> + +#include "wdgcustompalette.h" + + +class KisResource; +class KisView; +class KisPalette; +class KisResourceServerBase; + +class KisCustomPalette : public KisWdgCustomPalette +{ + Q_OBJECT +public: + KisCustomPalette(QWidget *parent, const char* name, const QString& caption, KisView* view); + virtual ~KisCustomPalette(); + void setResourceServer(KisResourceServerBase* server) { m_server = server; } + void setEditMode(bool b); + bool editMode() const { return m_editMode; } + void setPalette(KisPalette* p); + +signals: + void activatedResource(KisResource *); + +private slots: + void slotAddPredefined(); + void slotAddNew(); + void slotRemoveCurrent(); + +private: + bool m_ownPalette; + bool m_editMode; + KisView* m_view; + KisPalette* m_palette; + KisResourceMediator* m_mediator; + KisResourceServerBase* m_server; +}; + + +#endif // KIS_CUSTOM_PALETTE_H_ diff --git a/krita/ui/kis_custom_pattern.cc b/krita/ui/kis_custom_pattern.cc new file mode 100644 index 000000000..41ba73a73 --- /dev/null +++ b/krita/ui/kis_custom_pattern.cc @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2006 Bart Coppens <kde@bartcoppens.be> + * + * 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 <KoImageResource.h> +#include <kdebug.h> +#include <qlabel.h> +#include <qimage.h> +#include <qpushbutton.h> +#include <qcombobox.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <ktempfile.h> + +#include "kis_view.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_pattern.h" +#include "kis_custom_pattern.h" +#include "kis_resource_mediator.h" +#include "kis_resourceserver.h" +#include "kis_paint_layer.h" + +KisCustomPattern::KisCustomPattern(QWidget *parent, const char* name, const QString& caption, KisView* view) + : KisWdgCustomPattern(parent, name), m_view(view) +{ + Q_ASSERT(m_view); + m_mediator = 0; + setCaption(caption); + + m_pattern = 0; + + preview->setScaledContents(true); + + connect(addButton, SIGNAL(pressed()), this, SLOT(slotAddPredefined())); + connect(patternButton, SIGNAL(pressed()), this, SLOT(slotUsePattern())); + connect(exportButton, SIGNAL(pressed()), this, SLOT(slotExport())); +} + +KisCustomPattern::~KisCustomPattern() { + delete m_pattern; +} + +void KisCustomPattern::showEvent(QShowEvent *) { + slotUpdateCurrentPattern(0); +} + +void KisCustomPattern::slotUpdateCurrentPattern(int) { + delete m_pattern; + if (m_view->canvasSubject() && m_view->canvasSubject()->currentImg()) { + createPattern(); + preview->setPixmap(QPixmap(m_pattern->img())); + } else { + m_pattern = 0; + } +} + +void KisCustomPattern::slotExport() { + ; +} + +void KisCustomPattern::slotAddPredefined() { + if (!m_pattern) + return; + + // Save in the directory that is likely to be: ~/.kde/share/apps/krita/patterns + // a unique file with this pattern name + QString dir = KGlobal::dirs()->saveLocation("data", "krita/patterns"); + QString extension; + + KTempFile file(dir, ".pat"); + file.close(); // If we don't, and pattern->save first, it might get truncated! + + // Save it to that file + m_pattern->setFilename(file.name()); + + // Add it to the pattern server, so that it automatically gets to the mediators, and + // so to the other pattern choosers can pick it up, if they want to + if (m_server) + m_server->addResource(m_pattern->clone()); +} + +void KisCustomPattern::slotUsePattern() { + if (!m_pattern) + return; + KisPattern* copy = m_pattern->clone(); + + Q_CHECK_PTR(copy); + + emit(activatedResource(copy)); +} + +void KisCustomPattern::createPattern() { + KisImageSP img = m_view->canvasSubject()->currentImg(); + + if (!img) + return; + + m_pattern = new KisPattern(img->mergedImage(), 0, 0, img->width(), img->height()); +} + + +#include "kis_custom_pattern.moc" diff --git a/krita/ui/kis_custom_pattern.h b/krita/ui/kis_custom_pattern.h new file mode 100644 index 000000000..0e45e5567 --- /dev/null +++ b/krita/ui/kis_custom_pattern.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2006 Bart Coppens <kde@bartcoppens.be> + * + * 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_CUSTOM_PATTERN_H_ +#define KIS_CUSTOM_PATTERN_H_ + +#include <qobject.h> + +#include "wdgcustompattern.h" + + +class KisResource; +class KisView; +class KisResourceServerBase; + +class KisCustomPattern : public KisWdgCustomPattern +{ + Q_OBJECT +public: + KisCustomPattern(QWidget *parent, const char* name, const QString& caption, KisView* view); + virtual ~KisCustomPattern(); + void setResourceServer(KisResourceServerBase* server) { m_server = server; } + +signals: + void activatedResource(KisResource *); + +protected: + virtual void showEvent(QShowEvent *); + +private slots: + void slotExport(); + void slotAddPredefined(); + void slotUsePattern(); + void slotUpdateCurrentPattern(int); + +private: + void createPattern(); + KisView* m_view; + KisPattern* m_pattern; + KisResourceMediator* m_mediator; + KisResourceServerBase* m_server; +}; + + +#endif // KIS_CUSTOM_PATTERN_H_ diff --git a/krita/ui/kis_dlg_adj_layer_props.cc b/krita/ui/kis_dlg_adj_layer_props.cc new file mode 100644 index 000000000..b994ae5df --- /dev/null +++ b/krita/ui/kis_dlg_adj_layer_props.cc @@ -0,0 +1,168 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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 <klocale.h> + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klineedit.h> +#include <klocale.h> + +#include "kis_filter_config_widget.h" +#include "kis_transaction.h" +#include "kis_filter.h" +#include "kis_filter_configuration.h" +#include "kis_filters_listview.h" +#include "kis_image.h" +#include "kis_previewwidget.h" +#include "kis_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_paint_device.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" +#include "kis_dlg_adj_layer_props.h" +#include "kis_filter.h" +#include "kis_filter_configuration.h" + +KisDlgAdjLayerProps::KisDlgAdjLayerProps(KisAdjustmentLayerSP layer, + const QString & layerName, + const QString & caption, + QWidget *parent, + const char *name) + : KDialogBase(parent, name, true, "", Ok | Cancel) +{ + Q_ASSERT( layer ); + m_layer = layer; + + KisLayerSP next = layer->nextSibling(); + Q_ASSERT( next ); + + m_currentConfiguration = layer->filter(); + m_currentFilter = KisFilterRegistry::instance()->get(m_currentConfiguration->name()); + if (!m_currentFilter) { + kdWarning() << "No filter specified!\n"; + } + + KisPaintDeviceSP dev = 0; + + if( next ) + { + KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>(next.data()); + if (pl) { + dev = pl->paintDevice(); + } + else { + KisGroupLayer * gl = dynamic_cast<KisGroupLayer*>(next.data()); + if (gl) { + dev = gl->projection(gl->extent()); + } + else { + KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(next.data()); + if (al) { + dev = al->cachedPaintDevice(); + } + } + } + } else { + dev = new KisPaintDevice(m_layer->image()->colorSpace()); + } + setCaption(caption); + QWidget * page = new QWidget(this, "page widget"); + QHBoxLayout * layout = new QHBoxLayout(page, 0, 6); + setMainWidget(page); + + m_preview = new KisPreviewWidget(page, "dlgadjustment.preview"); + m_preview->slotSetDevice( dev ); + + connect( m_preview, SIGNAL(updated()), this, SLOT(refreshPreview())); + layout->addWidget(m_preview, 1, 1); + + QVBoxLayout *v1 = new QVBoxLayout( layout ); + QHBoxLayout *hl = new QHBoxLayout( v1 ); + + QLabel * lblName = new QLabel(i18n("Layer name:"), page, "lblName"); + hl->addWidget(lblName, 0, 0); + + m_layerName = new KLineEdit(page, "m_layerName"); + m_layerName->setText(layerName); + m_layerName->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + hl->addWidget(m_layerName, 0, 1); + connect( m_layerName, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotNameChanged( const QString & ) ) ); + + if ( m_currentFilter ) { + m_currentConfigWidget = m_currentFilter->createConfigurationWidget(page, dev); + if (m_currentConfigWidget) { + m_currentConfigWidget->setConfiguration( m_currentConfiguration ); + } + } + if ( m_currentFilter == 0 || m_currentConfigWidget == 0 ) { + QLabel * labelNoConfigWidget = new QLabel( i18n("No configuration options are available for this filter"), page ); + v1->addWidget( labelNoConfigWidget ); + } + else { + v1->addWidget( m_currentConfigWidget ); + connect(m_currentConfigWidget, SIGNAL(sigPleaseUpdatePreview()), this, SLOT(slotConfigChanged())); + } + + refreshPreview(); + enableButtonOK( !m_layerName->text().isEmpty() ); +} + +void KisDlgAdjLayerProps::slotNameChanged( const QString & text ) +{ + enableButtonOK( !text.isEmpty() ); +} + +KisFilterConfiguration * KisDlgAdjLayerProps::filterConfiguration() const +{ + return m_currentFilter->configuration(m_currentConfigWidget); +} + +QString KisDlgAdjLayerProps::layerName() const +{ + return m_layerName->text(); +} + +void KisDlgAdjLayerProps::slotConfigChanged() +{ + if(m_preview->getAutoUpdate()) + { + refreshPreview(); + } else { + m_preview->needUpdate(); + } +} + +void KisDlgAdjLayerProps::refreshPreview() +{ + if (!m_preview) { + kdDebug() << "no preview!\n"; + return; + } + + if (!m_currentFilter) { + return; + } + KisFilterConfiguration* config = m_currentFilter->configuration(m_currentConfigWidget); + + m_preview->runFilter(m_currentFilter, config); +} + +#include "kis_dlg_adj_layer_props.moc" diff --git a/krita/ui/kis_dlg_adj_layer_props.h b/krita/ui/kis_dlg_adj_layer_props.h new file mode 100644 index 000000000..783e65e51 --- /dev/null +++ b/krita/ui/kis_dlg_adj_layer_props.h @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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_DLG_ADJ_LAYER_PROPS_H +#define KIS_DLG_ADJ_LAYER_PROPS_H + +#include <kdialogbase.h> + +class KisFilter; +class QIconViewItem; +class QLabel; +class QHBoxLayout; +class KisPreviewWidget; +class KisFiltersListView; +class KisFilterConfiguration; +class KisImage; +class QGroupBox; + +/** + * Create a new adjustment layer. + */ +class KisDlgAdjLayerProps : public KDialogBase +{ + + Q_OBJECT + +public: + + /** + * Create a new adjustmentlayer dialog + * + * @param img the current image + * @param layername the name of the adjustment layer + * @param caption the caption for the dialog -- create or properties + * @param create if true, set the dialog up for creating a new adj. layer, if false, edit the + * propeties of the current adj. layer + * @param parent the widget parent of this dialog + * @param name the QObject name, if any + */ + KisDlgAdjLayerProps(KisAdjustmentLayerSP layer, + const QString & layerName, + const QString & caption, + QWidget *parent = 0, + const char *name = 0); + + KisFilterConfiguration * filterConfiguration() const; + QString layerName() const; + +protected slots: + + void slotNameChanged( const QString & ); + void slotConfigChanged(); + void refreshPreview(); + +private: + KisImage * m_image; + KisPreviewWidget * m_preview; + KisFilterConfigWidget * m_currentConfigWidget; + KisFilter* m_currentFilter; + KisFilterConfiguration * m_currentConfiguration; + KisAdjustmentLayer * m_layer; + KLineEdit * m_layerName; +}; + +#endif // KIS_DLG_ADJ_LAYER_PROPS_H diff --git a/krita/ui/kis_dlg_adjustment_layer.cc b/krita/ui/kis_dlg_adjustment_layer.cc new file mode 100644 index 000000000..407340ac8 --- /dev/null +++ b/krita/ui/kis_dlg_adjustment_layer.cc @@ -0,0 +1,193 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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 <klocale.h> + +#include <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klineedit.h> +#include <klocale.h> + +#include "kis_filter_config_widget.h" +#include "kis_transaction.h" +#include "kis_filter.h" +#include "kis_filter_configuration.h" +#include "kis_dlg_adjustment_layer.h" +#include "kis_filters_listview.h" +#include "kis_image.h" +#include "kis_previewwidget.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_filter.h" +#include "kis_filter_configuration.h" + +KisDlgAdjustmentLayer::KisDlgAdjustmentLayer(KisImage * img, + const QString & /*layerName*/, + const QString & caption, + QWidget *parent, + const char *name) + : KDialogBase(parent, name, true, "", Ok | Cancel) + , m_image(img) + , m_currentFilter(0) + , m_customName(false) + , m_freezeName(false) +{ + Q_ASSERT(img); + + KisLayerSP activeLayer = img->activeLayer(); + m_dev = 0; + + KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>(activeLayer.data()); + if (pl) { + m_dev = pl->paintDevice(); + } + else { + KisGroupLayer * gl = dynamic_cast<KisGroupLayer*>(activeLayer.data()); + if (gl) { + m_dev = gl->projection(img->bounds()); + } + else { + KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(activeLayer.data()); + if (al) { + m_dev = al->cachedPaintDevice(); + } + } + } + + setCaption(caption); + QWidget * page = new QWidget(this, "page widget"); + QGridLayout * grid = new QGridLayout(page, 3, 2, 0, 6); + setMainWidget(page); + + QLabel * lblName = new QLabel(i18n("Layer name:"), page, "lblName"); + grid->addWidget(lblName, 0, 0); + + m_layerName = new KLineEdit(page, "m_layerName"); + grid->addWidget(m_layerName, 0, 1); + connect( m_layerName, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotNameChanged( const QString & ) ) ); + + m_filtersList = new KisFiltersListView(m_dev, page, true, "dlgadjustment.filtersList"); + connect(m_filtersList , SIGNAL(selectionChanged(QIconViewItem*)), this, SLOT(selectionHasChanged(QIconViewItem* ))); + grid->addMultiCellWidget(m_filtersList, 1, 2, 0, 0); + + m_preview = new KisPreviewWidget(page, "dlgadjustment.preview"); + m_preview->slotSetDevice( m_dev ); + + connect( m_preview, SIGNAL(updated()), this, SLOT(refreshPreview())); + grid->addWidget(m_preview, 1, 1); + + m_configWidgetHolder = new QGroupBox(i18n("Configuration"), page, "currentConfigWidget"); + m_configWidgetHolder->setColumnLayout(0, Qt::Horizontal); + grid->addWidget(m_configWidgetHolder, 2, 1); + + m_labelNoConfigWidget = new QLabel(i18n("No configuration options are available for this filter"), + m_configWidgetHolder); + m_configWidgetHolder->layout()->add(m_labelNoConfigWidget); + m_labelNoConfigWidget->hide(); + + resize( QSize(600, 480).expandedTo(minimumSizeHint()) ); + + m_currentConfigWidget = 0; + + enableButtonOK(0); +} + +void KisDlgAdjustmentLayer::slotNameChanged( const QString & text ) +{ + if (m_freezeName) + return; + + m_customName = !text.isEmpty(); + enableButtonOK( m_currentFilter && m_customName ); +} + +KisFilterConfiguration * KisDlgAdjustmentLayer::filterConfiguration() const +{ + return m_currentFilter->configuration(m_currentConfigWidget); +} + +QString KisDlgAdjustmentLayer::layerName() const +{ + return m_layerName->text(); +} + +void KisDlgAdjustmentLayer::slotConfigChanged() +{ + if(m_preview->getAutoUpdate()) + { + refreshPreview(); + } else { + m_preview->needUpdate(); + } +} + +void KisDlgAdjustmentLayer::refreshPreview() +{ + KisFilterConfiguration* config = m_currentFilter->configuration(m_currentConfigWidget); + + m_preview->runFilter(m_currentFilter, config); +} + +void KisDlgAdjustmentLayer::selectionHasChanged ( QIconViewItem * item ) +{ + KisFiltersIconViewItem* kisitem = (KisFiltersIconViewItem*) item; + + m_currentFilter = kisitem->filter(); + + if ( m_currentConfigWidget != 0 ) + { + m_configWidgetHolder->layout()->remove(m_currentConfigWidget); + + delete m_currentConfigWidget; + m_currentConfigWidget = 0; + + } else { + + m_labelNoConfigWidget->hide(); + } + + if (m_dev) { + m_currentConfigWidget = m_currentFilter->createConfigurationWidget(m_configWidgetHolder, + m_dev); + } + + if (m_currentConfigWidget != 0) + { + m_configWidgetHolder->layout()->add(m_currentConfigWidget); + m_currentConfigWidget->show(); + connect(m_currentConfigWidget, SIGNAL(sigPleaseUpdatePreview()), this, SLOT(slotConfigChanged())); + } else { + m_labelNoConfigWidget->show(); + } + + if (!m_customName) { + m_freezeName = true; + m_layerName->setText(m_currentFilter->id().name()); + m_freezeName = false; + } + + enableButtonOK( !m_layerName->text().isEmpty() ); + refreshPreview(); +} + +#include "kis_dlg_adjustment_layer.moc" diff --git a/krita/ui/kis_dlg_adjustment_layer.h b/krita/ui/kis_dlg_adjustment_layer.h new file mode 100644 index 000000000..93b32fdab --- /dev/null +++ b/krita/ui/kis_dlg_adjustment_layer.h @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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 KISDLGAdjustMENTLAYER_H +#define KISDLGAdjustMENTLAYER_H + +#include <kdialogbase.h> + +class KisFilter; +class QIconViewItem; +class QLabel; +class QHBoxLayout; +class KisPreviewWidget; +class KisFiltersListView; +class KisFilterConfiguration; +class KisImage; +class QGroupBox; + +/** + * Create a new adjustment layer. + */ +class KisDlgAdjustmentLayer : public KDialogBase +{ + + Q_OBJECT + +public: + + /** + * Create a new adjustmentlayer dialog + * + * @param img the current image + * @param layername the name of the adjustment layer + * @param caption the caption for the dialog -- create or properties + * @param create if true, set the dialog up for creating a new adj. layer, if false, edit the + * propeties of the current adj. layer + * @param parent the widget parent of this dialog + * @param name the QObject name, if any + */ + KisDlgAdjustmentLayer(KisImage * img, + const QString & layerName, + const QString & caption, + QWidget *parent = 0, + const char *name = 0); + + KisFilterConfiguration * filterConfiguration() const; + QString layerName() const; + +protected slots: + + void slotNameChanged( const QString & ); + void slotConfigChanged(); + void refreshPreview(); + void selectionHasChanged ( QIconViewItem * item ); + +private: + KisImage * m_image; + KisPaintDeviceSP m_dev; + KisFiltersListView * m_filtersList; + KisPreviewWidget * m_preview; + QGroupBox * m_configWidgetHolder; + QWidget * m_currentConfigWidget; + KisFilter* m_currentFilter; + KLineEdit * m_layerName; + QLabel* m_labelNoConfigWidget; + bool m_customName; + bool m_freezeName; +}; + +#endif diff --git a/krita/ui/kis_dlg_apply_profile.cc b/krita/ui/kis_dlg_apply_profile.cc new file mode 100644 index 000000000..5240a47d8 --- /dev/null +++ b/krita/ui/kis_dlg_apply_profile.cc @@ -0,0 +1,96 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qcombobox.h> +#include <klocale.h> +#include <qbuttongroup.h> + +#include "kis_factory.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_types.h" +#include "kis_profile.h" +#include "kis_colorspace.h" +#include "kis_dlg_apply_profile.h" +#include "kis_config.h" +#include "kis_id.h" +#include <kis_meta_registry.h> +#include "kis_cmb_idlist.h" +#include "squeezedcombobox.h" +#include "wdgapplyprofile.h" + +// XXX: Hardcode RGBA name. This should be a constant, somewhere. +KisDlgApplyProfile::KisDlgApplyProfile(QWidget *parent, const char *name) + : super(parent, name, true, "", Ok | Cancel) +{ + + setCaption(i18n("Apply Image Profile to Clipboard Data")); + m_page = new WdgApplyProfile(this); + + setMainWidget(m_page); + resize(m_page->sizeHint()); + + // XXX: This is BAD! (bsar) + fillCmbProfiles(KisID("RGBA", "")); + KisConfig cfg; + m_page->grpRenderIntent->setButton(cfg.renderIntent()); + +} + +KisDlgApplyProfile::~KisDlgApplyProfile() +{ + delete m_page; +} + + +KisProfile * KisDlgApplyProfile::profile() const +{ + QString profileName; + + profileName = m_page->cmbProfile->currentText(); + + return KisMetaRegistry::instance()->csRegistry()->getProfileByName(profileName); +} + +int KisDlgApplyProfile::renderIntent() const +{ + return m_page->grpRenderIntent->selectedId(); +} + + +// XXX: Copy & paste from kis_custom_image_widget -- refactor to separate class +void KisDlgApplyProfile::fillCmbProfiles(const KisID & s) +{ + m_page->cmbProfile->clear(); + + if (!KisMetaRegistry::instance()->csRegistry()->exists(s)) { + return; + } + + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + if (csf == 0) return; + + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + m_page->cmbProfile->insertItem((*it)->productName()); + } + m_page->cmbProfile->setCurrentText(csf->defaultProfile()); +} + +#include "kis_dlg_apply_profile.moc" + diff --git a/krita/ui/kis_dlg_apply_profile.h b/krita/ui/kis_dlg_apply_profile.h new file mode 100644 index 000000000..2e9566294 --- /dev/null +++ b/krita/ui/kis_dlg_apply_profile.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_DLG_APPLY_PROFILE_H_ +#define KIS_DLG_APPLY_PROFILE_H_ + +#include <kdialogbase.h> + +class KisID; +class WdgApplyProfile; + +class KisDlgApplyProfile : public KDialogBase { + typedef KDialogBase super; + + Q_OBJECT + +public: + KisDlgApplyProfile(QWidget *parent = 0, + const char *name = 0); + virtual ~KisDlgApplyProfile(); + + + KisProfile * profile() const; + int renderIntent() const; + + void fillCmbProfiles(const KisID & s); + +private: + + WdgApplyProfile * m_page; +}; + +#endif // KIS_DLG_APPLY_PROFILE_H_ + diff --git a/krita/ui/kis_dlg_image_properties.cc b/krita/ui/kis_dlg_image_properties.cc new file mode 100644 index 000000000..871fd9d6a --- /dev/null +++ b/krita/ui/kis_dlg_image_properties.cc @@ -0,0 +1,173 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qbuttongroup.h> +#include <qpushbutton.h> +#include <qradiobutton.h> +#include <qgroupbox.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qtextedit.h> +#include <qcheckbox.h> + +#include <klocale.h> +#include <kcolorcombo.h> + +#include <KoUnitWidgets.h> + +#include "kis_factory.h" +#include "kis_meta_registry.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_dlg_image_properties.h" +#include "kis_profile.h" +#include "kis_types.h" +#include "kis_image.h" +#include "kis_config.h" +#include "kis_id.h" +#include "kis_cmb_idlist.h" +#include "squeezedcombobox.h" +#include "wdgnewimage.h" + +KisDlgImageProperties::KisDlgImageProperties(KisImageSP image, QWidget *parent, const char *name) + : super(parent, name, true, "", Ok | Cancel) +{ + + setCaption(i18n("Image Properties")); + m_page = new WdgNewImage(this); + + m_page->lblResolution->hide(); + m_page->doubleResolution->hide(); + + + m_image = image; + + setMainWidget(m_page); + resize(m_page->sizeHint()); + + m_page->txtName->setText(image->name()); + m_page->m_createButton->hide(); + KisConfig cfg; + + m_page->intWidth->setValue(image->width()); + m_page->intHeight->setValue(image->height()); + m_page->txtDescription->setText(image->description()); + m_page->doubleResolution->setValue(image->xRes()); // XXX: separate values for x & y? + + //m_page->cmbColorSpaces->hide(); + //m_page->lblColorSpaces->setText(image->colorSpace()->id().name()); + KisIDList colorSpaces = KisMetaRegistry::instance()->csRegistry()->listKeys(); + KisIDList::iterator i = colorSpaces.find(KisID("WET","")); + if (i != colorSpaces.end()) { + colorSpaces.remove(i); + } + m_page->cmbColorSpaces->setIDList(colorSpaces); + m_page->cmbColorSpaces->setCurrent(image->colorSpace()->id()); + + fillCmbProfiles(image->colorSpace()->id()); + + if (image->getProfile()) { + m_page->cmbProfile->setCurrentText(image->getProfile()->productName()); + } + else { + m_page->cmbProfile->setCurrentItem(0); + } + + m_page->sliderOpacity->setEnabled(false); // XXX re-enable when figured out a way to do this + m_page->opacityPanel->hide(); + m_page->lblOpacity->hide(); + + m_page->cmbColor->setEnabled(false); // XXX re-enable when figured out a way to do this + m_page->cmbColor->hide(); + m_page->lblColor->hide(); + + connect(m_page->cmbColorSpaces, SIGNAL(activated(const KisID &)), + this, SLOT(fillCmbProfiles(const KisID &))); + + +} + +KisDlgImageProperties::~KisDlgImageProperties() +{ + delete m_page; +} + +int KisDlgImageProperties::imageWidth() +{ + return m_page->intWidth->value(); +} + +int KisDlgImageProperties::imageHeight() +{ + return m_page->intHeight->value(); +} + +int KisDlgImageProperties::opacity() +{ + return m_page->sliderOpacity->value(); +} + +QString KisDlgImageProperties::imageName() +{ + return m_page->txtName->text(); +} + +double KisDlgImageProperties::resolution() +{ + return m_page->doubleResolution->value(); +} + +QString KisDlgImageProperties::description() +{ + return m_page->txtDescription->text(); +} + +KisColorSpace * KisDlgImageProperties::colorSpace() +{ + return KisMetaRegistry::instance()->csRegistry()->getColorSpace(m_page->cmbColorSpaces->currentItem(), m_page->cmbProfile->currentText()); +} + +KisProfile * KisDlgImageProperties::profile() +{ + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( m_image->colorSpace()->id() ); + Q_UINT32 index = m_page->cmbProfile->currentItem(); + + if (index < profileList.count()) { + return profileList.at(index); + } else { + return 0; + } +} + +// XXX: Copy & paste from kis_dlg_create_img -- refactor to separate class +void KisDlgImageProperties::fillCmbProfiles(const KisID & s) +{ + + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + m_page->cmbProfile->clear(); + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + m_page->cmbProfile->insertItem((*it)->productName()); + } + + +} + +#include "kis_dlg_image_properties.moc" + diff --git a/krita/ui/kis_dlg_image_properties.h b/krita/ui/kis_dlg_image_properties.h new file mode 100644 index 000000000..2a4b84c91 --- /dev/null +++ b/krita/ui/kis_dlg_image_properties.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_DLG_IMAGE_PROPERTIES_H_ +#define KIS_DLG_IMAGE_PROPERTIES_H_ + +#include <kdialogbase.h> + +#include <kis_types.h> + +class WdgNewImage; +class QButtonGroup; +class KisID; + +class KisDlgImageProperties : public KDialogBase { + typedef KDialogBase super; + Q_OBJECT + +public: + KisDlgImageProperties(KisImageSP image, + QWidget *parent = 0, + const char *name = 0); + virtual ~KisDlgImageProperties(); + + int imageWidth(); + int imageHeight(); + int opacity(); + QString imageName(); + double resolution(); + QString description(); + KisColorSpace * colorSpace(); + KisProfile * profile(); + +private slots: + + void fillCmbProfiles(const KisID &); + +private: + + WdgNewImage * m_page; + KisImageSP m_image; +}; + + + +#endif // KIS_DLG_IMAGE_PROPERTIES_H_ + diff --git a/krita/ui/kis_dlg_layer_properties.cc b/krita/ui/kis_dlg_layer_properties.cc new file mode 100644 index 000000000..442d2da1b --- /dev/null +++ b/krita/ui/kis_dlg_layer_properties.cc @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <limits.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qgroupbox.h> +#include <qslider.h> +#include <qstring.h> +#include <klineedit.h> +#include <klocale.h> +#include <kpushbutton.h> +#include <knuminput.h> +#include "kis_global.h" +#include "squeezedcombobox.h" +#include "wdglayerproperties.h" +#include "kis_dlg_layer_properties.h" +#include "kis_cmb_composite.h" +#include "kis_cmb_idlist.h" +#include "kis_profile.h" +#include "kis_int_spinbox.h" +#include "kis_colorspace.h" + +KisDlgLayerProperties::KisDlgLayerProperties(const QString& deviceName, + Q_INT32 opacity, + const KisCompositeOp& compositeOp, + const KisColorSpace * colorSpace, + QWidget *parent, const char *name, WFlags f) + : super(parent, name, f, name, Ok | Cancel) +{ + m_page = new WdgLayerProperties(this); + m_page->layout()->setMargin(0); + + opacity = int((opacity * 100.0) / 255 + 0.5); + + setCaption(i18n("Layer Properties")); + setMainWidget(m_page); + + m_page->editName->setText(deviceName); + connect( m_page->editName, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotNameChanged( const QString & ) ) ); + + m_page->cmbColorSpaces->setCurrent(colorSpace->id()); + m_page->cmbColorSpaces->setEnabled(false); + + QString profilename; + if (KisProfile* profile = const_cast<KisColorSpace *>(colorSpace)->getProfile()) + profilename = profile->productName(); + m_page->cmbProfile->insertItem(profilename); + m_page->cmbProfile->setEnabled(false); + + m_page->intOpacity->setRange(0, 100, 13); + m_page->intOpacity->setValue(opacity); + + m_page->cmbComposite->setCompositeOpList(colorSpace->userVisiblecompositeOps()); + m_page->cmbComposite->setCurrentItem(compositeOp); + + slotNameChanged( m_page->editName->text() ); +} + +KisDlgLayerProperties::~KisDlgLayerProperties() +{ +} + +void KisDlgLayerProperties::slotNameChanged( const QString &_text ) +{ + enableButtonOK( !_text.isEmpty() ); +} + +QString KisDlgLayerProperties::getName() const +{ + return m_page->editName->text(); +} + +int KisDlgLayerProperties::getOpacity() const +{ + Q_INT32 opacity = m_page->intOpacity->value(); + + if (!opacity) + return 0; + + opacity = int((opacity * 255.0) / 100 + 0.5); + if(opacity>255) + opacity=255; + return opacity; +} + +KisCompositeOp KisDlgLayerProperties::getCompositeOp() const +{ + return m_page->cmbComposite->currentItem(); +} + +#include "kis_dlg_layer_properties.moc" diff --git a/krita/ui/kis_dlg_layer_properties.h b/krita/ui/kis_dlg_layer_properties.h new file mode 100644 index 000000000..2dc823cea --- /dev/null +++ b/krita/ui/kis_dlg_layer_properties.h @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_DLG_LAYER_PROPERTIES_H_ +#define KIS_DLG_LAYER_PROPERTIES_H_ + +#include <kdialogbase.h> + +class QWidget; +class WdgLayerProperties; +class KisCompositeOp; +class KisColorSpace; + +class KisDlgLayerProperties : public KDialogBase { + typedef KDialogBase super; + Q_OBJECT + +public: + KisDlgLayerProperties(const QString& deviceName, + Q_INT32 opacity, + const KisCompositeOp& compositeOp, + const KisColorSpace * colorSpace, + QWidget *parent = 0, const char *name = 0, WFlags f = 0); + + virtual ~KisDlgLayerProperties(); + + QString getName() const; + Q_INT32 getOpacity() const; + KisCompositeOp getCompositeOp() const; + +protected slots: + void slotNameChanged( const QString & ); + +private: + WdgLayerProperties * m_page; +}; + +#endif // KIS_DLG_LAYER_PROPERTIES_H_ + diff --git a/krita/ui/kis_dlg_new_layer.cc b/krita/ui/kis_dlg_new_layer.cc new file mode 100644 index 000000000..3cdd58d4e --- /dev/null +++ b/krita/ui/kis_dlg_new_layer.cc @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2000 Michael Koch <koch@kde.org> + * Copyright (c) 2000 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2004 Boudewijn Remot <boud@valdyas.org> + * Copyright (c) 2006 Casper Boemann <cbr@boemann.dk> + * + * 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 <qgroupbox.h> +#include <qlabel.h> +#include <qlayout.h> + +#include <klineedit.h> +#include <klocale.h> +#include <knuminput.h> +#include <kpushbutton.h> + +#include "kis_factory.h" +#include "kis_global.h" +#include "kis_cmb_composite.h" +#include "kis_cmb_idlist.h" +#include "squeezedcombobox.h" +#include "kis_dlg_new_layer.h" +#include <kis_meta_registry.h> +#include "kis_colorspace_factory_registry.h" +#include "kis_profile.h" +#include "kis_colorspace.h" +#include "wdglayerproperties.h" +#include "kis_int_spinbox.h" + +NewLayerDialog::NewLayerDialog(const KisID colorSpaceID, + const QString & profilename, + const QString & deviceName, + QWidget *parent, + const char *name) + : super(parent, name, true, "", Ok | Cancel) +{ + m_page = new WdgLayerProperties(this); + m_page->layout()->setMargin(0); + + setCaption(i18n("New Layer")); + + setMainWidget(m_page); + + // Name + m_page->editName->setText(deviceName); + + // Opacity + m_page->intOpacity->setRange(0, 100, 13); + m_page->intOpacity->setValue(100); + + // ColorSpace + m_page->cmbColorSpaces->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys()); + m_page->cmbColorSpaces->setCurrentText(colorSpaceID.id()); + connect(m_page->cmbColorSpaces, SIGNAL(activated(const KisID &)), + this, SLOT(fillCmbProfiles(const KisID &))); + connect(m_page->cmbColorSpaces, SIGNAL(activated(const KisID &)), + this, SLOT(fillCmbComposite(const KisID &))); + + // Init profiles + fillCmbProfiles(m_page->cmbColorSpaces->currentItem()); + m_page->cmbProfile->setCurrentText(profilename); + + // Init composite op + fillCmbComposite(m_page->cmbColorSpaces->currentItem()); + +/* + connect( m_page->editName, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotNameChanged( const QString & ) ) ); + + slotNameChanged( m_page->editName->text() ); +*/ +} + +void NewLayerDialog::setColorSpaceEnabled(bool enabled) +{ + m_page->cmbProfile->setEnabled(enabled); + m_page->cmbColorSpaces->setEnabled(enabled); +} + +void NewLayerDialog::fillCmbProfiles(const KisID & s) +{ + m_page->cmbProfile->clear(); + + if (!KisMetaRegistry::instance()->csRegistry()->exists(s)) { + return; + } + + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + if (csf == 0) return; + + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + m_page->cmbProfile->insertItem((*it)->productName()); + } + m_page->cmbProfile->setCurrentText(csf->defaultProfile()); +} + +void NewLayerDialog::fillCmbComposite(const KisID & s) +{ + m_page->cmbComposite->clear(); + + if (!KisMetaRegistry::instance()->csRegistry()->exists(s)) { + return; + } + + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(s,""); + if (cs) { + m_page->cmbComposite->setCompositeOpList(cs->userVisiblecompositeOps()); + } +} + +int NewLayerDialog::opacity() const +{ + Q_INT32 opacity = m_page->intOpacity->value(); + + if (!opacity) + return 0; + + opacity = int((opacity * 255.0) / 100 + 0.5); + if(opacity>255) + opacity=255; + return opacity; +} + +KisCompositeOp NewLayerDialog::compositeOp() const +{ + return m_page->cmbComposite->currentItem(); +} + +KisID NewLayerDialog::colorSpaceID() const +{ + return m_page->cmbColorSpaces->currentItem(); +} + +QString NewLayerDialog::layerName() const +{ + return m_page->editName->text(); +} + +QString NewLayerDialog::profileName() const +{ + return m_page->cmbProfile-> currentText(); +} + +#include "kis_dlg_new_layer.moc" + diff --git a/krita/ui/kis_dlg_new_layer.h b/krita/ui/kis_dlg_new_layer.h new file mode 100644 index 000000000..e250185ca --- /dev/null +++ b/krita/ui/kis_dlg_new_layer.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2000 Michael Koch <koch@kde.org> + * Copyright (c) 2000 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2006 Casper Boemann <cbr@boemann.dk> + * + * 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_DLG_NEW_LAYER_H_ +#define KIS_DLG_NEW_LAYER_H_ + +#include <kdialogbase.h> + +#include "kis_composite_op.h" +#include <kis_global.h> + +class QWidget; +class KisPaintDevice; +class WdgLayerProperties; + +class NewLayerDialog : public KDialogBase { + typedef KDialogBase super; + Q_OBJECT + +public: + NewLayerDialog(const KisID colorSpace, + const QString & profilename, + const QString & deviceName, + QWidget *parent = 0, + const char *name = 0); + + QString layerName() const; + KisCompositeOp compositeOp() const; + Q_INT32 opacity() const; + KisID colorSpaceID() const; + QString profileName() const; + + void setColorSpaceEnabled(bool enabled); + +private slots: + void fillCmbProfiles(const KisID & s); + void fillCmbComposite(const KisID & s); + +private: + WdgLayerProperties * m_page; +}; + +#endif // KIS_DLG_NEW_LAYER_H_ + diff --git a/krita/ui/kis_dlg_preferences.cc b/krita/ui/kis_dlg_preferences.cc new file mode 100644 index 000000000..5522bcdf0 --- /dev/null +++ b/krita/ui/kis_dlg_preferences.cc @@ -0,0 +1,821 @@ +/* + * preferencesdlg.cc - part of KImageShop + * + * Copyright (c) 1999 Michael Koch <koch@kde.org> + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qbitmap.h> +#include <qbuttongroup.h> +#include <qcheckbox.h> +#include <qcursor.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qpixmap.h> +#include <qpushbutton.h> +#include <qslider.h> +#include <qtoolbutton.h> +#include <qvbox.h> + +#ifdef HAVE_GL +#include <qgl.h> +#endif + +#include <KoImageResource.h> + +#include <kcolorbutton.h> +#include <kcombobox.h> +#include <kfiledialog.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <knuminput.h> +#include <kurlrequester.h> + +#include "squeezedcombobox.h" +#include "kis_cmb_idlist.h" +#include "kis_colorspace.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_cursor.h" +#include "kis_config.h" +#include "kis_dlg_preferences.h" +#include "kis_factory.h" +#include "kis_id.h" +#include "kis_meta_registry.h" +#include "kis_profile.h" + +#include "kis_canvas.h" + +#include "wdgcolorsettings.h" +#include "wdgperformancesettings.h" +#include "wdggeneralsettings.h" + +// for the performance update +#include "tiles/kis_tilemanager.h" + +GeneralTab::GeneralTab( QWidget *_parent, const char *_name ) + : WdgGeneralSettings( _parent, _name ) +{ + + KisConfig cfg; + + m_cmbCursorShape->setCurrentItem(cfg.cursorStyle()); + grpDockability->setButton(cfg.dockability()); + numDockerFontSize->setValue((int)cfg.dockerFontSize()); +} + +void GeneralTab::setDefault() +{ + KisConfig cfg; + + m_cmbCursorShape->setCurrentItem( cfg.getDefaultCursorStyle()); + grpDockability->setButton(cfg.getDefaultDockability()); + numDockerFontSize->setValue((int)(cfg.getDefaultDockerFontSize())); +} + +enumCursorStyle GeneralTab::cursorStyle() +{ + return (enumCursorStyle)m_cmbCursorShape->currentItem(); +} + +enumKoDockability GeneralTab::dockability() +{ + return (enumKoDockability)grpDockability->selectedId(); +} + +float GeneralTab::dockerFontSize() +{ + return (float)numDockerFontSize->value(); +} + +//--------------------------------------------------------------------------------------------------- + +ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name ) + : QWidget(parent, name) +{ + // XXX: Make sure only profiles that fit the specified color model + // are shown in the profile combos + + QGridLayout * l = new QGridLayout( this, 1, 1, KDialog::marginHint(), KDialog::spacingHint()); + l->setMargin(0); + m_page = new WdgColorSettings(this); + l->addWidget( m_page, 0, 0); + + KisConfig cfg; + + m_page->cmbWorkingColorSpace->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys()); + m_page->cmbWorkingColorSpace->setCurrentText(cfg.workingColorSpace()); + + m_page->cmbPrintingColorSpace->setIDList(KisMetaRegistry::instance()->csRegistry()->listKeys()); + m_page->cmbPrintingColorSpace->setCurrentText(cfg.printerColorSpace()); + + refillMonitorProfiles(KisID("RGBA", "")); + refillPrintProfiles(KisID(cfg.printerColorSpace(), "")); + + if(m_page->cmbMonitorProfile->contains(cfg.monitorProfile())) + m_page->cmbMonitorProfile->setCurrentText(cfg.monitorProfile()); + if(m_page->cmbPrintProfile->contains(cfg.printerProfile())) + m_page->cmbPrintProfile->setCurrentText(cfg.printerProfile()); + m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); + m_page->grpPasteBehaviour->setButton(cfg.pasteBehaviour()); + m_page->cmbMonitorIntent->setCurrentItem(cfg.renderIntent()); + + connect(m_page->cmbPrintingColorSpace, SIGNAL(activated(const KisID &)), + this, SLOT(refillPrintProfiles(const KisID &))); +} + +void ColorSettingsTab::setDefault() +{ + m_page->cmbWorkingColorSpace->setCurrentText("RGBA"); + + m_page->cmbPrintingColorSpace->setCurrentText("CMYK"); + refillPrintProfiles(KisID("CMYK", "")); + + m_page->chkBlackpoint->setChecked(false); + m_page->cmbMonitorIntent->setCurrentItem(INTENT_PERCEPTUAL); + m_page->grpPasteBehaviour->setButton(2); +} + + +void ColorSettingsTab::refillMonitorProfiles(const KisID & s) +{ + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + + m_page->cmbMonitorProfile->clear(); + + if ( !csf ) + return; + + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + if ((*it)->deviceClass() == icSigDisplayClass) + m_page->cmbMonitorProfile->insertItem((*it)->productName()); + } + + m_page->cmbMonitorProfile->setCurrentText(csf->defaultProfile()); +} + +void ColorSettingsTab::refillPrintProfiles(const KisID & s) +{ + KisColorSpaceFactory * csf = KisMetaRegistry::instance()->csRegistry()->get(s); + + m_page->cmbPrintProfile->clear(); + + if ( !csf ) + return; + + QValueVector<KisProfile *> profileList = KisMetaRegistry::instance()->csRegistry()->profilesFor( csf ); + QValueVector<KisProfile *> ::iterator it; + for ( it = profileList.begin(); it != profileList.end(); ++it ) { + if ((*it)->deviceClass() == icSigOutputClass) + m_page->cmbPrintProfile->insertItem((*it)->productName()); + } + + m_page->cmbPrintProfile->setCurrentText(csf->defaultProfile()); +} + +//--------------------------------------------------------------------------------------------------- + +PerformanceTab::PerformanceTab(QWidget *parent, const char *name ) + : WdgPerformanceSettings(parent, name) +{ + // XXX: Make sure only profiles that fit the specified color model + // are shown in the profile combos + + KisConfig cfg; + + // it's scaled from 0 - 6, but the config is in 0 - 300 + m_swappiness->setValue(cfg.swappiness() / 50); + m_maxTiles->setValue(cfg.maxTilesInMem()); +} + +void PerformanceTab::setDefault() +{ + m_swappiness->setValue(3); + m_maxTiles->setValue(500); +} + +//--------------------------------------------------------------------------------------------------- + +TabletSettingsTab::TabletSettingsTab( QWidget *parent, const char *name) + : WdgTabletSettings( parent, name ) +{ +#ifdef EXTENDED_X11_TABLET_SUPPORT + initTabletDevices(); +#else + grpTabletDevices->hide(); +#endif +} + +void TabletSettingsTab::setDefault() +{ +} + +void TabletSettingsTab::applySettings() +{ + +#ifdef EXTENDED_X11_TABLET_SUPPORT + applyTabletDeviceSettings(); +#endif +} + +#ifdef EXTENDED_X11_TABLET_SUPPORT +TabletSettingsTab::DeviceSettings::DeviceSettings(KisCanvasWidget::X11TabletDevice *tabletDevice, bool enabled, + Q_INT32 xAxis, Q_INT32 yAxis, Q_INT32 pressureAxis, + Q_INT32 xTiltAxis, Q_INT32 yTiltAxis, Q_INT32 wheelAxis, + Q_INT32 toolIDAxis, Q_INT32 serialNumberAxis) + : m_tabletDevice(tabletDevice), + m_enabled(enabled), + m_xAxis(xAxis), + m_yAxis(yAxis), + m_pressureAxis(pressureAxis), + m_xTiltAxis(xTiltAxis), + m_yTiltAxis(yTiltAxis), + m_wheelAxis(wheelAxis), + m_toolIDAxis(toolIDAxis), + m_serialNumberAxis(serialNumberAxis) +{ +} + +TabletSettingsTab::DeviceSettings::DeviceSettings() + : m_tabletDevice(0), + m_enabled(false), + m_xAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_yAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_pressureAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_xTiltAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_yTiltAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_wheelAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_toolIDAxis(KisCanvasWidget::X11TabletDevice::NoAxis), + m_serialNumberAxis(KisCanvasWidget::X11TabletDevice::NoAxis) +{ +} + +void TabletSettingsTab::DeviceSettings::applySettings() +{ + m_tabletDevice->setEnabled(enabled()); + m_tabletDevice->setXAxis(xAxis()); + m_tabletDevice->setYAxis(yAxis()); + m_tabletDevice->setPressureAxis(pressureAxis()); + m_tabletDevice->setXTiltAxis(xTiltAxis()); + m_tabletDevice->setYTiltAxis(yTiltAxis()); + m_tabletDevice->setWheelAxis(wheelAxis()); + m_tabletDevice->setToolIDAxis(toolIDAxis()); + m_tabletDevice->setSerialNumberAxis(serialNumberAxis()); + m_tabletDevice->writeSettingsToConfig(); +} + +void TabletSettingsTab::DeviceSettings::setEnabled(bool enabled) +{ + m_enabled = enabled; +} + +bool TabletSettingsTab::DeviceSettings::enabled() const +{ + return m_enabled; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::numAxes() const +{ + return m_tabletDevice->numAxes(); +} + +void TabletSettingsTab::DeviceSettings::setXAxis(Q_INT32 axis) +{ + m_xAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setYAxis(Q_INT32 axis) +{ + m_yAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setPressureAxis(Q_INT32 axis) +{ + m_pressureAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setXTiltAxis(Q_INT32 axis) +{ + m_xTiltAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setYTiltAxis(Q_INT32 axis) +{ + m_yTiltAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setWheelAxis(Q_INT32 axis) +{ + m_wheelAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setToolIDAxis(Q_INT32 axis) +{ + m_toolIDAxis = axis; +} + +void TabletSettingsTab::DeviceSettings::setSerialNumberAxis(Q_INT32 axis) +{ + m_serialNumberAxis = axis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::xAxis() const +{ + return m_xAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::yAxis() const +{ + return m_yAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::pressureAxis() const +{ + return m_pressureAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::xTiltAxis() const +{ + return m_xTiltAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::yTiltAxis() const +{ + return m_yTiltAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::wheelAxis() const +{ + return m_wheelAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::toolIDAxis() const +{ + return m_toolIDAxis; +} + +Q_INT32 TabletSettingsTab::DeviceSettings::serialNumberAxis() const +{ + return m_serialNumberAxis; +} + +TabletSettingsTab::TabletDeviceSettingsDialog::TabletDeviceSettingsDialog(const QString& deviceName, DeviceSettings settings, + QWidget *parent, const char *name) + : super(parent, name, true, "", Ok | Cancel) +{ + setCaption(i18n("Configure %1").arg(deviceName)); + + m_page = new WdgTabletDeviceSettings(this); + + setMainWidget(m_page); + resize(m_page->sizeHint()); + + for (Q_INT32 axis = 0; axis < settings.numAxes(); axis++) { + QString axisString; + + axisString.setNum(axis); + + m_page->cbX->insertItem(axisString); + m_page->cbY->insertItem(axisString); + m_page->cbPressure->insertItem(axisString); + m_page->cbXTilt->insertItem(axisString); + m_page->cbYTilt->insertItem(axisString); + m_page->cbWheel->insertItem(axisString); +// m_page->cbToolID->insertItem(axisString); +// m_page->cbSerialNumber->insertItem(axisString); + } + + m_page->cbX->insertItem(i18n("None")); + m_page->cbY->insertItem(i18n("None")); + m_page->cbPressure->insertItem(i18n("None")); + m_page->cbXTilt->insertItem(i18n("None")); + m_page->cbYTilt->insertItem(i18n("None")); + m_page->cbWheel->insertItem(i18n("None")); +// m_page->cbToolID->insertItem(i18n("None")); +// m_page->cbSerialNumber->insertItem(i18n("None")); + + if (settings.xAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbX->setCurrentItem(settings.xAxis()); + } else { + m_page->cbX->setCurrentItem(settings.numAxes()); + } + + if (settings.yAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbY->setCurrentItem(settings.yAxis()); + } else { + m_page->cbY->setCurrentItem(settings.numAxes()); + } + + if (settings.pressureAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbPressure->setCurrentItem(settings.pressureAxis()); + } else { + m_page->cbPressure->setCurrentItem(settings.numAxes()); + } + + if (settings.xTiltAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbXTilt->setCurrentItem(settings.xTiltAxis()); + } else { + m_page->cbXTilt->setCurrentItem(settings.numAxes()); + } + + if (settings.yTiltAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbYTilt->setCurrentItem(settings.yTiltAxis()); + } else { + m_page->cbYTilt->setCurrentItem(settings.numAxes()); + } + + if (settings.wheelAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { + m_page->cbWheel->setCurrentItem(settings.wheelAxis()); + } else { + m_page->cbWheel->setCurrentItem(settings.numAxes()); + } + +// if (settings.toolIDAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { +// m_page->cbToolID->setCurrentItem(settings.toolIDAxis()); +// } else { +// m_page->cbToolID->setCurrentItem(settings.numAxes()); +// } +// +// if (settings.serialNumberAxis() != KisCanvasWidget::X11TabletDevice::NoAxis) { +// m_page->cbSerialNumber->setCurrentItem(settings.serialNumberAxis()); +// } else { +// m_page->cbSerialNumber->setCurrentItem(settings.numAxes()); +// } + + m_settings = settings; +} + +TabletSettingsTab::TabletDeviceSettingsDialog::~TabletDeviceSettingsDialog() +{ + delete m_page; +} + +TabletSettingsTab::DeviceSettings TabletSettingsTab::TabletDeviceSettingsDialog::settings() +{ + const Q_INT32 noAxis = m_settings.numAxes(); + + if (m_page->cbX->currentItem() != noAxis ) { + m_settings.setXAxis(m_page->cbX->currentItem()); + } else { + m_settings.setXAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + + if (m_page->cbY->currentItem() != noAxis ) { + m_settings.setYAxis(m_page->cbY->currentItem()); + } else { + m_settings.setYAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + + if (m_page->cbPressure->currentItem() != noAxis ) { + m_settings.setPressureAxis(m_page->cbPressure->currentItem()); + } else { + m_settings.setPressureAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + + if (m_page->cbXTilt->currentItem() != noAxis ) { + m_settings.setXTiltAxis(m_page->cbXTilt->currentItem()); + } else { + m_settings.setXTiltAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + + if (m_page->cbYTilt->currentItem() != noAxis ) { + m_settings.setYTiltAxis(m_page->cbYTilt->currentItem()); + } else { + m_settings.setYTiltAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + + if (m_page->cbWheel->currentItem() != noAxis ) { + m_settings.setWheelAxis(m_page->cbWheel->currentItem()); + } else { + m_settings.setWheelAxis(KisCanvasWidget::X11TabletDevice::NoAxis); + } + +// if (m_page->cbToolID->currentItem() != noAxis ) { +// m_settings.setToolIDAxis(m_page->cbToolID->currentItem()); +// } else { +// m_settings.setToolIDAxis(KisCanvasWidget::X11TabletDevice::NoAxis); +// } +// +// if (m_page->cbSerialNumber->currentItem() != noAxis ) { +// m_settings.setSerialNumberAxis(m_page->cbSerialNumber->currentItem()); +// } else { +// m_settings.setSerialNumberAxis(KisCanvasWidget::X11TabletDevice::NoAxis); +// } + + return m_settings; +} + +void TabletSettingsTab::initTabletDevices() +{ + connect(cbTabletDevice, SIGNAL(activated(int)), SLOT(slotActivateDevice(int))); + connect(chkEnableTabletDevice, SIGNAL(toggled(bool)), SLOT(slotSetDeviceEnabled(bool))); + connect(btnConfigureTabletDevice, SIGNAL(clicked()), SLOT(slotConfigureDevice())); + + KisCanvasWidget::X11XIDTabletDeviceMap& tabletDevices = KisCanvasWidget::tabletDeviceMap(); + + cbTabletDevice->clear(); + + if (!tabletDevices.empty()) { + KisCanvasWidget::X11XIDTabletDeviceMap::iterator it; + + for (it = tabletDevices.begin(); it != tabletDevices.end(); ++it) { + KisCanvasWidget::X11TabletDevice& device = (*it).second; + + m_deviceSettings.append(DeviceSettings(&device, device.enabled(), device.xAxis(), device.yAxis(), + device.pressureAxis(), device.xTiltAxis(), device.yTiltAxis(), device.wheelAxis(), + device.toolIDAxis(), device.serialNumberAxis())); + cbTabletDevice->insertItem(device.name()); + } + slotActivateDevice(0); + } else { + cbTabletDevice->insertItem(i18n("No devices detected")); + cbTabletDevice->setEnabled(false); + chkEnableTabletDevice->setEnabled(false); + btnConfigureTabletDevice->setEnabled(false); + } +} + +void TabletSettingsTab::slotActivateDevice(int deviceIndex) +{ + bool deviceEnabled = m_deviceSettings[deviceIndex].enabled(); + + chkEnableTabletDevice->setChecked(deviceEnabled); + slotSetDeviceEnabled(deviceEnabled); +} + +void TabletSettingsTab::slotSetDeviceEnabled(bool enabled) +{ + btnConfigureTabletDevice->setEnabled(enabled); + m_deviceSettings[cbTabletDevice->currentItem()].setEnabled(enabled); +} + +void TabletSettingsTab::slotConfigureDevice() +{ + TabletDeviceSettingsDialog dialog(cbTabletDevice->currentText(), m_deviceSettings[cbTabletDevice->currentItem()], + this, "TabletDeviceSettings"); + + if (dialog.exec() == QDialog::Accepted) + { + m_deviceSettings[cbTabletDevice->currentItem()] = dialog.settings(); + } +} + +void TabletSettingsTab::applyTabletDeviceSettings() +{ + for (Q_UINT32 deviceIndex = 0; deviceIndex < m_deviceSettings.count(); ++deviceIndex) { + m_deviceSettings[deviceIndex].applySettings(); + } +} + +#else // EXTENDED_X11_TABLET_SUPPORT + +// Fix compilation. moc seems to not see the undefined symbol needed +// for these slots to be declared. +void TabletSettingsTab::slotActivateDevice(int /*deviceIndex*/) +{ +} + +void TabletSettingsTab::slotSetDeviceEnabled(bool /*enabled*/) +{ +} + +void TabletSettingsTab::slotConfigureDevice() +{ +} + +void TabletSettingsTab::applyTabletDeviceSettings() +{ +} + +#endif + +//--------------------------------------------------------------------------------------------------- + +DisplaySettingsTab::DisplaySettingsTab( QWidget *parent, const char *name) + : WdgDisplaySettings( parent, name ) +{ +#ifdef HAVE_GL + KisConfig cfg; + + if (!QGLFormat::hasOpenGL()) { + cbUseOpenGL->setEnabled(false); + //cbUseOpenGLShaders->setEnabled(false); + } else { + cbUseOpenGL->setChecked(cfg.useOpenGL()); + //cbUseOpenGLShaders->setChecked(cfg.useOpenGLShaders()); + //cbUseOpenGLShaders->setEnabled(cfg.useOpenGL()); + } +#else + cbUseOpenGL->setEnabled(false); + //cbUseOpenGLShaders->setEnabled(false); +#endif + + connect(cbUseOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); +} + +void DisplaySettingsTab::setDefault() +{ + cbUseOpenGL->setChecked(false); + //cbUseOpenGLShaders->setChecked(false); + //cbUseOpenGLShaders->setEnabled(false); +} + +void DisplaySettingsTab::slotUseOpenGLToggled(bool /*isChecked*/) +{ + //cbUseOpenGLShaders->setEnabled(isChecked); +} + +//--------------------------------------------------------------------------------------------------- +GridSettingsTab::GridSettingsTab(QWidget* parent) : WdgGridSettingsBase(parent) +{ + KisConfig cfg; + selectMainStyle->setCurrentItem(cfg.getGridMainStyle()); + selectSubdivisionStyle->setCurrentItem(cfg.getGridSubdivisionStyle()); + +#if KDE_IS_VERSION(3,4,0) + colorMain->setDefaultColor( QColor( 99, 99, 99 ) ); + colorSubdivision->setDefaultColor( QColor( 200, 200, 200 ) ); +#endif + colorMain->setColor(cfg.getGridMainColor()); + colorSubdivision->setColor(cfg.getGridSubdivisionColor()); + + intHSpacing->setValue( cfg.getGridHSpacing() ); + intVSpacing->setValue( cfg.getGridVSpacing() ); + intSubdivision->setValue( cfg.getGridSubdivisions()); + intOffsetX->setValue( cfg.getGridOffsetX()); + intOffsetY->setValue( cfg.getGridOffsetY()); + + linkSpacingToggled(true); + connect(bnLinkSpacing, SIGNAL(toggled(bool)), this, SLOT(linkSpacingToggled( bool ))); + + connect(intHSpacing, SIGNAL(valueChanged(int)),this,SLOT(spinBoxHSpacingChanged(int))); + connect(intVSpacing, SIGNAL(valueChanged(int)),this,SLOT(spinBoxVSpacingChanged(int))); + + +} + +void GridSettingsTab::setDefault() +{ + KisConfig cfg; + selectMainStyle->setCurrentItem(0); + selectSubdivisionStyle->setCurrentItem(1); + + colorMain->setColor(QColor(99,99,99)); + colorSubdivision->setColor(QColor(199,199,199)); + + intHSpacing->setValue( 10 ); + intVSpacing->setValue( 10 ); + intSubdivision->setValue( 1 ); + intOffsetX->setValue( 0 ); + intOffsetY->setValue( 0 ); +} + +void GridSettingsTab::spinBoxHSpacingChanged(int v) +{ + if(m_linkSpacing) + { + intVSpacing->setValue(v); + } +} + +void GridSettingsTab::spinBoxVSpacingChanged(int v ) +{ + if(m_linkSpacing) + { + intHSpacing->setValue(v); + } +} + + +void GridSettingsTab::linkSpacingToggled(bool b) +{ + m_linkSpacing = b; + + KoImageResource kir; + if (b) { + bnLinkSpacing->setPixmap(kir.chain()); + } + else { + bnLinkSpacing->setPixmap(kir.chainBroken()); + } +} + + +//--------------------------------------------------------------------------------------------------- + +PreferencesDialog::PreferencesDialog( QWidget* parent, const char* name ) + : KDialogBase( IconList, i18n("Preferences"), Ok | Cancel | Help | Default /*| Apply*/, Ok, parent, name, true, true ) +{ + QVBox *vbox; + + vbox = addVBoxPage( i18n( "General"), i18n( "General"), BarIcon( "misc", KIcon::SizeMedium )); + m_general = new GeneralTab( vbox ); +#ifdef HAVE_GL + vbox = addVBoxPage ( i18n( "Display" ), i18n( "Display" ), BarIcon( "kscreensaver", KIcon::SizeMedium )); + m_displaySettings = new DisplaySettingsTab( vbox ); +#endif + vbox = addVBoxPage( i18n( "Color Management"), i18n( "Color"), BarIcon( "colorize", KIcon::SizeMedium )); + m_colorSettings = new ColorSettingsTab( vbox ); + + vbox = addVBoxPage( i18n( "Performance"), i18n( "Performance"), BarIcon( "fork", KIcon::SizeMedium )); + m_performanceSettings = new PerformanceTab ( vbox ); + + vbox = addVBoxPage ( i18n( "Tablet" ), i18n( "Tablet" ), BarIcon( "tablet", KIcon::SizeMedium )); + m_tabletSettings = new TabletSettingsTab( vbox ); + + vbox = addVBoxPage ( i18n( "Grid" ), i18n( "Grid" ), BarIcon( "grid", KIcon::SizeMedium )); + m_gridSettings = new GridSettingsTab( vbox ); + +} + +PreferencesDialog::~PreferencesDialog() +{ +} + +void PreferencesDialog::slotDefault() +{ + m_general->setDefault(); + m_colorSettings->setDefault(); + m_tabletSettings->setDefault(); + m_performanceSettings->setDefault(); +#ifdef HAVE_GL + m_displaySettings->setDefault(); +#endif + m_gridSettings->setDefault(); +} + +bool PreferencesDialog::editPreferences() +{ + PreferencesDialog* dialog; + + dialog = new PreferencesDialog(); + bool baccept = ( dialog->exec() == Accepted ); + if( baccept ) + { + KisConfig cfg; + cfg.setCursorStyle(dialog->m_general->cursorStyle()); + cfg.setDockability( dialog->m_general->dockability() ); + cfg.setDockerFontSize( dialog->m_general->dockerFontSize() ); + + // Color settings + cfg.setMonitorProfile( dialog->m_colorSettings->m_page->cmbMonitorProfile->currentText()); + cfg.setWorkingColorSpace( dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentText()); + cfg.setPrinterColorSpace( dialog->m_colorSettings->m_page->cmbPrintingColorSpace->currentText()); + cfg.setPrinterProfile( dialog->m_colorSettings->m_page->cmbPrintProfile->currentText()); + + cfg.setUseBlackPointCompensation( dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); + cfg.setPasteBehaviour( dialog->m_colorSettings->m_page->grpPasteBehaviour->selectedId()); + cfg.setRenderIntent( dialog->m_colorSettings->m_page->cmbMonitorIntent->currentItem()); + + // it's scaled from 0 - 6, but the config is in 0 - 300 + cfg.setSwappiness(dialog->m_performanceSettings->m_swappiness->value() * 50); + cfg.setMaxTilesInMem(dialog->m_performanceSettings->m_maxTiles->value()); + // let the tile manager know + KisTileManager::instance()->configChanged(); + + dialog->m_tabletSettings->applySettings(); + +#ifdef HAVE_GL + cfg.setUseOpenGL(dialog->m_displaySettings->cbUseOpenGL->isChecked()); + //cfg.setUseOpenGLShaders(dialog->m_displaySettings->cbUseOpenGLShaders->isChecked()); +#endif + + // Grid settings + cfg.setGridMainStyle( dialog->m_gridSettings->selectMainStyle->currentItem() ); + cfg.setGridSubdivisionStyle( dialog->m_gridSettings->selectSubdivisionStyle->currentItem() ); + + cfg.setGridMainColor( dialog->m_gridSettings->colorMain->color() ); + cfg.setGridSubdivisionColor(dialog->m_gridSettings->colorSubdivision->color() ); + + cfg.setGridHSpacing( dialog->m_gridSettings->intHSpacing->value( )); + cfg.setGridVSpacing( dialog->m_gridSettings->intVSpacing->value( )); + cfg.setGridSubdivisions( dialog->m_gridSettings->intSubdivision->value( )); + cfg.setGridOffsetX( dialog->m_gridSettings->intOffsetX->value( )); + cfg.setGridOffsetY( dialog->m_gridSettings->intOffsetY->value( )); + + } + delete dialog; + return baccept; +} + +#include "kis_dlg_preferences.moc" diff --git a/krita/ui/kis_dlg_preferences.h b/krita/ui/kis_dlg_preferences.h new file mode 100644 index 000000000..2d79826b3 --- /dev/null +++ b/krita/ui/kis_dlg_preferences.h @@ -0,0 +1,270 @@ +/* + * preferencesdlg.h - part of KImageShop^WKrita + * + * Copyright (c) 1999 Michael Koch <koch@kde.org> + * + * 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 __preferencesdlg_h__ +#define __preferencesdlg_h__ + +#include <qwidget.h> + +#include <kdialogbase.h> + +#include <kopalettemanager.h> + +#include "kis_canvas.h" + +#include "wdggeneralsettings.h" +#include "wdgtabletsettings.h" +#include "wdgtabletdevicesettings.h" +#include "wdgperformancesettings.h" +#include "wdgdisplaysettings.h" +#include "wdggridsettings.h" + +class QLineEdit; +class QCheckBox; +class KURLRequester; +class WdgColorSettings; +class KisCmbIDList; +class KisID; + +/** + * "General"-tab for preferences dialog + */ +class GeneralTab : public WdgGeneralSettings +{ + Q_OBJECT + +public: + + GeneralTab( QWidget *parent = 0, const char *name = 0 ); + + enumCursorStyle cursorStyle(); + enumKoDockability dockability(); + float dockerFontSize(); + + void setDefault(); + +}; + +//======================= + +class ColorSettingsTab : public QWidget +{ + Q_OBJECT + +public: + + ColorSettingsTab( QWidget *parent = 0, const char * name = 0 ); + +private slots: + + void refillMonitorProfiles(const KisID & s); + void refillPrintProfiles(const KisID & s); + +public: + void setDefault(); + WdgColorSettings * m_page; +}; + + +/** + * "Performance"-tab for preferences dialog + */ +class PerformanceTab : public WdgPerformanceSettings +{ +Q_OBJECT + +public: + PerformanceTab( QWidget *parent = 0, const char *name = 0 ); + +public: + void setDefault(); +}; + +//======================= + + +/** + * Tablet settings tab for preferences dialog + */ +class TabletSettingsTab : public WdgTabletSettings +{ +Q_OBJECT + +public: + TabletSettingsTab( QWidget *parent = 0, const char *name = 0 ); + +public: + void setDefault(); + void applySettings(); + +private slots: + void slotActivateDevice(int deviceIndex); + void slotSetDeviceEnabled(bool enabled); + void slotConfigureDevice(); + void applyTabletDeviceSettings(); + +#ifdef EXTENDED_X11_TABLET_SUPPORT + +private: + class DeviceSettings { + public: + DeviceSettings(KisCanvasWidget::X11TabletDevice *tabletDevice, bool enabled, + Q_INT32 xAxis, Q_INT32 yAxis, Q_INT32 pressureAxis, + Q_INT32 xTiltAxis, Q_INT32 yTiltAxis, Q_INT32 wheelAxis, + Q_INT32 toolIDAxis, Q_INT32 serialNumberAxis); + DeviceSettings(); + + void applySettings(); + + void setEnabled(bool enabled); + bool enabled() const; + + Q_INT32 numAxes() const; + + void setXAxis(Q_INT32 axis); + void setYAxis(Q_INT32 axis); + void setPressureAxis(Q_INT32 axis); + void setXTiltAxis(Q_INT32 axis); + void setYTiltAxis(Q_INT32 axis); + void setWheelAxis(Q_INT32 axis); + void setToolIDAxis(Q_INT32 axis); + void setSerialNumberAxis(Q_INT32 axis); + + Q_INT32 xAxis() const; + Q_INT32 yAxis() const; + Q_INT32 pressureAxis() const; + Q_INT32 xTiltAxis() const; + Q_INT32 yTiltAxis() const; + Q_INT32 wheelAxis() const; + Q_INT32 toolIDAxis() const; + Q_INT32 serialNumberAxis() const; + + private: + KisCanvasWidget::X11TabletDevice *m_tabletDevice; + + bool m_enabled; + Q_INT32 m_xAxis; + Q_INT32 m_yAxis; + Q_INT32 m_pressureAxis; + Q_INT32 m_xTiltAxis; + Q_INT32 m_yTiltAxis; + Q_INT32 m_wheelAxis; + Q_INT32 m_toolIDAxis; + Q_INT32 m_serialNumberAxis; + }; + + class TabletDeviceSettingsDialog : public KDialogBase { + typedef KDialogBase super; + + public: + TabletDeviceSettingsDialog(const QString& deviceName, + DeviceSettings settings, + QWidget *parent = 0, + const char *name = 0); + virtual ~TabletDeviceSettingsDialog(); + + DeviceSettings settings(); + + private: + WdgTabletDeviceSettings *m_page; + DeviceSettings m_settings; + }; + + void initTabletDevices(); + + QValueVector<DeviceSettings> m_deviceSettings; +#endif +}; + +//======================= + + +/** + * Display settings tab for preferences dialog + */ +class DisplaySettingsTab : public WdgDisplaySettings +{ +Q_OBJECT + +public: + DisplaySettingsTab( QWidget *parent = 0, const char *name = 0 ); + +public: + void setDefault(); +protected slots: + void slotUseOpenGLToggled(bool isChecked); +}; + +//======================= + + +/** + * Grid settings tab for preferences dialog + */ +class GridSettingsTab : public WdgGridSettingsBase { + Q_OBJECT + public: + GridSettingsTab(QWidget* parent); + public: + void setDefault(); + private slots: + void linkSpacingToggled(bool); + void spinBoxHSpacingChanged(int ); + void spinBoxVSpacingChanged(int ); + private: + bool m_linkSpacing; +}; + +//======================= + + +/** + * Preferences dialog of KImageShop^WKrayon^WKrita + */ +class PreferencesDialog : public KDialogBase +{ + Q_OBJECT + +public: + + static bool editPreferences(); + + +protected: + + PreferencesDialog( QWidget *parent = 0, const char *name = 0 ); + ~PreferencesDialog(); + +protected: + + GeneralTab* m_general; + ColorSettingsTab* m_colorSettings; + PerformanceTab* m_performanceSettings; + TabletSettingsTab * m_tabletSettings; + DisplaySettingsTab * m_displaySettings; + GridSettingsTab* m_gridSettings; + +protected slots: + + void slotDefault(); + +}; + +#endif diff --git a/krita/ui/kis_doc.cc b/krita/ui/kis_doc.cc new file mode 100644 index 000000000..7ae27bde3 --- /dev/null +++ b/krita/ui/kis_doc.cc @@ -0,0 +1,1171 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2000 John Califf <jcaliff@compuzone.net> + * Copyright (c) 2001 Toshitaka Fujioka <fujioka@kde.org> + * Copyright (c) 2002, 2003 Patrick Julien <freak@codepimps.org> + * + * 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. + */ + +// Qt +#include <qapplication.h> +#include <qdom.h> +#include <qimage.h> +#include <qpainter.h> +#include <qtl.h> +#include <qstringlist.h> +#include <qwidget.h> +#include <qpaintdevicemetrics.h> + +// KDE +#include <dcopobject.h> +#include <kapplication.h> +#include <kcommand.h> +#include <kdebug.h> +#include <kimageio.h> +#include <kfiledialog.h> +#include <kglobal.h> +#include <kmimetype.h> +#include <knotifyclient.h> +#include <klocale.h> +#include <kmessagebox.h> + +// KOffice +#include <KoFilterManager.h> +#include <KoMainWindow.h> +#include <KoQueryTrader.h> +#include <KoStore.h> +#include <KoStoreDevice.h> +#include <KoTemplateChooseDia.h> +#include <KoApplication.h> +#include <KoCommandHistory.h> + +// Local +#include <kis_clipboard.h> +#include <kis_meta_registry.h> +#include "kis_annotation.h" +#include "kis_types.h" +#include "kis_config.h" +#include "kis_debug_areas.h" +#include "kis_doc.h" +#include "kis_factory.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_paint_layer.h" +#include "kis_nameserver.h" +#include "kis_painter.h" +#include "kis_selection.h" +#include "kis_fill_painter.h" +#include "kis_command.h" +#include "kis_view.h" +#include "kis_colorspace.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_profile.h" +#include "kis_id.h" +#include "kis_part_layer.h" +#include "kis_doc_iface.h" +#include "kis_paint_device_action.h" +#include "kis_custom_image_widget.h" +#include "kis_load_visitor.h" +#include "kis_save_visitor.h" +#include "kis_savexml_visitor.h" + +static const char *CURRENT_DTD_VERSION = "1.3"; + +/** + * Mime type for this app - not same as file type, but file types + * can be associated with a mime type and are opened with applications + * associated with the same mime type + */ +#define APP_MIMETYPE "application/x-krita" + +/** + * Mime type for native file format + */ +#define NATIVE_MIMETYPE "application/x-kra" + +namespace { + class KisCommandImageMv : public KisCommand { + typedef KisCommand super; + + public: + KisCommandImageMv(KisDoc *doc, + KisUndoAdapter *adapter, + const QString& name, + const QString& oldName) : super(i18n("Rename Image"), adapter) + { + m_doc = doc; + m_name = name; + m_oldName = oldName; + } + + virtual ~KisCommandImageMv() + { + } + + virtual void execute() + { + adapter()->setUndo(false); + m_doc->renameImage(m_oldName, m_name); + adapter()->setUndo(true); + } + + virtual void unexecute() + { + adapter()->setUndo(false); + m_doc->renameImage(m_name, m_oldName); + adapter()->setUndo(true); + } + + private: + KisDoc *m_doc; + QString m_name; + QString m_oldName; + }; + +} + +KisDoc::KisDoc(QWidget *parentWidget, const char *widgetName, QObject *parent, const char *name, bool singleViewMode) : + super(parentWidget, widgetName, parent, name, singleViewMode) +{ + + m_undo = false; + m_dcop = 0; + m_cmdHistory = 0; + m_nserver = 0; + m_currentImage = 0; + m_currentMacro = 0; + m_macroNestDepth = 0; + m_ioProgressBase = 0; + m_ioProgressTotalSteps = 0; + + setInstance( KisFactory::instance(), false ); + setTemplateType( "krita_template" ); + + init(); + + if (name) + dcopObject(); +} + +KisDoc::~KisDoc() +{ + delete m_cmdHistory; + delete m_nserver; + m_undoListeners.setAutoDelete(false); + delete m_dcop; +} + +QCString KisDoc::mimeType() const +{ + return APP_MIMETYPE; +} + +DCOPObject *KisDoc::dcopObject() +{ + if (!m_dcop) { + m_dcop = new KisDocIface(this); + Q_CHECK_PTR(m_dcop); + } + return m_dcop; +} + +bool KisDoc::initDoc(InitDocFlags flags, QWidget* parentWidget) +{ + if (!init()) + return false; + + bool ok = false; + + QString file; + KoTemplateChooseDia::DialogType dlgtype; + + if (flags != KoDocument::InitDocFileNew) { + dlgtype = KoTemplateChooseDia::Everything; + } else { + dlgtype = KoTemplateChooseDia::OnlyTemplates; + } + + KoTemplateChooseDia::ReturnType ret = + KoTemplateChooseDia::choose(KisFactory::instance(), + file, + dlgtype, + "krita_template", + parentWidget); + setUndo(false); + + if (ret == KoTemplateChooseDia::Template) { + resetURL(); + ok = loadNativeFormat( file ); + setEmpty(); + ok = true; + + } else if (ret == KoTemplateChooseDia::File) { + KURL url( file ); + ok = openURL(url); + } else if (ret == KoTemplateChooseDia::Empty) { + setEmpty(); + ok = true; + } + + setModified(false); + KisConfig cfg; + setUndo(cfg.undoEnabled()); + + return ok; +} + +void KisDoc::openExistingFile(const QString& file) +{ + setUndo(false); + + KoDocument::openExistingFile(file); + + setUndo(true); +} + +void KisDoc::openTemplate(const QString& file) +{ + setUndo(false); + + KoDocument::openTemplate(file); + + setUndo(true); +} + +bool KisDoc::init() +{ + if (m_cmdHistory) { + delete m_cmdHistory; + m_cmdHistory = 0; + } + + if (m_nserver) { + delete m_nserver; + m_nserver = 0; + } + + m_cmdHistory = new KoCommandHistory(actionCollection(), true); + Q_CHECK_PTR(m_cmdHistory); + + connect(m_cmdHistory, SIGNAL(documentRestored()), this, SLOT(slotDocumentRestored())); + connect(m_cmdHistory, SIGNAL(commandExecuted(KCommand *)), this, SLOT(slotCommandExecuted(KCommand *))); + setUndo(true); + + m_nserver = new KisNameServer(i18n("Image %1"), 1); + Q_CHECK_PTR(m_nserver); + + if (!KisMetaRegistry::instance()->csRegistry()->exists(KisID("RGBA",""))) { + KMessageBox::sorry(0, i18n("No colorspace modules loaded: cannot run Krita")); + return false; + } + + m_undoListeners.setAutoDelete(false); + + return true; +} + +QDomDocument KisDoc::saveXML() +{ + QDomDocument doc = createDomDocument("DOC", CURRENT_DTD_VERSION); + QDomElement root = doc.documentElement(); + + root.setAttribute("editor", "Krita"); + root.setAttribute("depth", sizeof(Q_UINT8)); + root.setAttribute("syntaxVersion", "1"); + + root.appendChild(saveImage(doc, m_currentImage)); + + return doc; +} + +bool KisDoc::loadOasis( const QDomDocument&, KoOasisStyles&, const QDomDocument&, KoStore* ) +{ + //XXX: todo (and that includes defining an OASIS format for layered 2D raster data!) + return false; +} + + +bool KisDoc::saveOasis( KoStore*, KoXmlWriter* ) +{ + //XXX: todo (and that includes defining an OASIS format for layered 2D raster data!) + return false; +} + +bool KisDoc::loadXML(QIODevice *, const QDomDocument& doc) +{ + QDomElement root; + QString attr; + QDomNode node; + KisImageSP img; + + if (!init()) + return false; + if (doc.doctype().name() != "DOC") + return false; + root = doc.documentElement(); + attr = root.attribute("syntaxVersion"); + if (attr.toInt() > 1) + return false; + if ((attr = root.attribute("depth")).isNull()) + return false; + m_conversionDepth = attr.toInt(); + + if (!root.hasChildNodes()) { + return false; // XXX used to be: return slotNewImage(); + } + + setUndo(false); + + for (node = root.firstChild(); !node.isNull(); node = node.nextSibling()) { + if (node.isElement()) { + if (node.nodeName() == "IMAGE") { + QDomElement elem = node.toElement(); + if (!(img = loadImage(elem))) + return false; + m_currentImage = img; + } else { + return false; + } + } + } + + emit loadingFinished(); + return true; +} + +bool KisDoc::loadChildren(KoStore* store) { + QPtrListIterator<KoDocumentChild> it(children()); + for( ; it.current(); ++it ) { + if (!it.current()->loadDocument(store)) { + return false; + } + } + return true; +} + +QDomElement KisDoc::saveImage(QDomDocument& doc, KisImageSP img) +{ + QDomElement image = doc.createElement("IMAGE"); + + Q_ASSERT(img); + image.setAttribute("name", img->name()); + image.setAttribute("mime", "application/x-kra"); + image.setAttribute("width", img->width()); + image.setAttribute("height", img->height()); + image.setAttribute("colorspacename", img->colorSpace()->id().id()); + image.setAttribute("description", img->description()); + // XXX: Save profile as blob inside the image, instead of the product name. + if (img->getProfile() && img->getProfile()-> valid()) + image.setAttribute("profile", img->getProfile()->productName()); + image.setAttribute("x-res", img->xRes()); + image.setAttribute("y-res", img->yRes()); + + Q_UINT32 count=0; + KisSaveXmlVisitor visitor(doc, image, count, true); + + m_currentImage->rootLayer()->accept(visitor); + + return image; +} + +KisImageSP KisDoc::loadImage(const QDomElement& element) +{ + + KisConfig cfg; + QString attr; + QDomNode node; + QDomNode child; + KisImageSP img; + QString name; + Q_INT32 width; + Q_INT32 height; + QString description; + QString profileProductName; + double xres; + double yres; + QString colorspacename; + KisColorSpace * cs; + + if ((attr = element.attribute("mime")) == NATIVE_MIMETYPE) { + if ((name = element.attribute("name")).isNull()) + return 0; + if ((attr = element.attribute("width")).isNull()) + return 0; + width = attr.toInt(); + if ((attr = element.attribute("height")).isNull()) + return 0; + height = attr.toInt(); + + description = element.attribute("description"); + + if ((attr = element.attribute("x-res")).isNull()) + xres = 100.0; + xres = attr.toDouble(); + + if ((attr = element.attribute("y-res")).isNull()) + yres = 100.0; + yres = attr.toDouble(); + + if ((colorspacename = element.attribute("colorspacename")).isNull()) + { + // An old file: take a reasonable default. + // Krita didn't support anything else in those + // days anyway. + colorspacename = "RGBA"; + } + + // A hack for an old colorspacename + if (colorspacename == "Grayscale + Alpha") + colorspacename = "GRAYA"; + + if ((profileProductName = element.attribute("profile")).isNull()) { + // no mention of profile so get default profile + cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename,""); + } + else { + cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename, profileProductName); + } + + if (cs == 0) { + kdWarning(DBG_AREA_FILE) << "Could not open colorspace\n"; + return 0; + } + + img = new KisImage(this, width, height, cs, name); + img->blockSignals(true); // Don't send out signals while we're building the image + Q_CHECK_PTR(img); + connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() )); + img->setDescription(description); + img->setResolution(xres, yres); + + loadLayers(element, img, img->rootLayer().data()); + + } + + img->notifyImageLoaded(); + + return img; +} + +void KisDoc::loadLayers(const QDomElement& element, KisImageSP img, KisGroupLayerSP parent) +{ + QDomNode node = element.firstChild(); + QDomNode child; + + if(!node.isNull()) + { + if (node.isElement()) { + if (node.nodeName() == "LAYERS") { + for (child = node.firstChild(); !child.isNull(); child = child.nextSibling()) { + KisLayerSP layer = loadLayer(child.toElement(), img); + + if (!layer) { + kdWarning(DBG_AREA_FILE) << "Could not load layer\n"; + } + else { + img->nextLayerName(); // Make sure the nameserver is current with the number of layers. + img->addLayer(layer, parent, 0); + } + } + } + } + } +} + +KisLayerSP KisDoc::loadLayer(const QDomElement& element, KisImageSP img) +{ + // Nota bene: If you add new properties to layers, you should + // ALWAYS define a default value in case the property is not + // present in the layer definition: this helps a LOT with backward + // compatibilty. + QString attr; + QString name; + Q_INT32 x; + Q_INT32 y; + Q_INT32 opacity; + bool visible; + bool locked; + + if ((name = element.attribute("name")).isNull()) + return 0; + + if ((attr = element.attribute("x")).isNull()) + return 0; + x = attr.toInt(); + + if ((attr = element.attribute("y")).isNull()) + return 0; + + y = attr.toInt(); + + if ((attr = element.attribute("opacity")).isNull()) + return 0; + + if ((opacity = attr.toInt()) < 0 || opacity > Q_UINT8_MAX) + opacity = OPACITY_OPAQUE; + + + QString compositeOpName = element.attribute("compositeop"); + KisCompositeOp compositeOp; + + if (compositeOpName.isNull()) { + compositeOp = COMPOSITE_OVER; + } else { + compositeOp = KisCompositeOp(compositeOpName); + } + + if (!compositeOp.isValid()) { + return 0; + } + + if ((attr = element.attribute("visible")).isNull()) + attr = "1"; + + visible = attr == "0" ? false : true; + + if ((attr = element.attribute("locked")).isNull()) + attr = "0"; + + locked = attr == "0" ? false : true; + + // Now find out the layer type and do specific handling + if ((attr = element.attribute("layertype")).isNull()) + return loadPaintLayer(element, img, name, x, y, opacity, visible, locked, compositeOp) ; + + if(attr == "paintlayer") + return loadPaintLayer(element, img, name, x, y, opacity, visible, locked, compositeOp); + + if(attr == "grouplayer") + return loadGroupLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data(); + + if(attr == "adjustmentlayer") + return loadAdjustmentLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data(); + + if(attr == "partlayer") + return loadPartLayer(element, img, name, x, y, opacity, visible, locked, compositeOp).data(); + + kdWarning(DBG_AREA_FILE) << "Specified layertype is not recognised\n"; + return 0; +} + + +KisLayerSP KisDoc::loadPaintLayer(const QDomElement& element, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, + Q_INT32 opacity, bool visible, bool locked, KisCompositeOp compositeOp) +{ + QString attr; + KisPaintLayerSP layer; + KisColorSpace * cs; + + QString colorspacename; + QString profileProductName; + + if ((colorspacename = element.attribute("colorspacename")).isNull()) + cs = img->colorSpace(); + else + // use default profile - it will be replaced later in completLoading + cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(colorspacename,""); + + layer = new KisPaintLayer(img, name, opacity, cs); + Q_CHECK_PTR(layer); + + layer->setCompositeOp(compositeOp); + layer->setVisible(visible); + layer->setLocked(locked); + layer->setX(x); + layer->setY(y); + + if ((element.attribute("filename")).isNull()) + m_layerFilenames[layer.data()] = name; + else + m_layerFilenames[layer.data()] = QString(element.attribute("filename")); + + if ((attr = element.attribute("hasmask")).isNull()) + attr = "0"; + + if (attr == "1") { + // We add a mask, but we'll fill in the actual mask later in completeLoading with the visitor + layer->createMask(); + } + + + // Load exif info + for( QDomNode node = element.firstChild(); !node.isNull(); node = node.nextSibling() ) + { + QDomElement e = node.toElement(); + if ( !e.isNull() && e.tagName() == "ExifInfo" ) + { + layer->paintDevice()->exifInfo()->load(e); + } + } + return layer.data(); +} + +KisGroupLayerSP KisDoc::loadGroupLayer(const QDomElement& element, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked, + KisCompositeOp compositeOp) +{ + QString attr; + KisGroupLayerSP layer; + + layer = new KisGroupLayer(img, name, opacity); + Q_CHECK_PTR(layer); + + layer->setCompositeOp(compositeOp); + layer->setVisible(visible); + layer->setLocked(locked); + layer->setX(x); + layer->setY(y); + + loadLayers(element, img, layer); + + return layer; +} + +KisAdjustmentLayerSP KisDoc::loadAdjustmentLayer(const QDomElement& element, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked, + KisCompositeOp compositeOp) +{ + QString attr; + KisAdjustmentLayerSP layer; + QString filtername; + + if ((filtername = element.attribute("filtername")).isNull()) { + // XXX: Invalid adjustmentlayer! We should warn about it! + kdWarning(DBG_AREA_FILE) << "No filter in adjustment layer" << endl; + return 0; + } + + KisFilter * f = KisFilterRegistry::instance()->get(filtername); + if (!f) { + kdWarning(DBG_AREA_FILE) << "No filter for filtername " << filtername << "\n"; + return 0; // XXX: We don't have this filter. We should warn about it! + } + + KisFilterConfiguration * kfc = f->configuration(); + + // We'll load the configuration and the selection later. + layer = new KisAdjustmentLayer(img, name, kfc, 0); + Q_CHECK_PTR(layer); + + layer->setCompositeOp(compositeOp); + layer->setVisible(visible); + layer->setLocked(locked); + layer->setX(x); + layer->setY(y); + layer->setOpacity(opacity); + + if ((element.attribute("filename")).isNull()) + m_layerFilenames[layer.data()] = name; + else + m_layerFilenames[layer.data()] = QString(element.attribute("filename")); + + return layer; +} + +KisPartLayerSP KisDoc::loadPartLayer(const QDomElement& element, KisImageSP img, + QString name, Q_INT32 /*x*/, Q_INT32 /*y*/, Q_INT32 opacity, + bool visible, bool locked, + KisCompositeOp compositeOp) { + KisChildDoc* child = new KisChildDoc(this); + QString filename(element.attribute("filename")); + QDomElement partElement = element.namedItem("object").toElement(); + + if (partElement.isNull()) { + kdWarning() << "loadPartLayer failed with partElement isNull" << endl; + return 0; + } + + child->load(partElement); + insertChild(child); + + KisPartLayerSP layer = new KisPartLayerImpl(img, child); + Q_CHECK_PTR(layer); + + layer->setCompositeOp(compositeOp); + layer->setVisible(visible); + layer->setLocked(locked); + layer->setOpacity(opacity); + layer->setName(name); + + return layer; +} + +bool KisDoc::completeSaving(KoStore *store) +{ + QString uri = url().url(); + QString location; + bool external = isStoredExtern(); + Q_INT32 totalSteps = 0; + + if (!m_currentImage) return false; + + totalSteps = (m_currentImage)->nlayers(); + + + setIOSteps(totalSteps + 1); + + // Save the layers data + Q_UINT32 count=0; + KisSaveVisitor visitor(m_currentImage, store, count); + + if(external) + visitor.setExternalUri(uri); + + m_currentImage->rootLayer()->accept(visitor); + + // saving annotations + // XXX this only saves EXIF and ICC info. This would probably need + // a redesign of the dtd of the krita file to do this more generally correct + // e.g. have <ANNOTATION> tags or so. + KisAnnotationSP annotation = (m_currentImage)->annotation("exif"); + if (annotation) { + location = external ? QString::null : uri; + location += (m_currentImage)->name() + "/annotations/exif"; + if (store->open(location)) { + store->write(annotation->annotation()); + store->close(); + } + } + if (m_currentImage->getProfile()) { + annotation = m_currentImage->getProfile()->annotation(); + + if (annotation) { + location = external ? QString::null : uri; + location += m_currentImage->name() + "/annotations/icc"; + if (store->open(location)) { + store->write(annotation->annotation()); + store->close(); + } + } + } + + IODone(); + return true; +} + +bool KisDoc::completeLoading(KoStore *store) +{ + QString uri = url().url(); + QString location; + bool external = isStoredExtern(); + Q_INT32 totalSteps = 0; + + totalSteps = (m_currentImage)->nlayers(); + + setIOSteps(totalSteps); + + // Load the layers data + KisLoadVisitor visitor(m_currentImage, store, m_layerFilenames); + + if(external) + visitor.setExternalUri(uri); + + m_currentImage->rootLayer()->accept(visitor); + + // annotations + // exif + location = external ? QString::null : uri; + location += (m_currentImage)->name() + "/annotations/exif"; + if (store->hasFile(location)) { + QByteArray data; + store->open(location); + data = store->read(store->size()); + store->close(); + (m_currentImage)->addAnnotation(new KisAnnotation("exif", "", data)); + } + // icc profile + location = external ? QString::null : uri; + location += (m_currentImage)->name() + "/annotations/icc"; + if (store->hasFile(location)) { + QByteArray data; + store->open(location); + data = store->read(store->size()); + store->close(); + (m_currentImage)->setProfile(new KisProfile(data)); + } + + IODone(); + + setModified( false ); + setUndo(true); + return true; +} + +QWidget* KisDoc::createCustomDocumentWidget(QWidget *parent) +{ + + KisConfig cfg; + + int w = cfg.defImgWidth(); + int h = cfg.defImgHeight(); + + QSize sz = KisClipboard::instance()->clipSize(); + if (sz.isValid() && sz.width() != 0 && sz.height() != 0) { + w = sz.width(); + h = sz.height(); + } + return new KisCustomImageWidget(parent, this, w, h, cfg.defImgResolution(), cfg.workingColorSpace(),"unnamed"); +} + + +KoDocument* KisDoc::hitTest(const QPoint &pos, const QWMatrix& matrix) { + KoDocument* doc = super::hitTest(pos, matrix); + if (doc && doc != this) { + // We hit a child document. We will only acknowledge we hit it, if the hit child + // is the currently active parts layer. + KisPartLayerImpl* partLayer + = dynamic_cast<KisPartLayerImpl*>(currentImage()->activeLayer().data()); + + if (!partLayer) + return this; + + if (doc == partLayer->childDoc()->document()) { + return doc; + } + return this; + } + return doc; +} + +void KisDoc::renameImage(const QString& oldName, const QString& newName) +{ + (m_currentImage)->setName(newName); + + if (undo()) + addCommand(new KisCommandImageMv(this, this, newName, oldName)); +} + + +KisImageSP KisDoc::newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * colorstrategy) +{ + if (!init()) + return 0; + + setUndo(false); + + KisImageSP img = new KisImage(this, width, height, colorstrategy, name); + Q_CHECK_PTR(img); + connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() )); + + KisPaintLayer *layer = new KisPaintLayer(img, img->nextLayerName(), OPACITY_OPAQUE,colorstrategy); + Q_CHECK_PTR(layer); + + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8(); + KisFillPainter painter; + + painter.begin(layer->paintDevice()); + painter.fillRect(0, 0, width, height, KisColor(Qt::white, cs), OPACITY_OPAQUE); + painter.end(); + + img->addLayer(layer, img->rootLayer(), 0); + img->activate(layer); + + m_currentImage = img; + + setUndo(true); + + return img; +} + +bool KisDoc::newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * cs, const KisColor &bgColor, const QString &imgDescription, const double imgResolution) +{ + if (!init()) + return false; + + KisConfig cfg; + + Q_UINT8 opacity = OPACITY_OPAQUE;//bgColor.getAlpha(); + KisImageSP img; + KisPaintLayer *layer; + + if (!cs) return false; + + setUndo(false); + + img = new KisImage(this, width, height, cs, name); + Q_CHECK_PTR(img); + connect( img, SIGNAL( sigImageModified() ), this, SLOT( slotImageUpdated() )); + img->setResolution(imgResolution, imgResolution); + img->setDescription(imgDescription); + img->setProfile(cs->getProfile()); + + layer = new KisPaintLayer(img, img->nextLayerName(), OPACITY_OPAQUE, cs); + Q_CHECK_PTR(layer); + + KisFillPainter painter; + painter.begin(layer->paintDevice()); + painter.fillRect(0, 0, width, height, bgColor, opacity); + painter.end(); + + QValueVector<KisPaintDeviceAction *> actions = KisMetaRegistry::instance() -> + csRegistry()->paintDeviceActionsFor(cs); + for (uint i = 0; i < actions.count(); i++) + actions.at(i)->act(layer->paintDevice(), img->width(), img->height()); + + img->setBackgroundColor(bgColor); + img->addLayer(layer, img->rootLayer(), 0); + img->activate(layer); + + m_currentImage = img; + + cfg.defImgWidth(width); + cfg.defImgHeight(height); + cfg.defImgResolution(imgResolution); + + setUndo(true); + + return true; +} + +KoView* KisDoc::createViewInstance(QWidget* parent, const char *name) +{ + KisView * v = new KisView(this, this, parent, name); + Q_CHECK_PTR(v); + + return v; +} + +void KisDoc::paintContent(QPainter& painter, const QRect& rc, bool transparent, double zoomX, double zoomY) +{ + KisConfig cfg; + QString monitorProfileName = cfg.monitorProfile(); + KisProfile * profile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName); + painter.scale(zoomX, zoomY); + QRect rect = rc & m_currentImage->bounds(); + KisImage::PaintFlags paintFlags; + if (transparent) { + paintFlags = KisImage::PAINT_SELECTION; + } else { + paintFlags = (KisImage::PaintFlags)(KisImage::PAINT_BACKGROUND|KisImage::PAINT_SELECTION); + } + + paintFlags = (KisImage::PaintFlags)(paintFlags | KisImage::PAINT_EMBEDDED_RECT); + + m_currentImage->renderToPainter(rect.left(), rect.top(), rect.right(), rect.bottom(), painter, profile, paintFlags); +} + +void KisDoc::slotImageUpdated() +{ + emit docUpdated(); + setModified(true); +} + +void KisDoc::slotImageUpdated(const QRect& rect) +{ + emit docUpdated(rect); +} + +void KisDoc::beginMacro(const QString& macroName) +{ + if (m_undo) { + if (m_macroNestDepth == 0) { + Q_ASSERT(m_currentMacro == 0); + m_currentMacro = new KMacroCommand(macroName); + Q_CHECK_PTR(m_currentMacro); + } + + m_macroNestDepth++; + } +} + +void KisDoc::endMacro() +{ + if (m_undo) { + Q_ASSERT(m_macroNestDepth > 0); + if (m_macroNestDepth > 0) { + m_macroNestDepth--; + + if (m_macroNestDepth == 0) { + Q_ASSERT(m_currentMacro != 0); + + m_cmdHistory->addCommand(m_currentMacro, false); + m_currentMacro = 0; + emit sigCommandExecuted(); + } + } + } +} + +void KisDoc::setCommandHistoryListener(const KisCommandHistoryListener * l) +{ + // Never have more than one instance of a listener around. Qt should prove a Set class for this... + m_undoListeners.removeRef(l); + m_undoListeners.append(l); +} + +void KisDoc::removeCommandHistoryListener(const KisCommandHistoryListener * l) +{ + m_undoListeners.removeRef(l); +} + +KCommand * KisDoc::presentCommand() +{ + return m_cmdHistory->presentCommand(); +} + +void KisDoc::addCommand(KCommand *cmd) +{ + Q_ASSERT(cmd); + + KisCommandHistoryListener* l = 0; + + for (l = m_undoListeners.first(); l; l = m_undoListeners.next()) { + l->notifyCommandAdded(cmd); + } + + setModified(true); + + if (m_undo) { + if (m_currentMacro) + m_currentMacro->addCommand(cmd); + else { + m_cmdHistory->addCommand(cmd, false); + emit sigCommandExecuted(); + } + } else { + kdDebug() << "Deleting command\n"; + delete cmd; + } +} + +void KisDoc::setUndo(bool undo) +{ + m_undo = undo; + if (m_undo && m_cmdHistory->undoLimit() == 50 /*default*/) { + KisConfig cfg; + setUndoLimit( cfg.defUndoLimit() ); + } +} + +Q_INT32 KisDoc::undoLimit() const +{ + return m_cmdHistory->undoLimit(); +} + +void KisDoc::setUndoLimit(Q_INT32 limit) +{ + m_cmdHistory->setUndoLimit(limit); +} + +Q_INT32 KisDoc::redoLimit() const +{ + return m_cmdHistory->redoLimit(); +} + +void KisDoc::setRedoLimit(Q_INT32 limit) +{ + m_cmdHistory->setRedoLimit(limit); +} + +void KisDoc::slotDocumentRestored() +{ + setModified(false); +} + +void KisDoc::slotCommandExecuted(KCommand *command) +{ + setModified(true); + emit sigCommandExecuted(); + + KisCommandHistoryListener* l = 0; + + for (l = m_undoListeners.first(); l; l = m_undoListeners.next()) { + l->notifyCommandExecuted(command); + } + +} + +void KisDoc::slotUpdate(KisImageSP, Q_UINT32 x, Q_UINT32 y, Q_UINT32 w, Q_UINT32 h) +{ + QRect rc(x, y, w, h); + + emit docUpdated(rc); +} + +bool KisDoc::undo() const +{ + return m_undo; +} + +void KisDoc::setIOSteps(Q_INT32 nsteps) +{ + m_ioProgressTotalSteps = nsteps * 100; + m_ioProgressBase = 0; + emitProgress(0); +} + +void KisDoc::IOCompletedStep() +{ + m_ioProgressBase += 100; +} + +void KisDoc::IODone() +{ + emitProgress(-1); +} + +void KisDoc::slotIOProgress(Q_INT8 percentage) +{ + KApplication *app = KApplication::kApplication(); + + Q_ASSERT(app); + + if (app->hasPendingEvents()) + app->processEvents(); + + int totalPercentage = ((m_ioProgressBase + percentage) * 100) / m_ioProgressTotalSteps; + + emitProgress(totalPercentage); +} + +KisChildDoc * KisDoc::createChildDoc( const QRect & rect, KoDocument* childDoc ) +{ + KisChildDoc * ch = new KisChildDoc( this, rect, childDoc ); + insertChild( ch ); + ch->document()->setStoreInternal(true); + return ch; +} + +void KisDoc::prepareForImport() +{ + if (m_nserver == 0) + init(); + setUndo(false); +} + +KisImageSP KisDoc::currentImage() +{ + return m_currentImage; +} + +void KisDoc::setCurrentImage(KisImageSP image) +{ + m_currentImage = image; + setUndo(true); + image->notifyImageLoaded(); + emit loadingFinished(); +} + +void KisDoc::initEmpty() +{ + KisConfig cfg; + KisColorSpace * rgb = KisMetaRegistry::instance()->csRegistry()->getRGB8(); + newImage("", cfg.defImgWidth(), cfg.defImgHeight(), rgb); +} + +#include "kis_doc.moc" + diff --git a/krita/ui/kis_doc.h b/krita/ui/kis_doc.h new file mode 100644 index 000000000..5d538cd71 --- /dev/null +++ b/krita/ui/kis_doc.h @@ -0,0 +1,223 @@ +/* + * Copyright (c) 1999-2000 Matthias Elter <me@kde.org> + * Copyright (c) 2001 Toshitaka Fujioka <fujioka@kde.org> + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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_DOC_H_ +#define KIS_DOC_H_ + +#include <kdebug.h> + +#include <KoDocument.h> + +#include "kis_types.h" +#include "kis_undo_adapter.h" + +#include <koffice_export.h> + +class QImage; +class QString; + +class DCOPObject; +class KCommand; + +class KoCommandHistory; +class KMacroCommand; + +class KisProfile; +class KisView; +class KisNameServer; +class KisChildDoc; +class KisColorSpace; +class KisColor; +class KisCompositeOp; + +class KRITACORE_EXPORT KisDoc : public KoDocument, private KisUndoAdapter { + + typedef KoDocument super; + Q_OBJECT + +public: + KisDoc(QWidget *parentWidget = 0, const char *widgetName = 0, QObject* parent = 0, const char* name = 0, bool singleViewMode = false); + virtual ~KisDoc(); + +public: + // Overide KoDocument + virtual bool wantExportConfirmation() const { return false; }; + virtual bool completeLoading(KoStore *store); + virtual bool completeSaving(KoStore*); + virtual DCOPObject* dcopObject(); + virtual bool initDoc(InitDocFlags flags, QWidget* parentWidget=0); + virtual bool loadOasis( const QDomDocument&, KoOasisStyles&, const QDomDocument&, KoStore* ); + virtual bool saveOasis( KoStore*, KoXmlWriter* ); + virtual bool loadChildren( KoStore* store); + virtual bool loadXML(QIODevice *, const QDomDocument& doc); + virtual QCString mimeType() const; + virtual QWidget* createCustomDocumentWidget(QWidget *parent); + virtual KoDocument* hitTest(const QPoint &pos, const QWMatrix& matrix = QWMatrix()); + + /** + * Draw the image embedded in another KOffice document + * + * XXX: Use of transparent, zoomX and zoomY is not supported + * by Krita because we appear to be doing our zooming + * elsewhere. This may affect KOffice compatibility. + */ + virtual void paintContent(QPainter& painter, const QRect& rect, bool /*transparent*/, double /*zoomX*/, double /*zoomY*/); + + virtual QDomDocument saveXML(); + +public slots: + + + /** + * Initialize an empty document using default values + * @since 1.5 + */ + virtual void initEmpty(); + +private: // Undo adapter + + virtual void setCommandHistoryListener(const KisCommandHistoryListener *); + virtual void removeCommandHistoryListener(const KisCommandHistoryListener *); + + virtual KCommand * presentCommand(); + virtual void addCommand(KCommand *cmd); + virtual void setUndo(bool undo); + virtual bool undo() const; + virtual void beginMacro(const QString& macroName); + virtual void endMacro(); + + +public: + + + Q_INT32 undoLimit() const; + void setUndoLimit(Q_INT32 limit); + + Q_INT32 redoLimit() const; + void setRedoLimit(Q_INT32 limit); + + /** + * Create a new image that has this document as a parent and + * replace the current image with this image. + */ + bool newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * cs, const KisColor &bgColor, const QString &imgDescription, const double imgResolution); + + /** + * Create a new image that has this document as a parent and + * replace the current image with this image. + */ + KisImageSP newImage(const QString& name, Q_INT32 width, Q_INT32 height, KisColorSpace * colorstrategy); + + void renameImage(const QString& oldName, const QString& newName); + + + /** + * Adds the specified child document to this document; this + * is not done with KoDocument::insertChild() because that + * is protected and cannot be called from KisView. + */ + KisChildDoc * createChildDoc( const QRect& rect, KoDocument* childDoc ); + + /** + * Makes an otherwise empty document ready for import/export + */ + void prepareForImport(); + + KisImageSP currentImage(); + + /** + * Set the current image to the specified image and turn undo on. + */ + void setCurrentImage(KisImageSP image); + + KisUndoAdapter * undoAdapter() { return this; } + +public slots: + void slotImageUpdated(); + void slotImageUpdated(const QRect& rect); + void slotDocumentRestored(); + void slotCommandExecuted(KCommand *command); + +signals: + void docUpdated(); + void docUpdated(QRect rect); + void loadingFinished(); + + /* + * Emitted every time a command is added to the undo history, or executed + * due to an undo or redo action. + */ + void sigCommandExecuted(); + +protected: + // Overide KoDocument + virtual KoView* createViewInstance(QWidget *parent, const char *name); + +protected slots: + // Overide KoDocument + virtual void openExistingFile(const QString& file); + virtual void openTemplate(const QString& file); + +private slots: + void slotUpdate(KisImageSP img, Q_UINT32 x, Q_UINT32 y, Q_UINT32 w, Q_UINT32 h); + void slotIOProgress(Q_INT8 percentage); + +private: + + QDomElement saveImage(QDomDocument& doc, KisImageSP img); + KisImageSP loadImage(const QDomElement& elem); + void loadLayers(const QDomElement& element, KisImageSP img, KisGroupLayerSP parent); + KisLayerSP loadLayer(const QDomElement& elem, KisImageSP img); + KisLayerSP loadPaintLayer(const QDomElement& elem, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked, + KisCompositeOp compositeOp); + KisGroupLayerSP loadGroupLayer(const QDomElement& elem, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked, + KisCompositeOp compositeOp); + KisAdjustmentLayerSP loadAdjustmentLayer(const QDomElement& elem, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, bool visible, bool locked, + KisCompositeOp compositeOp); + KisPartLayerSP loadPartLayer(const QDomElement& elem, KisImageSP img, + QString name, Q_INT32 x, Q_INT32 y, Q_INT32 opacity, + bool visible, bool locked, KisCompositeOp compositeOp); + bool init(); + + void setIOSteps(Q_INT32 nsteps); + void IOCompletedStep(); + void IODone(); + +private: + + bool m_undo; + KoCommandHistory *m_cmdHistory; + QPtrList<KisCommandHistoryListener> m_undoListeners; + KisImageSP m_currentImage; + DCOPObject *m_dcop; + KisNameServer *m_nserver; + KMacroCommand *m_currentMacro; + Q_INT32 m_macroNestDepth; + Q_INT32 m_conversionDepth; + int m_ioProgressTotalSteps; + int m_ioProgressBase; + QMap<KisLayerSP, QString> m_layerFilenames; // temp storage during load + +}; + +#endif // KIS_DOC_H_ + diff --git a/krita/ui/kis_doc_iface.cc b/krita/ui/kis_doc_iface.cc new file mode 100644 index 000000000..d7db6e5dd --- /dev/null +++ b/krita/ui/kis_doc_iface.cc @@ -0,0 +1,67 @@ +/* This file is part of the KDE project + * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com> + * + * 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_doc_iface.h" +#include <kapplication.h> + +#include "kis_doc.h" +#include "kis_image.h" + +#include <dcopclient.h> + +KisDocIface::KisDocIface( KisDoc *doc_ ) + : KoDocumentIface( doc_ ) +{ + m_doc = doc_; +} + +DCOPRef KisDocIface::currentImage() +{ + KisImage *img = m_doc->currentImage(); + if( !img ) + return DCOPRef(); + else + return DCOPRef( kapp->dcopClient()->appId(), + img->dcopObject()->objId(), + "KisImageIface"); +} + +int KisDocIface::undoLimit () const +{ + return m_doc->undoLimit(); +} + +void KisDocIface::setUndoLimit(int limit) +{ + m_doc->setUndoLimit(limit); +} + +int KisDocIface::redoLimit() const +{ + return m_doc->redoLimit(); +} + +void KisDocIface::setRedoLimit(int limit) +{ + m_doc->setRedoLimit(limit); +} + +void KisDocIface::renameImage(const QString& oldName, const QString& newName) +{ + m_doc->renameImage(oldName,newName); +} diff --git a/krita/ui/kis_doc_iface.h b/krita/ui/kis_doc_iface.h new file mode 100644 index 000000000..204d8b773 --- /dev/null +++ b/krita/ui/kis_doc_iface.h @@ -0,0 +1,50 @@ +/* This file is part of the KDE project + * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com> + * + * 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_DOC_IFACE_H +#define KIS_DOC_IFACE_H + +#include <KoViewIface.h> +#include <KoDocumentIface.h> + +#include <dcopref.h> +#include <qstring.h> +#include <kis_image_iface.h> + +class KisDoc; + +class KisDocIface : virtual public KoDocumentIface +{ + K_DCOP +public: + KisDocIface( KisDoc *doc_ ); +k_dcop: + virtual DCOPRef currentImage(); + + virtual int undoLimit () const; + virtual void setUndoLimit(int limit); + virtual int redoLimit() const; + virtual void setRedoLimit(int limit); + + virtual void renameImage(const QString& oldName, const QString& newName); + +private: + KisDoc *m_doc; +}; + +#endif diff --git a/krita/ui/kis_double_click_event.h b/krita/ui/kis_double_click_event.h new file mode 100644 index 000000000..0d6765aaa --- /dev/null +++ b/krita/ui/kis_double_click_event.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_DOUBLE_CLICK_EVENT_H_ +#define KIS_DOUBLE_CLICK_EVENT_H_ + +#include "kis_button_event.h" + +class KisDoubleClickEvent : public KisButtonEvent { + typedef KisButtonEvent super; +public: + KisDoubleClickEvent() {} + KisDoubleClickEvent(KisInputDevice device, const KisPoint& pos, const KisPoint& globalPos, double pressure, double xTilt, double yTilt, Qt::ButtonState button, Qt::ButtonState state) : super(DoubleClickEvent, device, pos, globalPos, pressure, xTilt, yTilt, button, state) {} +}; + +#endif // KIS_DOUBLE_CLICK_EVENT_H_ + diff --git a/krita/ui/kis_double_widget.cc b/krita/ui/kis_double_widget.cc new file mode 100644 index 000000000..935df9a21 --- /dev/null +++ b/krita/ui/kis_double_widget.cc @@ -0,0 +1,147 @@ +/* + * kis_double_widget.cc - part of Krita + * + * Copyright (c) 1999 Carsten Pfeiffer <pfeiffer@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qhbox.h> +#include <qlayout.h> +#include <qslider.h> + +#include <knuminput.h> + +#include "kis_double_widget.h" + +KisDoubleWidget::KisDoubleWidget(QWidget* parent, const char* name) + : super(parent, name) +{ + init(0, 1); +} + +KisDoubleWidget::KisDoubleWidget(double min, double max, QWidget* parent, const char* name) + : super(parent, name) +{ + init(min, max); +} + +KisDoubleWidget::~KisDoubleWidget() +{ +} + +void KisDoubleWidget::init(double min, double max) +{ + m_spinBox = new KDoubleSpinBox(min, max, 0.05, 0, 2, this, "spinbox"); + connect(m_spinBox, SIGNAL(valueChanged(double)), this, SLOT(setSliderValue(double))); + + m_slider = new QSlider(static_cast<int>(min * 100 + 0.5), static_cast<int>(max * 100 + 0.5), 1, 0, QSlider::Horizontal, this, "sld"); + connect(m_slider, SIGNAL(valueChanged(int)), this, SLOT(sliderValueChanged(int))); + connect(m_slider, SIGNAL(sliderPressed()), SIGNAL(sliderPressed())); + connect(m_slider, SIGNAL(sliderReleased()), SIGNAL(sliderReleased())); + + m_layout = new QHBoxLayout(this, 0, -1, "hbox layout"); + + m_layout->addWidget(m_slider); + m_layout->addSpacing(5); + m_layout->addWidget(m_spinBox); + m_layout->addItem(new QSpacerItem(5,1,QSizePolicy::Expanding, QSizePolicy::Minimum)); +} + +double KisDoubleWidget::value() const +{ + return m_spinBox->value(); +} + +void KisDoubleWidget::setValue(double value) +{ + int intValue; + + if (value < 0) { + intValue = static_cast<int>(value * 100 - 0.5); + } else { + intValue = static_cast<int>(value * 100 + 0.5); + } + m_slider->setValue(intValue); +} + +void KisDoubleWidget::setRange(double min, double max) +{ + m_spinBox->setRange(min, max); + m_slider->setRange(static_cast<int>(min * 100 + 0.5), static_cast<int>(max * 100 + 0.5)); +} + +void KisDoubleWidget::setTickmarks(QSlider::TickSetting tickSetting) +{ + m_slider->setTickmarks(tickSetting); +} + +void KisDoubleWidget::setTickInterval(double value) +{ + m_slider->setTickInterval(static_cast<int>(value * 100 + 0.5)); +} + +double KisDoubleWidget::tickInterval() const +{ + return m_slider->tickInterval() / 100.0; +} + +void KisDoubleWidget::setSliderValue(double value) +{ + int intValue; + + if (value < 0) { + intValue = static_cast<int>(value * 100 - 0.5); + } else { + intValue = static_cast<int>(value * 100 + 0.5); + } + m_slider->setValue(intValue); + emit valueChanged(value); +} + +void KisDoubleWidget::sliderValueChanged(int value) +{ + m_spinBox->setValue(value / 100.0); +} + +void KisDoubleWidget::setPrecision(int precision) +{ + m_spinBox->setPrecision(precision); +} + +void KisDoubleWidget::setLineStep(double step) +{ + m_spinBox->setLineStep(step); + m_slider->setLineStep(static_cast<int>(step * 100)); +} + +void KisDoubleWidget::setPageStep(double step) +{ + m_slider->setPageStep(static_cast<int>(step * 100)); +} + +void KisDoubleWidget::setTracking(bool tracking) +{ + m_slider->setTracking(tracking); +} + +bool KisDoubleWidget::tracking() const +{ + return m_slider->tracking(); +} + +#include "kis_double_widget.moc" + diff --git a/krita/ui/kis_double_widget.h b/krita/ui/kis_double_widget.h new file mode 100644 index 000000000..bd6043e0a --- /dev/null +++ b/krita/ui/kis_double_widget.h @@ -0,0 +1,77 @@ +/* + * kis_double_widget.h - part of Krita + * + * Copyright (c) 1999 Carsten Pfeiffer <pfeiffer@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_DOUBLE_WIDGET_H +#define KIS_DOUBLE_WIDGET_H + +#include <qwidget.h> +#include <qslider.h> + +class QHBoxLayout; +class KDoubleSpinBox; + +class KisDoubleWidget : public QWidget +{ + Q_OBJECT + + typedef QWidget super; +public: + KisDoubleWidget(QWidget* parent = 0, const char* name = 0); + KisDoubleWidget(double min, double max, QWidget* parent = 0, const char* name = 0); + ~KisDoubleWidget(); + + double value() const; + void setRange(double min, double max); + + void setTickmarks(QSlider::TickSetting tickMarks); + void setTickInterval(double tickInterval); + double tickInterval() const; + + void setPrecision(int precision); + void setLineStep(double step); + void setPageStep(double step); + + void setTracking(bool tracking); + bool tracking() const; + +signals: + void valueChanged(double); + void sliderPressed(); + void sliderReleased(); + +public slots: + void setValue(double value); + +protected slots: + void setSliderValue(double); + void sliderValueChanged(int); + +private: + void init(double min, double max); + +protected: + QHBoxLayout* m_layout; + QSlider* m_slider; + KDoubleSpinBox *m_spinBox; +}; + +#endif // KIS_DOUBLE_WIDGET_H + diff --git a/krita/ui/kis_event.h b/krita/ui/kis_event.h new file mode 100644 index 000000000..3d4d21bca --- /dev/null +++ b/krita/ui/kis_event.h @@ -0,0 +1,62 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_EVENT_H_ +#define KIS_EVENT_H_ + +#include <qevent.h> + +#include "kis_point.h" +#include "kis_input_device.h" + +class KisEvent { +public: + enum enumEventType { + UnknownEvent, + MoveEvent, + ButtonPressEvent, + ButtonReleaseEvent, + DoubleClickEvent + }; + + KisEvent() : m_type(UnknownEvent), m_device(KisInputDevice::unknown()) {} + KisEvent(enumEventType type, KisInputDevice device, const KisPoint& pos, const KisPoint& globalPos, double pressure, double xTilt, double yTilt, Qt::ButtonState state) : m_type(type), m_device(device), m_pos(pos), m_globalPos(globalPos), m_pressure(pressure), m_xTilt(xTilt), m_yTilt(yTilt), m_state(state) {} + + enumEventType type() const { return m_type; } + KisInputDevice device() const { return m_device; } + KisPoint pos() const { return m_pos; } + double x() const { return m_pos.x(); } + double y() const { return m_pos.y(); } + KisPoint globalPos() const { return m_globalPos; } + double pressure() const { return m_pressure; } + double xTilt() const { return m_xTilt; } + double yTilt() const { return m_yTilt; } + Qt::ButtonState state() const { return m_state; } + +protected: + enumEventType m_type; + KisInputDevice m_device; + KisPoint m_pos; + KisPoint m_globalPos; + double m_pressure; + double m_xTilt; + double m_yTilt; + Qt::ButtonState m_state; +}; + +#endif // KIS_EVENT_H_ + diff --git a/krita/ui/kis_factory.cc b/krita/ui/kis_factory.cc new file mode 100644 index 000000000..54a08da95 --- /dev/null +++ b/krita/ui/kis_factory.cc @@ -0,0 +1,153 @@ +/* + * kis_factory.cc - part of Krayon + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * + * 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 <config.h> +#include LCMS_HEADER + +#include <qstringlist.h> +#include <qdir.h> + +#include <kdebug.h> +#include <kinstance.h> +#include <kglobal.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <kiconloader.h> + +#include "kis_aboutdata.h" +#include "kis_resourceserver.h" +#include "kis_paintop_registry.h" +#include "kis_filter_registry.h" +#include "kis_tool_registry.h" +#include "kis_doc.h" +#include "kis_brush.h" +#include "kis_imagepipe_brush.h" +#include "kis_gradient.h" +#include "kis_pattern.h" +#include "kis_palette.h" +#include <kogradientmanager.h> + +#include "kis_factory.h" + +KAboutData* KisFactory::s_aboutData = 0; +KInstance* KisFactory::s_instance = 0; + + + +KisFactory::KisFactory( QObject* parent, const char* name ) + : KoFactory( parent, name ) +{ + s_aboutData = newKritaAboutData(); + + (void)instance(); + + // Load extension modules and plugins + KisToolRegistry::instance(); + KisPaintOpRegistry::instance(); + KisFilterRegistry::instance(); + KisResourceServerRegistry::instance(); + + + +} + +KisFactory::~KisFactory() +{ + delete s_aboutData; + s_aboutData = 0L; + delete s_instance; + s_instance = 0L; +} + +/** + * Create the document + */ +KParts::Part* KisFactory::createPartObject( QWidget *parentWidget, + const char *widgetName, QObject* parent, + const char* name, const char* classname, const QStringList & ) +{ + bool bWantKoDocument = ( strcmp( classname, "KoDocument" ) == 0 ); + + KisDoc *doc = new KisDoc( parentWidget, + widgetName, parent, name, !bWantKoDocument ); + Q_CHECK_PTR(doc); + + if ( !bWantKoDocument ) + doc->setReadWrite( false ); + + return doc; +} + + +KAboutData* KisFactory::aboutData() +{ + return s_aboutData; +} + +KInstance* KisFactory::instance() +{ + QString homedir = getenv("HOME"); + + if ( !s_instance ) + { + s_instance = new KInstance(s_aboutData); + Q_CHECK_PTR(s_instance); + + s_instance->dirs()->addResourceType("krita_template", KStandardDirs::kde_default("data") + "krita/templates"); + + // XXX: Are these obsolete? + s_instance->dirs()->addResourceType("kis", KStandardDirs::kde_default("data") + "krita/"); + + s_instance->dirs()->addResourceType("kis_pics", KStandardDirs::kde_default("data") + "krita/pics/"); + + s_instance->dirs()->addResourceType("kis_images", KStandardDirs::kde_default("data") + "krita/images/"); + + s_instance->dirs()->addResourceType("toolbars", KStandardDirs::kde_default("data") + "koffice/toolbar/"); + + // Create spec + + s_instance->dirs()->addResourceType("kis_brushes", KStandardDirs::kde_default("data") + "krita/brushes/"); + s_instance->dirs()->addResourceDir("kis_brushes", "/usr/share/create/brushes/gimp"); + s_instance->dirs()->addResourceDir("kis_brushes", QDir::homeDirPath() + QString("/.create/brushes/gimp")); + + s_instance->dirs()->addResourceType("kis_patterns", KStandardDirs::kde_default("data") + "krita/patterns/"); + s_instance->dirs()->addResourceDir("kis_patterns", "/usr/share/create/patterns/gimp"); + s_instance->dirs()->addResourceDir("kis_patterns", QDir::homeDirPath() + QString("/.create/patterns/gimp")); + + s_instance->dirs()->addResourceType("kis_gradients", KStandardDirs::kde_default("data") + "krita/gradients/"); + s_instance->dirs()->addResourceDir("kis_gradients", "/usr/share/create/gradients/gimp"); + s_instance->dirs()->addResourceDir("kis_gradients", QDir::homeDirPath() + QString("/.create/gradients/gimp")); + + s_instance->dirs()->addResourceType("kis_profiles", KStandardDirs::kde_default("data") + "krita/profiles/"); + s_instance->dirs()->addResourceDir("kis_profiles", "/usr/share/color/icc"); + s_instance->dirs()->addResourceDir("kis_profiles", QDir::homeDirPath() + QString("/.icc")); + s_instance->dirs()->addResourceDir("kis_profiles", QDir::homeDirPath() + QString("/.color/icc")); + + s_instance->dirs()->addResourceType("kis_palettes", KStandardDirs::kde_default("data") + "krita/palettes/"); + s_instance->dirs()->addResourceDir("kis_palettes", "/usr/share/create/swatches"); + s_instance->dirs()->addResourceDir("kis_palettes", QDir::homeDirPath() + QString("/.create/swatches")); + + // Tell the iconloader about share/apps/koffice/icons + s_instance->iconLoader()->addAppDir("koffice"); + } + + return s_instance; +} + +#include "kis_factory.moc" diff --git a/krita/ui/kis_factory.h b/krita/ui/kis_factory.h new file mode 100644 index 000000000..c89b7a92c --- /dev/null +++ b/krita/ui/kis_factory.h @@ -0,0 +1,58 @@ +/* + * kis_factory.h - part of Krayon + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * + * 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_factory_h__ +#define __kis_factory_h__ + +#include <qptrlist.h> + +#include <kparts/plugin.h> + +#include <KoFactory.h> + +#include <koffice_export.h> + +class KInstance; +class KAboutData; + +class KRITACORE_EXPORT KisFactory : public KoFactory +{ + Q_OBJECT + +public: + KisFactory( QObject* parent = 0, const char* name = 0 ); + ~KisFactory(); + + virtual KParts::Part *createPartObject(QWidget *parentWidget = 0, + const char *widgetName = 0, + QObject *parent = 0, + const char *name = 0, + const char *classname = "KoDocument", + const QStringList &args = QStringList() ); + + static KAboutData *aboutData(); + static KInstance *instance(); + +private: + static KInstance *s_instance; + static KAboutData *s_aboutData; +}; + +#endif diff --git a/krita/ui/kis_filter_manager.cc b/krita/ui/kis_filter_manager.cc new file mode 100644 index 000000000..550805caa --- /dev/null +++ b/krita/ui/kis_filter_manager.cc @@ -0,0 +1,408 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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 "qsignalmapper.h" +#include <qlayout.h> +#include <qframe.h> +#include <qcursor.h> +#include <qapplication.h> +#include <kmessagebox.h> +#include <kguiitem.h> + +#include <kis_cursor.h> +#include "kaction.h" + +#include "kis_part_layer.h" +#include "kis_id.h" +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_filter.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_paint_layer.h" +#include "kis_filter_manager.h" +#include "kis_filter_config_widget.h" +#include "kis_previewwidget.h" +#include "kis_previewdialog.h" +#include "kis_filter_registry.h" +#include "kis_transaction.h" +#include "kis_undo_adapter.h" +#include "kis_previewdialog.h" +#include "kis_previewwidget.h" +#include "kis_painter.h" +#include "kis_selection.h" +#include "kis_id.h" +#include "kis_canvas_subject.h" +#include "kis_doc.h" +#include "kis_transaction.h" +#include <kis_progress_display_interface.h> + +KisFilterManager::KisFilterManager(KisView * view, KisDoc * doc) + : m_view(view), + m_doc(doc) +{ + // XXX: Store & restore last filter & last filter configuration in session settings + m_reapplyAction = 0; + m_lastFilterConfig = 0; + m_lastDialog = 0; + m_lastFilter = 0; + m_lastWidget = 0; + + m_filterMapper = new QSignalMapper(this); + + connect(m_filterMapper, SIGNAL(mapped(int)), this, SLOT(slotApplyFilter(int))); + +} + +KisFilterManager::~KisFilterManager() +{ + //delete m_reapplyAction; + //delete m_lastFilterConfig; + //delete m_filterMapper; +} + +void KisFilterManager::setup(KActionCollection * ac) +{ + KisFilter * f = 0; + int i = 0; + + // Only create the submenu's we've actually got filters for. + // XXX: Make this list extensible after 1.5 + + KActionMenu * other = 0; + KActionMenu * am = 0; + + m_filterList = KisFilterRegistry::instance()->listKeys(); + + for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) { + f = KisFilterRegistry::instance()->get(*it); + if (!f) break; + + QString s = f->menuCategory(); + if (s == "adjust" && !m_filterActionMenus.find("adjust")) { + am = new KActionMenu(i18n("Adjust"), ac, "adjust_filters"); + m_filterActionMenus.insert("adjust", am); + } + + else if (s == "artistic" && !m_filterActionMenus.find("artistic")) { + am = new KActionMenu(i18n("Artistic"), ac, "artistic_filters"); + m_filterActionMenus.insert("artistic", am); + } + + else if (s == "blur" && !m_filterActionMenus.find("blur")) { + am = new KActionMenu(i18n("Blur"), ac, "blur_filters"); + m_filterActionMenus.insert("blur", am); + } + + else if (s == "colors" && !m_filterActionMenus.find("colors")) { + am = new KActionMenu(i18n("Colors"), ac, "color_filters"); + m_filterActionMenus.insert("colors", am); + } + + else if (s == "decor" && !m_filterActionMenus.find("decor")) { + am = new KActionMenu(i18n("Decor"), ac, "decor_filters"); + m_filterActionMenus.insert("decor", am); + } + + else if (s == "edge" && !m_filterActionMenus.find("edge")) { + am = new KActionMenu(i18n("Edge Detection"), ac, "edge_filters"); + m_filterActionMenus.insert("edge", am); + } + + else if (s == "emboss" && !m_filterActionMenus.find("emboss")) { + am = new KActionMenu(i18n("Emboss"), ac, "emboss_filters"); + m_filterActionMenus.insert("emboss", am); + } + + else if (s == "enhance" && !m_filterActionMenus.find("enhance")) { + am = new KActionMenu(i18n("Enhance"), ac, "enhance_filters"); + m_filterActionMenus.insert("enhance", am); + } + + else if (s == "map" && !m_filterActionMenus.find("map")) { + am = new KActionMenu(i18n("Map"), ac, "map_filters"); + m_filterActionMenus.insert("map", am); + } + + else if (s == "nonphotorealistic" && !m_filterActionMenus.find("nonphotorealistic")) { + am = new KActionMenu(i18n("Non-photorealistic"), ac, "nonphotorealistic_filters"); + m_filterActionMenus.insert("nonphotorealistic", am); + } + + else if (s == "other" && !m_filterActionMenus.find("other")) { + other = new KActionMenu(i18n("Other"), ac, "misc_filters"); + m_filterActionMenus.insert("other", other); + } + + } + + m_reapplyAction = new KAction(i18n("Apply Filter Again"), + "Ctrl+Shift+F", + this, SLOT(slotApply()), + ac, "filter_apply_again"); + + m_reapplyAction->setEnabled(false); + + f = 0; + i = 0; + for ( KisIDList::Iterator it = m_filterList.begin(); it != m_filterList.end(); ++it ) { + f = KisFilterRegistry::instance()->get(*it); + + if (!f) break; + + // Create action + KAction * a = new KAction(f->menuEntry(), 0, m_filterMapper, SLOT(map()), ac, + QString("krita_filter_%1").arg((*it) . id()).ascii()); + + // Add action to the right submenu + KActionMenu * m = m_filterActionMenus.find( f->menuCategory() ); + if (m) { + m->insert(a); + } + else { + if (!other) { + other = new KActionMenu(i18n("Other"), ac, "misc_filters"); + m_filterActionMenus.insert("other", am); + } + other->insert(a); + } + + // Add filter to list of filters for mapper + m_filterMapper->setMapping( a, i ); + + m_filterActions.append( a ); + ++i; + } +} + +void KisFilterManager::updateGUI() +{ + KisImageSP img = m_view->currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(layer.data()); + + bool enable = !(layer->locked() || !layer->visible() || partLayer); + KisPaintLayerSP player = dynamic_cast<KisPaintLayer*>( layer.data()); + if(!player) + { + enable = false; + } + m_reapplyAction->setEnabled(m_lastFilterConfig); + if (m_lastFilterConfig) + m_reapplyAction->setText(i18n("Apply Filter Again") + ": " + + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name()); + else + m_reapplyAction->setText(i18n("Apply Filter Again")); + + KAction * a; + int i = 0; + for (a = m_filterActions.first(); a; a = m_filterActions.next() , i++) { + KisFilter* filter = KisFilterRegistry::instance()->get(m_filterList[i]); + if(player && filter->workWith( player->paintDevice()->colorSpace())) + { + a->setEnabled(enable); + } else { + a->setEnabled(false); + } + } + +} + +void KisFilterManager::slotApply() +{ + apply(); +} + +bool KisFilterManager::apply() +{ + if (!m_lastFilter) return false; + + KisImageSP img = m_view->currentImg(); + if (!img) return false; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return false; + + QApplication::setOverrideCursor( KisCursor::waitCursor() ); + + //Apply the filter + m_lastFilterConfig = m_lastFilter->configuration(m_lastWidget); + + QRect r1 = dev->extent(); + QRect r2 = img->bounds(); + + // Filters should work only on the visible part of an image. + QRect rect = r1.intersect(r2); + + if (dev->hasSelection()) { + QRect r3 = dev->selection()->selectedExactRect(); + rect = rect.intersect(r3); + } + + m_lastFilter->enableProgress(); + + m_view->progressDisplay()->setSubject(m_lastFilter, true, true); + m_lastFilter->setProgressDisplay( m_view->progressDisplay()); + + KisTransaction * cmd = 0; + if (img->undo()) cmd = new KisTransaction(m_lastFilter->id().name(), dev); + + m_lastFilter->process(dev, dev, m_lastFilterConfig, rect); + m_reapplyAction->setEnabled(m_lastFilterConfig); + if (m_lastFilterConfig) + m_reapplyAction->setText(i18n("Apply Filter Again") + ": " + + KisFilterRegistry::instance()->get(m_lastFilterConfig->name())->id().name()); + + else + m_reapplyAction->setText(i18n("Apply Filter Again")); + + m_lastFilter->disableProgress(); + QApplication::restoreOverrideCursor(); + + + if (m_lastFilter->cancelRequested()) { + delete m_lastFilterConfig; + if (cmd) { + cmd->unexecute(); + delete cmd; + } + return false; + + } else { + if (dev->parentLayer()) dev->parentLayer()->setDirty(rect); + m_doc->setModified(true); + if (img->undo() && cmd) img->undoAdapter()->addCommand(cmd); + return true; + } +} + +void KisFilterManager::slotApplyFilter(int i) +{ + KisPreviewDialog * oldDialog = m_lastDialog; + KisFilterConfiguration * oldConfig = m_lastFilterConfig; + KisFilter * oldFilter = m_lastFilter; + + m_lastFilter = KisFilterRegistry::instance()->get(m_filterList[i]); + + if (!m_lastFilter) { + m_lastFilter = oldFilter; + return; + } + + KisImageSP img = m_view->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (dev->colorSpace()->willDegrade(m_lastFilter->colorSpaceIndependence())) { + // Warning bells! + if (m_lastFilter->colorSpaceIndependence() == TO_LAB16) { + if (KMessageBox::warningContinueCancel(m_view, + i18n("The %1 filter will convert your %2 data to 16-bit L*a*b* and vice versa. ") + .arg(m_lastFilter->id().name()) + .arg(dev->colorSpace()->id().name()), + i18n("Filter Will Convert Your Layer Data"), + KGuiItem(i18n("Continue")), + "lab16degradation") != KMessageBox::Continue) return; + + } + else if (m_lastFilter->colorSpaceIndependence() == TO_RGBA8) { + if (KMessageBox::warningContinueCancel(m_view, + i18n("The %1 filter will convert your %2 data to 8-bit RGBA and vice versa. ") + .arg(m_lastFilter->id().name()) + .arg(dev->colorSpace()->id().name()), + i18n("Filter Will Convert Your Layer Data"), + KGuiItem(i18n("Continue")), + "rgba8degradation") != KMessageBox::Continue) return; + } + } + + m_lastFilter->disableProgress(); + + // Create the config dialog + m_lastDialog = new KisPreviewDialog(m_view, m_lastFilter->id().name().ascii(), true, m_lastFilter->id().name()); + Q_CHECK_PTR(m_lastDialog); + m_lastWidget = m_lastFilter->createConfigurationWidget( (QWidget*)m_lastDialog->container(), dev ); + + bool accepted = true; + + if( m_lastWidget != 0) + { + connect(m_lastWidget, SIGNAL(sigPleaseUpdatePreview()), this, SLOT(slotConfigChanged())); + + m_lastDialog->previewWidget()->slotSetDevice( dev ); + + connect(m_lastDialog->previewWidget(), SIGNAL(updated()), this, SLOT(refreshPreview())); + + QGridLayout *widgetLayout = new QGridLayout((QWidget *)m_lastDialog->container(), 1, 1); + + widgetLayout->addWidget(m_lastWidget, 0 , 0); + + m_lastDialog->container()->setMinimumSize(m_lastWidget->minimumSize()); + + refreshPreview(); + + if(m_lastDialog->exec() == QDialog::Rejected ) + { + accepted = false; + } + } + + if (!accepted || !apply()) { + // Override the old configuration + m_lastFilterConfig = oldConfig; + m_lastDialog = oldDialog; + m_lastFilter = oldFilter; + } else { + delete oldDialog; + delete oldConfig; + } + +} + +void KisFilterManager::slotConfigChanged() +{ + if( m_lastDialog == 0 ) + return; + if(m_lastDialog->previewWidget()->getAutoUpdate()) + { + refreshPreview(); + } else { + m_lastDialog->previewWidget()->needUpdate(); + } +} + + +void KisFilterManager::refreshPreview( ) +{ + if( m_lastDialog == 0 ) return; + + KisFilterConfiguration* config = m_lastFilter->configuration(m_lastWidget); + + // The preview widget is in charge of running the filter so it can optimize the performance + m_lastDialog->previewWidget()->runFilter(m_lastFilter, config); +} + + +#include "kis_filter_manager.moc" diff --git a/krita/ui/kis_filter_manager.h b/krita/ui/kis_filter_manager.h new file mode 100644 index 000000000..69c87565c --- /dev/null +++ b/krita/ui/kis_filter_manager.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_FILTER_MANAGER_ +#define _KIS_FILTER_MANAGER_ + +#include "qdict.h" +#include "qobject.h" +#include "qptrlist.h" +#include "qsignalmapper.h" +#include "kactionclasses.h" +#include "kis_image.h" +#include "kis_selection.h" + +#include <koffice_export.h> + +class KAction; +class KisView; +class KisDoc; +class KisFilter; +class KisFilterConfiguration; +class KAction; +class KActionCollection; +class KisPreviewDialog; + +/** + * Create all the filter actions for the specified view and implement re-apply filter + */ +class KRITACORE_EXPORT KisFilterManager : public QObject { + + Q_OBJECT + +public: + + KisFilterManager(KisView * parent, KisDoc * doc); + ~KisFilterManager(); + + void setup(KActionCollection * ac); + void updateGUI(); + + + bool apply(); + +protected slots: + + void slotApply(); + void slotConfigChanged(); + void slotApplyFilter(int); + void refreshPreview(); + +private: + + KisView * m_view; + KisDoc * m_doc; + + KAction * m_reapplyAction; + + QPtrList<KAction> m_filterActions; + + KisFilterConfiguration * m_lastFilterConfig; + KisFilter * m_lastFilter; + KisPreviewDialog * m_lastDialog; + KisFilterConfigWidget * m_lastWidget; + + KisIDList m_filterList; // Map the actions in the signalmapper to the filters + QSignalMapper * m_filterMapper; + + QDict<KActionMenu> m_filterActionMenus; +}; + +#endif diff --git a/krita/ui/kis_filters_listview.cc b/krita/ui/kis_filters_listview.cc new file mode 100644 index 000000000..04039a3b0 --- /dev/null +++ b/krita/ui/kis_filters_listview.cc @@ -0,0 +1,250 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + * 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_filters_listview.h" + +#include <qapplication.h> +#include "qtimer.h" +#include "qpainter.h" +#include "qpixmap.h" + +#include <kglobalsettings.h> + +#include "kis_types.h" +#include "kis_paint_device.h" +#include "kis_cursor.h" +#include "kis_image.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" +#include "kis_filter.h" +#include "kis_filter_strategy.h" +#include "kis_thread_pool.h" + +// ------------------------------------------------ + +KisFiltersThumbnailThread::KisFiltersThumbnailThread(QIconView * parent, KisFiltersIconViewItem * iconItem, KisFilterConfiguration * config, KisFilter * filter, KisPaintDeviceSP dev, const QRect & bounds, KisProfile * profile) + : m_parent(parent) + , m_iconItem(iconItem) + , m_config(config) + , m_filter(filter) + , m_dev(dev) + , m_bounds(bounds) + , m_profile(profile) +{ +} + +KisFiltersThumbnailThread::~KisFiltersThumbnailThread() +{ + m_iconItem->resetThread(); +} + +void KisFiltersThumbnailThread::run() +{ + if (m_canceled) return; + + KisPaintDeviceSP thumbPreview = new KisPaintDevice(*m_dev); + m_filter->disableProgress(); + m_filter->process(thumbPreview, thumbPreview, m_config, m_bounds); + + if (!m_canceled) { + m_pixmap = thumbPreview->convertToQImage(m_profile); + + qApp->postEvent(m_parent, new KisThumbnailDoneEvent (m_iconItem, m_pixmap)); + + } +} + +QPixmap KisFiltersThumbnailThread::pixmap() +{ + return m_pixmap; +} + +void KisFiltersThumbnailThread::cancel() +{ + m_canceled = true; + m_filter->cancel(); + +} + + +// ------------------------------------------------ + +KisFiltersIconViewItem::KisFiltersIconViewItem(QIconView * parent, const QString & text, const QPixmap & icon, + KisID id, KisFilter* filter, KisFilterConfiguration* filterConfig, + KisPaintDeviceSP thumb, const QRect & bounds, KisProfile * profile) + : QIconViewItem(parent, text, icon) + , m_id(id) + , m_filter(filter) + , m_filterconfig(filterConfig) +{ + m_thread = new KisFiltersThumbnailThread(parent, this, filterConfig, filter, thumb, bounds, profile); +} + +KisFiltersIconViewItem::~KisFiltersIconViewItem() +{ + if (m_thread) m_thread->cancel(); +} + + +// ------------------------------------------------ + +KisFiltersListView::KisFiltersListView(QWidget* parent, bool filterForAdjustmentLayers, const char* name) + : KIconView(parent, name) + , m_original(0) + , m_profile(0) + , m_filterForAdjustmentLayers(filterForAdjustmentLayers) +{ + init(); +} + +KisFiltersListView::KisFiltersListView(QWidget * parent, const char * name, WFlags f, bool filterForAdjustmentLayers) + : KIconView(parent, name, f) + , m_original(0) + , m_profile(0) + , m_filterForAdjustmentLayers(filterForAdjustmentLayers) +{ + init(); +} + +KisFiltersListView::KisFiltersListView(KisLayerSP layer, QWidget* parent, bool filterForAdjustmentLayers, const char * name) + : KIconView(parent, name) + , m_original(0) + , m_profile(0) + , m_filterForAdjustmentLayers(filterForAdjustmentLayers) +{ + KisPaintLayer* pl = dynamic_cast<KisPaintLayer*>(layer.data()); + if(pl != 0) + { + m_original = pl->paintDevice(); + buildPreview(); + } + init(); +} + +KisFiltersListView::KisFiltersListView(KisPaintDeviceSP device, QWidget* parent, bool filterForAdjustmentLayers, const char * name) + : KIconView(parent, name) + , m_original(device) + , m_profile(0) + , m_filterForAdjustmentLayers(filterForAdjustmentLayers) +{ + buildPreview(); + init(); +} + +void KisFiltersListView::init() +{ + setCaption(i18n("Filters List")); + setItemsMovable(false); + setSelectionMode(QIconView::Single); + setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Expanding )); + setMinimumWidth(160); + +} + +void KisFiltersListView::setLayer(KisLayerSP layer) { + KisPaintLayer* pl = dynamic_cast<KisPaintLayer*>(layer.data()); + if(pl == 0) + return; + KisPaintDeviceSP npd = pl->paintDevice(); + if(npd!= m_original) + { + m_original = npd; + buildPreview(); + } +} + +void KisFiltersListView::setCurrentFilter(KisID filter) +{ + setCurrentItem(findItem(filter.name())); +} + +void KisFiltersListView::buildPreview() +{ + QTime t; + if(m_original== 0) + return; + + QApplication::setOverrideCursor(KisCursor::waitCursor()); + t.start(); + m_thumb = m_original->createThumbnailDevice(150, 150); + + t.start(); + QRect bounds = m_thumb->exactBounds(); + QPixmap pm(bounds.width(), bounds.height()); + QPainter gc(&pm); + gc.fillRect(0, 0, bounds.width(), bounds.height(), backgroundColor()); + gc.end(); + + t.start(); + KisIDList l = KisFilterRegistry::instance()->listKeys(); + KisIDList::iterator it; + it = l.begin(); + // Iterate over the list of filters + for (it = l.begin(); it != l.end(); ++it) { + KisFilterSP f = KisFilterRegistry::instance()->get(*it); + // Check if filter support the preview and work with the current colorspace + if (f->supportsPreview() && f->workWith( m_original->colorSpace() ) ) { + + if (m_filterForAdjustmentLayers) { + kdDebug() << "We're filtering for adj layers, and this filter (" << f->id().name() << ") supports them: " << f->supportsAdjustmentLayers() << endl; + if(!f->supportsAdjustmentLayers()) continue; + } + std::list<KisFilterConfiguration*> configlist = f->listOfExamplesConfiguration(m_thumb); + // apply the filter for each of example of configuration + for(std::list<KisFilterConfiguration*>::iterator itc = configlist.begin(); + itc != configlist.end(); + itc++) + { + KisFiltersIconViewItem * icon = new KisFiltersIconViewItem( this, (*it).name(), pm, *it, f, *itc, m_thumb, bounds, m_profile ); + //KisThreadPool::instance()->enqueue(icon->thread()); + icon->thread()->runDirectly(); + } + } + } + QApplication::restoreOverrideCursor(); +} + + +void KisFiltersListView::customEvent(QCustomEvent * e) +{ + KisThumbnailDoneEvent * ev = dynamic_cast<KisThumbnailDoneEvent *>(e); + if (ev) { + QPixmap * p = ev->m_iconItem->pixmap(); + QImage img = ev->m_image; + int x, y; + + if (p->width() > img.width()) + x = (p->width() - img.width()) / 2; + else + x = 0; + if (p->height() > img.height()) + y = (p->height() - img.height()) / 2; + else + y = 0; + + QPainter gc(p); + gc.drawImage(QPoint(x,y), img); + gc.end(); + + //ev->m_iconItem->setPixmap(QPixmap(*p)); + arrangeItemsInGrid(); + } +} diff --git a/krita/ui/kis_filters_listview.h b/krita/ui/kis_filters_listview.h new file mode 100644 index 000000000..7a7e5e897 --- /dev/null +++ b/krita/ui/kis_filters_listview.h @@ -0,0 +1,143 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * + * 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_FILTERS_LIST_VIEW_H_ +#define _KIS_FILTERS_LIST_VIEW_H_ + +#include <qevent.h> + +#include <kiconview.h> + +#include "kis_id.h" +#include "kis_types.h" +#include "kis_layer.h" +#include "kis_paint_device.h" +#include "kis_thread.h" + +class KisView; +class KisFilter; +class KisFilterConfiguration; +class KisPreviewView; +class KisFiltersIconViewItem; +class KisFiltersListView; +class KisThreadPool; + +class KisThumbnailDoneEvent : public QCustomEvent +{ +public: + + KisThumbnailDoneEvent(KisFiltersIconViewItem * iconItem, const QImage & img) + : QCustomEvent(QEvent::User + 1969) + , m_iconItem(iconItem) + , m_image(img) {}; + + KisFiltersIconViewItem * m_iconItem; + QImage m_image; + +}; + + +class KisFiltersThumbnailThread : public KisThread +{ +public: + + KisFiltersThumbnailThread(QIconView * parent, + KisFiltersIconViewItem * iconItem, + KisFilterConfiguration * config, KisFilter * filter, + KisPaintDeviceSP dev, const QRect & bounds, + KisProfile * profile); + + ~KisFiltersThumbnailThread(); + + virtual void run(); + QPixmap pixmap(); + void cancel(); + +private: + QIconView * m_parent; + KisFiltersIconViewItem * m_iconItem; + KisFilterConfiguration * m_config; + KisFilter * m_filter; + KisPaintDeviceSP m_dev; + const QRect m_bounds; + KisProfile * m_profile; + QImage m_pixmap; +}; + +class KisFiltersIconViewItem : public QIconViewItem { +public: + KisFiltersIconViewItem( QIconView * parent, const QString & text, const QPixmap & icon, + KisID id, KisFilter* filter, KisFilterConfiguration* filterConfig, + KisPaintDeviceSP thumb, const QRect & bounds, KisProfile * profile); + + virtual ~KisFiltersIconViewItem(); + KisID id() { return m_id; } + KisFilter* filter() { return m_filter; } + void setFilterConfiguration(KisFilterConfiguration* fc) { m_filterconfig = fc; } + + void resetThread() { m_thread = 0; }; + KisThread * thread() { return m_thread; } + +private: + KisID m_id; + KisFilter* m_filter; + KisFilterConfiguration* m_filterconfig; + KisFiltersThumbnailThread * m_thread; +}; + +class KisFiltersListView : public KIconView { + +public: + explicit KisFiltersListView(QWidget * parent = 0, const char * name = 0, WFlags f = 0, bool filterForAdjustmentLayers = false); + KisFiltersListView(QWidget* parent, bool filterForAdjustmentLayers = false, const char* name = 0); + KisFiltersListView(KisLayerSP layer, QWidget* parent, bool filterForAdjustmentLayers = false, const char * name = 0) KDE_DEPRECATED; + KisFiltersListView(KisPaintDeviceSP layer, QWidget* parent, bool filterForAdjustmentLayers = false, const char * name = 0); + + virtual void customEvent(QCustomEvent *); + + private: + + void init(); + +public: + void setLayer(KisLayerSP layer) KDE_DEPRECATED; + void setProfile(KisProfile * profile) { m_profile = profile; }; + + inline void setPaintDevice(KisPaintDeviceSP pd) { + if( pd != m_original) + { + m_original = pd; + buildPreview(); + } + } + void buildPreview(); + void setCurrentFilter(KisID filter); + +private: + + KisPaintDeviceSP m_original; + KisImageSP m_imgthumb; + KisPaintDeviceSP m_thumb; + KisProfile * m_profile; + KisThreadPool * threadPool; + bool m_filterForAdjustmentLayers; +}; + +#endif diff --git a/krita/ui/kis_gradient_chooser.cc b/krita/ui/kis_gradient_chooser.cc new file mode 100644 index 000000000..ca0bfeb05 --- /dev/null +++ b/krita/ui/kis_gradient_chooser.cc @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <klocale.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qpushbutton.h> + +#include <kdialogbase.h> + +#include <koIconChooser.h> +#include <kis_view.h> + +#include "kis_global.h" +#include "kis_icon_item.h" +#include "kis_gradient.h" +#include "kis_autogradient.h" + +#include "kis_gradient_chooser.h" + +KisCustomGradientDialog::KisCustomGradientDialog(KisView * view, QWidget * parent, const char *name) + : KDialogBase(parent, name, false, i18n("Custom Gradient"), Close) +{ + m_page = new KisAutogradient(this, "autogradient", i18n("Custom Gradient")); + setMainWidget(m_page); + connect(m_page, SIGNAL(activatedResource(KisResource *)), view, SLOT(gradientActivated(KisResource*))); +} + +KisGradientChooser::KisGradientChooser(KisView * view, QWidget *parent, const char *name) : super(parent, name) +{ + m_lbName = new QLabel(this); + + m_customGradient = new QPushButton(i18n("Custom Gradient..."), this, "custom gradient button"); + + KisCustomGradientDialog * autogradient = new KisCustomGradientDialog(view, this, "autogradient"); + connect(m_customGradient, SIGNAL(clicked()), autogradient, SLOT(show())); + + QVBoxLayout *mainLayout = new QVBoxLayout(this, 2, -1, "main layout"); + + mainLayout->addWidget(m_lbName); + mainLayout->addWidget(chooserWidget(), 10); + mainLayout->addWidget(m_customGradient, 10); + +} + +KisGradientChooser::~KisGradientChooser() +{ +} + +void KisGradientChooser::update(KoIconItem *item) +{ + KisIconItem *kisItem = static_cast<KisIconItem *>(item); + + if (item) { + KisGradient *gradient = static_cast<KisGradient *>(kisItem->resource()); + + m_lbName->setText(gradient->name()); + } +} + + +#include "kis_gradient_chooser.moc" + diff --git a/krita/ui/kis_gradient_chooser.h b/krita/ui/kis_gradient_chooser.h new file mode 100644 index 000000000..5b6d72267 --- /dev/null +++ b/krita/ui/kis_gradient_chooser.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_GRADIENT_CHOOSER_H_ +#define KIS_GRADIENT_CHOOSER_H_ + +#include <kdialogbase.h> + +#include "kis_itemchooser.h" + +class QLabel; +class QPushButton; +class KisView; + +class KisCustomGradientDialog : public KDialogBase { + + Q_OBJECT + +public: + + KisCustomGradientDialog(KisView * view, QWidget * parent, const char *name); + +private: + + KisAutogradient * m_page; + +}; + +class KisGradientChooser : public KisItemChooser { + typedef KisItemChooser super; + Q_OBJECT + +public: + // XXX: On library redesign, remove m_view parameter here, it's just a temporary hack for the autogradient dialog! + KisGradientChooser(KisView * view, QWidget *parent = 0, const char *name = 0); + virtual ~KisGradientChooser(); + +protected: + virtual void update(KoIconItem *item); + +private: + QLabel *m_lbName; + QPushButton * m_customGradient; +}; + +#endif // KIS_GRADIENT_CHOOSER_H_ + diff --git a/krita/ui/kis_gradient_slider_widget.cc b/krita/ui/kis_gradient_slider_widget.cc new file mode 100644 index 000000000..05e724a38 --- /dev/null +++ b/krita/ui/kis_gradient_slider_widget.cc @@ -0,0 +1,219 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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_gradient_slider_widget.h" + +#include <qpainter.h> + +#include <kdebug.h> +#include <kpopupmenu.h> +#include <klocale.h> + +#include "kis_autogradient_resource.h" + +#define MARGIN 5 +#define HANDLE_SIZE 10 + +KisGradientSliderWidget::KisGradientSliderWidget(QWidget *parent, const char* name, WFlags f ) + : QWidget( parent, name, f), + m_currentSegment(0), + m_selectedSegment(0), + m_drag(0) +{ + setMinimumHeight(30); + + m_segmentMenu = new KPopupMenu(); + m_segmentMenu->insertItem(i18n("Split Segment"), SPLIT_SEGMENT); + m_segmentMenu->insertItem(i18n("Duplicate Segment"), DUPLICATE_SEGMENT); + m_segmentMenu->insertItem(i18n("Mirror Segment"), MIRROR_SEGMENT); + m_segmentMenu->insertItem(i18n("Remove Segment"), REMOVE_SEGMENT); + connect( m_segmentMenu, SIGNAL( activated(int) ), SLOT( slotMenuAction(int) ) ); +} + +void KisGradientSliderWidget::setGradientResource( KisAutogradientResource* agr) +{ + m_autogradientResource = agr; + m_selectedSegment = m_autogradientResource->segmentAt(0.0); + emit sigSelectedSegment( m_selectedSegment ); +} + +void KisGradientSliderWidget::paintEvent ( QPaintEvent* pe ) +{ + QWidget::paintEvent( pe ); + QPixmap pixmap( width(), height() ); + pixmap.fill( colorGroup().background() ); + QPainter painter( &pixmap ); + painter.setPen( Qt::black ); + painter.drawRect( MARGIN, MARGIN, width() - 2 * MARGIN, height()- 2 * MARGIN - HANDLE_SIZE ); + if(m_autogradientResource) + { + QImage img = m_autogradientResource->generatePreview(width()- 2* MARGIN - 2, height()- 2* MARGIN - HANDLE_SIZE - 2); + QPixmap pixmap(img.width(), img.height()); + if (!img.isNull()) { + m_pixmapIO.putImage(&pixmap, 0, 0, &img); + painter.drawPixmap( MARGIN + 1, MARGIN + 1, pixmap, 0, 0, pixmap.width(), pixmap.height()); + } + + painter.fillRect( MARGIN + 1, height()- MARGIN - HANDLE_SIZE, width() - 2 * MARGIN, HANDLE_SIZE, QBrush( Qt::white ) ); + if( m_selectedSegment ) + { + QRect selection( qRound( m_selectedSegment->startOffset()*(double)(width()- 2 * MARGIN - 2) ) + 6, + height()- HANDLE_SIZE - MARGIN, + qRound( ( m_selectedSegment->endOffset() - m_selectedSegment->startOffset() )*(double)(width()-12) ), + HANDLE_SIZE ); + painter.fillRect( selection, QBrush( colorGroup().highlight() ) ); + } + + QPointArray triangle(3); + QValueVector<double> handlePositions = m_autogradientResource->getHandlePositions(); + int position; + painter.setBrush( QBrush( Qt::black) ); + for (uint i = 0; i < handlePositions.count(); i++) + { + position = qRound( handlePositions[i] * (double)( width()-12) ) + 6; + triangle[0] = QPoint(position, height() - HANDLE_SIZE - MARGIN ); + triangle[1] = QPoint(position + (HANDLE_SIZE / 2 - 1), height() - MARGIN ); + triangle[2] = QPoint(position - (HANDLE_SIZE / 2 - 1), height() - MARGIN ); + painter.drawPolygon(triangle); + } + painter.setBrush( QBrush( Qt::white ) ); + QValueVector<double> middleHandlePositions = m_autogradientResource->getMiddleHandlePositions(); + for (uint i = 0; i < middleHandlePositions.count(); i++) + { + position = qRound( middleHandlePositions[i] * (double)(width()-12) ) + 6; + triangle[0] = QPoint(position, height()-HANDLE_SIZE - MARGIN); + triangle[1] = QPoint(position + (HANDLE_SIZE / 2 - 2), height() - MARGIN); + triangle[2] = QPoint(position - (HANDLE_SIZE / 2 - 2), height() - MARGIN); + painter.drawPolygon(triangle); + } + } + bitBlt( this, 0, 0, &pixmap, 0, 0, pixmap.width(), pixmap.height(), Qt::CopyROP); +} + +void KisGradientSliderWidget::mousePressEvent( QMouseEvent * e ) +{ + QWidget::mousePressEvent( e ); + if( ( e->y() < MARGIN || e->y() > height() - MARGIN ) || ( e->x() < MARGIN || e->x() > width() - MARGIN ) || e-> button() != LeftButton ) + return; + double t = (double)(e->x() - MARGIN) / (double)(width() - 2 * MARGIN); + KisGradientSegment* segment = 0; + segment = m_autogradientResource->segmentAt(t); + if(segment != 0) + { + m_currentSegment = segment; + QRect leftHandle( qRound(m_currentSegment->startOffset() * (double)(width()-2*MARGIN-2)+ MARGIN - (HANDLE_SIZE/2 - 1 )), + height() - HANDLE_SIZE, + HANDLE_SIZE - 1, + HANDLE_SIZE); + QRect middleHandle( qRound(m_currentSegment->middleOffset() * (double)(width()-2*MARGIN-2)+ MARGIN - (HANDLE_SIZE/2 -2) ), + height() - HANDLE_SIZE - MARGIN, + HANDLE_SIZE - 1, + HANDLE_SIZE); + QRect rightHandle( qRound(m_currentSegment->endOffset() * (double)(width()-2*MARGIN-2)+ MARGIN - (HANDLE_SIZE/2 - 1 )), + height() - HANDLE_SIZE, + HANDLE_SIZE - 1, + HANDLE_SIZE); + // Change the activation order of the handles to avoid deadlocks + if( t > 0.5 ) + { + if( leftHandle.contains( e->pos() ) ) + m_drag = LEFT_DRAG; + else if( middleHandle.contains( e->pos() ) ) + m_drag = MIDDLE_DRAG; + else if( rightHandle.contains( e->pos() ) ) + m_drag = RIGHT_DRAG; + } + else + { + if( rightHandle.contains( e->pos() ) ) + m_drag = RIGHT_DRAG; + else if( middleHandle.contains( e->pos() ) ) + m_drag = MIDDLE_DRAG; + else if( leftHandle.contains( e->pos() ) ) + m_drag = LEFT_DRAG; + } + + if( m_drag == NO_DRAG ) + { + m_selectedSegment = m_currentSegment; + emit sigSelectedSegment( m_selectedSegment ); + } + } + repaint(false); +} + +void KisGradientSliderWidget::mouseReleaseEvent ( QMouseEvent * e ) +{ + QWidget::mouseReleaseEvent( e ); + m_drag = NO_DRAG; +} + +void KisGradientSliderWidget::mouseMoveEvent( QMouseEvent * e ) +{ + QWidget::mouseMoveEvent( e ); + if( ( e->y() < MARGIN || e->y() > height() - MARGIN ) || ( e->x() < MARGIN || e->x() > width() - MARGIN ) ) + return; + double t = (double)(e->x() - MARGIN) / (double)(width() - 2 * MARGIN); + switch( m_drag ) + { + case RIGHT_DRAG: + m_autogradientResource->moveSegmentEndOffset( m_currentSegment, t ); + break; + case LEFT_DRAG: + m_autogradientResource->moveSegmentStartOffset( m_currentSegment, t ); + break; + case MIDDLE_DRAG: + m_autogradientResource->moveSegmentMiddleOffset( m_currentSegment, t ); + break; + } + + if ( m_drag != NO_DRAG) + emit sigChangedSegment( m_currentSegment ); + + repaint(false); +} + +void KisGradientSliderWidget::contextMenuEvent( QContextMenuEvent * e ) +{ + m_segmentMenu->setItemEnabled( REMOVE_SEGMENT, m_autogradientResource->removeSegmentPossible() ); + m_segmentMenu->popup( e->globalPos()); +} + +void KisGradientSliderWidget::slotMenuAction( int id ) +{ + switch( id ) + { + case SPLIT_SEGMENT: + m_autogradientResource->splitSegment( m_selectedSegment ); + break; + case DUPLICATE_SEGMENT: + m_autogradientResource->duplicateSegment( m_selectedSegment ); + break; + case MIRROR_SEGMENT: + m_autogradientResource->mirrorSegment( m_selectedSegment ); + break; + case REMOVE_SEGMENT: + m_selectedSegment = m_autogradientResource->removeSegment( m_selectedSegment ); + break; + } + emit sigSelectedSegment( m_selectedSegment ); + repaint(false); +} + +#include "kis_gradient_slider_widget.moc" diff --git a/krita/ui/kis_gradient_slider_widget.h b/krita/ui/kis_gradient_slider_widget.h new file mode 100644 index 000000000..4bc005437 --- /dev/null +++ b/krita/ui/kis_gradient_slider_widget.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * 2004 Sven Langkamp <longamp@reallygood.de> + * + * 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_WDG_GRADIENT_SLIDER_H_ +#define _KIS_WDG_GRADIENT_SLIDER_H_ + +#include <kpixmapio.h> +#include <qwidget.h> + +class KPopupMenu; +class KisAutogradientResource; +class KisGradientSegment; + +class KisGradientSliderWidget : public QWidget +{ + Q_OBJECT + +public: + KisGradientSliderWidget(QWidget *parent = 0, const char* name = 0, WFlags f = 0); + +public: + virtual void paintEvent ( QPaintEvent * ); + void setGradientResource( KisAutogradientResource* agr); + KisGradientSegment* selectedSegment() { return m_selectedSegment; }; + +signals: + void sigSelectedSegment(KisGradientSegment*); + void sigChangedSegment(KisGradientSegment*); + +protected: + virtual void mousePressEvent( QMouseEvent * e ); + virtual void mouseReleaseEvent ( QMouseEvent * e ); + virtual void mouseMoveEvent( QMouseEvent * e ); + virtual void contextMenuEvent( QContextMenuEvent * e ); + +private slots: + void slotMenuAction(int id); + +private: + + enum { + NO_DRAG, + LEFT_DRAG, + RIGHT_DRAG, + MIDDLE_DRAG + }; + + enum { + SPLIT_SEGMENT, + DUPLICATE_SEGMENT, + MIRROR_SEGMENT, + REMOVE_SEGMENT + }; + + KPixmapIO m_pixmapIO; + KisAutogradientResource* m_autogradientResource; + KisGradientSegment* m_currentSegment; + KisGradientSegment* m_selectedSegment; + KPopupMenu* m_segmentMenu; + int m_drag; +}; + +#endif diff --git a/krita/ui/kis_grid_drawer.cpp b/krita/ui/kis_grid_drawer.cpp new file mode 100644 index 000000000..3af8a92e0 --- /dev/null +++ b/krita/ui/kis_grid_drawer.cpp @@ -0,0 +1,223 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_grid_drawer.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL +#include <qgl.h> +#endif + +#include "kis_config.h" +#include "kis_image.h" +#include "kis_perspective_grid.h" +#include "kis_perspective_grid_manager.h" + +Qt::PenStyle GridDrawer::gs2style(Q_UINT32 s) +{ + switch(s) + { + case 1: + return Qt::DashLine; + case 2: + return Qt::DotLine; + case 3: + return Qt::DashDotLine; + case 4: + return Qt::DashDotDotLine; + default: + return Qt::SolidLine; + } +} + +void GridDrawer::drawPerspectiveGrid(KisImageSP image, const QRect& /*wr*/, const KisSubPerspectiveGrid* grid) +{ + Q_UNUSED(image); + KisConfig cfg; + QPen mainPen = QPen ( cfg.getGridMainColor(), 1, gs2style( cfg.getGridMainStyle() ) ); + QPen subdivisionPen = QPen ( cfg.getGridSubdivisionColor(), 1, gs2style( cfg.getGridSubdivisionStyle() ) ); + setPen(subdivisionPen ); + // 1 -> top-left corner + // 2 -> top-right corner + // 3 -> bottom-right corner + // 4 -> bottom-left corner + // d12 line from top-left to top-right + // note that the notion of top-left is purely theorical + KisPerspectiveMath::LineEquation d12 = KisPerspectiveMath::computeLineEquation( grid->topLeft(), grid->topRight() ) ; + KisPoint v12 = KisPoint(*grid->topLeft() - *grid->topRight()); + v12.setX( v12.x() / grid->subdivisions()); v12.setY( v12.y() / grid->subdivisions() ); + KisPerspectiveMath::LineEquation d23 = KisPerspectiveMath::computeLineEquation( grid->topRight(), grid->bottomRight() ); + KisPoint v23 = KisPoint(*grid->topRight() - *grid->bottomRight()); + v23.setX( v23.x() / grid->subdivisions()); v23.setY( v23.y() / grid->subdivisions() ); + KisPerspectiveMath::LineEquation d34 = KisPerspectiveMath::computeLineEquation( grid->bottomRight(), grid->bottomLeft() ); + KisPerspectiveMath::LineEquation d41 = KisPerspectiveMath::computeLineEquation( grid->bottomLeft(), grid->topLeft() ); + + KisPoint horizVanishingPoint = KisPerspectiveMath::computeIntersection(d12,d34); + KisPoint vertVanishingPoint = KisPerspectiveMath::computeIntersection(d23,d41); + + for(uint i = 1; i < static_cast<uint>(grid->subdivisions()); i ++) + { + KisPoint pol1 = *grid->topRight() + i * v12; + KisPerspectiveMath::LineEquation d1 = KisPerspectiveMath::computeLineEquation( &pol1, &vertVanishingPoint ); + KisPoint pol1b = KisPerspectiveMath::computeIntersection(d1,d34); + drawLine( pol1.roundQPoint(), pol1b.roundQPoint() ); + + KisPoint pol2 = *grid->bottomRight() + i * v23; + KisPerspectiveMath::LineEquation d2 = KisPerspectiveMath::computeLineEquation( &pol2, &horizVanishingPoint ); + KisPoint pol2b = KisPerspectiveMath::computeIntersection(d2,d41); + drawLine( pol2.roundQPoint(), pol2b.roundQPoint() ); + } + setPen(mainPen); + drawLine( grid->topLeft(), grid->topRight() ); + drawLine( grid->topRight(), grid->bottomRight() ); + drawLine( grid->bottomRight(), grid->bottomLeft() ); + drawLine( grid->bottomLeft(), grid->topLeft() ); +} + +void GridDrawer::drawGrid(KisImageSP image, const QRect& wr) +{ + KisConfig cfg; + + Q_UINT32 offsetx = cfg.getGridOffsetX(); + Q_UINT32 offsety = cfg.getGridOffsetY(); + Q_UINT32 hspacing = cfg.getGridHSpacing(); + Q_UINT32 vspacing = cfg.getGridVSpacing(); + Q_UINT32 subdivision = cfg.getGridSubdivisions() - 1; + //double ihspsub = hspacing / (double)subdivision; + //double ivspsub = hspacing / (double)subdivision; + + Q_INT32 imageWidth = image->width(); + Q_INT32 imageHeight = image->height(); + + // Draw vertical line + QPen mainPen = QPen ( cfg.getGridMainColor(), 1, gs2style( cfg.getGridMainStyle() ) ); + QPen subdivisionPen = QPen ( cfg.getGridSubdivisionColor(), 1, gs2style( cfg.getGridSubdivisionStyle() ) ); + Q_UINT32 i = 0; + for( Q_INT32 x = offsetx; x <= wr.right(); x +=hspacing) + { + if( i == subdivision ) + { + setPen(mainPen); + i = 0; + } else { + setPen(subdivisionPen); + i++; + } + if( x >= wr.x() ) + { + // Always draw the full line otherwise the line stippling varies + // with the location of wr and we get glitchy patterns. + drawLine(x, 0, x, imageHeight); + } + } + // Draw horizontal line + i = 0; + for( Q_INT32 y = offsety; y <= wr.bottom(); y +=vspacing) + { + if( i == subdivision ) + { + setPen(mainPen); + i = 0; + } else { + setPen(subdivisionPen); + i++; + } + if( y >= wr.y() ) + { + drawLine(0, y, imageWidth, y); + } + } +} + +OpenGLGridDrawer::OpenGLGridDrawer() +{ +#ifdef HAVE_GL + glPushAttrib(GL_ALL_ATTRIB_BITS); +#endif +} + +OpenGLGridDrawer::~OpenGLGridDrawer() +{ +#ifdef HAVE_GL + glPopAttrib(); +#endif +} + +void OpenGLGridDrawer::setPen(const QPen& pen) +{ +#ifdef HAVE_GL + Qt::PenStyle penStyle = pen.style(); + + if (penStyle == Qt::SolidLine) { + glDisable(GL_LINE_STIPPLE); + } else { + GLushort lineStipple; + + switch (penStyle) { + case Qt::NoPen: + lineStipple = 0; + break; + default: + case Qt::SolidLine: + lineStipple = 0xffff; + break; + case Qt::DashLine: + lineStipple = 0x3fff; + break; + case Qt::DotLine: + lineStipple = 0x3333; + break; + case Qt::DashDotLine: + lineStipple = 0x33ff; + break; + case Qt::DashDotDotLine: + lineStipple = 0x333f; + break; + } + + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, lineStipple); + } + + QColor penColor = pen.color(); + + glColor3ub(penColor.red(), penColor.green(), penColor.blue()); +#else + Q_UNUSED(pen); +#endif +} + +void OpenGLGridDrawer::drawLine(Q_INT32 x1, Q_INT32 y1, Q_INT32 x2, Q_INT32 y2) +{ +#ifdef HAVE_GL + glBegin(GL_LINES); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); +#else + Q_UNUSED(x1); + Q_UNUSED(y1); + Q_UNUSED(x2); + Q_UNUSED(y2); +#endif +} diff --git a/krita/ui/kis_grid_drawer.h b/krita/ui/kis_grid_drawer.h new file mode 100644 index 000000000..1078883ec --- /dev/null +++ b/krita/ui/kis_grid_drawer.h @@ -0,0 +1,71 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_GRID_DRAWER_H +#define KIS_GRID_DRAWER_H + +#include <math.h> + +#include <qobject.h> +#include <qpainter.h> + +#include "kis_types.h" +#include "kis_point.h" + +class KisSubPerspectiveGrid; + +class GridDrawer { + public: + GridDrawer() {} + virtual ~GridDrawer() {} + + public: + void drawGrid(KisImageSP image, const QRect& wr); + void drawPerspectiveGrid(KisImageSP image, const QRect& wr, const KisSubPerspectiveGrid* grid); + + virtual void setPen(const QPen& pen) = 0; + virtual void drawLine(Q_INT32 x1, Q_INT32 y1, Q_INT32 x2, Q_INT32 y2) = 0; + inline void drawLine(const QPoint& p1, const QPoint& p2) { drawLine(p1.x(), p1.y(), p2.x(), p2.y() ); } + inline void drawLine(const KisPoint* p1, const KisPoint* p2) { drawLine( p1->roundQPoint(), p2->roundQPoint()); } + private: + Qt::PenStyle gs2style(Q_UINT32 s); +}; + +class QPainterGridDrawer : public GridDrawer { +public: + QPainterGridDrawer(QPainter *p) { m_painter = p; } + + virtual void setPen(const QPen& pen) { m_painter->setPen(pen); } + virtual void drawLine(Q_INT32 x1, Q_INT32 y1, Q_INT32 x2, Q_INT32 y2) { m_painter->drawLine(x1, y1, x2, y2); } + +private: + QPainter *m_painter; +}; + +class OpenGLGridDrawer : public GridDrawer { +public: + OpenGLGridDrawer(); + virtual ~OpenGLGridDrawer(); + + virtual void setPen(const QPen& pen); + virtual void drawLine(Q_INT32 x1, Q_INT32 y1, Q_INT32 x2, Q_INT32 y2); +}; + +#endif diff --git a/krita/ui/kis_grid_manager.cpp b/krita/ui/kis_grid_manager.cpp new file mode 100644 index 000000000..0bbbcd88f --- /dev/null +++ b/krita/ui/kis_grid_manager.cpp @@ -0,0 +1,156 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_grid_manager.h" + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL +#include <qgl.h> +#endif + +#include <qradiobutton.h> + +#include <kaction.h> +#include <kdialogbase.h> +#include <klocale.h> + + +#include "kis_config.h" +#include "kis_grid_drawer.h" +#include "kis_image.h" +#include "kis_view.h" + +KisGridManager::KisGridManager(KisView * parent) + : QObject(parent), m_view(parent) +{ + +} + +KisGridManager::~KisGridManager() +{ + +} + +void KisGridManager::setup(KActionCollection * collection) +{ + m_toggleGrid = new KToggleAction(i18n("Show Grid"), "", this, SLOT(toggleGrid()), collection, "view_toggle_grid"); + m_toggleGrid->setCheckedState(KGuiItem(i18n("Hide Grid"))); + m_toggleGrid->setChecked(false); + + // Fast grid config + m_gridFastConfig1x1 = new KAction(i18n("1x1"), 0, "", this, SLOT(fastConfig1x1()), collection, "view_fast_grid_1x1"); + m_gridFastConfig2x2 = new KAction(i18n("2x2"), 0, "", this, SLOT(fastConfig2x2()), collection, "view_fast_grid_2x2"); + m_gridFastConfig5x5 = new KAction(i18n("5x5"), 0, "", this, SLOT(fastConfig5x5()), collection, "view_fast_grid_5x5"); + m_gridFastConfig10x10 = new KAction(i18n("10x10"), 0, "", this, SLOT(fastConfig10x10()), collection, "view_fast_grid_10x10"); + m_gridFastConfig20x20 = new KAction(i18n("20x20"), 0, "", this, SLOT(fastConfig20x20()), collection, "view_fast_grid_20x20"); + m_gridFastConfig40x40 = new KAction(i18n("40x40"), 0, "", this, SLOT(fastConfig40x40()), collection, "view_fast_grid_40x40"); +} + +void KisGridManager::updateGUI() +{ + +} + +void KisGridManager::toggleGrid() +{ + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig1x1() +{ + KisConfig cfg; + cfg.setGridHSpacing(1); + cfg.setGridVSpacing(1); + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig2x2() +{ + KisConfig cfg; + cfg.setGridHSpacing(2); + cfg.setGridVSpacing(2); + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig5x5() +{ + KisConfig cfg; + cfg.setGridHSpacing(5); + cfg.setGridVSpacing(5); + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig10x10() +{ + KisConfig cfg; + cfg.setGridHSpacing(10); + cfg.setGridVSpacing(10); + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig20x20() +{ + KisConfig cfg; + cfg.setGridHSpacing(20); + cfg.setGridVSpacing(20); + m_view->updateCanvas(); +} + +void KisGridManager::fastConfig40x40() +{ + KisConfig cfg; + cfg.setGridHSpacing(40); + cfg.setGridVSpacing(40); + m_view->updateCanvas(); +} + +void KisGridManager::drawGrid(QRect wr, QPainter *p, bool openGL) +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + + if (image) { + if (m_toggleGrid->isChecked()) + { + GridDrawer *gridDrawer = 0; + + if (openGL) { + gridDrawer = new OpenGLGridDrawer(); + } else { + Q_ASSERT(p); + + if (p) { + gridDrawer = new QPainterGridDrawer(p); + } + } + + Q_ASSERT(gridDrawer != 0); + + if (gridDrawer) { + gridDrawer->drawGrid(image, wr); + delete gridDrawer; + } + } + } +} + +#include "kis_grid_manager.moc" diff --git a/krita/ui/kis_grid_manager.h b/krita/ui/kis_grid_manager.h new file mode 100644 index 000000000..bd46b5bcd --- /dev/null +++ b/krita/ui/kis_grid_manager.h @@ -0,0 +1,64 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_GRID_MANAGER_H +#define KIS_GRID_MANAGER_H + +#include <qobject.h> + +#include "kis_types.h" + +class KisView; +class KActionCollection; +class KToggleAction; +class KAction; + +class KisGridManager : public QObject +{ + Q_OBJECT + public: + KisGridManager(KisView * parent); + ~KisGridManager(); + public: + void setup(KActionCollection * collection); + void drawGrid(QRect wr, QPainter *p, bool openGL = false); + public slots: + void updateGUI(); + private slots: + void toggleGrid(); + void fastConfig1x1(); + void fastConfig2x2(); + void fastConfig5x5(); + void fastConfig10x10(); + void fastConfig20x20(); + void fastConfig40x40(); + private: + KisView* m_view; + KToggleAction* m_toggleGrid; + KAction* m_gridConfig; + KAction* m_gridFastConfig1x1; + KAction* m_gridFastConfig2x2; + KAction* m_gridFastConfig5x5; + KAction* m_gridFastConfig10x10; + KAction* m_gridFastConfig20x20; + KAction* m_gridFastConfig40x40; +}; + +#endif diff --git a/krita/ui/kis_histogram_view.cc b/krita/ui/kis_histogram_view.cc new file mode 100644 index 000000000..67c308897 --- /dev/null +++ b/krita/ui/kis_histogram_view.cc @@ -0,0 +1,354 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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 <math.h> + +#include <qpainter.h> +#include <qpixmap.h> +#include <qlabel.h> +#include <qcombobox.h> +#include <qbuttongroup.h> +#include <qpushbutton.h> +#include <qscrollbar.h> + +#include <kdebug.h> + +#include "kis_channelinfo.h" +#include "kis_histogram.h" +#include "kis_global.h" +#include "kis_types.h" +#include "kis_layer.h" +#include "kis_colorspace.h" +#include "kis_histogram_view.h" +#include "kis_basic_histogram_producers.h" +#include "kis_paint_device.h" + +KisHistogramView::KisHistogramView(QWidget *parent, const char *name, WFlags f) + : QLabel(parent, name, f) +{ + // This is needed until we can computationally scale it well. Until then, this is needed + // And when we have it, it won't hurt to have it around + setScaledContents(true); + setFrameShape(QFrame::Box); // Draw a box around ourselves +} + +KisHistogramView::~KisHistogramView() +{ +} + +void KisHistogramView::setPaintDevice(KisPaintDeviceSP dev) +{ + m_cs = dev->colorSpace(); + + setChannels(); // Sets m_currentProducer to the first in the list + + if (!m_currentProducer) + return; + + m_from = m_currentProducer->viewFrom(); + m_width = m_currentProducer->viewWidth(); + + m_histogram = new KisHistogram(dev, m_currentProducer, LINEAR); + + updateHistogram(); +} + +void KisHistogramView::setHistogram(KisHistogramSP histogram) +{ + m_cs = 0; + m_histogram = histogram; + m_currentProducer = m_histogram->producer(); + m_from = m_currentProducer->viewFrom(); + m_width = m_currentProducer->viewWidth(); + + m_comboInfo.clear(); + m_channelStrings.clear(); + m_channels.clear(); + m_channelToOffset.clear(); + + addProducerChannels(m_currentProducer); + + // Set the currently viewed channel: + m_color = false; + m_channels.append(m_comboInfo.at(1).channel); + m_channelToOffset.append(0); + + updateHistogram(); +} + +void KisHistogramView::setView(double from, double size) +{ + m_from = from; + m_width = size; + if (m_from + m_width > 1.0) + m_from = 1.0 - m_width; + m_histogram->producer()->setView(m_from, m_width); + + m_histogram->updateHistogram(); + updateHistogram(); +} + +KisHistogramProducerSP KisHistogramView::currentProducer() +{ + return m_currentProducer; +} + +QStringList KisHistogramView::channelStrings() +{ + return m_channelStrings; +} + +KisIDList KisHistogramView::listProducers() +{ + if (m_cs) + return KisHistogramProducerFactoryRegistry::instance()->listKeysCompatibleWith(m_cs); + return KisIDList(); +} + +void KisHistogramView::setCurrentChannels(const KisID& producerID, QValueVector<KisChannelInfo *> channels) +{ + setCurrentChannels( + KisHistogramProducerFactoryRegistry::instance()->get(producerID)->generate(), + channels); +} + +void KisHistogramView::setCurrentChannels(KisHistogramProducerSP producer, QValueVector<KisChannelInfo *> channels) +{ + m_currentProducer = producer; + m_currentProducer->setView(m_from, m_width); + m_histogram->setProducer(m_currentProducer); + m_histogram->updateHistogram(); + m_histogram->setChannel(0); // Set a default channel, just being nice + + m_channels.clear(); + m_channelToOffset.clear(); + + if (channels.count() == 0) { + updateHistogram(); + return; + } + + QValueVector<KisChannelInfo *> producerChannels = m_currentProducer->channels(); + + for (uint i = 0; i < channels.count(); i++) { + // Also makes sure the channel is actually in the producer's list + for (uint j = 0; j < producerChannels.count(); j++) { + if (channels.at(i)->name() == producerChannels.at(j)->name()) { + m_channelToOffset.append(m_channels.count()); // The first we append maps to 0 + m_channels.append(channels.at(i)); + } + } + } + + updateHistogram(); +} + +bool KisHistogramView::hasColor() +{ + return m_color; +} + +void KisHistogramView::setColor(bool set) +{ + if (set != m_color) { + m_color = set; + updateHistogram(); + } +} + +void KisHistogramView::setActiveChannel(int channel) +{ + ComboboxInfo info = m_comboInfo.at(channel); + if (info.producer.data() != m_currentProducer.data()) { + m_currentProducer = info.producer; + m_currentProducer->setView(m_from, m_width); + m_histogram->setProducer(m_currentProducer); + m_histogram->updateHistogram(); + } + + m_channels.clear(); + m_channelToOffset.clear(); + + if (!m_currentProducer) { + updateHistogram(); + return; + } + + if (info.isProducer) { + m_color = true; + m_channels = m_currentProducer->channels(); + for (uint i = 0; i < m_channels.count(); i++) + m_channelToOffset.append(i); + m_histogram->setChannel(0); // Set a default channel, just being nice + } else { + m_color = false; + QValueVector<KisChannelInfo *> channels = m_currentProducer->channels(); + for (uint i = 0; i < channels.count(); i++) { + KisChannelInfo* channel = channels.at(i); + if (channel->name() == info.channel->name()) { + m_channels.append(channel); + m_channelToOffset.append(i); + break; + } + } + } + + updateHistogram(); +} + +void KisHistogramView::setHistogramType(enumHistogramType type) +{ + m_histogram->setHistogramType(type); + updateHistogram(); +} + +void KisHistogramView::setChannels() +{ + m_comboInfo.clear(); + m_channelStrings.clear(); + m_channels.clear(); + m_channelToOffset.clear(); + + KisIDList list = KisHistogramProducerFactoryRegistry::instance()->listKeysCompatibleWith(m_cs); + + if (list.count() == 0) { + // XXX: No native histogram for this colorspace. Using converted RGB. We should have a warning + KisGenericRGBHistogramProducerFactory f; + addProducerChannels(f.generate()); + } else { + for (uint i = 0; i < list.count(); i++) { + KisID id(*(list.at(i))); + addProducerChannels( KisHistogramProducerFactoryRegistry::instance()->get(id)->generate() ); + } + } + + m_currentProducer = m_comboInfo.at(0).producer; + m_color = false; + // The currently displayed channel and its offset + m_channels.append(m_comboInfo.at(1).channel); + m_channelToOffset.append(0); +} + +void KisHistogramView::addProducerChannels(KisHistogramProducerSP producer) { + ComboboxInfo info; + info.isProducer = true; + info.producer = producer; + // channel not used for a producer + QValueVector<KisChannelInfo *> channels = info.producer->channels(); + int count = channels.count(); + m_comboInfo.append(info); + m_channelStrings.append(producer->id() . name()); + for (int j = 0; j < count; j++) { + info.isProducer = false; + info.channel = channels.at(j); + m_comboInfo.append(info); + m_channelStrings.append(QString(" ").append(info.channel->name())); + } +} + +void KisHistogramView::updateHistogram() +{ + Q_UINT32 height = this->height(); + int selFrom, selTo; // from - to in bins + + if (!m_currentProducer) { // Something's very wrong: no producer for this colorspace to update histogram with! + return; + } + + Q_INT32 bins = m_histogram->producer()->numberOfBins(); + m_pix = QPixmap(bins, height); + m_pix.fill(); + QPainter p(&m_pix); + p.setBrush(Qt::black); + + // Draw the box of the selection, if any + if (m_histogram->hasSelection()) { + double width = m_histogram->selectionTo() - m_histogram->selectionFrom(); + double factor = static_cast<double>(bins) / m_histogram->producer()->viewWidth(); + selFrom = static_cast<int>(m_histogram->selectionFrom() * factor); + selTo = selFrom + static_cast<int>(width * factor); + p.drawRect(selFrom, 0, selTo - selFrom, height); + } else { + // We don't want the drawing to think we're in a selected area + selFrom = -1; + selTo = 2; + } + + Q_INT32 i = 0; + double highest = 0; + bool blackOnBlack = false; + + // First we iterate once, so that we have the overall maximum. This is a bit inefficient, + // but not too much since the histogram caches the calculations + for (uint chan = 0; chan < m_channels.count(); chan++) { + m_histogram->setChannel(m_channelToOffset.at(chan)); + if ((double)m_histogram->calculations().getHighest() > highest) + highest = (double)m_histogram->calculations().getHighest(); + } + + for (uint chan = 0; chan < m_channels.count(); chan++) { + QColor color; + m_histogram->setChannel(m_channelToOffset.at(chan)); + + if (m_color) { + color = m_channels.at(chan)->color(); + p.setPen(color); + } else { + color = Qt::black; + } + blackOnBlack = (color == Qt::black); + + if (m_histogram->getHistogramType() == LINEAR) { + double factor = (double)height / highest; + for( i=0; i<bins; ++i ) { + // So that we get a good view even with a selection box with + // black colors on background of black selection + if (i >= selFrom && i < selTo && blackOnBlack) { + p.setPen(Qt::white); + } else { + p.setPen(color); + } + p.drawLine(i, height, i, height - int(m_histogram->getValue(i) * factor)); + } + } else { + double factor = (double)height / (double)log(highest); + for( i = 0; i < bins; ++i ) { + // Same as above + if (i >= selFrom && i < selTo && blackOnBlack) { + p.setPen(Qt::white); + } else { + p.setPen(color); + } + p.drawLine(i, height, i, + height - int(log((double)m_histogram->getValue(i)) * factor)); + } + } + } + + setPixmap(m_pix); +} + +void KisHistogramView::mousePressEvent(QMouseEvent * e) { + if (e->button() == Qt::RightButton) + emit rightClicked(e->globalPos()); + else + QLabel::mousePressEvent(e); +} + + +#include "kis_histogram_view.moc" diff --git a/krita/ui/kis_histogram_view.h b/krita/ui/kis_histogram_view.h new file mode 100644 index 000000000..b44ee79d2 --- /dev/null +++ b/krita/ui/kis_histogram_view.h @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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_HISTOGRAM_VIEW_ +#define _KIS_HISTOGRAM_VIEW_ + +#include <qlabel.h> +#include <qpixmap.h> +#include <qvaluevector.h> +#include <qstringlist.h> + +#include "kis_types.h" +#include "kis_histogram_producer.h" +#include "kis_histogram.h" + +class KisChannelInfo; + +/** + * This class displays a histogram. It has a list of channels it can select. The easy + * way is to display channelStrings() to the user, and then use a setActiveChannel + * with the integer the same as the one the selected string in that stringlist has. + * If the selected one is a producer, the histogram will automatically display all its + * channels, and color them if that is possible. + * + * You can also set the channels manually, just don't forget that the displayed channels + * all need to belong to the same producer! If you set them manually, don't forget to set + * the (non)usage of color as well. + * + * You can either set this to use a specific layer, or use a specific histogram. With the latter, + * some functionality will disappear, like listProducers(). Setting a histogram will discard + * info on the layer, and setting a layer will discard info on the histogram. + **/ +class KisHistogramView : public QLabel { + Q_OBJECT +public: + KisHistogramView(QWidget *parent = 0, const char *name = 0, WFlags f = 0); + virtual ~KisHistogramView(); + + void setPaintDevice(KisPaintDeviceSP dev); + void setHistogram(KisHistogramSP histogram); + void setView(double from, double size); + KisHistogramProducerSP currentProducer(); + QStringList channelStrings(); + /** Lists all producers currently available */ + KisIDList listProducers(); + /** Sets the currently displayed channels to channels of the producer with producerID as ID*/ + void setCurrentChannels(const KisID& producerID, QValueVector<KisChannelInfo *> channels); + /** Be careful, producer will be modified */ + void setCurrentChannels(KisHistogramProducerSP producer, QValueVector<KisChannelInfo *> channels); + bool hasColor(); + void setColor(bool set); + +public slots: + void setActiveChannel(int channel); + void setHistogramType(enumHistogramType type); + void updateHistogram(); + +signals: + void rightClicked(const QPoint& pos); + +protected: + virtual void mousePressEvent(QMouseEvent * e); + +private: + void setChannels(); + void addProducerChannels(KisHistogramProducerSP producer); + + typedef struct { + bool isProducer; + KisHistogramProducerSP producer; + KisChannelInfo * channel; + } ComboboxInfo; + + QValueVector<ComboboxInfo> m_comboInfo; + QPixmap m_pix; + KisHistogramSP m_histogram; + KisColorSpace* m_cs; + KisHistogramProducerSP m_currentProducer; + QValueVector<KisChannelInfo *> m_channels; + // Maps the channels in m_channels to a real channel offset in the producer->channels() + QValueVector<Q_INT32> m_channelToOffset; + QStringList m_channelStrings; + bool m_color; + double m_from; + double m_width; +}; + +#endif // _KIS_HISTOGRAM_VIEW_ diff --git a/krita/ui/kis_icon_item.cc b/krita/ui/kis_icon_item.cc new file mode 100644 index 000000000..443416cc1 --- /dev/null +++ b/krita/ui/kis_icon_item.cc @@ -0,0 +1,116 @@ +/* + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org + * + * 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.g + * + * 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 <kdebug.h> + +#include "kis_resource.h" +#include "kis_global.h" +#include "kis_icon_item.h" + +#define THUMB_SIZE 30 + +KisIconItem::KisIconItem(KisResource *resource) +{ + m_resource = resource; + validPixmap = false; + validThumb = false; + updatePixmaps(); +} + +KisIconItem::~KisIconItem() +{ +} + +void KisIconItem::updatePixmaps() +{ + validPixmap = false; + validThumb = false; + + if (m_resource && m_resource->valid()) { + QImage img = m_resource->img(); + + if (img.isNull()) { + m_resource->setValid(false); + m_resource = 0; + return; + } + + if (img.width() > THUMB_SIZE || img.height() > THUMB_SIZE) { + QImage thumb = img; + Q_INT32 xsize = THUMB_SIZE; + Q_INT32 ysize = THUMB_SIZE; + Q_INT32 picW = thumb.width(); + Q_INT32 picH = thumb.height(); + + if (picW > picH) { + float yFactor = (float)((float)(float)picH / (float)picW); + + ysize = (Q_INT32)(yFactor * (float)THUMB_SIZE); + + if (ysize > THUMB_SIZE) + ysize = THUMB_SIZE; + } else if (picW < picH) { + float xFactor = (float)((float)picW / (float)picH); + + xsize = (Q_INT32)(xFactor * (float)THUMB_SIZE); + + if (xsize > THUMB_SIZE) + xsize = THUMB_SIZE; + } + + thumb = thumb.smoothScale(xsize, ysize); + + if (!thumb.isNull()) { + m_thumb = QPixmap(thumb); + validThumb = !m_thumb.isNull(); + } + } + + img = img.convertDepth(32); + m_pixmap = QPixmap(img); + validPixmap = true; + } +} + +QPixmap& KisIconItem::pixmap() const +{ + return const_cast<QPixmap&>(m_pixmap); +} + +QPixmap& KisIconItem::thumbPixmap() const +{ + return const_cast<QPixmap&>(m_thumb); +} + +KisResource *KisIconItem::resource() const +{ + return m_resource; +} + +int KisIconItem::compare(const KoIconItem *o) const +{ + const KisIconItem *other = dynamic_cast<const KisIconItem *>(o); + + if (other != 0) { + return m_resource->name().localeAwareCompare(other->m_resource->name()); + } else { + return 0; + } +} + diff --git a/krita/ui/kis_icon_item.h b/krita/ui/kis_icon_item.h new file mode 100644 index 000000000..7d76f05c5 --- /dev/null +++ b/krita/ui/kis_icon_item.h @@ -0,0 +1,48 @@ +/* + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org + * + * 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.g + * + * 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_ICON_ITEM_H_ +#define KIS_ICON_ITEM_H_ + +#include <koIconChooser.h> + +class KisResource; + +class KisIconItem : public KoIconItem { + +public: + KisIconItem(KisResource *resource); + virtual ~KisIconItem(); + + virtual QPixmap& pixmap() const; + virtual QPixmap& thumbPixmap() const; + + KisResource *resource() const; + + virtual int compare(const KoIconItem *other) const; + + void updatePixmaps(); + +private: + KisResource *m_resource; + QPixmap m_pixmap; + QPixmap m_thumb; +}; + +#endif // KIS_ICON_ITEM_H_ + diff --git a/krita/ui/kis_iconwidget.cc b/krita/ui/kis_iconwidget.cc new file mode 100644 index 000000000..20f8838d9 --- /dev/null +++ b/krita/ui/kis_iconwidget.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2000 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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.g + * + * 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 <qpainter.h> +#include <koIconChooser.h> +#include "kis_iconwidget.h" + +KisIconWidget::KisIconWidget(QWidget *parent, const char *name) : super(parent, name) +{ + m_item = 0; +} + +void KisIconWidget::slotSetItem(KoIconItem& item) +{ + m_item = &item; + update(); +} + +void KisIconWidget::drawButtonLabel(QPainter *p) +{ + if (m_item) { + const QPixmap& pix = m_item->pixmap(); + Q_INT32 x = 2; + Q_INT32 y = 2; + Q_INT32 pw = pix.width(); + Q_INT32 ph = pix.height(); + Q_INT32 cw = width(); + Q_INT32 ch = height(); + Q_INT32 itemWidth = 24; + Q_INT32 itemHeight = 24; + + if (pw < itemWidth) + x = (cw - pw) / 2; + if (ph < itemHeight) + y = (cw - ph) / 2; + + if (!m_item->hasValidThumb() || (pw <= itemWidth && ph <= itemHeight)) { + p->drawPixmap(x, y, pix, 0, 0, itemWidth, itemHeight); + } else { + const QPixmap& thumbpix = m_item->thumbPixmap(); + + x = 2; + y = 2; + pw = thumbpix.width(); + ph = thumbpix.height(); + cw = width(); + ch = height(); + + if (pw < itemWidth) + x = (cw - pw) / 2; + + if (ph < itemHeight) + y = (cw - ph) / 2; + + p->drawPixmap(x, y, thumbpix, 0, 0, itemWidth, itemHeight); + } + + p->setPen(gray); + p->drawRect(0, 0, cw + 1, ch + 1); + } +} + +#include "kis_iconwidget.moc" + diff --git a/krita/ui/kis_iconwidget.h b/krita/ui/kis_iconwidget.h new file mode 100644 index 000000000..e595dbe2f --- /dev/null +++ b/krita/ui/kis_iconwidget.h @@ -0,0 +1,49 @@ +/* + * Copyright (c) 2000 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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_ICONWIDGET_H_ +#define KIS_ICONWIDGET_H_ + +#include <qtoolbutton.h> + +class KoIconItem; + +class KisIconWidget : public QToolButton { + typedef QToolButton super; + Q_OBJECT + +/** + * The icon widget is used in the control box where the current color and brush + * are shown. + */ +public: + KisIconWidget(QWidget *parent = 0, const char *name = 0); + +public slots: + void slotSetItem(KoIconItem& item); + +protected: + virtual void drawButtonLabel(QPainter *gc); + +private: + KoIconItem *m_item; +}; + +#endif // KIS_ICONWIDGET_H_ + diff --git a/krita/ui/kis_import_catcher.cc b/krita/ui/kis_import_catcher.cc new file mode 100644 index 000000000..656ab9692 --- /dev/null +++ b/krita/ui/kis_import_catcher.cc @@ -0,0 +1,80 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <kdebug.h> + +#include "kis_import_catcher.h" +#include "kis_types.h" + +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_group_layer.h" + +KisImportCatcher::KisImportCatcher(KURL url, KisImageSP image) + : QObject() + , m_doc( new KisDoc() ) + , m_image( image ) + , m_url( url ) +{ + m_doc->openURL(url); + if ( !m_doc->isLoading() ) { + slotLoadingFinished(); + } + else { + connect(m_doc, SIGNAL(loadingFinished()), this, SLOT(slotLoadingFinished())); + } +} + +void KisImportCatcher::slotLoadingFinished() +{ + KisImageSP importedImage = m_doc->currentImage(); + + if (importedImage) { + KisLayerSP importedImageLayer = importedImage->rootLayer().data(); + + if (importedImageLayer != 0) { + + if (importedImageLayer->numLayers() == 2) { + // Don't import the root if this is not a layered image (1 group layer + // plus 1 other). + importedImageLayer = importedImageLayer->firstChild(); + importedImageLayer->parent()->removeLayer(importedImageLayer); + } + + importedImageLayer->setName(m_url.prettyURL()); + + KisGroupLayerSP parent = 0; + KisLayerSP currentActiveLayer = m_image->activeLayer(); + + if (currentActiveLayer) { + parent = currentActiveLayer->parent(); + } + + if (parent == 0) { + parent = m_image->rootLayer(); + } + + m_image->addLayer(importedImageLayer.data(), parent, currentActiveLayer); + } + } + m_doc->deleteLater(); + deleteLater(); +} + + diff --git a/krita/ui/kis_import_catcher.h b/krita/ui/kis_import_catcher.h new file mode 100644 index 000000000..8e7777ac8 --- /dev/null +++ b/krita/ui/kis_import_catcher.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * + * 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_IMPORT_CATCHER_H_ +#define KIS_IMPORT_CATCHER_H_ + +#include <qobject.h> + +#include <kurl.h> + +#include <kis_types.h> + +class KisView; +class KisDoc; + +/** + * This small helper class takes an url and an image; tries to import + * the image at the url and shove the layers of the imported image + * into the first image after loading is done. + * + * Caveat: this class calls "delete this", which means that you new + * it and then never touch it again. Thanks you very much. + */ +class KisImportCatcher : QObject { + + Q_OBJECT + +public: + + KisImportCatcher(KURL url, KisImageSP image); + +public slots: + + void slotLoadingFinished(); + +private: + KisDoc * m_doc; + KisImage * m_image; + KURL m_url; +}; + +#endif diff --git a/krita/ui/kis_input_device.cc b/krita/ui/kis_input_device.cc new file mode 100644 index 000000000..3f63e1564 --- /dev/null +++ b/krita/ui/kis_input_device.cc @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2006 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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_input_device.h" + +#define UNKNOWN_INPUT_DEVICE_ID -1 +#define FIRST_INPUT_DEVICE_ID 0 + +Q_INT32 KisInputDevice::NextInputDeviceID = FIRST_INPUT_DEVICE_ID; + +KisInputDevice KisInputDevice::Mouse; +KisInputDevice KisInputDevice::Stylus; +KisInputDevice KisInputDevice::Eraser; +KisInputDevice KisInputDevice::Puck; +KisInputDevice KisInputDevice::Unknown(UNKNOWN_INPUT_DEVICE_ID); + +QValueVector<KisInputDevice> KisInputDevice::InputDevices; + +KisInputDevice::KisInputDevice() +{ + m_id = UNKNOWN_INPUT_DEVICE_ID; +} + +KisInputDevice KisInputDevice::allocateNextDevice() +{ + KisInputDevice inputDevice(NextInputDeviceID); + NextInputDeviceID++; + InputDevices.append(inputDevice); + + return inputDevice; +} + +KisInputDevice KisInputDevice::allocateInputDevice() +{ + allocateDefaultDevicesIfNeeded(); + + return allocateNextDevice(); +} + +void KisInputDevice::allocateDefaultDevicesIfNeeded() +{ + if (NextInputDeviceID == FIRST_INPUT_DEVICE_ID) { + Mouse = allocateNextDevice(); + Stylus = allocateNextDevice(); + Eraser = allocateNextDevice(); + Puck = allocateNextDevice(); + } +} + +QValueVector<KisInputDevice> KisInputDevice::inputDevices() +{ + allocateDefaultDevicesIfNeeded(); + + return InputDevices; +} + +KisInputDevice KisInputDevice::mouse() +{ + allocateDefaultDevicesIfNeeded(); + return Mouse; +} + +KisInputDevice KisInputDevice::stylus() +{ + allocateDefaultDevicesIfNeeded(); + return Stylus; +} + +KisInputDevice KisInputDevice::eraser() +{ + allocateDefaultDevicesIfNeeded(); + return Eraser; +} + +KisInputDevice KisInputDevice::puck() +{ + allocateDefaultDevicesIfNeeded(); + return Puck; +} + +KisInputDevice KisInputDevice::unknown() +{ + allocateDefaultDevicesIfNeeded(); + return Unknown; +} + diff --git a/krita/ui/kis_input_device.h b/krita/ui/kis_input_device.h new file mode 100644 index 000000000..91c5ff4ff --- /dev/null +++ b/krita/ui/kis_input_device.h @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2006 Adrian Page <adrian@pagenet.plus.com> + * + * 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_INPUT_DEVICE_H_ +#define KIS_INPUT_DEVICE_H_ + +#include <qvaluevector.h> + +class KisInputDevice { +public: + KisInputDevice(); + + static KisInputDevice allocateInputDevice(); + static QValueVector<KisInputDevice> inputDevices(); + + friend inline bool operator==(const KisInputDevice&, const KisInputDevice&); + friend inline bool operator!=(const KisInputDevice&, const KisInputDevice&); + + friend inline bool operator<(const KisInputDevice &, const KisInputDevice &); + friend inline bool operator>(const KisInputDevice &, const KisInputDevice &); + + static KisInputDevice mouse(); // Standard mouse + static KisInputDevice stylus(); // Wacom stylus via QTabletEvent + static KisInputDevice eraser(); // Wacom eraser via QTabletEvent + static KisInputDevice puck(); // Wacom puck via QTabletEvent + static KisInputDevice unknown(); + +private: + KisInputDevice(Q_INT32 id) : m_id(id) {} + + Q_INT32 id() const { return m_id; } + + static void allocateDefaultDevicesIfNeeded(); + static KisInputDevice allocateNextDevice(); + +private: + Q_INT32 m_id; + + static Q_INT32 NextInputDeviceID; + static QValueVector<KisInputDevice> InputDevices; + + static KisInputDevice Mouse; + static KisInputDevice Stylus; + static KisInputDevice Eraser; + static KisInputDevice Puck; + static KisInputDevice Unknown; +}; + +inline bool operator==(const KisInputDevice &a, const KisInputDevice &b) +{ + return a.id() == b.id(); +} + +inline bool operator!=(const KisInputDevice &a, const KisInputDevice &b) +{ + return a.id() != b.id(); +} + +inline bool operator<(const KisInputDevice &a, const KisInputDevice &b) +{ + return a.id() < b.id(); +} + + +inline bool operator>(const KisInputDevice &a, const KisInputDevice &b) +{ + return a.id() > b.id(); +} + +#endif // KIS_INPUT_DEVICE_H_ + diff --git a/krita/ui/kis_int_spinbox.cc b/krita/ui/kis_int_spinbox.cc new file mode 100644 index 000000000..0d5d8c75b --- /dev/null +++ b/krita/ui/kis_int_spinbox.cc @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2006 Casper Boemann <cbr@boemann.dk> + * + * Requires the Qt widget libraries, available at no cost at + * http://www.troll.no/ + * + * 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. + */ + +#ifdef HAVE_LIMITS_H +#include <limits.h> +#endif +#include <assert.h> +#include <math.h> +#include <algorithm> + +#include <qtimer.h> +#include <qapplication.h> +#include <qsize.h> +#include <qslider.h> +#include <qstyle.h> +#include <qlabel.h> +#include <qpopupmenu.h> +#include <qlineedit.h> +#include <qlayout.h> +#include <qvalidator.h> + +#include <knuminput.h> +#include <kglobal.h> +#include <klocale.h> +#include <kdebug.h> +#include <karrowbutton.h> + +#include "kdialog.h" +#include "knumvalidator.h" +#include "kis_int_spinbox.h" + +class KisIntSpinbox::KisIntSpinboxPrivate { +public: + + KIntSpinBox * m_numinput; + KisPopupSlider *m_slider; + KArrowButton *m_arrow; + int m_prevValue; + QValidator *m_validator; + QTimer m_timer; +}; + + +KisIntSpinbox::KisIntSpinbox(QWidget *parent, const char *name) + : QWidget(parent, name) +{ + init(0); +} + +KisIntSpinbox::KisIntSpinbox(const QString & /*label*/, int val, QWidget *parent, const char *name) + : QWidget(parent, name) +{ + init(val); +} + +void KisIntSpinbox::init(int val) +{ + d = new KisIntSpinboxPrivate( ); + QBoxLayout * l = new QHBoxLayout( this ); + + l->insertStretch(0, 1); + d->m_numinput = new KIntSpinBox(0, 100, 1, val, 10, this, "KisIntSpinbox::KIntSpinBox"); + + d->m_numinput->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed); + d->m_numinput->setSuffix("%"); + l->addWidget( d->m_numinput ); + + d->m_slider = new KisPopupSlider(0, 100, 10, val, QSlider::Horizontal, this); + d->m_slider->setFrameStyle(QFrame::Panel|QFrame::Raised); + + d->m_arrow = new KArrowButton(this, Qt::DownArrow); + d->m_arrow->setPopup(d->m_slider); + d->m_arrow->setMaximumHeight( fontMetrics().height() + 4); + d->m_arrow->setEnabled(true); // Why is the arrow still gray? + + l->addWidget( d->m_arrow ); + + d->m_prevValue = val; + setValue(val); + setFocusProxy(d->m_numinput); + layout(); + + connect(d->m_numinput, SIGNAL(valueChanged(int)), SLOT(spinboxValueChanged(int))); + connect(d->m_slider, SIGNAL(valueChanged(int)), SLOT(sliderValueChanged(int))); + connect(d->m_slider, SIGNAL(aboutToShow()), SLOT(slotAboutToShow())); + connect(d->m_slider, SIGNAL(aboutToHide()), SLOT(slotAboutToHide())); + + connect(&(d->m_timer), SIGNAL(timeout()), this, SLOT(slotTimeout())); +} + +void KisIntSpinbox::spinboxValueChanged(int val) +{ + setValue(val); + d->m_timer.start(300, true); + +} + +void KisIntSpinbox::sliderValueChanged(int val) +{ + setValue(val); + emit valueChanged(val); + emit valueChanged(val, true); +} + +void KisIntSpinbox::setRange(int lower, int upper, int /*step*/) +{ + upper = kMax(upper, lower); + lower = kMin(upper, lower); + d->m_slider->setRange(lower, upper); + + layout(); +} + +void KisIntSpinbox::setMinValue(int min) +{ + setRange(min, maxValue(), d->m_slider->lineStep()); +} + +int KisIntSpinbox::minValue() const +{ + return d->m_slider->minValue(); +} + +void KisIntSpinbox::setMaxValue(int max) +{ + setRange(minValue(), max, d->m_slider->lineStep()); +} + +int KisIntSpinbox::maxValue() const +{ + return d->m_slider->maxValue(); +} + +KisIntSpinbox::~KisIntSpinbox() +{ + delete d; +} + +void KisIntSpinbox::setValue(int val) +{ + d->m_slider->blockSignals(true); + d->m_slider->setValue(val); + d->m_slider->blockSignals(false); + + d->m_numinput->blockSignals(true); + d->m_numinput->setValue(val); + d->m_numinput->blockSignals(false); +} + +int KisIntSpinbox::value() const +{ + return d->m_numinput->value(); // From the numinput: that one isn't in steps of ten +} + +void KisIntSpinbox::setLabel(const QString & /*label*/) +{ +} + +void KisIntSpinbox::slotAboutToShow() +{ + d->m_prevValue = value(); +} + +void KisIntSpinbox::slotAboutToHide() +{ + if( d->m_prevValue != value() ) + { + emit finishedChanging( d->m_prevValue, value() ); + d->m_prevValue = value(); + } +} + +void KisIntSpinbox::slotTimeout() +{ + emit valueChanged(value()); + emit valueChanged(value(), true); +} +#include "kis_int_spinbox.moc" diff --git a/krita/ui/kis_int_spinbox.h b/krita/ui/kis_int_spinbox.h new file mode 100644 index 000000000..873a2f39f --- /dev/null +++ b/krita/ui/kis_int_spinbox.h @@ -0,0 +1,198 @@ +/* + * Copyright (c) 2006 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2006 Casper Boemann <cbr@boemann.dk> + * + * 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_INT_SPINBOX_H_ +#define KIS_INT_SPINBOX_H_ + +#include <qwidget.h> +#include <qspinbox.h> +#include <qslider.h> +#include <qpopupmenu.h> + +#include <knumvalidator.h> + +class QLabel; +class QLineEdit; +class QLayout; +class QValidator; + +class KisPopupSlider : public QPopupMenu { + Q_OBJECT + +public: + + KisPopupSlider(int minValue, int maxValue, int pageStep, int value, Orientation orientation, QWidget * parent, const char * name = 0) + : QPopupMenu(parent, name) + { + m_slider = new QSlider(minValue, maxValue, pageStep, value, orientation, this, name); + //m_slider->setTracking(false); + insertItem(m_slider); + connect(m_slider, SIGNAL(valueChanged(int)), SIGNAL(valueChanged(int))); + } + void setTickInterval(int i) { m_slider->setTickInterval(i); } + void setRange(int minValue, int maxValue) { m_slider->setRange(minValue, maxValue); } + void setValue(int val) { m_slider->setValue(val); } + void setTickmarks(QSlider::TickSetting t) { m_slider->setTickmarks(t); } + int lineStep () const{ return m_slider->lineStep(); } + int minValue () const{ return m_slider->minValue(); } + int maxValue () const{ return m_slider->maxValue(); } + int value () const{ return m_slider->value(); } + QSlider *m_slider; + +signals: + void valueChanged(int); + +}; + +/** + * @short An input widget for integer numbers, consisting of a spinbox and + * a dropdown slider. + * + * KisIntSpinbox combines a QSpinBox and a dropdown QSlider + * to make an easy to use control for setting some integer + * parameter. + * + * + */ +class KisIntSpinbox : public QWidget +{ + + Q_OBJECT + Q_PROPERTY( int value READ value WRITE setValue ) + Q_PROPERTY( int minValue READ minValue WRITE setMinValue ) + Q_PROPERTY( int maxValue READ maxValue WRITE setMaxValue ) + +public: + + /** + * Constructs an input control for integer values + * with base 10 and initial value 0. + * + * @param parent parent QWidget + * @param name internal name for this widget + */ + KisIntSpinbox(QWidget *parent=0, const char *name=0); + /** + * Constructor + * It constructs a QSpinBox that allows the input of integer numbers + * in the range of -INT_MAX to +INT_MAX. + * To enforce the value being in a range, use setRange(). + * + * @param label the tabel (may contain &, and my be empty) + * @param value initial value for the control + * @param parent parent QWidget + * @param name internal name for this widget + */ + KisIntSpinbox(const QString & label, int value, QWidget* parent=0, const char *name=0); + + /** + * Destructor + * + * + */ + virtual ~KisIntSpinbox(); + + /** + * @return the current value. + */ + int value() const; + + /** + * @param min minimum value + * @param max maximum value + * @param step step size for the QSlider + */ + void setRange(int min, int max, int step=1); + /** + * Sets the minimum value. + */ + void setMinValue(int min); + /** + * @return the minimum value. + */ + int minValue() const; + /** + * Sets the maximum value. + */ + void setMaxValue(int max); + /** + * @return the maximum value. + */ + int maxValue() const; + + /** + * Sets the spacing of tickmarks for the slider. + * + * @param minor Minor tickmark separation. + * @param major Major tickmark separation. + */ + void setSteps(int minor, int major); + + void setLabel(const QString & label); + +public slots: + /** + * Sets the value of the control. + */ + void setValue(int); + + + void spinboxValueChanged(int val); + void sliderValueChanged(int val); + + void slotTimeout(); + +signals: + + /** + * Emitted every time the value changes (by calling setValue() or + * by user interaction). + * @param value the new opacity + */ + void valueChanged(int value); + + /** + * Emitted every time the value changes (by calling setValue() or + * by user interaction). + * @param value the new opacity + * @param withSlider whether the value was set by dragging the slider + */ + void valueChanged(int value, bool withSlider); + + /** + * Emitted after the slider has been hidden, if the value was changed while it was shown. + * @param previous the value before the slider was shown + * @param value the value after the slider was hidden + */ + void finishedChanging(int previous, int value); + +private slots: + void slotAboutToShow(); + void slotAboutToHide(); + +private: + void init(int val); + +private: + + class KisIntSpinboxPrivate; + KisIntSpinboxPrivate *d; +}; + +#endif diff --git a/krita/ui/kis_itemchooser.cc b/krita/ui/kis_itemchooser.cc new file mode 100644 index 000000000..b5dc03e04 --- /dev/null +++ b/krita/ui/kis_itemchooser.cc @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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 <qvbox.h> +#include <kinstance.h> +#include <klocale.h> +#include <kstandarddirs.h> +#include <koIconChooser.h> + +#include "kis_itemchooser.h" +#include "kis_global.h" +#include "kis_icon_item.h" + +KisItemChooser::KisItemChooser(QWidget *parent, const char *name) : super(parent, name) +{ +/* m_frame = new QVBox(this); + m_frame->setFrameStyle(QFrame::Panel | QFrame::Sunken);*/ + m_chooser = new KoIconChooser(QSize(30,30), this, "icon_chooser", true); + QObject::connect(m_chooser, SIGNAL(selected(KoIconItem*)), this, SLOT(slotItemSelected(KoIconItem*))); +} + +KisItemChooser::~KisItemChooser() +{ +} + +void KisItemChooser::setCurrent(KoIconItem *item) +{ + m_chooser->setCurrentItem(item); + update(item); +} + +void KisItemChooser::setCurrent(int index) +{ + setCurrent(m_chooser->itemAt(index)); +} + +KoIconItem* KisItemChooser::currentItem() +{ + return m_chooser->currentItem(); +} + +void KisItemChooser::slotItemSelected(KoIconItem *item) +{ + update(item); + emit selected(currentItem()); +} + +void KisItemChooser::addItem(KoIconItem *item) +{ + m_chooser->addItem(item); +} + +void KisItemChooser::addItems(const vKoIconItem& items) +{ + QPtrListIterator<KoIconItem> itr(items); + + for (itr.toFirst(); itr.current(); ++itr) + m_chooser->addItem(itr.current()); +} + +QWidget *KisItemChooser::chooserWidget() const +{ + return m_chooser; +} + +#include "kis_itemchooser.moc" + diff --git a/krita/ui/kis_itemchooser.h b/krita/ui/kis_itemchooser.h new file mode 100644 index 000000000..b9eb59136 --- /dev/null +++ b/krita/ui/kis_itemchooser.h @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2002 Patrick Julein <freak@codepimps.org> + * + * 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_ITEM_CHOOSER_H_ +#define KIS_ITEM_CHOOSER_H_ + +#include <qptrlist.h> +#include <qwidget.h> + +class QHBox; + +class KoIconChooser; +class KoIconItem; + +typedef QPtrList<KoIconItem> vKoIconItem; + +class KisItemChooser : public QWidget { + typedef QWidget super; + Q_OBJECT + +public: + KisItemChooser(QWidget *parent = 0, + const char *name = 0); + virtual ~KisItemChooser(); + + KoIconItem *currentItem(); + void setCurrent(KoIconItem *item); + void setCurrent(int index); + +public slots: + void addItem(KoIconItem *item); + void addItems(const vKoIconItem& items); + +signals: + void selected(KoIconItem *item); + +protected: + virtual void update(KoIconItem *item) = 0; + QWidget *chooserWidget() const; + +private slots: + void slotItemSelected(KoIconItem *item); + +private: + QHBox *m_frame; + KoIconChooser *m_chooser; +}; + +#endif // KIS_ITEM_CHOOSER_H_ + diff --git a/krita/ui/kis_label_cursor_pos.cc b/krita/ui/kis_label_cursor_pos.cc new file mode 100644 index 000000000..40d2b99cb --- /dev/null +++ b/krita/ui/kis_label_cursor_pos.cc @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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.g + * + * 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_label_cursor_pos.h" +#include "kis_label_cursor_pos.moc" + +KisLabelCursorPos::KisLabelCursorPos(QWidget *parent, const char *name, WFlags f) : super(parent, name, f) +{ + setText("0:0"); + m_doUpdates = true; + + //setMinimumSize( 200, parent->height() - 4); +} + +KisLabelCursorPos::~KisLabelCursorPos() +{ +} + +void KisLabelCursorPos::updatePos(Q_INT32 xpos, Q_INT32 ypos) +{ + if (m_doUpdates) { + QString s; + + s.sprintf("%d:%d", xpos, ypos); + setText(s); + } +} + +void KisLabelCursorPos::enter() +{ + m_doUpdates = true; +} + +void KisLabelCursorPos::leave() +{ + m_doUpdates = false; + setText(QString::null); +} + diff --git a/krita/ui/kis_label_cursor_pos.h b/krita/ui/kis_label_cursor_pos.h new file mode 100644 index 000000000..3923c61d6 --- /dev/null +++ b/krita/ui/kis_label_cursor_pos.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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.g + * + * 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_LABEL_CURSOR_POS_H_ +#define KIS_LABEL_CURSOR_POS_H_ + +#include <qlabel.h> + +class KisLabelCursorPos : public QLabel { + Q_OBJECT + typedef QLabel super; + +public: + KisLabelCursorPos(QWidget *parent, const char *name = 0, WFlags f = 0); + virtual ~KisLabelCursorPos(); + +public slots: + void updatePos(Q_INT32 xpos, Q_INT32 ypos); + void enter(); + void leave(); + +private: + bool m_doUpdates; + Q_INT32 m_ypos; +}; + +#endif // KIS_LABEL_CURSOR_POS_H_ + diff --git a/krita/ui/kis_label_progress.cc b/krita/ui/kis_label_progress.cc new file mode 100644 index 000000000..e08a7fcfe --- /dev/null +++ b/krita/ui/kis_label_progress.cc @@ -0,0 +1,214 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qlayout.h> +#include <qtooltip.h> +#include <qtoolbutton.h> +#include <qcursor.h> +#include <qeventloop.h> + +#include <kdebug.h> +#include <kapplication.h> +#include <klocale.h> +#include <kprogress.h> +#include <kiconloader.h> + +#include "kis_progress_subject.h" +#include "kis_label_progress.h" +#include "kis_cursor.h" + +class EscapeButton : public QToolButton { + +public: + + EscapeButton(QWidget * parent, const char * name) : QToolButton(parent, name) {}; + + void keyReleaseEvent(QKeyEvent *e) + { + if (e->key()==Qt::Key_Escape) + emit clicked(); + } +}; + +KisLabelProgress::KisLabelProgress(QWidget *parent, const char *name, WFlags f) : super(parent, name, f) +{ + m_subject = 0; + m_modal = false; + + QHBoxLayout *box = new QHBoxLayout(this); + box->setAutoAdd(true); + + QIconSet cancelIconSet = SmallIconSet("stop"); + + m_cancelButton = new EscapeButton(this, "cancel_button"); + m_cancelButton->setIconSet(cancelIconSet); + QToolTip::add(m_cancelButton, i18n("Cancel")); + connect(m_cancelButton, SIGNAL(clicked()), this, SLOT(cancelPressed())); + + m_bar = new KProgress(100, this); +} + +KisLabelProgress::~KisLabelProgress() +{ +} + +void KisLabelProgress::setSubject(KisProgressSubject *subject, bool modal, bool canCancel) +{ + reset(); + + if (subject) { + m_subject = subject; + m_modal = modal; + + connect(subject, SIGNAL(notifyProgress(int)), this, SLOT(update(int))); + connect(subject, SIGNAL(notifyProgressStage(const QString&, int)), this, SLOT(updateStage(const QString&, int))); + connect(subject, SIGNAL(notifyProgressDone()), this, SLOT(done())); + connect(subject, SIGNAL(notifyProgressError()), this, SLOT(error())); + connect(subject, SIGNAL(destroyed()), this, SLOT(subjectDestroyed())); + + show(); + + if (canCancel) { + if (modal) { + kdDebug() << "grabbing 1\n"; + m_cancelButton->grabMouse(); + m_cancelButton->grabKeyboard(); + } + } + else { + m_cancelButton->hide(); + + if (modal) { + // Only visible widgets can grab. + kdDebug() << "grabbing 2\n"; + grabMouse(); + grabKeyboard(); + } + } + + if (modal) { + QApplication::setOverrideCursor(KisCursor::waitCursor()); + } + + m_bar->setValue(0); + } +} + +bool KisLabelProgress::event(QEvent * e) +{ + + if (!e) return false; + + int type = e->type(); + + switch (type) { + case(KisProgress::ProgressEventBase + 1): + { + KisProgress::UpdateEvent * ue = dynamic_cast<KisProgress::UpdateEvent*>(e); + update(ue->m_percent); + break; + } + case(KisProgress::ProgressEventBase + 2): + { + KisProgress::UpdateStageEvent * use = dynamic_cast<KisProgress::UpdateStageEvent*>(e); + updateStage(use->m_stage, use->m_percent); + break; + } + case(KisProgress::ProgressEventBase + 3): + done(); + break; + case(KisProgress::ProgressEventBase + 4): + error(); + break; + case(KisProgress::ProgressEventBase + 5): + subjectDestroyed(); + break; + default: + return QLabel::event(e); + }; + + return true; +} + +void KisLabelProgress::reset() +{ + if (m_subject) { + m_subject->disconnect(this); + m_subject = 0; + + if (m_modal) { + QApplication::restoreOverrideCursor(); + } + + m_modal = false; + } + + releaseMouse(); + releaseKeyboard(); + m_cancelButton->releaseMouse(); + m_cancelButton->releaseKeyboard(); + hide(); +} + +void KisLabelProgress::update(int percent) +{ + m_bar->setValue(percent); + + KApplication *app = KApplication::kApplication(); + + app->processEvents(); + // The following is safer, but makes cancel impossible: + //QApplication::eventLoop()->processEvents(QEventLoop::ExcludeUserInput | + // QEventLoop::ExcludeSocketNotifiers); +} + +void KisLabelProgress::updateStage(const QString&, int percent) +{ + m_bar->setValue(percent); + + KApplication *app = KApplication::kApplication(); + Q_ASSERT(app); + + app->processEvents(); +} + +void KisLabelProgress::cancelPressed() +{ + if (m_subject) { + m_subject->cancel(); + reset(); + } +} + +void KisLabelProgress::subjectDestroyed() +{ + reset(); +} + +void KisLabelProgress::done() +{ + reset(); +} + +void KisLabelProgress::error() +{ + reset(); +} + +#include "kis_label_progress.moc" + diff --git a/krita/ui/kis_label_progress.h b/krita/ui/kis_label_progress.h new file mode 100644 index 000000000..f5385121b --- /dev/null +++ b/krita/ui/kis_label_progress.h @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_LABEL_PROGRESS_H_ +#define KIS_LABEL_PROGRESS_H_ + +#include <qlabel.h> +#include <qevent.h> + +#include "kis_progress_display_interface.h" + +class QToolButton; +class KProgress; + +class KisLabelProgress : public QLabel, public KisProgressDisplayInterface { + Q_OBJECT + typedef QLabel super; + +public: + KisLabelProgress(QWidget *parent, const char *name = 0, WFlags f = 0); + virtual ~KisLabelProgress(); + +public: + // Implements KisProgressDisplayInterface + void setSubject(KisProgressSubject *subject, bool modal, bool canCancel); + + // Overrides QLabel::event() + bool event(QEvent * ev); + +private slots: + virtual void update(int percent); + virtual void updateStage(const QString& stage, int percent); + virtual void done(); + virtual void error(); + virtual void subjectDestroyed(); + +private slots: + void cancelPressed(); + +private: + void reset(); + + KisProgressSubject *m_subject; + KProgress *m_bar; + QToolButton *m_cancelButton; + bool m_modal; +}; + +#endif // KIS_LABEL_PROGRESS_H_ + diff --git a/krita/ui/kis_label_zoom.cc b/krita/ui/kis_label_zoom.cc new file mode 100644 index 000000000..cd8620d68 --- /dev/null +++ b/krita/ui/kis_label_zoom.cc @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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_label_zoom.h" +#include "kis_label_zoom.moc" + diff --git a/krita/ui/kis_label_zoom.h b/krita/ui/kis_label_zoom.h new file mode 100644 index 000000000..295883688 --- /dev/null +++ b/krita/ui/kis_label_zoom.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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.g + * + * 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_LABEL_ZOOM_H_ +#define KIS_LABEL_ZOOM_H_ + +#include <qlabel.h> + +class KisLabelZoom : public QLabel { + Q_OBJECT + + KisLabelZoom( QWidget *parent, const char *name = 0, WFlags f = 0 ) : + QLabel( parent, name, f ) {} + virtual ~KisLabelZoom() {} + +}; + +#endif // KIS_LABEL_ZOOM_H_ + diff --git a/krita/ui/kis_layerbox.cc b/krita/ui/kis_layerbox.cc new file mode 100644 index 000000000..ef30e3319 --- /dev/null +++ b/krita/ui/kis_layerbox.cc @@ -0,0 +1,675 @@ +/* + * kis_layerbox.cc - part of Krita aka Krayon aka KimageShop + * + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (C) 2006 Gábor Lehel <illissius@gmail.com> + * + * 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 <qbutton.h> +#include <qtoolbutton.h> +#include <qbrush.h> +#include <qfont.h> +#include <qfontmetrics.h> +#include <qhbox.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qpoint.h> +#include <qrect.h> +#include <qstring.h> +#include <qstyle.h> +#include <qtooltip.h> +#include <qwidget.h> +#include <qcombobox.h> +#include <qcheckbox.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kpopupmenu.h> +#include <kmessagebox.h> +#include <kpushbutton.h> +#include <kiconloader.h> +#include <kicontheme.h> +#include <klocale.h> + +#include <KoPartSelectAction.h> + +#include "kis_layerlist.h" +#include "kis_cmb_composite.h" +#include "kis_int_spinbox.h" +#include "wdglayerbox.h" +#include "kis_colorspace.h" +#include "kis_paint_device.h" +#include "kis_layer.h" +#include "kis_group_layer.h" +#include "kis_image.h" + +#include "kis_populate_visitor.h" + +#include "kis_layerbox.h" + +KisLayerBox::KisLayerBox(KisCanvasSubject *subject, QWidget *parent, const char *name) + : super(parent, name), m_image(0) +{ + QVBoxLayout *vbox = new QVBoxLayout(this); + vbox->setAutoAdd(true); + + m_lst = new WdgLayerBox(this); + setMinimumSize(m_lst->minimumSizeHint()); + + QToolTip::add(m_lst->bnAdd, i18n("Create new layer")); + + QToolTip::add(m_lst->bnDelete, i18n("Remove current layer")); + + QToolTip::add(m_lst->bnRaise, i18n("Raise current layer")); + m_lst->bnRaise->setEnabled(false); + + m_lst->bnLower->setEnabled(false); + QToolTip::add(m_lst->bnLower, i18n("Lower current layer")); + + QToolTip::add(m_lst->bnProperties, i18n("Properties for layer")); + + KIconLoader il( "krita" ); + + list()->setPreviewsShown(true); + + list()->setFoldersCanBeActive(true); + + list()->addProperty("visible", i18n("Visible"), loadPixmap("visible.png", il, KIcon::SizeSmallMedium), + loadPixmap("novisible.png", il, KIcon::SizeSmallMedium), true); + + list()->addProperty("locked", i18n("Locked"), loadPixmap("locked.png", il, KIcon::SizeSmallMedium), + loadPixmap("unlocked.png", il, KIcon::SizeSmallMedium)); + + + connect(list()->contextMenu(), SIGNAL(aboutToShow()), SLOT(slotAboutToShow())); + connect(list(), SIGNAL(activated(LayerItem*)), + SLOT(slotLayerActivated(LayerItem*))); + connect(list(), SIGNAL(displayNameChanged(LayerItem*, const QString&)), + SLOT(slotLayerDisplayNameChanged(LayerItem*, const QString&))); + connect(list(), SIGNAL(propertyChanged(LayerItem*, const QString&, bool)), + SLOT(slotLayerPropertyChanged(LayerItem*, const QString&, bool))); + connect(list(), SIGNAL(layerMoved(LayerItem*, LayerItem*, LayerItem*)), + SLOT(slotLayerMoved(LayerItem*, LayerItem*, LayerItem*))); + connect(list(), SIGNAL(requestNewLayer(LayerItem*, LayerItem*)), + SLOT(slotRequestNewLayer(LayerItem*, LayerItem*))); + connect(list(), SIGNAL(requestNewFolder(LayerItem*, LayerItem*)), + SLOT(slotRequestNewFolder(LayerItem*, LayerItem*))); + connect(list(), SIGNAL(requestNewAdjustmentLayer(LayerItem*, LayerItem*)), + SLOT(slotRequestNewAdjustmentLayer(LayerItem*, LayerItem*))); + connect(list(), SIGNAL(requestNewObjectLayer(LayerItem*, LayerItem*, const KoDocumentEntry&)), + SLOT(slotRequestNewObjectLayer(LayerItem*, LayerItem*, const KoDocumentEntry&))); + connect(list(), SIGNAL(requestRemoveLayer(LayerItem*)), + SLOT(slotRequestRemoveLayer(LayerItem*))); + connect(list(), SIGNAL(requestLayerProperties(LayerItem*)), + SLOT(slotRequestLayerProperties(LayerItem*))); + + m_newLayerMenu = new KPopupMenu(this); + m_lst->bnAdd->setPopup(m_newLayerMenu); + m_lst->bnAdd->setPopupDelay(1); + m_newLayerMenu->insertItem( SmallIconSet( "filenew" ), i18n( "&New Layer..." ), PAINT_LAYER ); + m_newLayerMenu->insertItem( SmallIconSet( "folder" ), i18n( "New &Group Layer..." ), GROUP_LAYER ); + m_newLayerMenu->insertItem( SmallIconSet( "tool_filter" ), i18n( "New &Adjustment Layer..." ), ADJUSTMENT_LAYER ); + m_partLayerAction = new KoPartSelectAction( i18n( "New &Object Layer" ), "gear", this ); + m_partLayerAction->plug( m_newLayerMenu ); + connect(m_partLayerAction, SIGNAL(activated()), this, SLOT(slotAddMenuActivated())); + connect(m_newLayerMenu, SIGNAL(activated(int)), this, SLOT(slotAddMenuActivated(int))); + + + connect(m_lst->bnDelete, SIGNAL(clicked()), SLOT(slotRmClicked())); + connect(m_lst->bnRaise, SIGNAL(clicked()), SLOT(slotRaiseClicked())); + connect(m_lst->bnLower, SIGNAL(clicked()), SLOT(slotLowerClicked())); + connect(m_lst->bnProperties, SIGNAL(clicked()), SLOT(slotPropertiesClicked())); + connect(m_lst->intOpacity, SIGNAL(valueChanged(int, bool)), SIGNAL(sigOpacityChanged(int, bool))); + connect(m_lst->intOpacity, SIGNAL(finishedChanging(int, int)), SIGNAL(sigOpacityFinishedChanging(int, int))); + connect(m_lst->cmbComposite, SIGNAL(activated(const KisCompositeOp&)), SIGNAL(sigItemComposite(const KisCompositeOp&))); + + Q_ASSERT(subject->document() != 0); + + if (subject->document()) { + connect(subject->document(), SIGNAL(sigCommandExecuted()), SLOT(updateThumbnails())); + } +} + +KisLayerBox::~KisLayerBox() +{ +} + +KisLayerList* KisLayerBox::list() const +{ + return m_lst->listLayers; +} + +void KisLayerBox::setImage(KisImageSP img) +{ + if (m_image == img) + return; + + if (m_image) + m_image->disconnect(this); + + m_image = img; + + if (img) + { + connect(img, SIGNAL(sigLayerActivated(KisLayerSP)), this, SLOT(slotLayerActivated(KisLayerSP))); + connect(img, SIGNAL(sigLayerAdded(KisLayerSP)), this, SLOT(slotLayerAdded(KisLayerSP))); + connect(img, SIGNAL(sigLayerRemoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), + this, SLOT(slotLayerRemoved(KisLayerSP, KisGroupLayerSP, KisLayerSP))); + connect(img, SIGNAL(sigLayerPropertiesChanged(KisLayerSP)), + this, SLOT(slotLayerPropertiesChanged(KisLayerSP))); + connect(img, SIGNAL(sigLayerMoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), + this, SLOT(slotLayerMoved(KisLayerSP, KisGroupLayerSP, KisLayerSP))); + connect(img, SIGNAL(sigLayersChanged(KisGroupLayerSP)), this, SLOT(slotLayersChanged(KisGroupLayerSP))); + connect(img, SIGNAL(sigLayerUpdated(KisLayerSP, QRect)), this, SLOT(slotLayerUpdated(KisLayerSP, QRect))); + slotLayersChanged(img->rootLayer()); + updateThumbnails(); + } + else + { + clear(); + } +} + +void KisLayerBox::slotLayerActivated(KisLayerSP layer) +{ + if (layer) + list()->setActiveLayer(layer->id()); + else + list()->setActiveLayer(-1); + updateUI(); +} + +void KisLayerBox::slotLayerAdded(KisLayerSP layer) +{ + if (layer.data() == m_image->rootLayer().data() || list()->layer(layer->id())) + return; + + vKisLayerSP layersAdded; + + if (layer->parent() == m_image->rootLayer()) + { + KisPopulateVisitor visitor(list()); + layer->accept(visitor); + layersAdded = visitor.layersAdded(); + } + else + { + KisPopulateVisitor visitor(static_cast<KisLayerItem*>(list()->layer(layer->parent()->id()))); + layer->accept(visitor); + layersAdded = visitor.layersAdded(); + } + + for (vKisLayerSP::iterator it = layersAdded.begin(); it != layersAdded.end(); ++it) { + markModified(*it); + } + updateUI(); +} + +void KisLayerBox::slotLayerRemoved(KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP) +{ + list()->removeLayer(layer->id()); + m_modified.remove(layer->id()); + markModified(wasParent); + updateUI(); +} + +void KisLayerBox::slotLayerMoved(KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP) +{ + int parentID = layer->parent()->id(); + if (layer->parent() == m_image->rootLayer()) + parentID = -1; + + int siblingID = -1; + if (layer->prevSibling()) + siblingID = layer->prevSibling()->id(); + + list()->moveLayer(layer->id(), parentID, siblingID); + + markModified(layer->parent()); + markModified(wasParent); + updateUI(); +} + +void KisLayerBox::slotLayerPropertiesChanged(KisLayerSP layer) +{ + if (KisLayerItem* item = dynamic_cast<KisLayerItem*>(list()->layer(layer->id()))) + { + Q_ASSERT(item->layer() == layer.data()); + item->sync(); + updateUI(); + markModified(layer); + } +} + +void KisLayerBox::slotLayersChanged(KisGroupLayerSP rootLayer) +{ + list()->clear(); + KisPopulateVisitor visitor(list()); + for (KisLayerSP layer = rootLayer->firstChild(); layer; layer = layer->nextSibling()) + layer->accept(visitor); + m_modified.clear(); + for (QListViewItemIterator it(list()->lastItem()); *it; --it) + m_modified.append(static_cast<LayerItem*>(*it)->id()); + updateUI(); +} + +void KisLayerBox::slotLayerUpdated(KisLayerSP layer, QRect) +{ + markModified(layer); +} + +void KisLayerBox::slotLayerActivated(LayerItem* item) +{ + if (item) + m_image->activate(m_image->findLayer(item->id())); + else + m_image->activate(0); + updateUI(); +} + +void KisLayerBox::slotLayerDisplayNameChanged(LayerItem* item, const QString& displayName) +{ + if(KisLayerSP layer = m_image->findLayer(item->id())) + layer->setName(displayName); + updateUI(); +} + +void KisLayerBox::slotLayerPropertyChanged(LayerItem* item, const QString& name, bool on) +{ + if (KisLayerSP layer = m_image->findLayer(item->id())) + { + if (name == "visible") + layer->setVisible(on); + else if (name == "locked") + layer->setLocked(on); + } +} + +void KisLayerBox::slotLayerMoved(LayerItem* item, LayerItem*, LayerItem*) +{ + KisLayerSP layer = m_image->findLayer(item->id()); + KisGroupLayerSP parent; + if( item->parent() ) + parent = dynamic_cast<KisGroupLayer*>(m_image->findLayer(item->parent()->id()).data()); + if( !parent ) + parent = m_image->rootLayer(); + KisLayerSP above = 0; + if (item->nextSibling()) + above = m_image->findLayer(item->nextSibling()->id()); + if (layer) + m_image->moveLayer(layer, parent.data(), above); + updateUI(); +} + +void KisLayerBox::slotRequestNewLayer(LayerItem* p, LayerItem* after) +{ + KisLayer* l = m_image->rootLayer().data(); + if (p) + l = m_image->findLayer(p->id()).data(); + KisGroupLayerSP parent = dynamic_cast<KisGroupLayer*>(l); + + KisLayerSP above = 0; + if (after && after->nextSibling()) + above = m_image->findLayer(after->nextSibling()->id()); + else if (after) + above = 0; + else if (p && p->firstChild()) + above = parent->firstChild(); + else if (!p && m_image->rootLayer()->childCount()) + above = m_image->rootLayer()->firstChild(); + emit sigRequestLayer(parent, above); +} + +void KisLayerBox::slotRequestNewFolder(LayerItem* p, LayerItem* after) +{ + KisLayer* l = m_image->rootLayer().data(); //FIXME I hate copy-pasting like this. + if (p) + l = m_image->findLayer(p->id()).data(); + KisGroupLayerSP parent = dynamic_cast<KisGroupLayer*>(l); + + KisLayerSP above = 0; + if (after && after->nextSibling()) + above = m_image->findLayer(after->nextSibling()->id()); + else if (after) + above = 0; + else if (p && p->firstChild()) + above = parent->firstChild(); + else if (!p && m_image->rootLayer()->childCount()) + above = m_image->rootLayer()->firstChild(); + emit sigRequestGroupLayer(parent, above); +} + +void KisLayerBox::slotRequestNewAdjustmentLayer(LayerItem* p, LayerItem* after) +{ + KisLayer* l = m_image->rootLayer().data(); //FIXME here too. + if (p) + l = m_image->findLayer(p->id()).data(); + KisGroupLayerSP parent = dynamic_cast<KisGroupLayer*>(l); + + KisLayerSP above = 0; + if (after && after->nextSibling()) + above = m_image->findLayer(after->nextSibling()->id()); + else if (after) + above = 0; + else if (p && p->firstChild()) + above = parent->firstChild(); + else if (!p && m_image->rootLayer()->childCount()) + above = m_image->rootLayer()->firstChild(); + emit sigRequestAdjustmentLayer(parent, above); +} + +void KisLayerBox::slotRequestNewObjectLayer(LayerItem* p, LayerItem* after, const KoDocumentEntry& entry) +{ + KisLayer* l = m_image->rootLayer().data(); //FIXME and here. + if (p) + l = m_image->findLayer(p->id()).data(); + KisGroupLayerSP parent = dynamic_cast<KisGroupLayer*>(l); + + KisLayerSP above = 0; + if (after && after->nextSibling()) + above = m_image->findLayer(after->nextSibling()->id()); + else if (after) + above = 0; + else if (p && p->firstChild()) + above = parent->firstChild(); + else if (!p && m_image->rootLayer()->childCount()) + above = m_image->rootLayer()->firstChild(); + emit sigRequestPartLayer(parent, above, entry); +} + +void KisLayerBox::slotRequestRemoveLayer(LayerItem* item) +{ + if (KisLayerSP layer = m_image->findLayer(item->id())) { + m_image->removeLayer(layer); + } + updateUI(); +} + +void KisLayerBox::slotRequestLayerProperties(LayerItem* item) +{ + if (KisLayerSP layer = m_image->findLayer(item->id())) + { + emit sigRequestLayerProperties(layer); + } +} + +void KisLayerBox::updateUI() +{ + m_lst->bnDelete->setEnabled(list()->activeLayer()); + m_lst->bnRaise->setEnabled(list()->activeLayer() && (list()->activeLayer()->prevSibling() || list()->activeLayer()->parent())); + m_lst->bnLower->setEnabled(list()->activeLayer() && list()->activeLayer()->nextSibling()); + m_lst->intOpacity->setEnabled(list()->activeLayer()); + m_lst->cmbComposite->setEnabled(list()->activeLayer()); + if (m_image) + if (KisLayerSP active = m_image->activeLayer()) + { + if (m_image->activeDevice()) + slotSetColorSpace(m_image->activeDevice()->colorSpace()); + else + slotSetColorSpace(m_image->colorSpace()); + slotSetOpacity(int(float(active->opacity() * 100) / 255 + 0.5)); + slotSetCompositeOp(active->compositeOp()); + } +} + +void KisLayerBox::slotAboutToShow() +{ +} + +void KisLayerBox::slotSetCompositeOp(const KisCompositeOp& compositeOp) +{ + m_lst->cmbComposite->blockSignals(true); + m_lst->cmbComposite->setCurrentItem(compositeOp); + m_lst->cmbComposite->blockSignals(false); +} + +void KisLayerBox::slotSetColorSpace(const KisColorSpace * colorSpace) +{ + m_lst->cmbComposite->blockSignals(true); + m_lst->cmbComposite->setCompositeOpList(colorSpace->userVisiblecompositeOps()); + m_lst->cmbComposite->blockSignals(false); +} + +// range: 0-100 +void KisLayerBox::slotSetOpacity(int opacity) +{ + m_lst->intOpacity->blockSignals(true); + m_lst->intOpacity->setValue(opacity); + m_lst->intOpacity->blockSignals(false); +} + +void KisLayerBox::clear() +{ + list()->clear(); + updateUI(); +} + +void KisLayerBox::slotAddMenuActivated(int type) +{ + if(type == -1) + return; + + KisGroupLayerSP root = m_image->rootLayer(); + KisGroupLayerSP parent; + KisLayerSP above; + if (KisLayerSP active = m_image->activeLayer()) + { + parent = root; + above = active; + if (active->parent()) + parent = active->parent(); + } + else + { + parent = root; + above = m_image->rootLayer()->firstChild(); + } + + switch (type) + { + case PAINT_LAYER: + emit sigRequestLayer(parent, above); + break; + case GROUP_LAYER: + emit sigRequestGroupLayer(parent, above); + break; + case ADJUSTMENT_LAYER: + emit sigRequestAdjustmentLayer(parent, above); + break; + case OBJECT_LAYER: + default: //goddamned Qt doesn't emit activated for default-assigned IDs, so this does nothing + emit sigRequestPartLayer(parent, above, m_partLayerAction->documentEntry()); + } +} + +void KisLayerBox::slotRmClicked() +{ + QValueList<int> l = list()->selectedLayerIDs(); + if (l.count() < 2 && list()->activeLayer() && !l.contains(list()->activeLayer()->id())) + { + l.clear(); + l.append(list()->activeLayer()->id()); + } + + for (int i = 0, n = l.count(); i < n; ++i) + { + m_modified.remove(l[i]); + m_image->removeLayer(m_image->findLayer(l[i])); + } +} + +void KisLayerBox::slotRaiseClicked() +{ + QValueList<int> l = list()->selectedLayerIDs(); + if (l.count() < 2 && list()->activeLayer() && !l.contains(list()->activeLayer()->id())) + { + l.clear(); + l.append(list()->activeLayer()->id()); + } + + KisLayerSP layer = m_image->findLayer(l.first()); + if( l.count() == 1 && layer == layer->parent()->firstChild() && layer->parent() != m_image->rootLayer()) + { + if (KisGroupLayerSP grandparent = layer->parent()->parent()) + m_image->moveLayer(layer, grandparent, layer->parent().data()); + } + else + { + for (int i = 0, n = l.count(); i < n; ++i) + if (KisLayerSP li = m_image->findLayer(l[i])) + if (li->prevSibling()) + m_image->moveLayer(li, li->parent(), li->prevSibling()); + } + + if( !l.isEmpty() ) + list()->ensureItemVisible( list()->layer( l.first() ) ); +} + +void KisLayerBox::slotLowerClicked() +{ + QValueList<LayerItem*> l = list()->selectedLayers(); + if (l.count() < 2 && list()->activeLayer() && !l.contains(list()->activeLayer())) + { + l.clear(); + l.append(list()->activeLayer()); + } + + for (int i = l.count() - 1; i >= 0; --i) + if (LayerItem *layer = l[i]) + if (layer->nextSibling()) + list()->moveLayer(layer, layer->parent(), layer->nextSibling()); + + if( !l.isEmpty() ) + list()->ensureItemVisible( l.last() ); +} + +void KisLayerBox::slotPropertiesClicked() +{ + if (KisLayerSP active = m_image->activeLayer()) + emit sigRequestLayerProperties(active); +} + +void KisLayerBox::updateThumbnails() +{ + bool again = true; + while (m_modified.count() && again) + { + //again = false; + KisLayerItem* item = static_cast<KisLayerItem*>(list()->layer(m_modified.last())); + m_modified.pop_back(); + if (!item || !item->updatePreview()) + again = true; + } +} + +void KisLayerBox::setUpdatesAndSignalsEnabled(bool enable) +{ + setUpdatesEnabled(enable); + m_lst->intOpacity->setUpdatesEnabled(enable); + m_lst->cmbComposite->setUpdatesEnabled(enable); + + list()->blockSignals(!enable); + m_lst->intOpacity->blockSignals(!enable); + m_lst->cmbComposite->blockSignals(!enable); +} + + +QPixmap KisLayerBox::loadPixmap(const QString& filename, const KIconLoader& + il, int size) +{ + QPixmap pixmap = il.loadIcon(filename, KIcon::NoGroup, size); + + if (pixmap.isNull()) + KMessageBox::error(0, i18n("Cannot find %1").arg(filename), + i18n("Canvas")); + + return pixmap; +} + +void KisLayerBox::markModified(KisLayer* layer) +{ + if( !layer ) + return; + + QValueList<int> v; + while (layer && layer != m_image->rootLayer().data()) + { + v.append(layer->id()); + layer = layer->parent(); + } + for (int i = v.count() - 1; i >= 0; --i) + if (!m_modified.contains(v[i])) + m_modified.append(v[i]); +} + +void KisLayerBox::printKritaLayers() const +{ + static int indent = 0; + static KisLayer *root = 0; + if( !root ) + root = m_image->rootLayer(); + if( !root ) + return; + QString s = root->name(); + if( dynamic_cast<KisGroupLayer*>( root ) ) + s = QString("[%1]").arg( s ); + if( m_image->activeLayer().data() == root ) + s.prepend("*"); + kdDebug() << (QString().fill(' ', indent) + s) << endl; + for (KisLayer* layer = root->firstChild(); layer; layer = layer->nextSibling()) + { + indent += 2; + root = layer; + printKritaLayers(); + indent -= 2; + root = layer->parent(); + } +} + +void KisLayerBox::printLayerboxLayers() const +{ + static int indent = 0; + static LayerItem *root = 0; + if( !root ) + { + for (LayerItem* layer = list()->firstChild(); layer; layer = layer->nextSibling()) + { + indent += 2; + root = layer; + printLayerboxLayers(); + indent -= 2; + root = layer->parent(); + } + return; + } + QString s = root->displayName(); + if( root->isFolder() ) + s = QString("[%1]").arg( s ); + if( list()->activeLayer() == root ) + s.prepend("*"); + kdDebug() << (QString().fill(' ', indent) + s) << endl; + for (LayerItem* layer = root->firstChild(); layer; layer = layer->nextSibling()) + { + indent += 2; + root = layer; + printLayerboxLayers(); + indent -= 2; + root = layer->parent(); + } +} + +#include "kis_layerbox.moc" diff --git a/krita/ui/kis_layerbox.h b/krita/ui/kis_layerbox.h new file mode 100644 index 000000000..dab83d63e --- /dev/null +++ b/krita/ui/kis_layerbox.h @@ -0,0 +1,123 @@ +/* + * kis_layerbox.h - part of Krita aka Krayon aka KimageShop + * + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (C) 2006 Gábor Lehel <illissius@gmail.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KIS_LAYERBOX_H +#define KIS_LAYERBOX_H + +#include <qframe.h> +#include <kdebug.h> +#include <qtimer.h> + +#include "kis_types.h" +#include "kis_colorspace.h" + +class WdgLayerBox; +class QButton; +class QPainter; +class QWidget; +class KIconLoader; +class KPopupMenu; +class KoDocumentEntry; +class KisCompositeOp; +class KisLayerList; +class LayerItem; +class KisCanvasSubject; + +class KisLayerBox : public QFrame { + typedef QFrame super; + Q_OBJECT + +public: + KisLayerBox(KisCanvasSubject *subject, QWidget *parent = 0, const char *name = 0); + virtual ~KisLayerBox(); + + void clear(); + void setUpdatesAndSignalsEnabled(bool enable); + void setImage(KisImageSP image); + +public slots: + // connect to KisImage signals + void slotLayerActivated(KisLayerSP layer); + void slotLayerAdded(KisLayerSP layer); + void slotLayerRemoved(KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAboveThis); + void slotLayerMoved(KisLayerSP layer, KisGroupLayerSP wasParent, KisLayerSP wasAboveThis); + void slotLayerPropertiesChanged(KisLayerSP layer); + void slotLayersChanged(KisGroupLayerSP rootLayer); + void slotLayerUpdated(KisLayerSP layer, QRect rc); + + void slotSetCompositeOp(const KisCompositeOp& compositeOp); + void slotSetOpacity(int opacity); + void slotSetColorSpace(const KisColorSpace * colorSpace); + +signals: + void sigRequestLayer(KisGroupLayerSP parent, KisLayerSP above); + void sigRequestGroupLayer(KisGroupLayerSP parent, KisLayerSP above); + void sigRequestAdjustmentLayer(KisGroupLayerSP parent, KisLayerSP above); + void sigRequestPartLayer(KisGroupLayerSP parent, KisLayerSP above, const KoDocumentEntry& entry); + void sigRequestLayerProperties(KisLayerSP layer); + + void sigOpacityChanged(int opacity, bool withSlider); + void sigOpacityFinishedChanging(int previous, int opacity); + void sigItemComposite(const KisCompositeOp&); + +private: + enum LayerTypes { PAINT_LAYER, GROUP_LAYER, ADJUSTMENT_LAYER, OBJECT_LAYER }; + +private slots: + // connect to LayerList signals + void slotLayerActivated(LayerItem* layer); + void slotLayerDisplayNameChanged(LayerItem* layer, const QString& displayName); + void slotLayerPropertyChanged(LayerItem* layer, const QString& name, bool on); + void slotLayerMoved(LayerItem* layer, LayerItem* parent, LayerItem* after); + void slotRequestNewLayer(LayerItem* parent, LayerItem* after); + void slotRequestNewFolder(LayerItem* parent, LayerItem* after); + void slotRequestNewAdjustmentLayer(LayerItem* parent, LayerItem* after); + void slotRequestNewObjectLayer(LayerItem* parent, LayerItem* item, const KoDocumentEntry& entry); + void slotRequestRemoveLayer(LayerItem* layer); + void slotRequestLayerProperties(LayerItem* layer); + + void slotAboutToShow(); + void slotAddMenuActivated(int type = OBJECT_LAYER); + void slotRmClicked(); + void slotRaiseClicked(); + void slotLowerClicked(); + void slotPropertiesClicked(); + + void updateThumbnails(); + +private: + void updateUI(); + QPixmap loadPixmap(const QString& filename, const KIconLoader& il, int size); + KisLayerList* list() const; + void markModified(KisLayer *layer); + + KPopupMenu *m_newLayerMenu; + KoPartSelectAction *m_partLayerAction; + KisImageSP m_image; + QValueList<int> m_modified; + WdgLayerBox *m_lst; + + void printKritaLayers() const; + void printLayerboxLayers() const; +}; + +#endif // KIS_LAYERBOX_H + diff --git a/krita/ui/kis_layerlist.cc b/krita/ui/kis_layerlist.cc new file mode 100644 index 000000000..356d7e390 --- /dev/null +++ b/krita/ui/kis_layerlist.cc @@ -0,0 +1,220 @@ +/* + Copyright (c) 2005 Gábor Lehel <illissius@gmail.com> + + 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 <kaboutdata.h> +#include <kglobal.h> +#include <kiconloader.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <KoPartSelectAction.h> +#include <qimage.h> + +#include "kis_layer.h" +#include "kis_paint_layer.h" +#include "kis_part_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_filter.h" +#include "kis_filter_configuration.h" +#include "kis_filter_registry.h" +#include "kis_layerlist.h" + + +KisLayerList::KisLayerList( QWidget *parent, const char *name ) + : super( parent, name ) +{ + m_partLayerAction = new KoPartSelectAction( i18n( "New &Object Layer" ), "gear", this ); +} + +static const int ADJUSTMENT_LAYER = 5384; //hack? + +void KisLayerList::constructMenu( LayerItem *layer ) +{ + super::constructMenu( layer ); + + contextMenu()->removeItem( MenuItems::NewLayer ); + contextMenu()->removeItem( MenuItems::NewFolder ); + contextMenu()->changeItem( MenuItems::RemoveLayer, i18n( "&Remove Layer" ) ); + + if( layer ) + { + static KPopupMenu submenu; + submenu.clear(); + submenu.insertItem( SmallIconSet( "file" ), i18n( "&Layer..." ), MenuItems::NewLayer ); + submenu.insertItem( SmallIconSet( "folder" ), i18n( "&Group Layer..." ), MenuItems::NewFolder ); + submenu.insertItem( SmallIconSet( "tool_filter" ), i18n( "&Adjustment Layer..." ), ADJUSTMENT_LAYER ); + m_partLayerAction->setText( i18n( "&Object Layer" ) ); + m_partLayerAction->plug( &submenu ); + + contextMenu()->insertItem( SmallIconSet( "filenew" ), i18n( "&New" ), &submenu ); + } + else + { + contextMenu()->insertItem( SmallIconSet( "filenew" ), i18n( "&New Layer..." ), MenuItems::NewLayer ); + contextMenu()->insertItem( SmallIconSet( "folder" ), i18n( "New &Group Layer..." ), MenuItems::NewFolder ); + contextMenu()->insertItem( SmallIconSet( "tool_filter" ), i18n( "New &Adjustment Layer..." ), ADJUSTMENT_LAYER ); + m_partLayerAction->setText( i18n( "New &Object Layer" ) ); + m_partLayerAction->plug( contextMenu() ); + } +} + +void KisLayerList::menuActivated( int id, LayerItem *layer ) +{ + const QValueList<LayerItem*> selected = selectedLayers(); + LayerItem *parent = ( layer && layer->isFolder() ) ? layer : 0; + LayerItem *after = 0; + if( layer && !parent ) + { + parent = layer->parent(); + after = layer->prevSibling(); + } + switch( id ) + { + case MenuItems::NewLayer: + emit requestNewLayer( parent, after ); + emit requestNewLayer( parent ? parent->id() : -1, after ? after->id() : -1 ); + break; + case MenuItems::NewFolder: + emit requestNewFolder( parent, after ); + emit requestNewFolder( parent ? parent->id() : -1, after ? after->id() : -1 ); + break; + case ADJUSTMENT_LAYER: + emit requestNewAdjustmentLayer( parent, after ); + emit requestNewAdjustmentLayer( parent ? parent->id() : -1, after ? after->id() : -1 ); + break; + case MenuItems::RemoveLayer: + { + QValueList<int> ids; + for( int i = 0, n = selected.count(); i < n; ++i ) + { + ids.append( selected[i]->id() ); + emit requestRemoveLayer( selected[i]->id() ); + } + emit requestRemoveLayers( ids ); + } + for( int i = 0, n = selected.count(); i < n; ++i ) + emit requestRemoveLayer( selected[i] ); + emit requestRemoveLayers( selected ); + break; + case MenuItems::LayerProperties: + if( layer ) + { + emit requestLayerProperties( layer ); + emit requestLayerProperties( layer->id() ); + } + break; + default: + if( id >= MenuItems::COUNT && layer ) + super::menuActivated( id, layer ); + else if( id != -1 ) //object layer was selected + { + emit requestNewObjectLayer( parent, after, m_partLayerAction->documentEntry() ); + emit requestNewObjectLayer( parent ? parent->id() : -1, after ? after->id() : -1, m_partLayerAction->documentEntry() ); + } + } +} + +KisLayerItem::KisLayerItem( LayerList* parent, KisLayer* layer ) + : super( layer->name(), + parent, + layer->prevSibling() ? parent->layer( layer->prevSibling()->id() ) : 0, + layer->id() ) + , m_layer( layer ) +{ + init(); +} + +KisLayerItem::KisLayerItem( LayerItem* parent, KisLayer* layer ) + : super( layer->name(), + parent, + layer->prevSibling() ? parent->listView()->layer( layer->prevSibling()->id() ) : 0, + layer->id() ) + , m_layer( layer ) +{ + init(); +} + +void KisLayerItem::init() +{ + setPreviewImage( &m_preview ); + sync(); +} + +KisLayer* KisLayerItem::layer() const +{ + return m_layer; +} + +void KisLayerItem::sync() +{ + setProperty( "visible", layer()->visible() ); + setProperty( "locked", layer()->locked() ); + setDisplayName( layer()->name() ); + update(); +} + +bool KisLayerItem::updatePreview() +{ + m_preview = m_layer->createThumbnail( height()*2, height()*2 ); + m_preview.setAlphaBuffer( true ); + previewChanged(); + return !m_preview.isNull(); +} + +QString KisLayerItem::tooltip() const +{ + QString text = super::tooltip(); + text = text.left( text.length() - 8 ); //HACK -- strip the </table> + QString row = "<tr><td>%1</td><td>%2</td></tr>"; + text += row.arg( i18n( "Opacity:" ) ).arg( "%1%" ).arg( int( float( m_layer->opacity() * 100 ) / 255 + 0.5 ) ); + text += row.arg( i18n( "Composite mode:" ) ).arg( m_layer->compositeOp().id().name() ); + if( KisPaintLayer *player = dynamic_cast<KisPaintLayer*>( m_layer ) ) + { + text += row.arg( i18n( "Colorspace:" ) ).arg( player->paintDevice()->colorSpace()->id().name() ); + if( KisProfile *profile = player->paintDevice()->colorSpace()->getProfile() ) + text += row.arg( i18n( "Profile:" ) ).arg( profile->productName() ); + } + if( KisAdjustmentLayer *alayer = dynamic_cast<KisAdjustmentLayer*>( m_layer ) ) + text += row.arg( i18n( "Filter: " ) ).arg( KisFilterRegistry::instance()->get( alayer->filter()->name() )->id().name() ); + if( KisPartLayerImpl *player = dynamic_cast<KisPartLayerImpl*>( m_layer ) ) { + QString type = player->docType(); + + if( type.isEmpty() ) { + type = player->childDoc()->document()->instance()->aboutData()->programName(); + } + + text += row.arg( i18n( "Document type: " ) ).arg( type ); + } + text += "</table>"; + + return text; +} + +QImage KisLayerItem::tooltipPreview() const +{ + QImage img = m_layer->createThumbnail( 400, 400 ); + if( img.isNull() ) + return img; //so Qt doesn't complain + img.setAlphaBuffer( true ); + const int size = kMin( 200, kMax( img.width(), img.height() ) ); + return img.smoothScale( size, size, QImage::ScaleMin ); +} + +//void KisLayerItem::paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align ); + +#include "kis_layerlist.moc" diff --git a/krita/ui/kis_layerlist.h b/krita/ui/kis_layerlist.h new file mode 100644 index 000000000..e3bacdfdc --- /dev/null +++ b/krita/ui/kis_layerlist.h @@ -0,0 +1,79 @@ +/* + Copyright (c) 2005 Gábor Lehel <illissius@gmail.com> + + 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_LAYERLIST_H +#define KIS_LAYERLIST_H + +#include <qimage.h> +#include "layerlist.h" + +class KoPartSelectAction; +class KoDocumentEntry; +class KisLayer; + +class KisLayerList: public LayerList +{ + Q_OBJECT + typedef LayerList super; + +signals: + void requestNewObjectLayer( LayerItem *parent, LayerItem *after, const KoDocumentEntry &entry ); + void requestNewObjectLayer( int parentID, int afterID, const KoDocumentEntry &entry ); + void requestNewAdjustmentLayer( LayerItem *parent, LayerItem *after ); + void requestNewAdjustmentLayer( int parentID, int afterID ); + +public: + KisLayerList( QWidget *parent = 0, const char *name = 0 ); + + virtual void constructMenu( LayerItem *layer ); + virtual void menuActivated( int id, LayerItem *layer ); + + KoPartSelectAction *partLayerAction() const { return m_partLayerAction; } + +private: + KoPartSelectAction *m_partLayerAction; +}; + +class KisLayerItem: public LayerItem +{ + typedef LayerItem super; + +public: + KisLayerItem( LayerList* parent, KisLayer* layer ); + KisLayerItem( LayerItem* parent, KisLayer* layer ); + + KisLayer* layer() const; + + void sync(); + + /// returns whether any preview was retrieved + bool updatePreview(); + + virtual QString tooltip() const; + virtual QImage tooltipPreview() const; + + //virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align ); + +private: + void init(); + QImage m_preview; + KisLayer *m_layer; +}; + +#endif diff --git a/krita/ui/kis_load_visitor.h b/krita/ui/kis_load_visitor.h new file mode 100644 index 000000000..ff1c1cf8b --- /dev/null +++ b/krita/ui/kis_load_visitor.h @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk> + * + * 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_LOAD_VISITOR_H_ +#define KIS_LOAD_VISITOR_H_ + +#include <qrect.h> +#include "kis_types.h" +#include "kis_layer_visitor.h" +#include "kis_image.h" +#include "kis_selection.h" +#include "kis_layer.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_filter_configuration.h" + +#include "kis_datamanager.h" + +class KisLoadVisitor : public KisLayerVisitor { +public: + KisLoadVisitor(KisImageSP img, KoStore *store, QMap<KisLayerSP, QString> &layerFilenames) : + KisLayerVisitor(), + m_layerFilenames(layerFilenames) + { + m_external = false; + m_img = img; + m_store = store; + } + +public: + void setExternalUri(QString &uri) + { + m_external = true; + m_uri = uri; + } + + virtual bool visit(KisPaintLayer *layer) + { //connect(*layer->paintDevice(), SIGNAL(ioProgress(Q_INT8)), m_img, SLOT(slotIOProgress(Q_INT8))); + + QString location = m_external ? QString::null : m_uri; + location += m_img->name() + "/layers/" + m_layerFilenames[layer]; + + // Layer data + if (m_store->open(location)) { + if (!layer->paintDevice()->read(m_store)) { + layer->paintDevice()->disconnect(); + m_store->close(); + //IODone(); + return false; + } + + m_store->close(); + } + + // icc profile + location = m_external ? QString::null : m_uri; + location += m_img->name() + "/layers/" + m_layerFilenames[layer] + ".icc"; + + if (m_store->hasFile(location)) { + QByteArray data; + m_store->open(location); + data = m_store->read(m_store->size()); + m_store->close(); + // Create a colorspace with the embedded profile + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getColorSpace(layer->paintDevice()->colorSpace()->id(), + new KisProfile(data)); + // replace the old colorspace + layer->paintDevice()->setData(layer->paintDevice()->dataManager(), cs); + QRect rc = layer->paintDevice()->extent(); + kdDebug() << "After loading " << layer->name() << " extent is: " << rc.x() << ", " << rc.y() << ", " << rc.width() << ", " << rc.height() << endl; + layer->setDirty(rc); + kdDebug(DBG_AREA_FILE) << "Opened icc information, size is " << data.size() << endl; + } + + // mask + if (layer->hasMask()) { // We set this in KisDoc::loadPaintLayer + KisPaintDeviceSP mask = layer->getMask(); + location = m_external ? QString::null : m_uri; + location += m_img->name() + "/layers/" + m_layerFilenames[layer] + ".mask"; + + // Layer data + if (m_store->open(location)) { + if (!mask->read(m_store)) { + mask->disconnect(); + m_store->close(); + //IODone(); + return false; + } + + m_store->close(); + } + layer->setDirty(); // Update the entire layer + } + + return true; + + } + + virtual bool visit(KisGroupLayer *layer) + { + KisLoadVisitor visitor(m_img,m_store ,m_layerFilenames); + + if(m_external) + visitor.setExternalUri(m_uri); + + KisLayerSP child = layer->firstChild(); + + while(child) + { + child->accept(visitor); + child = child->nextSibling(); + } + + layer->setDirty(m_img->bounds()); + return true; + } + + virtual bool visit(KisPartLayer *) + { + return true; + } + + virtual bool visit(KisAdjustmentLayer* layer) + { + //connect(*layer->paintDevice(), SIGNAL(ioProgress(Q_INT8)), m_img, SLOT(slotIOProgress(Q_INT8))); + + // The selection -- if present. If not, we simply cannot open the dratted thing. + QString location = m_external ? QString::null : m_uri; + location += m_img->name() + "/layers/" + m_layerFilenames[layer] + ".selection"; + if (m_store->hasFile(location)) { + m_store->open(location); + KisSelectionSP selection = new KisSelection(); + if (!selection->read(m_store)) { + selection->disconnect(); + m_store->close(); + } + else { + layer->setSelection( selection ); + } + m_store->close(); + } + + // filter configuration + location = m_external ? QString::null : m_uri; + location += m_img->name() + "/layers/" + m_layerFilenames[layer] + ".filterconfig"; + + if (m_store->hasFile(location) && layer->filter()) { + QByteArray data; + m_store->open(location); + data = m_store->read(m_store->size()); + m_store->close(); + if (data) { + KisFilterConfiguration * kfc = layer->filter(); + kfc->fromXML(QString(data)); + } + } + + return true; + + } + +private: + KisImageSP m_img; + KoStore *m_store; + bool m_external; + QString m_uri; + QMap<KisLayerSP, QString> m_layerFilenames; +}; + +#endif // KIS_LOAD_VISITOR_H_ + diff --git a/krita/ui/kis_matrix_widget.ui b/krita/ui/kis_matrix_widget.ui new file mode 100644 index 000000000..dda7d63cb --- /dev/null +++ b/krita/ui/kis_matrix_widget.ui @@ -0,0 +1,210 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisMatrixWidget</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisMatrixWidget</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>191</width> + <height>115</height> + </rect> + </property> + <property name="caption"> + <string>Matrix Widget</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QSpinBox" row="0" column="0"> + <property name="name"> + <cstring>m11</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="0" column="2"> + <property name="name"> + <cstring>m13</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>m12</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="1" column="2"> + <property name="name"> + <cstring>m23</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="1" column="0"> + <property name="name"> + <cstring>m21</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>m22</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + <widget class="QSpinBox" row="2" column="0"> + <property name="name"> + <cstring>m31</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="2" column="1"> + <property name="name"> + <cstring>m32</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <widget class="QSpinBox" row="2" column="2"> + <property name="name"> + <cstring>m33</cstring> + </property> + <property name="minValue"> + <number>-99</number> + </property> + </widget> + <spacer row="3" column="1"> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>41</height> + </size> + </property> + </spacer> + <spacer row="1" column="3"> + <property name="name"> + <cstring>spacer5</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> +</widget> +<connections> + <connection> + <sender>m11</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m12</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m13</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m21</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m22</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m23</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m31</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m32</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> + <connection> + <sender>m33</sender> + <signal>valueChanged(int)</signal> + <receiver>KisMatrixWidget</receiver> + <slot>spinboxValueChanged()</slot> + </connection> +</connections> +<tabstops> + <tabstop>m11</tabstop> + <tabstop>m12</tabstop> + <tabstop>m13</tabstop> + <tabstop>m21</tabstop> + <tabstop>m22</tabstop> + <tabstop>m23</tabstop> + <tabstop>m31</tabstop> + <tabstop>m32</tabstop> + <tabstop>m33</tabstop> +</tabstops> +<includes> + <include location="local" impldecl="in implementation">kis_matrix_widget.ui.h</include> +</includes> +<signals> + <signal>valueChanged()</signal> +</signals> +<slots> + <slot access="private">spinboxValueChanged()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/kis_matrix_widget.ui.h b/krita/ui/kis_matrix_widget.ui.h new file mode 100644 index 000000000..a0b06224e --- /dev/null +++ b/krita/ui/kis_matrix_widget.ui.h @@ -0,0 +1,17 @@ +/**************************************************************************** +** ui.h extension file, included from the uic-generated form implementation. +** +** If you want to add, delete, or rename functions or slots, use +** Qt Designer to update this file, preserving your code. +** +** You should not define a constructor or destructor in this file. +** Instead, write your code in functions called init() and destroy(). +** These will automatically be called by the form's constructor and +** destructor. +*****************************************************************************/ + + +void KisMatrixWidget::spinboxValueChanged() +{ + emit valueChanged(); +} diff --git a/krita/ui/kis_move_event.h b/krita/ui/kis_move_event.h new file mode 100644 index 000000000..5a7b0ca98 --- /dev/null +++ b/krita/ui/kis_move_event.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_MOVE_EVENT_H_ +#define KIS_MOVE_EVENT_H_ + +#include "kis_event.h" + +class KisMoveEvent : public KisEvent { + typedef KisEvent super; +public: + KisMoveEvent() {} + KisMoveEvent(KisInputDevice device, const KisPoint& pos, const KisPoint& globalPos, double pressure, double xTilt, double yTilt, Qt::ButtonState state) : super(MoveEvent, device, pos, globalPos, pressure, xTilt, yTilt, state) {} +}; + +#endif // KIS_MOVE_EVENT_H_ + diff --git a/krita/ui/kis_multi_bool_filter_widget.cc b/krita/ui/kis_multi_bool_filter_widget.cc new file mode 100644 index 000000000..d5904287d --- /dev/null +++ b/krita/ui/kis_multi_bool_filter_widget.cc @@ -0,0 +1,68 @@ +/* + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> + * + * 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_multi_bool_filter_widget.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qcheckbox.h> + +#include <klocale.h> + +KisBoolWidgetParam::KisBoolWidgetParam( bool ninitvalue, QString nlabel, QString nname) : + initvalue(ninitvalue), + label(nlabel), + name(nname) +{ + +} + +KisMultiBoolFilterWidget::KisMultiBoolFilterWidget(QWidget * parent, const char * name, const char * caption, vKisBoolWidgetParam iwparam) : + KisFilterConfigWidget( parent, name ) +{ + Q_INT32 m_nbboolWidgets = iwparam.size(); + + this->setCaption(caption); + + QVBoxLayout *widgetLayout = new QVBoxLayout(this, m_nbboolWidgets + 1); + + m_boolWidgets = new QCheckBox*[ m_nbboolWidgets ]; + + for( Q_INT32 i = 0; i < m_nbboolWidgets; ++i) + { + m_boolWidgets[i] = new QCheckBox( this, iwparam[i].name.ascii()); + m_boolWidgets[i]->setChecked( iwparam[i].initvalue ); + m_boolWidgets[i]->setText( iwparam[i].label ); + connect(m_boolWidgets[i], SIGNAL(toggled( bool ) ), SIGNAL(sigPleaseUpdatePreview())); + widgetLayout->add( m_boolWidgets[i]); + } +// QSpacerItem * sp = new QSpacerItem(1, 1); + widgetLayout->addStretch(); +} + + +void KisMultiBoolFilterWidget::setConfiguration(KisFilterConfiguration * config) +{ + + for (int i = 0; i < m_nbboolWidgets; ++i) { + double val = config->getBool(m_boolWidgets[i]->name()); + m_boolWidgets[i]->setChecked(val); + } +} + +#include "kis_multi_bool_filter_widget.moc" diff --git a/krita/ui/kis_multi_bool_filter_widget.h b/krita/ui/kis_multi_bool_filter_widget.h new file mode 100644 index 000000000..b9b4b2d71 --- /dev/null +++ b/krita/ui/kis_multi_bool_filter_widget.h @@ -0,0 +1,55 @@ +/* + * Copyright (c) 2005 Michael Thaler <michael.thaler@physik.tu-muenchen.de> + * + * 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_MULTI_BOOL_FILTER_WIDGET_H_ +#define _KIS_MULTI_BOOL_FILTER_WIDGET_H_ + +#include <vector> + +#include <qcheckbox.h> + +#include "koffice_export.h" +#include <kis_filter_config_widget.h> + +class KIntNumInput; + +struct KisBoolWidgetParam { + KRITA_EXPORT KisBoolWidgetParam( bool ninitvalue, QString label, QString name); + bool initvalue; + QString label; + QString name; + +}; + +typedef std::vector<KisBoolWidgetParam> vKisBoolWidgetParam; + +class KRITA_EXPORT KisMultiBoolFilterWidget : public KisFilterConfigWidget +{ + Q_OBJECT +public: + KisMultiBoolFilterWidget(QWidget * parent, const char * name, const char *caption, vKisBoolWidgetParam iwparam); + virtual void setConfiguration(KisFilterConfiguration * cfg); +public: + inline Q_INT32 nbValues() { return m_nbboolWidgets; }; + inline Q_INT32 valueAt( Q_INT32 i ) { return m_boolWidgets[i]->isChecked(); }; +private: + QCheckBox** m_boolWidgets; + Q_INT32 m_nbboolWidgets; +}; + +#endif diff --git a/krita/ui/kis_multi_double_filter_widget.cc b/krita/ui/kis_multi_double_filter_widget.cc new file mode 100644 index 000000000..024b03681 --- /dev/null +++ b/krita/ui/kis_multi_double_filter_widget.cc @@ -0,0 +1,103 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_multi_double_filter_widget.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qtimer.h> + +#include <knuminput.h> +#include <kis_filter_config_widget.h> +#include <klocale.h> + +KisDelayedActionDoubleInput::KisDelayedActionDoubleInput(QWidget * parent, const char * name) + : KDoubleNumInput(parent, name) +{ + m_timer = new QTimer(this, name); + connect(m_timer, SIGNAL(timeout()), SLOT(slotValueChanged())); + connect(this, SIGNAL(valueChanged( double )), SLOT(slotTimeToUpdate())); +} + +void KisDelayedActionDoubleInput::slotTimeToUpdate() +{ + m_timer->start(50, true); +} + +void KisDelayedActionDoubleInput::slotValueChanged() +{ + emit valueChangedDelayed( value() ); +} + +void KisDelayedActionDoubleInput::cancelDelayedSignal() +{ + m_timer->stop(); +} + +KisDoubleWidgetParam::KisDoubleWidgetParam(double nmin, double nmax, double ninitvalue, QString nlabel, QString nname) : + min(nmin), + max(nmax), + initvalue(ninitvalue), + label(nlabel), + name(nname) +{ + +} + +KisMultiDoubleFilterWidget::KisMultiDoubleFilterWidget(QWidget * parent, const char * name, const char * caption, vKisDoubleWidgetParam dwparam) + : KisFilterConfigWidget( parent, name ) +{ + Q_INT32 m_nbdoubleWidgets = dwparam.size(); + + this->setCaption(caption); + + QGridLayout *widgetLayout = new QGridLayout(this, m_nbdoubleWidgets + 1, 3); + widgetLayout->setColStretch ( 1, 1 ); + + m_doubleWidgets = new KisDelayedActionDoubleInput*[ m_nbdoubleWidgets ]; + + for( Q_INT32 i = 0; i < m_nbdoubleWidgets; ++i) + { + m_doubleWidgets[i] = new KisDelayedActionDoubleInput(this, dwparam[i].name.ascii()); + m_doubleWidgets[i]->setRange( dwparam[i].min, dwparam[i].max ); + m_doubleWidgets[i]->setValue( dwparam[i].initvalue ); + m_doubleWidgets[i]->cancelDelayedSignal(); + + connect(m_doubleWidgets[i], SIGNAL(valueChangedDelayed(double)), SIGNAL(sigPleaseUpdatePreview())); + + QLabel* lbl = new QLabel(dwparam[i].label+":", this); + widgetLayout->addWidget( lbl, i , 0); + + widgetLayout->addWidget( m_doubleWidgets[i], i , 1); + } + QSpacerItem * sp = new QSpacerItem(1, 1); + widgetLayout->addItem(sp, m_nbdoubleWidgets, 0); + +} + +void KisMultiDoubleFilterWidget::setConfiguration(KisFilterConfiguration * config) +{ + + for (int i = 0; i < m_nbdoubleWidgets ; ++i) { + double val = config->getDouble(m_doubleWidgets[i]->name()); + m_doubleWidgets[i]->setValue(val); + m_doubleWidgets[i]->cancelDelayedSignal(); + } +} + +#include "kis_multi_double_filter_widget.moc" diff --git a/krita/ui/kis_multi_double_filter_widget.h b/krita/ui/kis_multi_double_filter_widget.h new file mode 100644 index 000000000..bd1cf2351 --- /dev/null +++ b/krita/ui/kis_multi_double_filter_widget.h @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_MULTI_DOUBLE_FILTER_WIDGET_H_ +#define _KIS_MULTI_DOUBLE_FILTER_WIDGET_H_ + +#include <vector> +#include <knuminput.h> +#include <kis_filter_config_widget.h> +#include "koffice_export.h" + +class KisDelayedActionDoubleInput : public KDoubleNumInput +{ + + Q_OBJECT + + public: + + KisDelayedActionDoubleInput(QWidget * parent, const char * name); + + void cancelDelayedSignal(); + + private slots: + void slotValueChanged(); + void slotTimeToUpdate(); + + signals: + + void valueChangedDelayed(double value); + + private: + + QTimer * m_timer; +}; + + +struct KRITA_EXPORT KisDoubleWidgetParam { + KisDoubleWidgetParam( double nmin, double nmax, double ninitvalue, QString label, QString nname); + double min; + double max; + double initvalue; + QString label; + QString name; +}; + +typedef std::vector<KisDoubleWidgetParam> vKisDoubleWidgetParam; + +class KRITA_EXPORT KisMultiDoubleFilterWidget : public KisFilterConfigWidget +{ + Q_OBJECT +public: + KisMultiDoubleFilterWidget(QWidget * parent, const char * name, const char * caption, vKisDoubleWidgetParam dwparam); + virtual void setConfiguration(KisFilterConfiguration * cfg); +public: + inline Q_INT32 nbValues() { return m_nbdoubleWidgets; }; + inline double valueAt( Q_INT32 i ) { return m_doubleWidgets[i]->value(); }; +private: + KisDelayedActionDoubleInput** m_doubleWidgets; + Q_INT32 m_nbdoubleWidgets; +}; + +#endif diff --git a/krita/ui/kis_multi_integer_filter_widget.cc b/krita/ui/kis_multi_integer_filter_widget.cc new file mode 100644 index 000000000..be50022d9 --- /dev/null +++ b/krita/ui/kis_multi_integer_filter_widget.cc @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_multi_integer_filter_widget.h" + +#include <qlabel.h> +#include <qlayout.h> +#include <qtimer.h> + +#include <knuminput.h> +#include <klocale.h> + +KisDelayedActionIntegerInput::KisDelayedActionIntegerInput(QWidget * parent, const char * name) + : KIntNumInput(parent, name) +{ + m_timer = new QTimer(this, name); + connect(m_timer, SIGNAL(timeout()), SLOT(slotValueChanged())); + connect(this, SIGNAL(valueChanged( int )), SLOT(slotTimeToUpdate())); +} + +void KisDelayedActionIntegerInput::slotTimeToUpdate() +{ + m_timer->start(50, true); +} + +void KisDelayedActionIntegerInput::slotValueChanged() +{ + emit valueChangedDelayed( value() ); +} + +void KisDelayedActionIntegerInput::cancelDelayedSignal() +{ + m_timer->stop(); +} + +KisIntegerWidgetParam::KisIntegerWidgetParam( Q_INT32 nmin, Q_INT32 nmax, Q_INT32 ninitvalue, QString label, QString nname) : + min(nmin), + max(nmax), + initvalue(ninitvalue), + label(label), + name(nname) +{ +} + +KisMultiIntegerFilterWidget::KisMultiIntegerFilterWidget(QWidget * parent, + const char * name, + const char * caption, + vKisIntegerWidgetParam iwparam) + : KisFilterConfigWidget( parent, name ) +{ + m_nbintegerWidgets = iwparam.size(); + this->setCaption(caption); + + QGridLayout *widgetLayout = new QGridLayout(this, m_nbintegerWidgets + 1, 3); + widgetLayout->setColStretch ( 1, 1 ); + + m_integerWidgets = new KisDelayedActionIntegerInput*[ m_nbintegerWidgets ]; + + for( Q_INT32 i = 0; i < m_nbintegerWidgets; ++i) + { + m_integerWidgets[i] = new KisDelayedActionIntegerInput( this, iwparam[i].name.ascii()); + m_integerWidgets[i]->setRange( iwparam[i].min, iwparam[i].max); + m_integerWidgets[i]->setValue( iwparam[i].initvalue ); + m_integerWidgets[i]->cancelDelayedSignal(); + + connect(m_integerWidgets[i], SIGNAL(valueChangedDelayed( int )), SIGNAL(sigPleaseUpdatePreview())); + + QLabel* lbl = new QLabel(iwparam[i].label+":", this); + widgetLayout->addWidget( lbl, i , 0); + + widgetLayout->addWidget( m_integerWidgets[i], i , 1); + } + QSpacerItem * sp = new QSpacerItem(1, 1); + widgetLayout->addItem(sp, m_nbintegerWidgets, 0); +} + +void KisMultiIntegerFilterWidget::setConfiguration( KisFilterConfiguration * config ) +{ + for (int i = 0; i < nbValues(); ++i) { + KisDelayedActionIntegerInput * w = m_integerWidgets[i]; + if (w) { + int val = config->getInt(m_integerWidgets[i]->name()); + m_integerWidgets[i]->setValue(val); + m_integerWidgets[i]->cancelDelayedSignal(); + } + } +} + +#include "kis_multi_integer_filter_widget.moc" diff --git a/krita/ui/kis_multi_integer_filter_widget.h b/krita/ui/kis_multi_integer_filter_widget.h new file mode 100644 index 000000000..fe0ececf7 --- /dev/null +++ b/krita/ui/kis_multi_integer_filter_widget.h @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_MULTI_INTEGER_FILTER_WIDGET_H_ +#define _KIS_MULTI_INTEGER_FILTER_WIDGET_H_ + +#include <vector> + +#include <knuminput.h> +#include <kis_filter_config_widget.h> +#include "koffice_export.h" + +class KisDelayedActionIntegerInput : public KIntNumInput +{ + + Q_OBJECT + +public: + + KisDelayedActionIntegerInput(QWidget * parent, const char * name); + + void cancelDelayedSignal(); + +private slots: + void slotValueChanged(); + void slotTimeToUpdate(); + +signals: + + void valueChangedDelayed(int value); + +private: + + QTimer * m_timer; +}; + + +struct KisIntegerWidgetParam { + KRITA_EXPORT KisIntegerWidgetParam( Q_INT32 nmin, Q_INT32 nmax, Q_INT32 ninitvalue, QString label, QString nname); + Q_INT32 min; + Q_INT32 max; + Q_INT32 initvalue; + QString label; + QString name; +}; + +typedef std::vector<KisIntegerWidgetParam> vKisIntegerWidgetParam; + +class KRITA_EXPORT KisMultiIntegerFilterWidget : public KisFilterConfigWidget +{ + Q_OBJECT +public: + KisMultiIntegerFilterWidget(QWidget * parent, const char * name, const char *caption, vKisIntegerWidgetParam iwparam); + + virtual void setConfiguration(KisFilterConfiguration * config); + +public: + inline Q_INT32 nbValues() { return m_nbintegerWidgets; }; + inline Q_INT32 valueAt( Q_INT32 i ) { return m_integerWidgets[i]->value(); }; + +private: + Q_INT32 m_nbintegerWidgets; + KisDelayedActionIntegerInput** m_integerWidgets; +}; + +#endif diff --git a/krita/ui/kis_opengl_canvas.cc b/krita/ui/kis_opengl_canvas.cc new file mode 100644 index 000000000..0ec9ec72a --- /dev/null +++ b/krita/ui/kis_opengl_canvas.cc @@ -0,0 +1,127 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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_canvas.h" +#include "kis_opengl_canvas.h" +#include "kis_opengl_canvas_painter.h" + +#ifdef HAVE_GL +KisOpenGLCanvasWidget::KisOpenGLCanvasWidget(QWidget *parent, const char *name, QGLWidget *sharedContextWidget) + : QGLWidget(KisOpenGLCanvasFormat, parent, name, sharedContextWidget) +{ + if (isSharing()) { + kdDebug(41001) << "Created QGLWidget with sharing\n"; + } else { + kdDebug(41001) << "Created QGLWidget with no sharing\n"; + } +} + +KisOpenGLCanvasWidget::~KisOpenGLCanvasWidget() +{ +} + +void KisOpenGLCanvasWidget::paintEvent(QPaintEvent *e) +{ + QGLWidget::paintEvent(e); + + widgetGotPaintEvent(e); +} + +void KisOpenGLCanvasWidget::mousePressEvent(QMouseEvent *e) +{ + widgetGotMousePressEvent(e); +} + +void KisOpenGLCanvasWidget::mouseReleaseEvent(QMouseEvent *e) +{ + widgetGotMouseReleaseEvent(e); +} + +void KisOpenGLCanvasWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + widgetGotMouseDoubleClickEvent(e); +} + +void KisOpenGLCanvasWidget::mouseMoveEvent(QMouseEvent *e) +{ + widgetGotMouseMoveEvent(e); +} + +void KisOpenGLCanvasWidget::tabletEvent(QTabletEvent *e) +{ + widgetGotTabletEvent(e); +} + +void KisOpenGLCanvasWidget::enterEvent(QEvent *e) +{ + widgetGotEnterEvent(e); +} + +void KisOpenGLCanvasWidget::leaveEvent(QEvent *e) +{ + widgetGotLeaveEvent(e); +} + +void KisOpenGLCanvasWidget::wheelEvent(QWheelEvent *e) +{ + widgetGotWheelEvent(e); +} + +void KisOpenGLCanvasWidget::keyPressEvent(QKeyEvent *e) +{ + widgetGotKeyPressEvent(e); +} + +void KisOpenGLCanvasWidget::keyReleaseEvent(QKeyEvent *e) +{ + widgetGotKeyReleaseEvent(e); +} + +void KisOpenGLCanvasWidget::dragEnterEvent(QDragEnterEvent *e) +{ + widgetGotDragEnterEvent(e); +} + +void KisOpenGLCanvasWidget::dropEvent(QDropEvent *e) +{ + widgetGotDropEvent(e); +} + +#ifdef Q_WS_X11 + +bool KisOpenGLCanvasWidget::x11Event(XEvent *event) +{ + return KisCanvasWidget::x11Event(event, x11Display(), winId(), mapToGlobal(QPoint(0, 0))); +} + +#endif // Q_WS_X11 + +KisCanvasWidgetPainter *KisOpenGLCanvasWidget::createPainter() +{ + return new KisOpenGLCanvasPainter(this); +} + +#if defined(EXTENDED_X11_TABLET_SUPPORT) +void KisOpenGLCanvasWidget::selectTabletDeviceEvents() +{ + KisCanvasWidget::selectTabletDeviceEvents(this); +} +#endif + +#endif // HAVE_GL + diff --git a/krita/ui/kis_opengl_canvas.h b/krita/ui/kis_opengl_canvas.h new file mode 100644 index 000000000..3e7231d71 --- /dev/null +++ b/krita/ui/kis_opengl_canvas.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_OPENGL_CANVAS_H_ +#define KIS_OPENGL_CANVAS_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL + +#include <qwidget.h> +#include <qgl.h> + +#include "kis_global.h" +#include "kis_canvas.h" + +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#endif // Q_WS_X11 + +#define KisOpenGLCanvasFormat (QGL::DoubleBuffer|QGL::Rgba|QGL::DirectRendering|QGL::NoDepthBuffer) + +class KisOpenGLCanvasWidget : public virtual QGLWidget, public virtual KisCanvasWidget { +public: + KisOpenGLCanvasWidget(QWidget *parent, const char *name, QGLWidget *sharedContextWidget); + ~KisOpenGLCanvasWidget(); + + virtual KisCanvasWidgetPainter *createPainter(); + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + virtual void selectTabletDeviceEvents(); +#endif + +protected: + virtual void paintEvent(QPaintEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void tabletEvent(QTabletEvent *event); + virtual void enterEvent(QEvent *event ); + virtual void leaveEvent(QEvent *event); + virtual void wheelEvent(QWheelEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); +#ifdef Q_WS_X11 + bool x11Event(XEvent *event); +#endif // Q_WS_X11 +}; +#endif // HAVE_GL + +#endif // KIS_OPENGL_CANVAS_H_ + diff --git a/krita/ui/kis_opengl_canvas_painter.cc b/krita/ui/kis_opengl_canvas_painter.cc new file mode 100644 index 000000000..06e38997d --- /dev/null +++ b/krita/ui/kis_opengl_canvas_painter.cc @@ -0,0 +1,849 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL + +#include <kdebug.h> + +#include "kis_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_opengl_canvas_painter.h" + +KisOpenGLCanvasPainter::KisOpenGLCanvasPainter() +: m_active(false), m_widget(0) +{ +} + +KisOpenGLCanvasPainter::KisOpenGLCanvasPainter(QGLWidget *widget) + : m_active(true), m_widget(widget) +{ + prepareForDrawing(); +} + +KisOpenGLCanvasPainter::~KisOpenGLCanvasPainter() +{ + if (m_widget) { + if (m_active) { + end(); + } + m_widget->doneCurrent(); + } +} + +bool KisOpenGLCanvasPainter::begin(KisCanvasWidget *canvasWidget, bool /*unclipped*/) +{ + m_widget = dynamic_cast<QGLWidget *>(canvasWidget); + + if (m_widget != 0) { + prepareForDrawing(); + return true; + } else { + return false; + } + return false; +} + +void KisOpenGLCanvasPainter::prepareForDrawing() +{ + if (m_widget != 0) { + m_widget->makeCurrent(); + m_active = true; + save(); + glDrawBuffer(GL_FRONT); + glBlendFunc(GL_ONE_MINUS_DST_COLOR, GL_ZERO); + glEnable(GL_BLEND); + + glMatrixMode(GL_TEXTURE); + glLoadIdentity(); + + m_window = QRect(0, 0, m_widget->width(), m_widget->height()); + m_viewport = m_window; + updateViewTransformation(); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + setPen(m_defaultPen); + } +} + +void KisOpenGLCanvasPainter::updateViewTransformation() +{ + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + + // We don't set the GL viewport directly from the Qt one as the GL + // has a limited size. Instead we fold it into the projection matrix. + glViewport(0, 0, m_widget->width(), m_widget->height()); + glOrtho(0, m_widget->width(), m_widget->height(), 0, -1, 1); + + glTranslatef(m_viewport.x(), m_viewport.y(), 0.0); + glScalef(static_cast<float>(m_viewport.width()) / m_window.width(), + static_cast<float>(m_viewport.height()) / m_window.height(), + 1.0); + glTranslatef(-m_window.x(), -m_window.y(), 0.0); +} + +bool KisOpenGLCanvasPainter::end() +{ + if (m_active) { + restore(); + m_active = false; + return true; + } else { + return false; + } +} + +void KisOpenGLCanvasPainter::save() +{ + glPushAttrib(GL_ALL_ATTRIB_BITS); + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + glMatrixMode(GL_TEXTURE); + glPushMatrix(); +} + +void KisOpenGLCanvasPainter::restore() +{ + glPopAttrib(); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + glMatrixMode(GL_TEXTURE); + glPopMatrix(); +} + +void KisOpenGLCanvasPainter::setPenStyle(Qt::PenStyle penStyle) +{ + if (penStyle == Qt::SolidLine) { + glDisable(GL_LINE_STIPPLE); + } else { + GLushort lineStipple; + + switch (penStyle) { + case Qt::NoPen: + lineStipple = 0; + break; + default: + case Qt::DashLine: + lineStipple = 0x3fff; + break; + case Qt::DotLine: + lineStipple = 0x3333; + break; + case Qt::DashDotLine: + lineStipple = 0x33ff; + break; + case Qt::DashDotDotLine: + lineStipple = 0x333f; + break; + } + + glEnable(GL_LINE_STIPPLE); + glLineStipple(1, lineStipple); + } +} + +QFontMetrics KisOpenGLCanvasPainter::fontMetrics() const +{ + return QFontMetrics(QFont()); +} + +QFontInfo KisOpenGLCanvasPainter::fontInfo() const +{ + return QFontInfo(QFont()); +} + +const QFont& KisOpenGLCanvasPainter::font() const +{ + return m_defaultFont; +} + +void KisOpenGLCanvasPainter::setFont(const QFont& /*font*/) +{ +} + +const QPen& KisOpenGLCanvasPainter::pen() const +{ + return m_defaultPen; +} + +void KisOpenGLCanvasPainter::setPen(const QPen& pen) +{ + setPenStyle(pen.style()); +} + +void KisOpenGLCanvasPainter::setPen(Qt::PenStyle penStyle) +{ + setPenStyle(penStyle); +} + +void KisOpenGLCanvasPainter::setPen(const QColor& /*color*/) +{ +} + +const QBrush& KisOpenGLCanvasPainter::brush() const +{ + return m_defaultBrush; +} + +void KisOpenGLCanvasPainter::setBrush(const QBrush& /*brush*/) +{ +} + +void KisOpenGLCanvasPainter::setBrush(Qt::BrushStyle /*brushStyle*/) +{ +} + +void KisOpenGLCanvasPainter::setBrush(const QColor& /*color*/) +{ +} + +QPoint KisOpenGLCanvasPainter::pos() const +{ + return QPoint(); +} + +const QColor& KisOpenGLCanvasPainter::backgroundColor() const +{ + return m_defaultColor; +} + +void KisOpenGLCanvasPainter::setBackgroundColor(const QColor& /*color*/) +{ +} + +Qt::Qt::BGMode KisOpenGLCanvasPainter::backgroundMode() const +{ + return Qt::TransparentMode; +} + +void KisOpenGLCanvasPainter::setBackgroundMode(Qt::Qt::BGMode /*bgMode*/) +{ +} + +Qt::Qt::RasterOp KisOpenGLCanvasPainter::rasterOp() const +{ + return Qt::CopyROP; +} + +void KisOpenGLCanvasPainter::setRasterOp(Qt::RasterOp /*rasterOp*/) +{ +} + +const QPoint& KisOpenGLCanvasPainter::brushOrigin() const +{ + return m_defaultBrushOrigin; +} + +void KisOpenGLCanvasPainter::setBrushOrigin(int /*x*/, int /*y*/) +{ +} + +void KisOpenGLCanvasPainter::setBrushOrigin(const QPoint& /*origin*/) +{ +} + +bool KisOpenGLCanvasPainter::hasViewXForm() const +{ + return false; +} + +bool KisOpenGLCanvasPainter::hasWorldXForm() const +{ + return false; +} + +void KisOpenGLCanvasPainter::setViewXForm(bool /*enable*/) +{ +} + +QRect KisOpenGLCanvasPainter::window() const +{ + return m_window; +} + +void KisOpenGLCanvasPainter::setWindow(const QRect& r) +{ + m_window = r; + updateViewTransformation(); +} + +void KisOpenGLCanvasPainter::setWindow(int x, int y, int w, int h) +{ + setWindow(QRect(x, y, w, h)); +} + +QRect KisOpenGLCanvasPainter::viewport() const +{ + return m_viewport; +} + +void KisOpenGLCanvasPainter::setViewport(const QRect& r) +{ + m_viewport = r; + updateViewTransformation(); +} + +void KisOpenGLCanvasPainter::setViewport(int x, int y, int w, int h) +{ + setViewport(QRect(x, y, w, h)); +} + +void KisOpenGLCanvasPainter::setWorldXForm(bool /*enable*/) +{ +} + +const QWMatrix& KisOpenGLCanvasPainter::worldMatrix() const +{ + return m_defaultWorldMatrix; +} + +void KisOpenGLCanvasPainter::setWorldMatrix(const QWMatrix& /*matrix*/, bool /*combine*/) +{ +} + +void KisOpenGLCanvasPainter::saveWorldMatrix() +{ +} + +void KisOpenGLCanvasPainter::restoreWorldMatrix() +{ +} + +void KisOpenGLCanvasPainter::scale(double /*sx*/, double /*sy*/) +{ +} + +void KisOpenGLCanvasPainter::shear(double /*sh*/, double /*sv*/) +{ +} + +void KisOpenGLCanvasPainter::rotate(double /*a*/) +{ +} + +void KisOpenGLCanvasPainter::translate(double dx, double dy) +{ + glMatrixMode(GL_MODELVIEW); + glTranslated(dx, dy, 0.0); +} + +void KisOpenGLCanvasPainter::resetXForm() +{ +} + +double KisOpenGLCanvasPainter::translationX() const +{ + return 0; +} + +double KisOpenGLCanvasPainter::translationY() const +{ + return 0; +} + +QPoint KisOpenGLCanvasPainter::xForm(const QPoint& point) const +{ + return point; +} + +QRect KisOpenGLCanvasPainter::xForm(const QRect& r) const +{ + return r; +} + +QPointArray KisOpenGLCanvasPainter::xForm(const QPointArray& pointArray) const +{ + return pointArray; +} + +QPointArray KisOpenGLCanvasPainter::xForm(const QPointArray& pointArray, int /*index*/, int /*npoints*/) const +{ + return pointArray; +} + +QPoint KisOpenGLCanvasPainter::xFormDev(const QPoint& point) const +{ + return point; +} + +QRect KisOpenGLCanvasPainter::xFormDev(const QRect& r) const +{ + return r; +} + +QPointArray KisOpenGLCanvasPainter::xFormDev(const QPointArray& pointArray) const +{ + return pointArray; +} + +QPointArray KisOpenGLCanvasPainter::xFormDev(const QPointArray& pointArray, int /*index*/, int /*npoints*/) const +{ + return pointArray; +} + +void KisOpenGLCanvasPainter::setClipping(bool /*enable*/) +{ +} + +bool KisOpenGLCanvasPainter::hasClipping() const +{ + return true; +} + +QRegion KisOpenGLCanvasPainter::clipRegion(QPainter::CoordinateMode /*mode*/) const +{ + return QRegion(); +} + +void KisOpenGLCanvasPainter::setClipRect(const QRect& /*r*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisOpenGLCanvasPainter::setClipRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisOpenGLCanvasPainter::setClipRegion(const QRegion& /*rgn*/, QPainter::CoordinateMode /*mode*/) +{ +} + +void KisOpenGLCanvasPainter::drawPoint(int x, int y) +{ + glBegin(GL_POINTS); + glVertex2i(x, y); + glEnd(); +} + +void KisOpenGLCanvasPainter::drawPoint(const QPoint& point) +{ + drawPoint(point.x(), point.y()); +} + +void KisOpenGLCanvasPainter::drawPoints(const QPointArray& pointArray, int index, int npoints) +{ + int firstPointIndex = index; + + if (firstPointIndex < 0) { + firstPointIndex = 0; + } + if (firstPointIndex > (int)pointArray.count() - 1) { + return; + } + + int lastPointIndex; + + if (npoints < 0) { + lastPointIndex = pointArray.count() - 1; + } else { + lastPointIndex = firstPointIndex + npoints; + if (lastPointIndex > (int)pointArray.count() - 1) { + lastPointIndex = pointArray.count() - 1; + } + } + + glBegin(GL_POINTS); + + for (int pointIndex = firstPointIndex; pointIndex <= lastPointIndex; pointIndex++) { + QPoint point = pointArray.point(pointIndex); + glVertex2i(point.x(), point.y()); + } + + glEnd(); +} + +void KisOpenGLCanvasPainter::moveTo(int /*x*/, int /*y*/) +{ +} + +void KisOpenGLCanvasPainter::moveTo(const QPoint& /*point*/) +{ +} + +void KisOpenGLCanvasPainter::lineTo(int /*x*/, int /*y*/) +{ +} + +void KisOpenGLCanvasPainter::lineTo(const QPoint& /*point*/) +{ +} + +void KisOpenGLCanvasPainter::drawLine(int x1, int y1, int x2, int y2) +{ + glBegin(GL_LINES); + glVertex2i(x1, y1); + glVertex2i(x2, y2); + glEnd(); +} + +void KisOpenGLCanvasPainter::drawLine(const QPoint& start, const QPoint& end) +{ + drawLine(start.x(), start.y(), end.x(), end.y()); +} + +void KisOpenGLCanvasPainter::drawRect(int x, int y, int w, int h) +{ + glBegin(GL_LINES); + + glVertex2i(x, y); + glVertex2i(x + w - 1, y); + + glVertex2i(x + w - 1, y); + glVertex2i(x + w - 1, y + h - 1); + + glVertex2i(x + w - 1, y + h - 1); + glVertex2i(x, y + h - 1); + + glVertex2i(x, y + h - 1); + glVertex2i(x, y); + + glEnd(); +} + +void KisOpenGLCanvasPainter::drawRect(const QRect& r) +{ + drawRect(r.x(), r.y(), r.width(), r.height()); +} + +void KisOpenGLCanvasPainter::drawWinFocusRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisOpenGLCanvasPainter::drawWinFocusRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, const QColor& /*bgColor*/) +{ +} + +void KisOpenGLCanvasPainter::drawWinFocusRect(const QRect& /*r*/) +{ +} + +void KisOpenGLCanvasPainter::drawWinFocusRect(const QRect& /*r*/, const QColor& /*bgColor*/) +{ +} + +void KisOpenGLCanvasPainter::drawRoundRect(int x, int y, int w, int h, int /*xRnd*/, int /*yRnd*/) +{ + glBegin(GL_LINES); + + glVertex2i(x, y); + glVertex2i(x + w - 1, y); + + glVertex2i(x + w - 1, y); + glVertex2i(x + w - 1, y + h - 1); + + glVertex2i(x + w - 1, y + h - 1); + glVertex2i(x, y + h - 1); + + glVertex2i(x, y + h - 1); + glVertex2i(x, y); + + glEnd(); +} + +void KisOpenGLCanvasPainter::drawRoundRect(const QRect& r, int /*xRnd*/, int /*yRnd*/) +{ + drawRoundRect(r.x(), r.y(), r.width(), r.height()); +} + +// void KisOpenGLCanvasPainter::drawRoundRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*xRnd*/, int /*yRnd*/) +// { +// } +// +// void KisOpenGLCanvasPainter::drawRoundRect(const QRect& /*r*/, int /*xRnd*/, int /*yRnd*/) +// { +// } + +void KisOpenGLCanvasPainter::drawEllipse(int x, int y, int w, int h) +{ + QRect r(x, y, w, h); + r = r.normalize(); + + QPointArray points; + + points.makeEllipse(r.x(), r.y(), r.width(), r.height()); + drawPoints(points); +} + +void KisOpenGLCanvasPainter::drawEllipse(const QRect& r) +{ + drawEllipse(r.x(), r.y(), r.width(), r.height()); +} + +void KisOpenGLCanvasPainter::drawArc(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawArc(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawPie(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawPie(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawChord(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawChord(const QRect& /*r*/, int /*a*/, int /*alen*/) +{ +} + +void KisOpenGLCanvasPainter::drawLineSegments(const QPointArray& /*pointArray*/, int /*index*/, int /*nlines*/) +{ +} + +void KisOpenGLCanvasPainter::drawPolyline(const QPointArray& pointArray, int index, int npoints) +{ + int firstPointIndex = index; + + if (firstPointIndex < 0) { + firstPointIndex = 0; + } + if (firstPointIndex > (int)pointArray.count() - 2) { + return; + } + + int lastPointIndex; + + if (npoints < 0) { + lastPointIndex = pointArray.count() - 1; + } else { + lastPointIndex = firstPointIndex + npoints - 1; + if (lastPointIndex > (int)pointArray.count() - 1) { + lastPointIndex = pointArray.count() - 1; + } + } + + if (firstPointIndex >= lastPointIndex) { + return; + } + + glBegin(GL_LINES); + + for (int pointIndex = firstPointIndex; pointIndex <= lastPointIndex; pointIndex++) { + QPoint point = pointArray.point(pointIndex); + glVertex2i(point.x(), point.y()); + } + + glEnd(); +} + +void KisOpenGLCanvasPainter::drawPolygon(const QPointArray& /*pointArray*/, bool /*winding*/, int /*index*/, int /*npoints*/) +{ +} + +void KisOpenGLCanvasPainter::drawConvexPolygon(const QPointArray& /*pointArray*/, int /*index*/, int /*npoints*/) +{ +} + +QPoint midpoint (const QPoint& P1, const QPoint& P2) +{ + QPoint temp; + temp.setX((P1.x()+P2.x())/2); + temp.setY((P1.y()+P2.y())/2); + return temp; +} + +#define MAX_LEVEL 5 + +void recursiveCurve (const QPoint& P1, const QPoint& P2, const QPoint& P3, + const QPoint& P4, int level, QValueList<QPoint>& dest) +{ + if (level > MAX_LEVEL) { + dest.append(midpoint(P1,P4)); + return; + } + + QPoint L1, L2, L3, L4; + QPoint H, R1, R2, R3, R4; + + L1 = P1; + L2 = midpoint(P1, P2); + H = midpoint(P2, P3); + R3 = midpoint(P3, P4); + R4 = P4; + L3 = midpoint(L2, H); + R2 = midpoint(R3, H); + L4 = midpoint(L3, R2); + R1 = L4; + recursiveCurve(L1, L2, L3, L4, level + 1, dest); + recursiveCurve(R1, R2, R3, R4, level + 1, dest); +} + +void KisOpenGLCanvasPainter::drawCubicBezier(const QPointArray& pointArray, int index) +{ + QPoint P1, P2, P3, P4; + QValueList<QPoint> dest; + P1 = pointArray[index++]; + P2 = pointArray[index++]; + P3 = pointArray[index++]; + P4 = pointArray[index]; + + recursiveCurve(P1, P2, P3, P4, 1, dest); + + glBegin(GL_LINE_STRIP); + + glVertex2i(P1.x(), P1.y()); + for (QValueList<QPoint>::iterator it = dest.begin(); it != dest.end(); it++) { + QPoint point = (*it); + glVertex2i(point.x(), point.y()); + } + glVertex2i(P4.x(), P4.y()); + + glEnd(); +} + +void KisOpenGLCanvasPainter::drawPixmap(int /*x*/, int /*y*/, const QPixmap& /*pixmap*/, int /*sx*/, int /*sy*/, int /*sw*/, int /*sh*/) +{ +} + +void KisOpenGLCanvasPainter::drawPixmap(const QPoint& /*point*/, const QPixmap& /*pixmap*/, const QRect& /*sr*/) +{ +} + +void KisOpenGLCanvasPainter::drawPixmap(const QPoint& /*point*/, const QPixmap& /*pixmap*/) +{ +} + +void KisOpenGLCanvasPainter::drawPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/) +{ +} + +void KisOpenGLCanvasPainter::drawImage(int /*x*/, int /*y*/, const QImage& /*image*/, int /*sx*/, int /*sy*/, int /*sw*/, int /*sh*/, int /*conversionFlags*/) +{ +} + +void KisOpenGLCanvasPainter::drawImage(const QPoint& /*point*/, const QImage& /*image*/, const QRect& /*sr*/, int /*conversionFlags*/) +{ +} + +void KisOpenGLCanvasPainter::drawImage(const QPoint& /*point*/, const QImage& /*image*/, int /*conversion_flags*/) +{ +} + +void KisOpenGLCanvasPainter::drawImage(const QRect& /*r*/, const QImage& /*image*/) +{ +} + +void KisOpenGLCanvasPainter::drawTiledPixmap(int /*x*/, int /*y*/, int /*w*/, int /*h*/, const QPixmap& /*pixmap*/, int /*sx*/, int /*sy*/) +{ +} + +void KisOpenGLCanvasPainter::drawTiledPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/, const QPoint& /*point*/) +{ +} + +void KisOpenGLCanvasPainter::drawTiledPixmap(const QRect& /*r*/, const QPixmap& /*pixmap*/) +{ +} + +void KisOpenGLCanvasPainter::fillRect(int x, int y, int w, int h, const QBrush& /*brush*/) +{ + // XXX: Set brush + glRecti(x, y, x + w, y + h); +} + +void KisOpenGLCanvasPainter::fillRect(const QRect& r, const QBrush& brush) +{ + fillRect(r.x(), r.y(), r.width(), r.height(), brush); +} + +void KisOpenGLCanvasPainter::eraseRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/) +{ +} + +void KisOpenGLCanvasPainter::eraseRect(const QRect& /*r*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(int /*x*/, int /*y*/, const QString& /*text*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(const QPoint& /*point*/, const QString& /*text*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(int /*x*/, int /*y*/, const QString& /*text*/, int /*pos*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(const QPoint& /*point*/, const QString& /*text*/, int /*pos*/, int /*len*/, QPainter::TextDirection /*dir*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*flags*/, const QString& /*text*/, int /*len*/, QRect */*br*/, QTextParag **/*intern*/) +{ +} + +void KisOpenGLCanvasPainter::drawText(const QRect& /*r*/, int /*flags*/, const QString& /*text*/, int /*len*/, QRect */*br*/, QTextParag **/*intern*/) +{ +} + +void KisOpenGLCanvasPainter::drawTextItem(int /*x*/, int /*y*/, const QTextItem& /*ti*/, int /*textflags*/) +{ +} + +void KisOpenGLCanvasPainter::drawTextItem(const QPoint& /*p*/, const QTextItem& /*ti*/, int /*textflags*/) +{ +} + +QRect KisOpenGLCanvasPainter::boundingRect(int /*x*/, int /*y*/, int /*w*/, int /*h*/, int /*flags*/, const QString& /*text*/, int /*len*/, QTextParag **/*intern*/) +{ + return QRect(); +} + +QRect KisOpenGLCanvasPainter::boundingRect(const QRect& /*r*/, int /*flags*/, const QString& /*text*/, int /*len*/, QTextParag **/*intern*/) +{ + return QRect(); +} + +int KisOpenGLCanvasPainter::tabStops() const +{ + return 0; +} + +void KisOpenGLCanvasPainter::setTabStops(int /*ts*/) +{ +} + +int *KisOpenGLCanvasPainter::tabArray() const +{ + return 0; +} + +void KisOpenGLCanvasPainter::setTabArray(int */*ts*/) +{ +} + +#endif // HAVE_GL + diff --git a/krita/ui/kis_opengl_canvas_painter.h b/krita/ui/kis_opengl_canvas_painter.h new file mode 100644 index 000000000..7f1299476 --- /dev/null +++ b/krita/ui/kis_opengl_canvas_painter.h @@ -0,0 +1,212 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_OPENGL_CANVAS_PAINTER_H_ +#define KIS_OPENGL_CANVAS_PAINTER_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL + +#include <qwidget.h> +#include <qgl.h> +#include <qpainter.h> + +#include "kis_global.h" +#include "kis_canvas_painter.h" + +class KisOpenGLCanvasPainter : public KisCanvasWidgetPainter { +public: + KisOpenGLCanvasPainter(); + KisOpenGLCanvasPainter(QGLWidget *widget); + + virtual ~KisOpenGLCanvasPainter(); + + virtual bool begin(KisCanvasWidget *canvasWidget, bool unclipped = false); + + // If we don't have OpenGL, we use the base class's no-op methods. + + virtual bool end(); + + virtual void save(); + virtual void restore(); + + virtual QFontMetrics fontMetrics() const; + virtual QFontInfo fontInfo() const; + + virtual const QFont& font() const; + virtual void setFont(const QFont&); + virtual const QPen& pen() const; + virtual void setPen(const QPen&); + virtual void setPen(Qt::PenStyle); + virtual void setPen(const QColor&); + virtual const QBrush&brush() const; + virtual void setBrush(const QBrush&); + virtual void setBrush(Qt::BrushStyle); + virtual void setBrush(const QColor&); + virtual QPoint pos() const; + + virtual const QColor& backgroundColor() const; + virtual void setBackgroundColor(const QColor&); + virtual Qt::BGMode backgroundMode() const; + virtual void setBackgroundMode(Qt::BGMode); + virtual Qt::RasterOp rasterOp() const; + virtual void setRasterOp(Qt::RasterOp); + virtual const QPoint& brushOrigin() const; + virtual void setBrushOrigin(int x, int y); + virtual void setBrushOrigin(const QPoint&); + + virtual bool hasViewXForm() const; + virtual bool hasWorldXForm() const; + + virtual void setViewXForm(bool); + virtual QRect window() const; + virtual void setWindow(const QRect&); + virtual void setWindow(int x, int y, int w, int h); + virtual QRect viewport() const; + virtual void setViewport(const QRect&); + virtual void setViewport(int x, int y, int w, int h); + + virtual void setWorldXForm(bool); + virtual const QWMatrix&worldMatrix() const; + virtual void setWorldMatrix(const QWMatrix&, bool combine=FALSE); + + virtual void saveWorldMatrix(); + virtual void restoreWorldMatrix(); + + virtual void scale(double sx, double sy); + virtual void shear(double sh, double sv); + virtual void rotate(double a); + + virtual void translate(double dx, double dy); + virtual void resetXForm(); + virtual double translationX() const; + virtual double translationY() const; + + virtual QPoint xForm(const QPoint&) const; + virtual QRect xForm(const QRect&) const; + virtual QPointArray xForm(const QPointArray&) const; + virtual QPointArray xForm(const QPointArray&, int index, int npoints) const; + virtual QPoint xFormDev(const QPoint&) const; + virtual QRect xFormDev(const QRect&) const; + virtual QPointArray xFormDev(const QPointArray&) const; + virtual QPointArray xFormDev(const QPointArray&, int index, int npoints) const; + + virtual void setClipping(bool); + virtual bool hasClipping() const; + virtual QRegion clipRegion(QPainter::CoordinateMode = QPainter::CoordDevice) const; + virtual void setClipRect(const QRect&, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRegion(const QRegion&, QPainter::CoordinateMode = QPainter::CoordDevice); + + virtual void drawPoint(int x, int y); + virtual void drawPoint(const QPoint&); + virtual void drawPoints(const QPointArray& a, int index=0, int npoints=-1); + virtual void moveTo(int x, int y); + virtual void moveTo(const QPoint&); + virtual void lineTo(int x, int y); + virtual void lineTo(const QPoint&); + virtual void drawLine(int x1, int y1, int x2, int y2); + virtual void drawLine(const QPoint&, const QPoint&); + virtual void drawRect(int x, int y, int w, int h); + virtual void drawRect(const QRect&); + virtual void drawWinFocusRect(int x, int y, int w, int h); + virtual void drawWinFocusRect(int x, int y, int w, int h, const QColor&bgColor); + virtual void drawWinFocusRect(const QRect&); + virtual void drawWinFocusRect(const QRect&, const QColor&bgColor); + virtual void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25); + virtual void drawRoundRect(const QRect&, int = 25, int = 25); + virtual void drawEllipse(int x, int y, int w, int h); + virtual void drawEllipse(const QRect&); + virtual void drawArc(int x, int y, int w, int h, int a, int alen); + virtual void drawArc(const QRect&, int a, int alen); + virtual void drawPie(int x, int y, int w, int h, int a, int alen); + virtual void drawPie(const QRect&, int a, int alen); + virtual void drawChord(int x, int y, int w, int h, int a, int alen); + virtual void drawChord(const QRect&, int a, int alen); + virtual void drawLineSegments(const QPointArray&, int index=0, int nlines=-1); + virtual void drawPolyline(const QPointArray&, int index=0, int npoints=-1); + virtual void drawPolygon(const QPointArray&, bool winding=FALSE, int index=0, int npoints=-1); + virtual void drawConvexPolygon(const QPointArray&, int index=0, int npoints=-1); + virtual void drawCubicBezier(const QPointArray&, int index=0); + virtual void drawPixmap(int x, int y, const QPixmap&, int sx=0, int sy=0, int sw=-1, int sh=-1); + virtual void drawPixmap(const QPoint&, const QPixmap&, const QRect&sr); + virtual void drawPixmap(const QPoint&, const QPixmap&); + virtual void drawPixmap(const QRect&, const QPixmap&); + virtual void drawImage(int x, int y, const QImage&, int sx = 0, int sy = 0, int sw = -1, int sh = -1, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, const QRect&sr, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, int conversion_flags = 0); + virtual void drawImage(const QRect&, const QImage&); + virtual void drawTiledPixmap(int x, int y, int w, int h, const QPixmap&, int sx=0, int sy=0); + virtual void drawTiledPixmap(const QRect&, const QPixmap&, const QPoint&); + virtual void drawTiledPixmap(const QRect&, const QPixmap&); + //virtual void drawPicture(const QPicture&); + //virtual void drawPicture(int x, int y, const QPicture&); + //virtual void drawPicture(const QPoint&, const QPicture&); + + virtual void fillRect(int x, int y, int w, int h, const QBrush&); + virtual void fillRect(const QRect&, const QBrush&); + virtual void eraseRect(int x, int y, int w, int h); + virtual void eraseRect(const QRect&); + + virtual void drawText(int x, int y, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&p, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, int w, int h, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + virtual void drawText(const QRect&, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + + virtual void drawTextItem(int x, int y, const QTextItem&ti, int textflags = 0); + virtual void drawTextItem(const QPoint& p, const QTextItem&ti, int textflags = 0); + + virtual QRect boundingRect(int x, int y, int w, int h, int flags, const QString&, int len = -1, QTextParag **intern=0); + virtual QRect boundingRect(const QRect&, int flags, const QString&, int len = -1, QTextParag **intern=0); + + virtual int tabStops() const; + virtual void setTabStops(int); + virtual int *tabArray() const; + virtual void setTabArray(int *); + +protected: + void prepareForDrawing(); + void updateViewTransformation(); + void setPenStyle(Qt::PenStyle penStyle); + +protected: + QFont m_defaultFont; + QPen m_defaultPen; + QBrush m_defaultBrush; + QColor m_defaultColor; + QPoint m_defaultBrushOrigin; + QWMatrix m_defaultWorldMatrix; + QRect m_window; + QRect m_viewport; + bool m_active; + +protected: + QGLWidget *m_widget; +}; + +#endif // HAVE_GL + +#endif // KIS_OPENGL_CANVAS_PAINTER_H_ + diff --git a/krita/ui/kis_opengl_image_context.cc b/krita/ui/kis_opengl_image_context.cc new file mode 100644 index 000000000..f3ad43414 --- /dev/null +++ b/krita/ui/kis_opengl_image_context.cc @@ -0,0 +1,371 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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. + */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL + +#include <kdebug.h> +#include <ksharedptr.h> + +#include "kis_global.h" +#include "kis_meta_registry.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_selection.h" +#include "kis_background.h" +#include "kis_opengl_canvas.h" +#include "kis_opengl_image_context.h" + +using namespace std; + +QGLWidget *KisOpenGLImageContext::SharedContextWidget = 0; +int KisOpenGLImageContext::SharedContextWidgetRefCount = 0; + +KisOpenGLImageContext::ImageContextMap KisOpenGLImageContext::imageContextMap; + +KisOpenGLImageContext::KisOpenGLImageContext() +{ + m_image = 0; + m_monitorProfile = 0; + m_exposure = 0; +} + +KisOpenGLImageContext::~KisOpenGLImageContext() +{ + kdDebug(41001) << "Destroyed KisOpenGLImageContext\n"; + + --SharedContextWidgetRefCount; + kdDebug(41001) << "Shared context widget ref count now " << SharedContextWidgetRefCount << endl; + + if (SharedContextWidgetRefCount == 0) { + + kdDebug(41001) << "Deleting shared context widget\n"; + delete SharedContextWidget; + SharedContextWidget = 0; + } + + imageContextMap.erase(m_image); +} + +KisOpenGLImageContext::KisOpenGLImageContext(KisImageSP image, KisProfile *monitorProfile) +{ + kdDebug(41001) << "Created KisOpenGLImageContext\n"; + + m_image = image; + m_monitorProfile = monitorProfile; + m_exposure = 0; + m_displaySelection = true; + + if (SharedContextWidget == 0) { + kdDebug(41001) << "Creating shared context widget\n"; + + SharedContextWidget = new QGLWidget(KisOpenGLCanvasFormat); + } + + ++SharedContextWidgetRefCount; + + kdDebug(41001) << "Shared context widget ref count now " << SharedContextWidgetRefCount << endl; + + SharedContextWidget->makeCurrent(); + glGenTextures(1, &m_backgroundTexture); + generateBackgroundTexture(); + + GLint max_texture_size; + + glGetIntegerv(GL_MAX_TEXTURE_SIZE, &max_texture_size); + + m_imageTextureTileWidth = QMIN(PREFERRED_IMAGE_TEXTURE_WIDTH, max_texture_size); + m_imageTextureTileHeight = QMIN(PREFERRED_IMAGE_TEXTURE_HEIGHT, max_texture_size); + + createImageTextureTiles(); + + connect(m_image, SIGNAL(sigImageUpdated(QRect)), + SLOT(slotImageUpdated(QRect))); + connect(m_image, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), + SLOT(slotImageSizeChanged(Q_INT32, Q_INT32))); + + updateImageTextureTiles(m_image->bounds()); +} + +KisOpenGLImageContextSP KisOpenGLImageContext::getImageContext(KisImageSP image, KisProfile *monitorProfile) +{ + if (imageCanShareImageContext(image)) { + ImageContextMap::iterator it = imageContextMap.find(image); + + if (it != imageContextMap.end()) { + + kdDebug(41001) << "Sharing image context from map\n"; + + KisOpenGLImageContextSP context = (*it).second; + context->setMonitorProfile(monitorProfile); + + return context; + } else { + KisOpenGLImageContext *imageContext = new KisOpenGLImageContext(image, monitorProfile); + imageContextMap[image] = imageContext; + + kdDebug(41001) << "Added shareable context to map\n"; + + return imageContext; + } + } else { + kdDebug(41001) << "Creating non-shareable image context\n"; + + return new KisOpenGLImageContext(image, monitorProfile); + } +} + +bool KisOpenGLImageContext::imageCanShareImageContext(KisImageSP image) +{ + if (image->colorSpace()->hasHighDynamicRange()) { + //XXX: and we don't have shaders... + return false; + } else { + return true; + } +} + +QGLWidget *KisOpenGLImageContext::sharedContextWidget() const +{ + return SharedContextWidget; +} + +void KisOpenGLImageContext::updateImageTextureTiles(const QRect& rect) +{ + //kdDebug() << "updateImageTextureTiles " << rect << endl; + + QRect updateRect = rect & m_image->bounds(); + + if (!updateRect.isEmpty()) { + + SharedContextWidget->makeCurrent(); + + int firstColumn = updateRect.left() / m_imageTextureTileWidth; + int lastColumn = updateRect.right() / m_imageTextureTileWidth; + int firstRow = updateRect.top() / m_imageTextureTileHeight; + int lastRow = updateRect.bottom() / m_imageTextureTileHeight; + + for (int column = firstColumn; column <= lastColumn; column++) { + for (int row = firstRow; row <= lastRow; row++) { + + QRect tileRect(column * m_imageTextureTileWidth, row * m_imageTextureTileHeight, + m_imageTextureTileWidth, m_imageTextureTileHeight); + + QRect tileUpdateRect = tileRect & updateRect; + + glBindTexture(GL_TEXTURE_2D, imageTextureTile(tileRect.x(), tileRect.y())); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);//GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + QImage tileUpdateImage = m_image->convertToQImage(tileUpdateRect.left(), tileUpdateRect.top(), + tileUpdateRect.right(), tileUpdateRect.bottom(), + m_monitorProfile, m_exposure); + + if (m_displaySelection) { + if (m_image->activeLayer() != 0) { + m_image->activeLayer()->paintSelection(tileUpdateImage, + tileUpdateRect.x(), tileUpdateRect.y(), + tileUpdateRect.width(), tileUpdateRect.height()); + } + } + + if (tileUpdateRect.width() == m_imageTextureTileWidth && tileUpdateRect.height() == m_imageTextureTileHeight) { + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_imageTextureTileWidth, m_imageTextureTileHeight, 0, + GL_BGRA, GL_UNSIGNED_BYTE, tileUpdateImage.bits()); + } else { + int xOffset = tileUpdateRect.x() - tileRect.x(); + int yOffset = tileUpdateRect.y() - tileRect.y(); + + glTexSubImage2D(GL_TEXTURE_2D, 0, xOffset, yOffset, tileUpdateRect.width(), tileUpdateRect.height(), + GL_BGRA, GL_UNSIGNED_BYTE, tileUpdateImage.bits()); + } + + GLenum error = glGetError (); + + if (error != GL_NO_ERROR) + { + kdDebug(41001) << "Error loading texture: " << endl; + } + } + } + } +} + +KisColorSpace* KisOpenGLImageContext::textureColorSpaceForImageColorSpace(KisColorSpace */*imageColorSpace*/) +{ + return KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA", ""), ""); +} + +void KisOpenGLImageContext::setMonitorProfile(KisProfile *monitorProfile) +{ + if (monitorProfile != m_monitorProfile) { + m_monitorProfile = monitorProfile; + generateBackgroundTexture(); + updateImageTextureTiles(m_image->bounds()); + } +} + +void KisOpenGLImageContext::setHDRExposure(float exposure) +{ + if (exposure != m_exposure) { + m_exposure = exposure; + + if (m_image->colorSpace()->hasHighDynamicRange()) { + //XXX: and we are not using shaders... + updateImageTextureTiles(m_image->bounds()); + } + } +} + +void KisOpenGLImageContext::generateBackgroundTexture() +{ + SharedContextWidget->makeCurrent(); + + glBindTexture(GL_TEXTURE_2D, m_backgroundTexture); + + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + QImage backgroundImage = m_image->background()->patternTile(); + + // XXX: temp. + Q_ASSERT(backgroundImage.width() == BACKGROUND_TEXTURE_WIDTH); + Q_ASSERT(backgroundImage.height() == BACKGROUND_TEXTURE_HEIGHT); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, BACKGROUND_TEXTURE_WIDTH, BACKGROUND_TEXTURE_HEIGHT, 0, + GL_BGRA, GL_UNSIGNED_BYTE, backgroundImage.bits()); +} + +GLuint KisOpenGLImageContext::backgroundTexture() const +{ + return m_backgroundTexture; +} + +int KisOpenGLImageContext::imageTextureTileIndex(int x, int y) const +{ + int column = x / m_imageTextureTileWidth; + int row = y / m_imageTextureTileHeight; + + return column + (row * m_numImageTextureTileColumns); +} + +GLuint KisOpenGLImageContext::imageTextureTile(int pixelX, int pixelY) const +{ + Q_INT32 textureTileIndex = imageTextureTileIndex(pixelX, pixelY); + + textureTileIndex = CLAMP(textureTileIndex, 0, ((Q_INT32)m_imageTextureTiles.count()) - 1); + + return m_imageTextureTiles[textureTileIndex]; +} + +int KisOpenGLImageContext::imageTextureTileWidth() const +{ + return m_imageTextureTileWidth; +} + +int KisOpenGLImageContext::imageTextureTileHeight() const +{ + return m_imageTextureTileHeight; +} + +void KisOpenGLImageContext::createImageTextureTiles() +{ + SharedContextWidget->makeCurrent(); + + destroyImageTextureTiles(); + + m_numImageTextureTileColumns = (m_image->width() + m_imageTextureTileWidth - 1) / m_imageTextureTileWidth; + int numImageTextureTileRows = (m_image->height() + m_imageTextureTileHeight - 1) / m_imageTextureTileHeight; + int numImageTextureTiles = m_numImageTextureTileColumns * numImageTextureTileRows; + + m_imageTextureTiles.resize(numImageTextureTiles); + glGenTextures(numImageTextureTiles, &(m_imageTextureTiles[0])); + + //XXX: will be float/half with shaders + #define RGBA_BYTES_PER_PIXEL 4 + + QByteArray emptyTilePixelData(m_imageTextureTileWidth * m_imageTextureTileHeight * RGBA_BYTES_PER_PIXEL); + emptyTilePixelData.fill(0); + + for (int tileIndex = 0; tileIndex < numImageTextureTiles; ++tileIndex) { + + glBindTexture(GL_TEXTURE_2D, m_imageTextureTiles[tileIndex]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_imageTextureTileWidth, m_imageTextureTileHeight, 0, + GL_BGRA, GL_UNSIGNED_BYTE, &emptyTilePixelData[0]); + } +} + +void KisOpenGLImageContext::destroyImageTextureTiles() +{ + if (!m_imageTextureTiles.empty()) { + SharedContextWidget->makeCurrent(); + glDeleteTextures(m_imageTextureTiles.count(), &(m_imageTextureTiles[0])); + m_imageTextureTiles.clear(); + } +} + +void KisOpenGLImageContext::update(const QRect& imageRect) +{ + updateImageTextureTiles(imageRect); +} + +void KisOpenGLImageContext::setSelectionDisplayEnabled(bool enable) +{ + m_displaySelection = enable; +} + +void KisOpenGLImageContext::slotImageUpdated(QRect rc) +{ + QRect r = rc & m_image->bounds(); + + updateImageTextureTiles(r); + emit sigImageUpdated(r); +} + +void KisOpenGLImageContext::slotImageSizeChanged(Q_INT32 w, Q_INT32 h) +{ + createImageTextureTiles(); + updateImageTextureTiles(m_image->bounds()); + + emit sigSizeChanged(w, h); +} + +#include "kis_opengl_image_context.moc" + +#endif // HAVE_GL + diff --git a/krita/ui/kis_opengl_image_context.h b/krita/ui/kis_opengl_image_context.h new file mode 100644 index 000000000..d1ba6278f --- /dev/null +++ b/krita/ui/kis_opengl_image_context.h @@ -0,0 +1,156 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_OPENGL_IMAGE_CONTEXT_H_ +#define KIS_OPENGL_IMAGE_CONTEXT_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#ifdef HAVE_GL + +#include <map> + +#include <qgl.h> +#include <qobject.h> +#include <qvaluevector.h> + +#include <koffice_export.h> + +#include "kis_types.h" + +class QRegion; + +class KisOpenGLImageContext; +typedef KSharedPtr<KisOpenGLImageContext> KisOpenGLImageContextSP; +class KisColorSpace; + +class KRITACORE_EXPORT KisOpenGLImageContext : public QObject , public KShared { + + Q_OBJECT + +public: + static KisOpenGLImageContextSP getImageContext(KisImageSP image, KisProfile *monitorProfile); + + KisOpenGLImageContext(); + virtual ~KisOpenGLImageContext(); + +public: + // In order to use the image textures, the caller must pass + // the sharedContextWidget() as the shareWidget argument to the + // QGLWidget constructor. + QGLWidget *sharedContextWidget() const; + + void setMonitorProfile(KisProfile *profile); + void setHDRExposure(float exposure); + + GLuint backgroundTexture() const; + + static const int BACKGROUND_TEXTURE_WIDTH = 32; + static const int BACKGROUND_TEXTURE_HEIGHT = 32; + + // Get the image texture tile containing the point (pixelX, pixelY). + GLuint imageTextureTile(int pixelX, int pixelY) const; + + int imageTextureTileWidth() const; + int imageTextureTileHeight() const; + + /** + * Select selection visualisation rendering. + * + * @param enable Set to true to enable selection visualisation rendering. + */ + void setSelectionDisplayEnabled(bool enable); + + /** + * Update the image textures for the given image rectangle. + * + * @param imageRect The rectangle to update in image coordinates. + */ + void update(const QRect& imageRect); + +signals: + /** + * Clients using the KisOpenGLImageContext should connect to the + * following signals rather than to the KisImage's own equivalent + * signals. This ensures that the image textures are always up to date + * when used. + */ + + /** + * Emitted whenever an action has caused the image to be recomposited. + * + * @param rc The rect that has been recomposited. + */ + void sigImageUpdated(QRect rc); + + /** + * Emitted whenever the image size changes. + * + * @param width New image width + * @param height New image height + */ + void sigSizeChanged(Q_INT32 width, Q_INT32 height); + +protected: + KisOpenGLImageContext(KisImageSP image, KisProfile *monitorProfile); + + void generateBackgroundTexture(); + void createImageTextureTiles(); + void destroyImageTextureTiles(); + int imageTextureTileIndex(int x, int y) const; + void updateImageTextureTiles(const QRect& rect); + + static KisColorSpace* textureColorSpaceForImageColorSpace(KisColorSpace *imageColorSpace); + static bool imageCanShareImageContext(KisImageSP image); + +protected slots: + void slotImageUpdated(QRect r); + void slotImageSizeChanged(Q_INT32 w, Q_INT32 h); + +private: + KisImageSP m_image; + KisProfile *m_monitorProfile; + float m_exposure; + bool m_displaySelection; + + GLuint m_backgroundTexture; + + static const int PREFERRED_IMAGE_TEXTURE_WIDTH = 256; + static const int PREFERRED_IMAGE_TEXTURE_HEIGHT = 256; + + QValueVector<GLuint> m_imageTextureTiles; + int m_imageTextureTileWidth; + int m_imageTextureTileHeight; + int m_numImageTextureTileColumns; + + // We create a single OpenGL context and share it between all views + // in the process. Apparently with some OpenGL implementations, only + // one context will be hardware accelerated. + static QGLWidget *SharedContextWidget; + static int SharedContextWidgetRefCount; + + typedef std::map<KisImageSP, KisOpenGLImageContext*> ImageContextMap; + + static ImageContextMap imageContextMap; +}; + +#endif // HAVE_GL + +#endif // KIS_OPENGL_IMAGE_CONTEXT_H_ + diff --git a/krita/ui/kis_paintop_box.cc b/krita/ui/kis_paintop_box.cc new file mode 100644 index 000000000..3479075d2 --- /dev/null +++ b/krita/ui/kis_paintop_box.cc @@ -0,0 +1,249 @@ +/* + * kis_paintop_box.cc - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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 <qwidget.h> +#include <qstring.h> +#include <qvaluelist.h> +#include <qpixmap.h> +#include <qlayout.h> +#include <qtooltip.h> + +#include <klocale.h> +#include <kactioncollection.h> +#include <kdebug.h> +#include <kglobal.h> +#include <klocale.h> +#include <kglobalsettings.h> +#include <kaccelmanager.h> +#include <kconfig.h> +#include <kstandarddirs.h> + +#include <kis_paintop_registry.h> +#include <kis_view.h> +#include <kis_painter.h> +#include <kis_paintop.h> +#include <kis_layer.h> +#include <kis_factory.h> + +#include "kis_paintop_box.h" + +KisPaintopBox::KisPaintopBox (KisView * view, QWidget *parent, const char * name) + : super (parent, name), + m_canvasController(view->getCanvasController()) +{ +#if KDE_VERSION >= KDE_MAKE_VERSION(3,3,90) + KAcceleratorManager::setNoAccel(this); +#endif + + Q_ASSERT(m_canvasController != 0); + + setCaption(i18n("Painter's Toolchest")); + m_optionWidget = 0; + m_paintops = new QValueList<KisID>(); + m_displayedOps = new QValueList<KisID>(); + + m_cmbPaintops = new QComboBox(this, "KisPaintopBox::m_cmbPaintops"); + m_cmbPaintops->setMinimumWidth(150); + QToolTip::add(m_cmbPaintops, i18n("Styles of painting for the painting tools")); + m_layout = new QHBoxLayout(this, 1, 1); + m_layout->addWidget(m_cmbPaintops); + + connect(this, SIGNAL(selected(const KisID &, const KisPaintOpSettings *)), view, SLOT(paintopActivated(const KisID &, const KisPaintOpSettings *))); + connect(m_cmbPaintops, SIGNAL(activated(int)), this, SLOT(slotItemSelected(int))); + + // XXX: Let's see... Are all paintops loaded and ready? + KisIDList keys = KisPaintOpRegistry::instance()->listKeys(); + for ( KisIDList::Iterator it = keys.begin(); it != keys.end(); ++it ) { + // add all paintops, and show/hide them afterwards + addItem(*it); + } + + connect(view, SIGNAL(currentColorSpaceChanged(KisColorSpace*)), + this, SLOT(colorSpaceChanged(KisColorSpace*))); + connect(view, SIGNAL(sigInputDeviceChanged(const KisInputDevice&)), + this, SLOT(slotInputDeviceChanged(const KisInputDevice&))); + + setCurrentPaintop(defaultPaintop(m_canvasController->currentInputDevice())); +} + +KisPaintopBox::~KisPaintopBox() +{ + delete m_paintops; + delete m_displayedOps; +} + +void KisPaintopBox::addItem(const KisID & paintop, const QString & /*category*/) +{ + m_paintops->append(paintop); +} + +void KisPaintopBox::slotItemSelected(int index) +{ + if ((uint)index > m_displayedOps->count()) { + return; + } + + KisID paintop = *m_displayedOps->at(index); + + setCurrentPaintop(paintop); +} + +void KisPaintopBox::colorSpaceChanged(KisColorSpace *cs) +{ + QValueList<KisID>::iterator it = m_paintops->begin(); + QValueList<KisID>::iterator end = m_paintops->end(); + m_displayedOps->clear(); + m_cmbPaintops->clear(); + + for ( ; it != end; ++it ) { + if (KisPaintOpRegistry::instance()->userVisible(*it, cs)) { + QPixmap pm = paintopPixmap(*it); + if (pm.isNull()) { + QPixmap p = QPixmap( 16, 16 ); + p.fill(); + m_cmbPaintops->insertItem(p, (*it).name()); + } + else { + m_cmbPaintops->insertItem(pm, (*it).name()); + } + m_displayedOps->append(*it); + } + } + + int index = m_displayedOps->findIndex(currentPaintop()); + + if (index == -1) { + // Must change the paintop as the current one is not supported + // by the new colourspace. + index = 0; + } + + m_cmbPaintops->setCurrentItem( index ); + slotItemSelected( index ); +} + +QPixmap KisPaintopBox::paintopPixmap(const KisID & paintop) +{ + QString pixmapName = KisPaintOpRegistry::instance()->pixmap(paintop); + + if (pixmapName.isEmpty()) { + return QPixmap(); + } + + QString fname = KisFactory::instance()->dirs()->findResource("kis_images", pixmapName); + + return QPixmap(fname); +} + +void KisPaintopBox::slotInputDeviceChanged(const KisInputDevice & inputDevice) +{ + KisID paintop; + InputDevicePaintopMap::iterator it = m_currentID.find(inputDevice); + + if (it == m_currentID.end()) { + paintop = defaultPaintop(inputDevice); + } else { + paintop = (*it).second; + } + + int index = m_displayedOps->findIndex(paintop); + + if (index == -1) { + // Must change the paintop as the current one is not supported + // by the new colourspace. + index = 0; + paintop = *m_displayedOps->at(index); + } + + m_cmbPaintops->setCurrentItem(index); + setCurrentPaintop(paintop); +} + +void KisPaintopBox::updateOptionWidget() +{ + if (m_optionWidget != 0) { + m_layout->remove(m_optionWidget); + m_optionWidget->hide(); + m_layout->invalidate(); + } + + const KisPaintOpSettings *settings = paintopSettings(currentPaintop(), m_canvasController->currentInputDevice()); + + if (settings != 0) { + m_optionWidget = settings->widget(); + Q_ASSERT(m_optionWidget != 0); + + m_layout->addWidget(m_optionWidget); + updateGeometry(); + m_optionWidget->show(); + } +} + +const KisID& KisPaintopBox::currentPaintop() +{ + return m_currentID[m_canvasController->currentInputDevice()]; +} + +void KisPaintopBox::setCurrentPaintop(const KisID & paintop) +{ + m_currentID[m_canvasController->currentInputDevice()] = paintop; + + updateOptionWidget(); + + emit selected(paintop, paintopSettings(paintop, m_canvasController->currentInputDevice())); +} + +KisID KisPaintopBox::defaultPaintop(const KisInputDevice& inputDevice) +{ + if (inputDevice == KisInputDevice::eraser()) { + return KisID("eraser",""); + } else { + return KisID("paintbrush",""); + } +} + +const KisPaintOpSettings *KisPaintopBox::paintopSettings(const KisID & paintop, const KisInputDevice & inputDevice) +{ + QValueVector<KisPaintOpSettings *> settingsArray; + InputDevicePaintopSettingsMap::iterator it = m_inputDevicePaintopSettings.find(inputDevice); + + if (it == m_inputDevicePaintopSettings.end()) { + // Create settings for each paintop. + + for (QValueList<KisID>::const_iterator pit = m_paintops->begin(); pit != m_paintops->end(); ++pit) { + KisPaintOpSettings *settings = KisPaintOpRegistry::instance()->settings(*pit, this, inputDevice); + settingsArray.append(settings); + if (settings && settings->widget()) { + settings->widget()->hide(); + } + } + m_inputDevicePaintopSettings[inputDevice] = settingsArray; + } else { + settingsArray = (*it).second; + } + + const int index = m_paintops->findIndex(paintop); + if (index >= 0 && index < (int)settingsArray.count()) + return settingsArray[index]; + else + return 0; +} + +#include "kis_paintop_box.moc" + diff --git a/krita/ui/kis_paintop_box.h b/krita/ui/kis_paintop_box.h new file mode 100644 index 000000000..da1581944 --- /dev/null +++ b/krita/ui/kis_paintop_box.h @@ -0,0 +1,103 @@ +/* + * kis_paintop_box.h - part of KImageShop/Krayon/Krita + * + * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) + * + * 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_PAINTOP_BOX_H_ +#define KIS_PAINTOP_BOX_H_ + +#include <map> + +#include <qwidget.h> +#include <qcombobox.h> +#include <qvaluelist.h> + +#include "kis_input_device.h" + +class QString; + +class KWidgetAction; +class KisView; +class KisCanvasController; +class KisID; +class KisColorSpace; + +/** + * This widget presents all paintops that a user can paint with. + * Paintops represent real-world tools or the well-known Shoup + * computer equivalents that do nothing but change color. + * + * XXX: When we have a lot of paintops, replace the listbox + * with a table, and for every category a combobox. + * + * XXX: instead of text, use pretty pictures. + */ +class KisPaintopBox : public QWidget { + + Q_OBJECT + + typedef QWidget super; + +public: + KisPaintopBox (KisView * view, QWidget * parent, const char * name = 0); + + ~KisPaintopBox(); + + +signals: + + void selected(const KisID & id, const KisPaintOpSettings *settings); + +private slots: + + void addItem(const KisID & paintop, const QString & category = ""); + +private slots: + + void slotItemSelected(int index); + void colorSpaceChanged(KisColorSpace *cs); + void slotInputDeviceChanged(const KisInputDevice & inputDevice); + +private: + QPixmap paintopPixmap(const KisID & paintop); + void updateOptionWidget(); + const KisID & currentPaintop(); + void setCurrentPaintop(const KisID & paintop); + KisID defaultPaintop(const KisInputDevice& inputDevice); + const KisPaintOpSettings *paintopSettings(const KisID & paintop, const KisInputDevice & inputDevice); + +private: + KisCanvasController *m_canvasController; + QComboBox * m_cmbPaintops; + QHBoxLayout * m_layout; + QWidget * m_optionWidget; + + QValueList<KisID> * m_paintops; + QValueList<KisID> * m_displayedOps; + + typedef std::map<KisInputDevice, KisID> InputDevicePaintopMap; + InputDevicePaintopMap m_currentID; + + typedef std::map<KisInputDevice, QValueVector<KisPaintOpSettings *> > InputDevicePaintopSettingsMap; + InputDevicePaintopSettingsMap m_inputDevicePaintopSettings; +}; + + + +#endif //KIS_PAINTOP_BOX_H_ + diff --git a/krita/ui/kis_palette_view.cc b/krita/ui/kis_palette_view.cc new file mode 100644 index 000000000..2fe3f6e9c --- /dev/null +++ b/krita/ui/kis_palette_view.cc @@ -0,0 +1,150 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * Based on already much changed code by Waldo Bastian <bastian@kde.org> from KisPaletteWidget + * + * 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 <stdio.h> +#include <stdlib.h> + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qdrawutil.h> +#include <qevent.h> +#include <qfile.h> +#include <qimage.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qvalidator.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> +#include <kpalette.h> +#include <kimageeffect.h> + +#include <kcolordialog.h> +#include <kcolordrag.h> +#include <config.h> +#include <kdebug.h> + +#include <kis_meta_registry.h> +#include <kis_color.h> +#include <kis_factory.h> +#include <kis_colorspace_factory_registry.h> +#include "kis_palette_view.h" +#include "kis_resource.h" +#include "kis_palette.h" + +KisPaletteView::KisPaletteView(QWidget *parent, const char* name, int minWidth, int cols) + : QScrollView( parent, name ), mMinWidth(minWidth), mCols(cols) +{ + m_cells = 0; + m_currentPalette = 0; + + QSize cellSize = QSize( mMinWidth, 50); + + setHScrollBarMode(QScrollView::AlwaysOff); + setVScrollBarMode(QScrollView::AlwaysOn); + + QSize minSize = QSize(verticalScrollBar()->width(), 0); + minSize += QSize(frameWidth(), 0); + minSize += QSize(cellSize); + + setMinimumSize(minSize); + setSizePolicy(QSizePolicy(QSizePolicy::Ignored, QSizePolicy::Ignored)); +} + +KisPaletteView::~KisPaletteView() +{ +} + +KisPalette* KisPaletteView::palette() const +{ + return m_currentPalette; +} + +void KisPaletteView::setPalette(KisPalette* palette) +{ + m_currentPalette = palette; + delete m_cells; + + int rows = (m_currentPalette->nColors() + mCols -1 ) / mCols; + + if (rows < 1) rows = 1; + + m_cells = new KColorCells(viewport(), rows, mCols); + Q_CHECK_PTR(m_cells); + + m_cells->setShading(false); + m_cells->setAcceptDrags(false); + + QSize cellSize = QSize( mMinWidth, mMinWidth * rows / mCols); + m_cells->setFixedSize( cellSize ); + + for( int i = 0; i < m_currentPalette->nColors(); i++) + { + QColor c = m_currentPalette->getColor(i).color; + m_cells->setColor( i, c ); + } + + connect(m_cells, SIGNAL(colorSelected(int)), + SLOT(slotColorCellSelected(int))); + + connect(m_cells, SIGNAL(colorDoubleClicked(int)), + SLOT(slotColorCellDoubleClicked(int)) ); + + addChild( m_cells ); + m_cells->show(); + updateScrollBars(); +} + +void KisPaletteView::slotColorCellSelected( int col ) +{ + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8(); + if (!m_currentPalette || (col >= m_currentPalette->nColors())) + return; + + m_currentEntry = m_currentPalette->getColor(col); + emit colorSelected(KisColor(m_currentPalette->getColor(col).color, cs)); + emit colorSelected(m_currentPalette->getColor(col).color); +} + +void KisPaletteView::slotColorCellDoubleClicked( int col ) +{ + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8(); + if (!m_currentPalette || (col >= m_currentPalette->nColors())) + return; + + emit colorDoubleClicked(KisColor(m_currentPalette->getColor(col).color, cs), + m_currentPalette->getColor(col).name); +} + +#include "kis_palette_view.moc" + diff --git a/krita/ui/kis_palette_view.h b/krita/ui/kis_palette_view.h new file mode 100644 index 000000000..8812acdbc --- /dev/null +++ b/krita/ui/kis_palette_view.h @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2005 Bart Coppens <kde@bartcoppens.be> + * (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_PALETTE_VIEW_H__ +#define __KIS_PALETTE_VIEW_H__ + +#include <qscrollview.h> +#include "kis_palette.h" + +class KListBox; +class KisPalette; +class KColorCells; +class KisResource; +class KisColor; + +/** + * A scrolling view that lists a single KisPalette + */ +class KisPaletteView : public QScrollView +{ + Q_OBJECT +public: + KisPaletteView(QWidget *parent, const char* name = 0, int minWidth=210, int cols = 16); + virtual ~KisPaletteView(); + + KisPalette* palette() const; + /// Might return the default constructed entry... + KisPaletteEntry currentEntry() const { return m_currentEntry; } + +public slots: + void setPalette(KisPalette* p); + +signals: + void colorSelected(const KisColor &); + void colorSelected(const QColor &); + void colorDoubleClicked(const KisColor &, const QString &); + +protected slots: + void slotColorCellSelected( int ); + void slotColorCellDoubleClicked( int ); + +protected: + KisPalette* m_currentPalette; + KColorCells* m_cells; + KisPaletteEntry m_currentEntry; + int mMinWidth; + int mCols; + + friend class KisPaletteWidget; // Because it calls slotColorCellSelected from a FIXME +}; + +#endif + diff --git a/krita/ui/kis_palette_widget.cc b/krita/ui/kis_palette_widget.cc new file mode 100644 index 000000000..507ccc159 --- /dev/null +++ b/krita/ui/kis_palette_widget.cc @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <stdio.h> +#include <stdlib.h> + +#include <qcheckbox.h> +#include <qcombobox.h> +#include <qdrawutil.h> +#include <qevent.h> +#include <qfile.h> +#include <qimage.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qlineedit.h> +#include <qvalidator.h> +#include <qpainter.h> +#include <qpushbutton.h> +#include <qspinbox.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kconfig.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klistbox.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <kseparator.h> +#include <kpalette.h> +#include <kimageeffect.h> + +#include <kcolordialog.h> +#include <kcolordrag.h> +#include <config.h> +#include <kdebug.h> + +#include <kis_meta_registry.h> +#include <kis_color.h> +#include <kis_factory.h> +#include <kis_colorspace_factory_registry.h> +#include "kis_palette_widget.h" +#include "kis_resource.h" +#include "kis_palette.h" +#include "kis_palette_view.h" + +KisPaletteWidget::KisPaletteWidget( QWidget *parent, int minWidth, int cols) + : QWidget( parent ), mMinWidth(minWidth), mCols(cols) +{ + init = false; + + m_currentPalette = 0; + + QVBoxLayout *layout = new QVBoxLayout( this ); + + combo = new QComboBox( false, this ); + combo->setFocusPolicy( QWidget::ClickFocus ); + layout->addWidget(combo); + + m_view = new KisPaletteView(this, 0, minWidth, cols); + layout->addWidget( m_view ); + + //setFixedSize(sizeHint()); + + connect(combo, SIGNAL(activated(const QString &)), + this, SLOT(slotSetPalette(const QString &))); + connect(m_view, SIGNAL(colorSelected(const KisColor &)), + this, SIGNAL(colorSelected(const KisColor &))); + connect(m_view, SIGNAL(colorSelected(const QColor &)), + this, SIGNAL(colorSelected(const QColor &))); + connect(m_view, SIGNAL(colorDoubleClicked(const KisColor &, const QString &)), + this, SIGNAL(colorDoubleClicked(const KisColor &, const QString &))); +} + +KisPaletteWidget::~KisPaletteWidget() +{ +} + +QString KisPaletteWidget::palette() const +{ + return combo->currentText(); +} + + +// 2000-02-12 Espen Sand +// Set the color in two steps. The setPalette() slot will not emit a signal +// with the current color setting. The reason is that setPalette() is used +// by the color selector dialog on startup. In the color selector dialog +// we normally want to display a startup color which we specify +// when the dialog is started. The slotSetPalette() slot below will +// set the palette and then use the information to emit a signal with the +// new color setting. It is only used by the combobox widget. +// +void KisPaletteWidget::slotSetPalette( const QString &_paletteName ) +{ + setPalette( _paletteName ); + m_view->slotColorCellSelected(0); // FIXME: We need to save the current value!! +} + + +void KisPaletteWidget::setPalette( const QString &_paletteName ) +{ + QString paletteName( _paletteName); + + m_currentPalette = m_namedPaletteMap[paletteName]; + + if (combo->currentText() != paletteName) + { + bool found = false; + for(int i = 0; i < combo->count(); i++) + { + if (combo->text(i) == paletteName) + { + combo->setCurrentItem(i); + found = true; + break; + } + } + if (!found) + { + combo->insertItem(paletteName); + combo->setCurrentItem(combo->count()-1); + } + } + + m_view->setPalette(m_currentPalette); +} + +void KisPaletteWidget::slotAddPalette(KisResource * palette) +{ + KisPalette * p = dynamic_cast<KisPalette*>(palette); + + m_namedPaletteMap.insert(palette->name(), p); + + combo->insertItem(palette->name()); + + if (!init) { + combo->setCurrentItem(0); + setPalette(combo ->currentText()); + init = true; + } +} + + +#include "kis_palette_widget.moc" + diff --git a/krita/ui/kis_palette_widget.h b/krita/ui/kis_palette_widget.h new file mode 100644 index 000000000..bdfa8cdf7 --- /dev/null +++ b/krita/ui/kis_palette_widget.h @@ -0,0 +1,79 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_PALETTE_WIDGET_H__ +#define __KIS_PALETTE_WIDGET_H__ + +#include <qdict.h> +#include "kis_palette_view.h" + +class QComboBox; +class QLineEdit; +class KListBox; +class KisPalette; +class KisResource; +class KisColor; + +/** + * A color palette in table form. + * + * This is copied, mostly, from KPaletteTable in KColorDialog, original + * @author was Waldo Bastian <bastian@kde.org> -- much has changed, though, + * to work with KisPalettes and the resource server. + */ +class KisPaletteWidget : public QWidget +{ + Q_OBJECT +public: + KisPaletteWidget( QWidget *parent, int minWidth=210, int cols = 16); + virtual ~KisPaletteWidget(); + + QString palette() const; + KisPaletteEntry currentEntry() const { return m_view->currentEntry(); } + +public slots: + void setPalette(const QString &paletteName); + +signals: + void colorSelected(const KisColor &); + void colorSelected(const QColor&); + void colorDoubleClicked( const KisColor &, const QString &); + +protected slots: + void slotSetPalette( const QString &_paletteName ); + +public slots: + // Called by the resource server whenever a palette is loaded. + void slotAddPalette(KisResource * palette); + +protected: + void readNamedColor( void ); + +protected: + KisPaletteView* m_view; + QDict<KisPalette> m_namedPaletteMap; + KisPalette * m_currentPalette; + QComboBox *combo; + QScrollView *sv; + int mMinWidth; + int mCols; + bool init; +}; + +#endif + diff --git a/krita/ui/kis_part_layer.cc b/krita/ui/kis_part_layer.cc new file mode 100644 index 000000000..f34f6ebcb --- /dev/null +++ b/krita/ui/kis_part_layer.cc @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * (c) 2005 Bart Coppens <kde@bartcoppens.be> + * + * 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 "qpaintdevice.h" +#include "qpixmap.h" +#include "qimage.h" +#include "qpainter.h" + +#include <klocale.h> + +#include "KoDocument.h" +#include "KoDocumentChild.h" +#include "KoFrame.h" +#include "KoView.h" + +#include "kis_layer.h" +#include "kis_types.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_part_layer.h" +#include "kis_group_layer.h" +#include "kis_factory.h" +#include "kis_paint_device.h" +#include <kis_meta_registry.h> + +KisChildDoc::KisChildDoc ( KisDoc * kisDoc, const QRect & rect, KoDocument * childDoc ) + : KoDocumentChild( kisDoc, childDoc, rect ) + , m_doc(kisDoc) + , m_partLayer(0) +{ +} + + +KisChildDoc::KisChildDoc ( KisDoc * kisDoc ) + : KoDocumentChild( kisDoc) + , m_partLayer(0) +{ +} + +KisChildDoc::~KisChildDoc () +{ + // XXX doesn't this get deleted by itself or by anything else? Certainly looks so + // (otherwise I get a double deletion of a QObject, and krita crashes) + //delete m_doc; +} + + +KisPartLayerImpl::KisPartLayerImpl(KisImageSP img, KisChildDoc * doc) + : super(img, i18n("Embedded Document"), OPACITY_OPAQUE), m_doc(doc) +{ + m_cache = new KisPaintDevice( + KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA",""),""), name().latin1() ); + m_activated = false; +} + +KisPartLayerImpl::~KisPartLayerImpl() +{ +} + +KisLayerSP KisPartLayerImpl::clone() const { + return new KisPartLayerImpl(image(), childDoc()); +} + +// Called when the layer is made active +void KisPartLayerImpl::childActivated(KoDocumentChild* child) +{ + // Clear the image, so that if we move the part while activated, no ghosts show up + if (!m_activated && child == m_doc) { + QRect rect = extent(); + m_activated = true; + setDirty(rect); + QPtrList<KoView> views = child->parentDocument()->views(); + Q_ASSERT(views.count()); + // XXX iterate over views + connect(views.at(0), SIGNAL(activated(bool)), + this, SLOT(childDeactivated(bool))); + } +} + +// Called when another layer is made inactive +void KisPartLayerImpl::childDeactivated(bool activated) +{ + // We probably changed, notify the image that it needs to repaint where we currently updated + // We use the original geometry + if (m_activated && !activated /* no clue, but debugging suggests it is false here */) { + QPtrList<KoView> views = m_doc->parentDocument()->views(); + Q_ASSERT(views.count()); + views.at(0)->disconnect(SIGNAL(activated(bool))); + m_activated = false; + setDirty(m_doc->geometry()); + } +} + +void KisPartLayerImpl::setX(Q_INT32 x) { + QRect rect = m_doc->geometry(); + + // KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here, + // since the part is not necesarily started at (0,0) + rect.moveBy(x - this->x(), 0); + m_doc->setGeometry(rect); +} + +void KisPartLayerImpl::setY(Q_INT32 y) { + QRect rect = m_doc->geometry(); + + // KisPaintDevice::move moves to absolute coordinates, not relative. Work around that here, + // since the part is not necesarily started at (0,0) + rect.moveBy(0, y - this->y()); + m_doc->setGeometry(rect); +} + +void KisPartLayerImpl::paintSelection(QImage &img, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h) { + uchar *j = img.bits(); + QRect rect = m_doc->geometry(); + + for (int y2 = y; y2 < h + y; ++y2) { + for (int x2 = x; x2 < w + x; ++x2) { + if (!rect.contains(x2, y2)) { + Q_UINT8 g = (*(j + 0) + *(j + 1 ) + *(j + 2 )) / 9; + *(j+0) = 165+g; + *(j+1) = 128+g; + *(j+2) = 128+g; + } + j+=4; + } + } + +} + +KisPaintDeviceSP KisPartLayerImpl::prepareProjection(KisPaintDeviceSP projection, const QRect& r) +{ + if (!m_doc || !m_doc->document() || m_activated) return 0; + + m_cache->clear(); + + QRect intersection(r.intersect(exactBounds())); + if (intersection.isEmpty()) + return m_cache; + // XXX: have a look at the comments and see if they still truthfully represent the code :/ + + // We know the embedded part's size through the ChildDoc + // We move it to (0,0), since that is what we will start painting from in paintEverything. + QRect embedRect(intersection); + embedRect.moveBy(- exactBounds().x(), - exactBounds().y()); + QRect paintRect(exactBounds()); + paintRect.moveBy(- exactBounds().x(), - exactBounds().y()); + + QPixmap pm1(projection->convertToQImage(0 /*srgb XXX*/, + intersection.x(), intersection.y(), + intersection.width(), intersection.height())); + QPixmap pm2(extent().width(), extent().height()); + copyBlt(&pm2, embedRect.x(), embedRect.y(), &pm1, + 0, 0, embedRect.width(), embedRect.height()); + QPainter painter(&pm2); + painter.setClipRect(embedRect); + + // KWord's KWPartFrameSet::drawFrameContents has some interesting remarks concerning + // the semantics of the paintEverything call. + // Since a Krita Device really is displaysize/zoom agnostic, caring about zoom is not + // really as important here. What we paint at the moment, is just (0,0)x(w,h) + // Paint transparent, no zoom: + m_doc->document()->paintEverything(painter, paintRect, true); + + copyBlt(&pm1, 0, 0, &pm2, + embedRect.x(), embedRect.y(), embedRect.width(), embedRect.height()); + QImage qimg = pm1.convertToImage(); + + //assume the part is sRGB for now, and that "" is sRGB + // And we need to paint offsetted + m_cache->convertFromQImage(qimg, "", intersection.left(), intersection.top()); + + return m_cache; +} + +QImage KisPartLayerImpl::createThumbnail(Q_INT32 w, Q_INT32 h) { + QRect bounds(exactBounds()); + QPixmap pm(w, h); + QPainter painter(&pm); + + painter.fillRect(0, 0, w, h, Qt::white); + + painter.scale(w / bounds.width(), h / bounds.height()); + m_doc->document()->paintEverything(painter, bounds); + QImage qimg = pm.convertToImage(); + + return qimg; +} + +bool KisPartLayerImpl::saveToXML(QDomDocument doc, QDomElement elem) +{ + QDomElement embeddedElement = doc.createElement("layer"); + embeddedElement.setAttribute("name", name()); + + // x and y are loaded from the rect element in the embedded object tag + embeddedElement.setAttribute("x", 0); + embeddedElement.setAttribute("y", 0); + + embeddedElement.setAttribute("opacity", opacity()); + embeddedElement.setAttribute("compositeop", compositeOp().id().id()); + embeddedElement.setAttribute("visible", visible()); + embeddedElement.setAttribute("locked", locked()); + embeddedElement.setAttribute("layertype", "partlayer"); + elem.appendChild(embeddedElement); + + QDomElement objectElem = childDoc()->save(doc); + embeddedElement.appendChild(objectElem); + + return true; +} + +KisConnectPartLayerVisitor::KisConnectPartLayerVisitor(KisImageSP img, KisView* view, bool mode) + : m_img(img), m_view(view), m_connect(mode) +{ +} + +bool KisConnectPartLayerVisitor::visit(KisGroupLayer *layer) { + KisLayerSP child = layer->lastChild(); + + while (child) { + child->accept(*this); + child = child->prevSibling(); + } + + return true; +} + +bool KisConnectPartLayerVisitor::visit(KisPartLayer *layer) { + if (m_connect) { + QObject::connect(m_view, SIGNAL(childActivated(KoDocumentChild*)), + layer, SLOT(childActivated(KoDocumentChild*))); + } else { + QObject::disconnect(m_view, SIGNAL(childActivated(KoDocumentChild*)), layer, 0 ); + } + + return true; +} + +bool KisConnectPartLayerVisitor::visit(KisPaintLayer*) { + return true; +} + +bool KisConnectPartLayerVisitor::visit(KisAdjustmentLayer*) { + return true; +} + +#include "kis_part_layer.moc" diff --git a/krita/ui/kis_part_layer.h b/krita/ui/kis_part_layer.h new file mode 100644 index 000000000..efe57c289 --- /dev/null +++ b/krita/ui/kis_part_layer.h @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_PART_LAYER_ +#define _KIS_PART_LAYER_ + +#include <qrect.h> + +#include <KoDocument.h> +#include <KoDocumentChild.h> + +#include "kis_paint_layer.h" +#include "kis_types.h" +#include "kis_doc.h" +#include "kis_part_layer_iface.h" +#include "kis_view.h" +#include "kis_layer_visitor.h" + +class KoFrame; +class KoDocument; + + +/** + * The child document is responsible for saving and loading the embedded layers. + */ +class KisChildDoc : public KoDocumentChild +{ + +public: + KisChildDoc ( KisDoc * kisDoc, const QRect& rect, KoDocument * childDoc ); + KisChildDoc ( KisDoc * kisDdoc ); + + virtual ~KisChildDoc(); + + KisDoc * parent() const { return m_doc; } + + void setPartLayer (KisPartLayerSP layer) { m_partLayer = layer; } + + KisPartLayerSP partLayer() const { return m_partLayer; } +protected: + + KisDoc * m_doc; + KisPartLayerSP m_partLayer; +}; + + +/** + * A PartLayer is a layer that contains a KOffice Part like a KWord document + * or a KSpread spreadsheet. Or whatever. A Karbon drawing. + * + * The part is rendered into an RBGA8 paint device so we can composite it with + * the other layers. + * + * When it is activated (see activate()), it draws a rectangle around itself on the kisdoc, + * whereas when it is deactivated (deactivate()), it removes that rectangle and commits + * the child to the paint device. + * + * Embedded parts should get loaded and saved to the Native Krita Fileformat natively. + */ +class KisPartLayerImpl : public KisPartLayer { + Q_OBJECT + typedef KisPartLayer super; +public: + KisPartLayerImpl(KisImageSP img, KisChildDoc * doc); + virtual ~KisPartLayerImpl(); + + virtual KisLayerSP clone() const; + + /// Called when the layer is made active + virtual void activate() {} + + /// Called when another layer is made inactive + virtual void deactivate() {} + + /// Returns the childDoc so that we can access the doc from other places, if need be (KisDoc) + virtual KisChildDoc* childDoc() const { return m_doc; } + + void setDocType(const QString& type) { m_docType = type; } + QString docType() const { return m_docType; } + + virtual void setX(Q_INT32 x); + virtual void setY(Q_INT32 y); + virtual Q_INT32 x() const { return m_doc->geometry() . x(); } + virtual Q_INT32 y() const { return m_doc->geometry() . y(); } //m_paintLayer->y(); } + virtual QRect extent() const { return m_doc->geometry(); } + virtual QRect exactBounds() const { return m_doc->geometry(); } + + virtual QImage createThumbnail(Q_INT32 w, Q_INT32 h); + + virtual bool accept(KisLayerVisitor& visitor) { + return visitor.visit(this); + } + + virtual KisPaintDeviceSP prepareProjection(KisPaintDeviceSP projection, const QRect& r); + + virtual void paintSelection(QImage &img, Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h); + + virtual bool saveToXML(QDomDocument doc, QDomElement elem); +private slots: + /// Repaints our device with the data from the embedded part + //void repaint(); + /// When we activate the embedding, we clear ourselves + void childActivated(KoDocumentChild* child); + void childDeactivated(bool activated); + + +private: + // KisPaintLayerSP m_paintLayer; + KisPaintDeviceSP m_cache; + KoFrame * m_frame; // The widget that holds the editable view of the embedded part + KisChildDoc * m_doc; // The sub-document + QString m_docType; + bool m_activated; +}; + +/** + * Visitor that connects all partlayers in an image to a KisView's signals + */ +class KisConnectPartLayerVisitor : public KisLayerVisitor { + KisImageSP m_img; + KisView* m_view; + bool m_connect; // connects, or disconnects signals +public: + KisConnectPartLayerVisitor(KisImageSP img, KisView* view, bool mode); + virtual ~KisConnectPartLayerVisitor() {} + + virtual bool visit(KisPaintLayer *layer); + virtual bool visit(KisGroupLayer *layer); + virtual bool visit(KisPartLayer *layer); + virtual bool visit(KisAdjustmentLayer *layer); +}; + +#endif // _KIS_PART_LAYER_ diff --git a/krita/ui/kis_part_layer_handler.cc b/krita/ui/kis_part_layer_handler.cc new file mode 100644 index 000000000..787de8727 --- /dev/null +++ b/krita/ui/kis_part_layer_handler.cc @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2006 Bart Coppens <kde@bartcoppens.be> + * + * 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_canvas.h" +#include <fixx11h.h> // kis_canvas.h does X11 stuff + +#include <qpainter.h> +#include <qcursor.h> + +#include "kis_cursor.h" +#include "kis_canvas_painter.h" +#include "kis_move_event.h" +#include "kis_button_press_event.h" +#include "kis_button_release_event.h" +#include "kis_group_layer.h" +#include "kis_part_layer_handler.h" + +KisPartLayerHandler::KisPartLayerHandler(KisView* view, const KoDocumentEntry& entry, + KisGroupLayerSP parent, KisLayerSP above) + : m_parent(parent), m_above(above), m_view(view), m_entry(entry) { + m_started = false; + view->getCanvasController()->setCanvasCursor( KisCursor::selectCursor() ); +} + +void KisPartLayerHandler::done() { + emit handlerDone(); // We will get deleted by the view +} + +void KisPartLayerHandler::gotMoveEvent(KisMoveEvent* event) { + if (!m_started) { + emit sigGotMoveEvent(event); + return; + } + + KisCanvasPainter painter(m_view->getCanvasController()->kiscanvas()); + painter.setRasterOp( NotROP ); + + // erase old lines + QRect r(m_start, m_end); + r = r.normalize(); + if (!r.isEmpty()) + painter.drawRect(r); + + m_end = event->pos().roundQPoint(); + r = QRect(m_start, m_end).normalize(); + + painter.drawRect(r); + painter.end(); +} + +void KisPartLayerHandler::gotButtonPressEvent(KisButtonPressEvent* event) { + m_start = event->pos().roundQPoint(); + m_end = m_start; + m_started = true; +} + +void KisPartLayerHandler::gotButtonReleaseEvent(KisButtonReleaseEvent* event) { + if (!m_started) { + done(); + return; + } + + m_end = event->pos().roundQPoint(); + + QRect r(m_start, m_end); + + m_view->insertPart(r.normalize(), m_entry, m_parent, m_above); + // We will get deleted by the view through the above +} + +void KisPartLayerHandler::gotKeyPressEvent(QKeyEvent* event) { + if (event->key() == Key_Escape) { + done(); + } else { + emit sigGotKeyPressEvent(event); + } +} + +#include "kis_part_layer_handler.moc" diff --git a/krita/ui/kis_part_layer_handler.h b/krita/ui/kis_part_layer_handler.h new file mode 100644 index 000000000..7b6d3f0b6 --- /dev/null +++ b/krita/ui/kis_part_layer_handler.h @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2006 Bart Coppens <kde@bartcoppens.be> + * + * 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_PART_LAYER_HANDLER_ +#define KIS_PART_LAYER_HANDLER_ + +#include <qobject.h> +#include <KoQueryTrader.h> // KoDocumentEntry + +#include "kis_types.h" +#include "kis_doc.h" +#include "kis_view.h" + +class QKeyEvent; + +class KisPartLayerHandler : public QObject { +Q_OBJECT +public: + KisPartLayerHandler(KisView* view, const KoDocumentEntry& entry, + KisGroupLayerSP parent, KisLayerSP above); +signals: + void sigGotMoveEvent(KisMoveEvent* event); + void sigGotKeyPressEvent(QKeyEvent* event); + void handlerDone(); + +protected slots: + + void gotMoveEvent(KisMoveEvent* event); + void gotButtonPressEvent(KisButtonPressEvent* event); + void gotButtonReleaseEvent(KisButtonReleaseEvent* event); + void gotKeyPressEvent(QKeyEvent* event); +protected: + void done(); + KisGroupLayerSP m_parent; + KisLayerSP m_above; + KisView* m_view; + KoDocumentEntry m_entry; + QPoint m_start; + QPoint m_end; + bool m_started; +}; + +#endif // KIS_PART_LAYER_HANDLER diff --git a/krita/ui/kis_pattern_chooser.cc b/krita/ui/kis_pattern_chooser.cc new file mode 100644 index 000000000..8a9d08b03 --- /dev/null +++ b/krita/ui/kis_pattern_chooser.cc @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qlabel.h> +#include <qlayout.h> +#include <klocale.h> +#include <koIconChooser.h> + +#include "kis_colorspace.h" +#include "kis_pattern_chooser.h" +#include "kis_global.h" +#include "kis_icon_item.h" +#include "kis_pattern.h" + +KisPatternChooser::KisPatternChooser(QWidget *parent, const char *name) : super(parent, name) +{ + m_lbName = new QLabel(this); + + QVBoxLayout *mainLayout = new QVBoxLayout(this, 2, -1, "main layout"); + + mainLayout->addWidget(m_lbName); + mainLayout->addWidget(chooserWidget(), 10); +} + +KisPatternChooser::~KisPatternChooser() +{ +} + +void KisPatternChooser::update(KoIconItem *item) +{ + KisIconItem *kisItem = static_cast<KisIconItem *>(item); + + if (item) { + KisPattern *pattern = static_cast<KisPattern *>(kisItem->resource()); + + QString text = QString("%1 (%2 x %3)").arg(pattern->name()).arg(pattern->width()).arg(pattern->height()); + + m_lbName->setText(text); + } +} + +#include "kis_pattern_chooser.moc" + diff --git a/krita/ui/kis_pattern_chooser.h b/krita/ui/kis_pattern_chooser.h new file mode 100644 index 000000000..76514f716 --- /dev/null +++ b/krita/ui/kis_pattern_chooser.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_PATTERN_CHOOSER_H_ +#define KIS_PATTERN_CHOOSER_H_ + +#include "kis_itemchooser.h" + +class QLabel; + +class KisPatternChooser : public KisItemChooser { + typedef KisItemChooser super; + Q_OBJECT + +public: + KisPatternChooser(QWidget *parent = 0, const char *name = 0); + virtual ~KisPatternChooser(); + +protected: + virtual void update(KoIconItem *item); + +private: + QLabel *m_lbName; +}; + +#endif // KIS_PATTERN_CHOOSER_H_ + diff --git a/krita/ui/kis_perspective_grid_manager.cpp b/krita/ui/kis_perspective_grid_manager.cpp new file mode 100644 index 000000000..13c5cb132 --- /dev/null +++ b/krita/ui/kis_perspective_grid_manager.cpp @@ -0,0 +1,159 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_perspective_grid_manager.h" + +#include <kaction.h> +#include <klocale.h> +#include <kmessagebox.h> + +#include "kis_image.h" +#include "kis_grid_drawer.h" +#include "kis_perspective_grid.h" +#include "kis_view.h" + +KisPerspectiveGridManager::KisPerspectiveGridManager(KisView * parent) + : QObject() + , m_toggleEdition(false) + , m_view(parent) +{ + +} + + +KisPerspectiveGridManager::~KisPerspectiveGridManager() +{ + +} + +void KisPerspectiveGridManager::updateGUI() +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + + + if (image ) { + KisPerspectiveGrid* pGrid = image->perspectiveGrid(); + m_toggleGrid->setEnabled( pGrid->hasSubGrids()); + } +} + +void KisPerspectiveGridManager::setup(KActionCollection * collection) +{ + kdDebug() << "KisPerspectiveGridManager::setup(KActionCollection * collection)" << endl; + m_toggleGrid = new KToggleAction(i18n("Show Perspective Grid"), "", this, SLOT(toggleGrid()), collection, "view_toggle_perspective_grid"); + m_toggleGrid->setCheckedState(KGuiItem(i18n("Hide Perspective Grid"))); + m_toggleGrid->setChecked(false); + m_gridClear = new KAction(i18n("Clear Perspective Grid"), 0, "", this, SLOT(clearPerspectiveGrid()), collection, "view_clear_perspective_grid"); +} + +void KisPerspectiveGridManager::setGridVisible(bool t) +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + + + if (t && image ) { + KisPerspectiveGrid* pGrid = image->perspectiveGrid(); + if( pGrid->hasSubGrids()) + { + m_toggleGrid->setChecked(true); + } + } else { + m_toggleGrid->setChecked(false); + } + m_view->refreshKisCanvas(); +} + + +void KisPerspectiveGridManager::toggleGrid() +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + + + if (image && m_toggleGrid->isChecked()) { + KisPerspectiveGrid* pGrid = image->perspectiveGrid(); + + if(!pGrid->hasSubGrids()) + { + KMessageBox::error(0, i18n("Before displaying the perspective grid, you need to initialize it with the perspective grid tool"), i18n("No Perspective Grid to Display") ); + m_toggleGrid->setChecked(false); + } + } + m_view->updateCanvas(); +} + +void KisPerspectiveGridManager::clearPerspectiveGrid() +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + if (image ) { + image->perspectiveGrid()->clearSubGrids(); + m_view->updateCanvas(); + m_toggleGrid->setChecked(false); + m_toggleGrid->setEnabled(false); + } +} + +void KisPerspectiveGridManager::startEdition() +{ + m_toggleEdition = true; + m_toggleGrid->setEnabled( false ); + if( m_toggleGrid->isChecked() ) + m_view->updateCanvas(); +} + +void KisPerspectiveGridManager::stopEdition() +{ + m_toggleEdition = false; + m_toggleGrid->setEnabled( true ); + if( m_toggleGrid->isChecked() ) + m_view->updateCanvas(); +} + +void KisPerspectiveGridManager::drawGrid(QRect wr, QPainter *p, bool openGL ) +{ + KisImageSP image = m_view->canvasSubject()->currentImg(); + + + if (image && m_toggleGrid->isChecked() && !m_toggleEdition) { + KisPerspectiveGrid* pGrid = image->perspectiveGrid(); + + GridDrawer *gridDrawer = 0; + + if (openGL) { + gridDrawer = new OpenGLGridDrawer(); + } else { + Q_ASSERT(p); + + if (p) { + gridDrawer = new QPainterGridDrawer(p); + } + } + + Q_ASSERT(gridDrawer != 0); + + for( QValueList<KisSubPerspectiveGrid*>::const_iterator it = pGrid->begin(); it != pGrid->end(); ++it) + { + gridDrawer->drawPerspectiveGrid(image, wr, *it ); + } + delete gridDrawer; + } +} + + +#include "kis_perspective_grid_manager.moc" diff --git a/krita/ui/kis_perspective_grid_manager.h b/krita/ui/kis_perspective_grid_manager.h new file mode 100644 index 000000000..a23abef31 --- /dev/null +++ b/krita/ui/kis_perspective_grid_manager.h @@ -0,0 +1,54 @@ +/* + * This file is part of Krita + * + * Copyright (c) 2006 Cyrille Berger <cberger@cberger.net> + * + * 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_PERSPECTIVE_GRID_MANAGER_H +#define KIS_PERSPECTIVE_GRID_MANAGER_H + +#include <qobject.h> + +class KAction; +class KActionCollection; +class KToggleAction; +class KisView; + +class KisPerspectiveGridManager : public QObject +{ + Q_OBJECT + public: + KisPerspectiveGridManager(KisView * parent); + ~KisPerspectiveGridManager(); + void setup(KActionCollection * collection); + void drawGrid(QRect wr, QPainter *p, bool openGL = false); + void startEdition(); + void stopEdition(); + void setGridVisible(bool t); + public slots: + void updateGUI(); + void clearPerspectiveGrid(); + private slots: + void toggleGrid(); + private: + bool m_toggleEdition; + KisView* m_view; + KToggleAction* m_toggleGrid; + KAction* m_gridClear; +}; + +#endif diff --git a/krita/ui/kis_populate_visitor.h b/krita/ui/kis_populate_visitor.h new file mode 100644 index 000000000..ee43e825b --- /dev/null +++ b/krita/ui/kis_populate_visitor.h @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2005 Gábor Lehel <illissius@gmail.com> + * + * 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_POPULATE_VISITOR_H +#define KIS_POPULATE_VISITOR_H + +#include <kiconloader.h> +#include "kis_types.h" +#include "kis_layer.h" +#include "kis_group_layer.h" +#include "kis_paint_layer.h" +#include "kis_part_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_layerlist.h" + + +/** + * This visitor walks over the layer tree to fill + * the layer box. + */ +class KisPopulateVisitor: public KisLayerVisitor +{ + public: + KisPopulateVisitor(KisLayerList* widget) + : m_widget(widget) + , m_parent(0) + { } + + KisPopulateVisitor(KisLayerItem* parent) + : m_widget(parent->listView()) + , m_parent(parent) + { } + + virtual bool visit(KisPaintLayer* layer) + { + if (!layer->temporary()) + add(layer); + return true; + } + + virtual bool visit(KisPartLayer* layer) + { + add(layer)->setPixmap(0, SmallIcon("gear", 16)); + return true; + } + + virtual bool visit(KisAdjustmentLayer* layer) + { + add(layer)->setPixmap(0, SmallIcon("tool_filter", 16)); + return true; + } + + virtual bool visit(KisGroupLayer* layer) + { + KisLayerItem* item = add(layer); + item->makeFolder(); + KisPopulateVisitor visitor(item); + for (KisLayerSP l = layer->firstChild(); l; l = l->nextSibling()) + l->accept(visitor); + + vKisLayerSP childLayersAdded = visitor.layersAdded(); + + for (vKisLayerSP::iterator it = childLayersAdded.begin(); it != childLayersAdded.end(); ++it) { + m_layersAdded.append(*it); + } + + return true; + } + + vKisLayerSP layersAdded() const + { + return m_layersAdded; + } + + private: + LayerList* m_widget; + KisLayerItem* m_parent; + vKisLayerSP m_layersAdded; + + KisLayerItem* add(KisLayer* layer) + { + if (!layer) return 0; + + KisImageSP img = layer->image(); + if (!img) return 0; + + KisLayerItem *item; + if (m_parent) { + item = new KisLayerItem(m_parent, layer); + } + else { + item = new KisLayerItem(m_widget, layer); + } + if (layer == img->activeLayer()) { + item->setActive(); + } + m_layersAdded.append(layer); + return item; + } +}; + +#endif diff --git a/krita/ui/kis_previewdialog.cc b/krita/ui/kis_previewdialog.cc new file mode 100644 index 000000000..6b7467762 --- /dev/null +++ b/krita/ui/kis_previewdialog.cc @@ -0,0 +1,46 @@ +/* + * kis_previewdialog.cc - part of Krita + * + * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de> + * + * 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 <qframe.h> +#include <qhbox.h> +#include <qgroupbox.h> +#include <qlayout.h> + +#include "kis_previewwidget.h" +#include "kis_previewdialog.h" + +KisPreviewDialog::KisPreviewDialog( QWidget * parent, const char * name, bool modal, const QString &caption) + : super (parent, name, modal, caption, Ok | Cancel, Ok) +{ + QHBox* layout = new QHBox(this); + layout->setSpacing( 6 ); + + m_containerFrame = new QFrame( layout, "container" ); + + m_preview = new KisPreviewWidget( layout, "previewWidget" ); + + setMainWidget(layout); +} + +KisPreviewDialog::~KisPreviewDialog() +{ + +} + +#include "kis_previewdialog.moc" diff --git a/krita/ui/kis_previewdialog.h b/krita/ui/kis_previewdialog.h new file mode 100644 index 000000000..ef46b0660 --- /dev/null +++ b/krita/ui/kis_previewdialog.h @@ -0,0 +1,44 @@ +/* + * kis_previewdialog.h -- part of Krita + * + * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de> + * + * 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_PREVIEWDIALOG_H +#define KIS_PREVIEWDIALOG_H + +#include <kdialogbase.h> + +class KisPreviewWidget; +class QFrame; + +class KisPreviewDialog: public KDialogBase { + typedef KDialogBase super; + Q_OBJECT + +public: + KisPreviewDialog( QWidget* parent = 0, const char* name = 0, bool modal = false, const QString &caption=QString::null); + ~KisPreviewDialog(); + + KisPreviewWidget* previewWidget() { return m_preview; } + QFrame* container() { return m_containerFrame; } +private: + KisPreviewWidget* m_preview; + QFrame* m_containerFrame; +}; + +#endif diff --git a/krita/ui/kis_previewwidget.cc b/krita/ui/kis_previewwidget.cc new file mode 100644 index 000000000..363302f7e --- /dev/null +++ b/krita/ui/kis_previewwidget.cc @@ -0,0 +1,409 @@ +/* + * kis_previewwidget.cc - part of Krita + * + * Copyright (c) 2001 John Califf <jwcaliff@compuzone.net> + * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be> + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * Copyright (c) 2007 Ben Schleimer <bensch128@yahoo.com> + * + * 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 <qcheckbox.h> +#include <qradiobutton.h> +#include <qpainter.h> +#include <qpoint.h> +#include <qpushbutton.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qapplication.h> +#include <qcolor.h> +#include <qgroupbox.h> +#include <qcursor.h> +#include <qtimer.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kpushbutton.h> + +#include <kis_cursor.h> +#include <kis_colorspace.h> +#include <kis_colorspace_factory_registry.h> +#include <kis_config.h> +#include <kis_filter_strategy.h> +#include <kis_global.h> +#include <kis_image.h> +#include <kis_layer.h> +#include <kis_paint_layer.h> +#include <kis_group_layer.h> +#include <kis_meta_registry.h> +#include <kis_painter.h> +#include <kis_profile.h> +#include <kis_types.h> +#include <kis_undo_adapter.h> +#include <kis_label_progress.h> +#include <kis_selection.h> +#include <kis_transform_worker.h> + +#include "kis_previewwidgetbase.h" +#include "kis_previewwidget.h" +#include "imageviewer.h" + +static const int ZOOM_PAUSE = 100; +static const int FILTER_PAUSE = 500; +static const double ZOOM_FACTOR = 1.1; + +KisPreviewWidget::KisPreviewWidget( QWidget* parent, const char* name ) + : PreviewWidgetBase( parent, name ) + , m_autoupdate(true) + , m_previewIsDisplayed(true) + , m_scaledOriginal() + , m_dirtyOriginal(true) + , m_origDevice(new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temp")) + , m_scaledPreview() + , m_dirtyPreview(true) + , m_previewDevice(new KisPaintDevice(KisMetaRegistry::instance()->csRegistry()->getRGB8(), "temp")) + , m_scaledImage(NULL) + , m_filterZoom(1.0) + , m_zoom(-1.0) + , m_profile(NULL) + , m_progress( 0 ) + , m_zoomTimer(new QTimer(this)) + , m_filterTimer(new QTimer(this)) + , m_firstFilter(true) + , m_firstZoom(true) +{ + btnZoomIn->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag+", KIcon::MainToolbar, 16 )); + connect(btnZoomIn, SIGNAL(clicked()), this, SLOT(zoomIn())); + btnZoomOut->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag-", KIcon::MainToolbar, 16 )); + connect(btnZoomOut, SIGNAL(clicked()), this, SLOT(zoomOut())); + btnUpdate->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "reload", KIcon::MainToolbar, 16 )); + connect(btnUpdate, SIGNAL(clicked()), this, SLOT(forceUpdate())); + + connect(radioBtnPreview, SIGNAL(toggled(bool)), this, SLOT(setPreviewDisplayed(bool))); + + connect(checkBoxAutoUpdate, SIGNAL(toggled(bool)), this, SLOT(slotSetAutoUpdate(bool))); + btnZoomOneToOne->setIconSet(KGlobal::instance()->iconLoader()->loadIconSet( "viewmag1", KIcon::MainToolbar, 16 )); + connect(btnZoomOneToOne, SIGNAL(clicked()), this, SLOT(zoomOneToOne())); + + m_progress = new KisLabelProgress(frmProgress); + m_progress->setMaximumHeight(fontMetrics().height() ); + QVBoxLayout *vbox = new QVBoxLayout( frmProgress ); + vbox->addWidget(m_progress); + m_progress->hide(); + + connect(m_zoomTimer, SIGNAL(timeout()), this, SLOT(updateZoom())); + connect(m_filterTimer, SIGNAL(timeout()), this, SLOT(runFilterHelper())); + +/* kToolBar1->insertLineSeparator(); + kToolBar1->insertButton("reload",2, true, i18n("Update")); + connect(kToolBar1->getButton(2),SIGNAL(clicked()),this,SLOT(forceUpdate())); + + kToolBar1->insertButton("",3, true, i18n("Auto Update")); + connect(kToolBar1->getButton(3),SIGNAL(clicked()),this,SLOT(toggleAutoUpdate())); + + kToolBar1->insertButton("",4, true, i18n("Switch")); + connect(kToolBar1->getButton(4),SIGNAL(clicked()),this,SLOT(toggleImageDisplayed()));*/ +// these currently don't yet work, reenable when they do work :) (TZ-12-2005) +// TODO reenable these +// kToolBar1->insertButton("",5, true, i18n("Popup Original and Preview")); +} + +KisPreviewWidget::~KisPreviewWidget() { } + +void KisPreviewWidget::forceUpdate() +{ + if(m_previewIsDisplayed) + { + m_groupBox->setTitle(m_origDevice->name()); + emit updated(); + } +} + +void KisPreviewWidget::slotSetDevice(KisPaintDeviceSP dev) +{ + Q_ASSERT( dev ); + + if (!dev) return; + + m_origDevice = dev; + m_previewDevice = dev; + m_filterZoom = 1.0; + + KisConfig cfg; + QString monitorProfileName = cfg.monitorProfile(); + m_profile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName); + + QRect r = dev->exactBounds(); + + m_groupBox->setTitle(i18n("Preview: ") + dev->name()); + m_previewIsDisplayed = true; + + m_zoom = -1.0; + zoomChanged(double(m_preview->width()) / double(r.width()) ); +} + +void KisPreviewWidget::updateZoom() +{ + QApplication::setOverrideCursor(KisCursor::waitCursor()); + + if(m_previewIsDisplayed) + { + if(m_dirtyPreview) + { + QSize r = m_previewDevice->extent().size(); + int w = r.width(), h = r.height(); + int sw = int(ceil(m_zoom * w / m_filterZoom)); + int sh = int(ceil(m_zoom * h / m_filterZoom)); + m_dirtyPreview = false; + m_scaledPreview = m_previewDevice->convertToQImage(m_profile, 0, 0, w, h); + m_scaledPreview = m_scaledPreview.scale(sw,sh, QImage::ScaleMax); // Use scale instead of smoothScale for speed up + } + m_preview->setImage(m_scaledPreview); + } else + { + if(m_dirtyOriginal) + { + QSize r = m_origDevice->extent().size(); + int w = r.width(), h = r.height(); + int sw = int(ceil(m_zoom * w)); + int sh = int(ceil(m_zoom * h)); + m_dirtyOriginal = false; + m_scaledOriginal = m_origDevice->convertToQImage(m_profile, 0, 0, w, h); + m_scaledOriginal = m_scaledOriginal.scale(sw,sh, QImage::ScaleMax); // Use scale instead of smoothScale for speed up + } + m_preview->setImage(m_scaledOriginal); + } + + QApplication::restoreOverrideCursor(); +} + +void KisPreviewWidget::slotSetAutoUpdate(bool set) { + m_autoupdate = set; +} + +void KisPreviewWidget::wheelEvent(QWheelEvent * e) +{ + if (e->delta() > 0) { + zoomIn(); + } else { + zoomOut(); + } + e->accept(); +} + +void KisPreviewWidget::setPreviewDisplayed(bool v) +{ + if(v != m_previewIsDisplayed) + { + m_previewIsDisplayed = v; + if(m_previewIsDisplayed) { + m_groupBox->setTitle(i18n("Preview: ") + m_origDevice->name()); + } else { + m_groupBox->setTitle(i18n("Original: ") + m_origDevice->name()); + } + // Call directly without any pause because there is no scaling + updateZoom(); + } +} + +void KisPreviewWidget::needUpdate() +{ + if(m_previewIsDisplayed) + m_groupBox->setTitle(i18n("Preview (needs update)")); +} + +bool KisPreviewWidget::getAutoUpdate() const { + return m_autoupdate; +} + +void KisPreviewWidget::zoomChanged(const double zoom) +{ + // constrain the zoom + double tZoom = zoom; + if(zoom <= 1./8.) { tZoom = 1./8.; } + if(zoom > 8.) { tZoom = 8.; } + + if(tZoom != m_zoom) + { + m_zoom = tZoom; + m_dirtyOriginal = true; + m_dirtyPreview = true; + + if(m_firstZoom) { + m_firstZoom = false; + updateZoom(); + } else { + m_zoomTimer->start(ZOOM_PAUSE, true); + } + } +} + +void KisPreviewWidget::zoomIn() { + zoomChanged(m_zoom * ZOOM_FACTOR); +} + +void KisPreviewWidget::zoomOut() { + zoomChanged(m_zoom / ZOOM_FACTOR); +} + +void KisPreviewWidget::zoomOneToOne() { + zoomChanged(1.0); +} + +static inline void cropDevice(KisPaintDevice * device, const double & zoom) { + QRect r = device->exactBounds(); + r.setX(int(zoom * r.x()) ); + r.setY(int(zoom * r.y()) ); + r.setWidth(int(zoom * r.width()) ); + r.setHeight(int(zoom * r.height()) ); + device->crop(r); +} + +class MyCropVisitor : public KisLayerVisitor { + const double m_zoom; + +public: + MyCropVisitor(const double & z) : m_zoom(z) { } + virtual ~MyCropVisitor() { } + + virtual bool visit(KisPaintLayer *layer) { + KisPaintDeviceSP device = layer->paintDevice(); + ::cropDevice(device.data(), m_zoom); + // Make sure we have a tight fit for the selection + if(device->hasSelection()) { + ::cropDevice(device->selection().data(), m_zoom); + } + + return true; + } + virtual bool visit(KisGroupLayer *layer) { + for(KisLayerSP l = layer->firstChild(); l; l = l->nextSibling()) { + l->accept(*this); + } + return true; + } + virtual bool visit(KisPartLayer *) { return true; } + virtual bool visit(KisAdjustmentLayer *) { return true; } +}; + +void KisPreviewWidget::runFilter(KisFilter * filter, KisFilterConfiguration * config) { + if(!filter) return; + if(!config) return; + + m_filter = filter; + m_config = config; + + if(m_firstFilter) { + m_firstFilter = false; + runFilterHelper(); + } else { + m_filterTimer->start(FILTER_PAUSE, true); + } +} + +/** + * XXX: Fix the situations which m_origDevice is NOT associated with a image. + * If it comes from a adjustment layer or projection or thumbnail. Currently, nothing happens + */ +void KisPreviewWidget::runFilterHelper() { + + m_filterZoom = m_zoom; + // Dont scale more then 1.0 so we don't waste time in preview widget for large scaling. + if(m_filterZoom > 1.0) { + m_filterZoom = 1.0; + } + + KisPaintDeviceSP scaledDevice; + KisHermiteFilterStrategy strategy; + + // Copy the image and scale + if (m_origDevice->image()) + { + m_scaledImage = new KisImage(*m_origDevice->image()); + if(!m_origDevice->parentLayer()) return; + QString layerName = m_origDevice->parentLayer()->name(); + KisPaintLayerSP pl = ::qt_cast<KisPaintLayer*>(m_scaledImage->findLayer(layerName)); + if(!pl) return; + scaledDevice = pl->paintDevice(); + + KisSelectionSP select; + if(scaledDevice->hasSelection()) + { + select = new KisSelection(*scaledDevice->selection()); + scaledDevice->deselect(); + } + // Scale + m_scaledImage->setUndoAdapter(NULL); + m_scaledImage->scale(m_filterZoom, m_filterZoom, NULL, &strategy); + // Scale the selection + if(select) + { + KisPaintDeviceSP t = select.data(); + KisTransformWorker tw(t, m_filterZoom, m_filterZoom, + 0.0, 0.0, 0.0, 0, 0, NULL, &strategy); + tw.run(); + scaledDevice->setSelection(select); + select->setParentLayer(scaledDevice->parentLayer()); + } + + // Crop by the zoom value instead of cropping by rectangle. It gives better results + MyCropVisitor v(m_filterZoom); + m_scaledImage->rootLayer()->accept(v); + } else + { + scaledDevice = new KisPaintDevice(*m_origDevice); + KisSelectionSP select; + if(scaledDevice->hasSelection()) + { + select = new KisSelection(*scaledDevice->selection()); + scaledDevice->deselect(); + } + KisTransformWorker tw(scaledDevice, m_filterZoom, m_filterZoom, + 0.0, 0.0, 0.0, 0, 0, NULL, &strategy); + tw.run(); + // Scale the selection + if(select) + { + KisPaintDeviceSP t = select.data(); + KisTransformWorker tw(t, m_filterZoom, m_filterZoom, + 0.0, 0.0, 0.0, 0, 0, NULL, &strategy); + tw.run(); + scaledDevice->setSelection(select); + ::cropDevice(select.data(), m_filterZoom); + } + ::cropDevice(scaledDevice.data(), m_filterZoom); + } + + m_previewDevice = new KisPaintDevice(*scaledDevice); + + // Setup the progress display + m_filter->enableProgress(); + m_progress->setSubject(m_filter, true, true); + m_filter->setProgressDisplay(m_progress); + m_filter->process(scaledDevice, m_previewDevice, m_config, scaledDevice->exactBounds()); + m_filter->disableProgress(); + + m_dirtyPreview = true; + + if(m_firstZoom) { + m_firstZoom = false; + updateZoom(); + } else { + m_zoomTimer->start(ZOOM_PAUSE, true); + } +} + +#include "kis_previewwidget.moc" diff --git a/krita/ui/kis_previewwidget.h b/krita/ui/kis_previewwidget.h new file mode 100644 index 000000000..f3b38e989 --- /dev/null +++ b/krita/ui/kis_previewwidget.h @@ -0,0 +1,140 @@ +/* + * kis_previewwidget.h - part of Krita + * + * Copyright (c) 2001 John Califf <jcaliff@compuzone.net> + * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be> + * Copyright (c) 2005 Cyrille Berger <cberger@cberger.net> + * Copyright (c) 2007 Benjamin Schleimer <bensch128@yahoo.com> + * + * 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_previewwidget_h__ +#define __kis_previewwidget_h__ + +#include <qimage.h> +#include <qevent.h> + +#include "kis_types.h" + +#include "kis_previewwidgetbase.h" + +class QWidget; +class KisProfile; +class KisFilter; +class KisFilterConfiguration; +class QTimer; +class KisLabelProgress; + +/** + * A widget that can be used by plugins to show a preview of the effect of the + * plugin to the user. This is a convenience class thand handily packs a source and a + * preview view together with a zoom button. + * It would be nice if every plugin that needs to show a preview + * (maybe not those that create a new image) would use this. This can prevent the distracting + * effect the GIMP has with a different preview for almost every filter. + */ +class KisPreviewWidget : public PreviewWidgetBase +{ + Q_OBJECT + +public: + /** Constructs the widget */ + KisPreviewWidget( QWidget* parent = 0, const char* name = 0 ); + virtual ~KisPreviewWidget(); + + /** returns if the preview is automatically updated */ + bool getAutoUpdate() const; + + void wheelEvent(QWheelEvent * e); + + /** Instructs the KisPreviewWidget to eventually update the preview. + * KisPreviewWidget delays the actual running of the filter for 500ms + * so if the user is changing a configuration setting, it won't run multiple time. + * @param filter to run on the image + * @config to use when filtering. + */ + void runFilter(KisFilter * filter, KisFilterConfiguration * config); + +public slots: + + /** Sets the preview to use the layer specified as argument */ + void slotSetDevice(KisPaintDeviceSP dev); + + /** Enables or disables the automatically updating of the preview */ + void slotSetAutoUpdate(bool set); + + /** Toggle between display preview and display original */ + void setPreviewDisplayed(bool v); + + /** use to indicate that the preview need to be updated. */ + void needUpdate(); + +signals: + /** This is emitted when the position or zoom factor of the widget has changed */ + void updated(); + +private slots: + + void zoomIn(); + void zoomOut(); + void zoomOneToOne(); + + /** + * Called when the "Force Update" button is clicked + */ + void forceUpdate(); + + /** + * Updates the zoom and redisplays either the original or the preview (filtered) image + */ + void updateZoom(); + + /** Internal method which actually runs the filter + */ + void runFilterHelper(); + +private: + /** + * Recalculates the zoom factor + */ + void zoomChanged(const double zoom); + + bool m_autoupdate; /// Flag indicating that the widget should auto update whenever a setting is changed + bool m_previewIsDisplayed; /// Flag indicating whether the filtered or original image is displayed + + QImage m_scaledOriginal; /// QImage copy of the original image + bool m_dirtyOriginal; /// flag indicating that the original image is dirty + KisPaintDeviceSP m_origDevice; /// Pointer to the original image + + QImage m_scaledPreview; /// QImage copy of the filtered image + bool m_dirtyPreview; /// flag indicating that the preview image is dirty + KisPaintDeviceSP m_previewDevice; /// Pointer to the preview image + KisImageSP m_scaledImage; /// Scaled image copied from the original + + double m_filterZoom; /// Zoom amount when the filtering occurred + double m_zoom; /// Current zoom amount + KisProfile * m_profile; /// the color profile to use when converting to QImage + + KisLabelProgress *m_progress; /// Progress bar of the preview. + + QTimer * m_zoomTimer; /// Timer used to update the view whenever the zoom changes + QTimer * m_filterTimer; /// Timer used to update the view whenever the filter changes + KisFilter * m_filter; /// Filter used + KisFilterConfiguration * m_config; /// Configuration used + bool m_firstFilter; /// Flag to determine if we should delay the first filter or not + bool m_firstZoom; /// Flag to determine if we should delay the first zoom or not +}; + +#endif diff --git a/krita/ui/kis_previewwidgetbase.ui b/krita/ui/kis_previewwidgetbase.ui new file mode 100644 index 000000000..f50fba6a1 --- /dev/null +++ b/krita/ui/kis_previewwidgetbase.ui @@ -0,0 +1,271 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>PreviewWidgetBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>PreviewWidgetBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>588</width> + <height>500</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>0</height> + </size> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>m_groupBox</cstring> + </property> + <property name="title"> + <string>Preview</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="ImageViewer"> + <property name="name"> + <cstring>m_preview</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>200</width> + <height>150</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>1000</width> + <height>1000</height> + </size> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="frameShape"> + <enum>GroupBoxPanel</enum> + </property> + <property name="title"> + <string></string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioBtnPreview</cstring> + </property> + <property name="text"> + <string>Pr&eview</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Preview modified layer</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioBtnOriginal</cstring> + </property> + <property name="text"> + <string>Ori&ginal</string> + </property> + <property name="toolTip" stdset="0"> + <string>Show original layer</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnZoomOut</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Zoom Out</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnZoomIn</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Zoom In</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnZoomOneToOne</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>1 : 1</string> + </property> + </widget> + <widget class="KPushButton"> + <property name="name"> + <cstring>btnUpdate</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="toolTip" stdset="0"> + <string>Update preview</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>checkBoxAutoUpdate</cstring> + </property> + <property name="text"> + <string>&Autoupdate</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + <property name="toolTip" stdset="0"> + <string>Automatically update the preview whenever the filter settings change</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>frmProgress</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>ImageViewer</class> + <header location="local">imageviewer.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + <signal>moved(QPoint)</signal> + <signal>moving(QPoint)</signal> + <signal>startMoving(QPoint)</signal> + <slot access="public" specifier="">zoomIn()</slot> + <slot access="public" specifier="">slot()</slot> + <slot access="public" specifier="">zoomOut()</slot> + <slot access="public" specifier="">slot()</slot> + <slot access="public" specifier="">slot()</slot> + <slot access="public" specifier="">slotMoving(QPoint)</slot> + <slot access="public" specifier="">slotMoved(QPoint)</slot> + <slot access="public" specifier="">slot()</slot> + <slot access="public" specifier="">slotStartMoving(QPoint)</slot> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="XBM.GZ" length="79">789c534e494dcbcc4b554829cdcdad8c2fcf4c29c95030e0524611cd48cd4ccf28010a1797249664262b2467241641a592324b8aa363156c15aab914146aadb90067111b1f</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>imageviewer.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> + <includehint>kpushbutton.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/kis_qpaintdevice_canvas.cc b/krita/ui/kis_qpaintdevice_canvas.cc new file mode 100644 index 000000000..675b71380 --- /dev/null +++ b/krita/ui/kis_qpaintdevice_canvas.cc @@ -0,0 +1,120 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_qpaintdevice_canvas.h" +#include "kis_qpaintdevice_canvas_painter.h" +#include <kdebug.h> + +KisQPaintDeviceCanvasWidget::KisQPaintDeviceCanvasWidget(QWidget *parent, const char *name) + : QWidget(parent, name) +{ +} + +KisQPaintDeviceCanvasWidget::~KisQPaintDeviceCanvasWidget() +{ +} + +void KisQPaintDeviceCanvasWidget::paintEvent(QPaintEvent *e) +{ + widgetGotPaintEvent(e); +} + +void KisQPaintDeviceCanvasWidget::mousePressEvent(QMouseEvent *e) +{ + widgetGotMousePressEvent(e); +} + +void KisQPaintDeviceCanvasWidget::mouseReleaseEvent(QMouseEvent *e) +{ + widgetGotMouseReleaseEvent(e); +} + +void KisQPaintDeviceCanvasWidget::mouseDoubleClickEvent(QMouseEvent *e) +{ + widgetGotMouseDoubleClickEvent(e); +} + +void KisQPaintDeviceCanvasWidget::mouseMoveEvent(QMouseEvent *e) +{ + widgetGotMouseMoveEvent(e); +} + +void KisQPaintDeviceCanvasWidget::tabletEvent(QTabletEvent *e) +{ + widgetGotTabletEvent(e); +} + +void KisQPaintDeviceCanvasWidget::enterEvent(QEvent *e) +{ + widgetGotEnterEvent(e); +} + +void KisQPaintDeviceCanvasWidget::leaveEvent(QEvent *e) +{ + widgetGotLeaveEvent(e); +} + +void KisQPaintDeviceCanvasWidget::wheelEvent(QWheelEvent *e) +{ + widgetGotWheelEvent(e); +} + +void KisQPaintDeviceCanvasWidget::keyPressEvent(QKeyEvent *e) +{ + widgetGotKeyPressEvent(e); +} + +void KisQPaintDeviceCanvasWidget::keyReleaseEvent(QKeyEvent *e) +{ + widgetGotKeyReleaseEvent(e); +} + +void KisQPaintDeviceCanvasWidget::dragEnterEvent(QDragEnterEvent *e) +{ + widgetGotDragEnterEvent(e); +} + +void KisQPaintDeviceCanvasWidget::dropEvent(QDropEvent *e) +{ + widgetGotDropEvent(e); +} + +#ifdef Q_WS_X11 + +bool KisQPaintDeviceCanvasWidget::x11Event(XEvent *event) +{ + return KisCanvasWidget::x11Event(event, x11Display(), winId(), mapToGlobal(QPoint(0, 0))); +} + +#endif // Q_WS_X11 + +KisCanvasWidgetPainter *KisQPaintDeviceCanvasWidget::createPainter() +{ + return new KisQPaintDeviceCanvasPainter(this); +} + +#if defined(EXTENDED_X11_TABLET_SUPPORT) +void KisQPaintDeviceCanvasWidget::selectTabletDeviceEvents() +{ + KisCanvasWidget::selectTabletDeviceEvents(this); +} +#endif + diff --git a/krita/ui/kis_qpaintdevice_canvas.h b/krita/ui/kis_qpaintdevice_canvas.h new file mode 100644 index 000000000..1046337a1 --- /dev/null +++ b/krita/ui/kis_qpaintdevice_canvas.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_QPAINTDEVICE_CANVAS_H_ +#define KIS_QPAINTDEVICE_CANVAS_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> + +#include "kis_global.h" +#include "kis_canvas.h" + +#ifdef Q_WS_X11 +#include <X11/Xlib.h> +#endif // Q_WS_X11 + +class KisQPaintDeviceCanvasWidget : public virtual QWidget, public virtual KisCanvasWidget { +public: + KisQPaintDeviceCanvasWidget(QWidget *parent = 0, const char *name = 0); + ~KisQPaintDeviceCanvasWidget(); + + virtual KisCanvasWidgetPainter *createPainter(); + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + virtual void selectTabletDeviceEvents(); +#endif + +protected: + virtual void paintEvent(QPaintEvent *event); + virtual void mousePressEvent(QMouseEvent *event); + virtual void mouseReleaseEvent(QMouseEvent *event); + virtual void mouseDoubleClickEvent(QMouseEvent *event); + virtual void mouseMoveEvent(QMouseEvent *event); + virtual void tabletEvent(QTabletEvent *event); + virtual void enterEvent(QEvent *event ); + virtual void leaveEvent(QEvent *event); + virtual void wheelEvent(QWheelEvent *event); + virtual void keyPressEvent(QKeyEvent *event); + virtual void keyReleaseEvent(QKeyEvent *event); + virtual void dragEnterEvent(QDragEnterEvent *event); + virtual void dropEvent(QDropEvent *event); +#ifdef Q_WS_X11 + bool x11Event(XEvent *event); +#endif // Q_WS_X11 +}; + +#endif // KIS_QPAINTDEVICE_CANVAS_H_ + diff --git a/krita/ui/kis_qpaintdevice_canvas_painter.cc b/krita/ui/kis_qpaintdevice_canvas_painter.cc new file mode 100644 index 000000000..eb68117d7 --- /dev/null +++ b/krita/ui/kis_qpaintdevice_canvas_painter.cc @@ -0,0 +1,647 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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.g + * + * 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_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_qpaintdevice_canvas_painter.h" + +KisQPaintDeviceCanvasPainter::KisQPaintDeviceCanvasPainter() +{ +} + +KisQPaintDeviceCanvasPainter::KisQPaintDeviceCanvasPainter(const QPaintDevice *paintDevice) + : m_painter(paintDevice) +{ +} + +KisQPaintDeviceCanvasPainter::~KisQPaintDeviceCanvasPainter() +{ +} + +bool KisQPaintDeviceCanvasPainter::begin(KisCanvasWidget *canvasWidget, bool unclipped) +{ + QWidget *widget = dynamic_cast<QWidget *>(canvasWidget); + + if (widget != 0) { + return m_painter.begin(widget, unclipped); + } else { + return false; + } +} + +bool KisQPaintDeviceCanvasPainter::begin(const QPaintDevice* paintDevice, bool unclipped) +{ + return m_painter.begin(paintDevice, unclipped); +} + +bool KisQPaintDeviceCanvasPainter::end() +{ + return m_painter.end(); +} + +void KisQPaintDeviceCanvasPainter::save() +{ + m_painter.save(); +} + +void KisQPaintDeviceCanvasPainter::restore() +{ + m_painter.restore(); +} + +QFontMetrics KisQPaintDeviceCanvasPainter::fontMetrics() const +{ + return m_painter.fontMetrics(); +} + +QFontInfo KisQPaintDeviceCanvasPainter::fontInfo() const +{ + return m_painter.fontInfo(); +} + +const QFont& KisQPaintDeviceCanvasPainter::font() const +{ + return m_painter.font(); +} + +void KisQPaintDeviceCanvasPainter::setFont(const QFont& font) +{ + m_painter.setFont(font); +} + +const QPen& KisQPaintDeviceCanvasPainter::pen() const +{ + return m_painter.pen(); +} + +void KisQPaintDeviceCanvasPainter::setPen(const QPen& pen) +{ + m_painter.setPen(pen); +} + +void KisQPaintDeviceCanvasPainter::setPen(Qt::PenStyle penStyle) +{ + m_painter.setPen(penStyle); +} + +void KisQPaintDeviceCanvasPainter::setPen(const QColor& color) +{ + m_painter.setPen(color);; +} + +const QBrush& KisQPaintDeviceCanvasPainter::brush() const +{ + return m_painter.brush(); +} + +void KisQPaintDeviceCanvasPainter::setBrush(const QBrush& brush) +{ + m_painter.setBrush(brush); +} + +void KisQPaintDeviceCanvasPainter::setBrush(Qt::BrushStyle brushStyle) +{ + m_painter.setBrush(brushStyle); +} + +void KisQPaintDeviceCanvasPainter::setBrush(const QColor& color) +{ + m_painter.setBrush(color); +} + +QPoint KisQPaintDeviceCanvasPainter::pos() const +{ + return m_painter.pos(); +} + +const QColor& KisQPaintDeviceCanvasPainter::backgroundColor() const +{ + return m_painter.backgroundColor(); +} + +void KisQPaintDeviceCanvasPainter::setBackgroundColor(const QColor& color) +{ + m_painter.setBackgroundColor(color); +} + +Qt::Qt::BGMode KisQPaintDeviceCanvasPainter::backgroundMode() const +{ + return m_painter.backgroundMode(); +} + +void KisQPaintDeviceCanvasPainter::setBackgroundMode(Qt::BGMode bgMode) +{ + m_painter.setBackgroundMode(bgMode); +} + +Qt::RasterOp KisQPaintDeviceCanvasPainter::rasterOp() const +{ + return m_painter.rasterOp(); +} + +void KisQPaintDeviceCanvasPainter::setRasterOp(Qt::RasterOp rasterOp) +{ + m_painter.setRasterOp(rasterOp); +} + +const QPoint& KisQPaintDeviceCanvasPainter::brushOrigin() const +{ + return m_painter.brushOrigin(); +} + +void KisQPaintDeviceCanvasPainter::setBrushOrigin(int x, int y) +{ + m_painter.setBrushOrigin(x, y); +} + +void KisQPaintDeviceCanvasPainter::setBrushOrigin(const QPoint& origin) +{ + m_painter.setBrushOrigin(origin); +} + +bool KisQPaintDeviceCanvasPainter::hasViewXForm() const +{ + return m_painter.hasViewXForm(); +} + +bool KisQPaintDeviceCanvasPainter::hasWorldXForm() const +{ + return m_painter.hasWorldXForm(); +} + +void KisQPaintDeviceCanvasPainter::setViewXForm(bool enable) +{ + m_painter.setViewXForm(enable); +} + +QRect KisQPaintDeviceCanvasPainter::window() const +{ + return m_painter.window(); +} + +void KisQPaintDeviceCanvasPainter::setWindow(const QRect& r) +{ + m_painter.setWindow(r); +} + +void KisQPaintDeviceCanvasPainter::setWindow(int x, int y, int w, int h) +{ + m_painter.setWindow(x, y, w, h); +} + +QRect KisQPaintDeviceCanvasPainter::viewport() const +{ + return m_painter.viewport(); +} + +void KisQPaintDeviceCanvasPainter::setViewport(const QRect& r) +{ + m_painter.setViewport(r); +} + +void KisQPaintDeviceCanvasPainter::setViewport(int x, int y, int w, int h) +{ + m_painter.setViewport(x, y, w, h); +} + +void KisQPaintDeviceCanvasPainter::setWorldXForm(bool enable) +{ + m_painter.setWorldXForm(enable); +} + +const QWMatrix& KisQPaintDeviceCanvasPainter::worldMatrix() const +{ + return m_painter.worldMatrix(); +} + +void KisQPaintDeviceCanvasPainter::setWorldMatrix(const QWMatrix& matrix, bool combine) +{ + m_painter.setWorldMatrix(matrix, combine); +} + +void KisQPaintDeviceCanvasPainter::saveWorldMatrix() +{ + m_painter.saveWorldMatrix(); +} + +void KisQPaintDeviceCanvasPainter::restoreWorldMatrix() +{ + m_painter.restoreWorldMatrix(); +} + +void KisQPaintDeviceCanvasPainter::scale(double sx, double sy) +{ + m_painter.scale(sx, sy); +} + +void KisQPaintDeviceCanvasPainter::shear(double sh, double sv) +{ + m_painter.shear(sh, sv); +} + +void KisQPaintDeviceCanvasPainter::rotate(double a) +{ + m_painter.rotate(a); +} + +void KisQPaintDeviceCanvasPainter::translate(double dx, double dy) +{ + m_painter.translate(dx, dy); +} + +void KisQPaintDeviceCanvasPainter::resetXForm() +{ + m_painter.resetXForm(); +} + +double KisQPaintDeviceCanvasPainter::translationX() const +{ + return m_painter.translationX(); +} + +double KisQPaintDeviceCanvasPainter::translationY() const +{ + return m_painter.translationY(); +} + +QPoint KisQPaintDeviceCanvasPainter::xForm(const QPoint& point) const +{ + return m_painter.xForm(point); +} + +QRect KisQPaintDeviceCanvasPainter::xForm(const QRect& r) const +{ + return m_painter.xForm(r); +} + +QPointArray KisQPaintDeviceCanvasPainter::xForm(const QPointArray& pointArray) const +{ + return m_painter.xForm(pointArray); +} + +QPointArray KisQPaintDeviceCanvasPainter::xForm(const QPointArray& pointArray, int index, int npoints) const +{ + return m_painter.xForm(pointArray, index, npoints); +} + +QPoint KisQPaintDeviceCanvasPainter::xFormDev(const QPoint& point) const +{ + return m_painter.xFormDev(point); +} + +QRect KisQPaintDeviceCanvasPainter::xFormDev(const QRect& r) const +{ + return m_painter.xFormDev(r); +} + +QPointArray KisQPaintDeviceCanvasPainter::xFormDev(const QPointArray& pointArray) const +{ + return m_painter.xFormDev(pointArray); +} + +QPointArray KisQPaintDeviceCanvasPainter::xFormDev(const QPointArray& pointArray, int index, int npoints) const +{ + return m_painter.xFormDev(pointArray, index, npoints); +} + +void KisQPaintDeviceCanvasPainter::setClipping(bool enable) +{ + m_painter.setClipping(enable); +} + +bool KisQPaintDeviceCanvasPainter::hasClipping() const +{ + return m_painter.hasClipping(); +} + +QRegion KisQPaintDeviceCanvasPainter::clipRegion(QPainter::CoordinateMode mode) const +{ + return m_painter.clipRegion(mode); +} + +void KisQPaintDeviceCanvasPainter::setClipRect(const QRect& r, QPainter::CoordinateMode mode) +{ + m_painter.setClipRect(r, mode); +} + +void KisQPaintDeviceCanvasPainter::setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode mode) +{ + m_painter.setClipRect(x, y, w, h, mode); +} + +void KisQPaintDeviceCanvasPainter::setClipRegion(const QRegion& rgn, QPainter::CoordinateMode mode) +{ + m_painter.setClipRegion(rgn, mode); +} + +void KisQPaintDeviceCanvasPainter::drawPoint(int x, int y) +{ + m_painter.drawPoint(x, y); +} + +void KisQPaintDeviceCanvasPainter::drawPoint(const QPoint& point) +{ + m_painter.drawPoint(point); +} + +void KisQPaintDeviceCanvasPainter::drawPoints(const QPointArray& pointArray, int index, int npoints) +{ + m_painter.drawPoints(pointArray, index, npoints); +} + +void KisQPaintDeviceCanvasPainter::moveTo(int x, int y) +{ + m_painter.moveTo(x, y); +} + +void KisQPaintDeviceCanvasPainter::moveTo(const QPoint& point) +{ + m_painter.moveTo(point); +} + +void KisQPaintDeviceCanvasPainter::lineTo(int x, int y) +{ + m_painter.lineTo(x, y); +} + +void KisQPaintDeviceCanvasPainter::lineTo(const QPoint& point) +{ + m_painter.lineTo(point); +} + +void KisQPaintDeviceCanvasPainter::drawLine(int x1, int y1, int x2, int y2) +{ + m_painter.drawLine(x1, y1, x2, y2); +} + +void KisQPaintDeviceCanvasPainter::drawLine(const QPoint& start, const QPoint& end) +{ + m_painter.drawLine(start, end); +} + +void KisQPaintDeviceCanvasPainter::drawRect(int x, int y, int w, int h) +{ + m_painter.drawRect(x, y, w, h); +} + +void KisQPaintDeviceCanvasPainter::drawRect(const QRect& r) +{ + m_painter.drawRect(r); +} + +void KisQPaintDeviceCanvasPainter::drawWinFocusRect(int x, int y, int w, int h) +{ + m_painter.drawWinFocusRect(x, y, w, h); +} + +void KisQPaintDeviceCanvasPainter::drawWinFocusRect(int x, int y, int w, int h, const QColor& bgColor) +{ + m_painter.drawWinFocusRect(x, y, w, h, bgColor); +} + +void KisQPaintDeviceCanvasPainter::drawWinFocusRect(const QRect& r) +{ + m_painter.drawWinFocusRect(r); +} + +void KisQPaintDeviceCanvasPainter::drawWinFocusRect(const QRect& r, const QColor& bgColor) +{ + m_painter.drawWinFocusRect(r, bgColor); +} + +void KisQPaintDeviceCanvasPainter::drawRoundRect(int x, int y, int w, int h, int xRnd, int yRnd) +{ + m_painter.drawRoundRect(x, y, w, h, xRnd, yRnd); +} + +void KisQPaintDeviceCanvasPainter::drawRoundRect(const QRect& r, int xRnd, int yRnd) +{ + m_painter.drawRoundRect(r, xRnd, yRnd); +} + +void KisQPaintDeviceCanvasPainter::drawEllipse(int x, int y, int w, int h) +{ + m_painter.drawEllipse(x, y, w, h); +} + +void KisQPaintDeviceCanvasPainter::drawEllipse(const QRect& r) +{ + m_painter.drawEllipse(r); +} + +void KisQPaintDeviceCanvasPainter::drawArc(int x, int y, int w, int h, int a, int alen) +{ + m_painter.drawArc(x, y, w, h, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawArc(const QRect& r, int a, int alen) +{ + m_painter.drawArc(r, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawPie(int x, int y, int w, int h, int a, int alen) +{ + m_painter.drawPie(x, y, w, h, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawPie(const QRect& r, int a, int alen) +{ + m_painter.drawPie(r, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawChord(int x, int y, int w, int h, int a, int alen) +{ + m_painter.drawChord(x, y, w, h, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawChord(const QRect& r, int a, int alen) +{ + m_painter.drawChord(r, a, alen); +} + +void KisQPaintDeviceCanvasPainter::drawLineSegments(const QPointArray& pointArray, int index, int nlines) +{ + m_painter.drawLineSegments(pointArray, index, nlines); +} + +void KisQPaintDeviceCanvasPainter::drawPolyline(const QPointArray& pointArray, int index, int npoints) +{ + m_painter.drawPolyline(pointArray, index, npoints); +} + +void KisQPaintDeviceCanvasPainter::drawPolygon(const QPointArray& pointArray, bool winding, int index, int npoints) +{ + m_painter.drawPolygon(pointArray, winding, index, npoints); +} + +void KisQPaintDeviceCanvasPainter::drawConvexPolygon(const QPointArray& pointArray, int index, int npoints) +{ + m_painter.drawConvexPolygon(pointArray, index, npoints); +} + +void KisQPaintDeviceCanvasPainter::drawCubicBezier(const QPointArray& pointArray, int index) +{ + m_painter.drawCubicBezier(pointArray, index); +} + +void KisQPaintDeviceCanvasPainter::drawPixmap(int x, int y, const QPixmap& pixmap, int sx, int sy, int sw, int sh) +{ + m_painter.drawPixmap(x, y, pixmap, sx, sy, sw, sh); +} + +void KisQPaintDeviceCanvasPainter::drawPixmap(const QPoint& point, const QPixmap& pixmap, const QRect& sr) +{ + m_painter.drawPixmap(point, pixmap, sr); +} + +void KisQPaintDeviceCanvasPainter::drawPixmap(const QPoint& point, const QPixmap& pixmap) +{ + m_painter.drawPixmap(point, pixmap); +} + +void KisQPaintDeviceCanvasPainter::drawPixmap(const QRect& r, const QPixmap& pixmap) +{ + m_painter.drawPixmap(r, pixmap); +} + +void KisQPaintDeviceCanvasPainter::drawImage(int x, int y, const QImage& image, int sx, int sy, int sw, int sh, int conversionFlags) +{ + m_painter.drawImage(x, y, image, sx, sy, sw, sh, conversionFlags); +} + +void KisQPaintDeviceCanvasPainter::drawImage(const QPoint& point, const QImage& image, const QRect& sr, int conversionFlags) +{ + m_painter.drawImage(point, image, sr, conversionFlags); +} + +void KisQPaintDeviceCanvasPainter::drawImage(const QPoint& point, const QImage& image, int conversion_flags) +{ + m_painter.drawImage(point, image, conversion_flags); +} + +void KisQPaintDeviceCanvasPainter::drawImage(const QRect& r, const QImage& image) +{ + m_painter.drawImage(r, image); +} + +void KisQPaintDeviceCanvasPainter::drawTiledPixmap(int x, int y, int w, int h, const QPixmap& pixmap, int sx, int sy) +{ + m_painter.drawTiledPixmap(x, y, w, h, pixmap, sx, sy); +} + +void KisQPaintDeviceCanvasPainter::drawTiledPixmap(const QRect& r, const QPixmap& pixmap, const QPoint& point) +{ + m_painter.drawTiledPixmap(r, pixmap, point); +} + +void KisQPaintDeviceCanvasPainter::drawTiledPixmap(const QRect& r, const QPixmap& pixmap) +{ + m_painter.drawTiledPixmap(r, pixmap); +} + +void KisQPaintDeviceCanvasPainter::fillRect(int x, int y, int w, int h, const QBrush& brush) +{ + m_painter.fillRect(x, y, w, h, brush); +} + +void KisQPaintDeviceCanvasPainter::fillRect(const QRect& r, const QBrush& brush) +{ + m_painter.fillRect(r, brush); +} + +void KisQPaintDeviceCanvasPainter::eraseRect(int x, int y, int w, int h) +{ + m_painter.eraseRect(x, y, w, h); +} + +void KisQPaintDeviceCanvasPainter::eraseRect(const QRect& r) +{ + m_painter.eraseRect(r); +} + +void KisQPaintDeviceCanvasPainter::drawText(int x, int y, const QString& text, int len, QPainter::TextDirection dir) +{ + m_painter.drawText(x, y, text, len, dir); +} + +void KisQPaintDeviceCanvasPainter::drawText(const QPoint& point, const QString& text, int len, QPainter::TextDirection dir) +{ + m_painter.drawText(point, text, len, dir); +} + +void KisQPaintDeviceCanvasPainter::drawText(int x, int y, const QString& text, int pos, int len, QPainter::TextDirection dir) +{ + m_painter.drawText(x, y, text, pos, len, dir); +} + +void KisQPaintDeviceCanvasPainter::drawText(const QPoint& point, const QString& text, int pos, int len, QPainter::TextDirection dir) +{ + m_painter.drawText(point, text, pos, len, dir); +} + +void KisQPaintDeviceCanvasPainter::drawText(int x, int y, int w, int h, int flags, const QString& text, int len, QRect *br, QTextParag **intern) +{ + m_painter.drawText(x, y, w, h, flags, text, len, br, intern); +} + +void KisQPaintDeviceCanvasPainter::drawText(const QRect& r, int flags, const QString& text, int len, QRect *br, QTextParag **intern) +{ + m_painter.drawText(r, flags, text, len, br, intern); +} + +void KisQPaintDeviceCanvasPainter::drawTextItem(int x, int y, const QTextItem& ti, int textflags) +{ + m_painter.drawTextItem(x, y, ti, textflags); +} + +void KisQPaintDeviceCanvasPainter::drawTextItem(const QPoint& p, const QTextItem& ti, int textflags) +{ + m_painter.drawTextItem(p, ti, textflags); +} + +QRect KisQPaintDeviceCanvasPainter::boundingRect(int x, int y, int w, int h, int flags, const QString& text, int len, QTextParag **intern) +{ + return m_painter.boundingRect(x, y, w, h, flags, text, len, intern); +} + +QRect KisQPaintDeviceCanvasPainter::boundingRect(const QRect& r, int flags, const QString& text, int len, QTextParag **intern) +{ + return m_painter.boundingRect(r, flags, text, len, intern); +} + +int KisQPaintDeviceCanvasPainter::tabStops() const +{ + return m_painter.tabStops(); +} + +void KisQPaintDeviceCanvasPainter::setTabStops(int ts) +{ + m_painter.setTabStops(ts); +} + +int *KisQPaintDeviceCanvasPainter::tabArray() const +{ + return m_painter.tabArray(); +} + +void KisQPaintDeviceCanvasPainter::setTabArray(int *ts) +{ + m_painter.setTabArray(ts); +} + + diff --git a/krita/ui/kis_qpaintdevice_canvas_painter.h b/krita/ui/kis_qpaintdevice_canvas_painter.h new file mode 100644 index 000000000..ddc306f18 --- /dev/null +++ b/krita/ui/kis_qpaintdevice_canvas_painter.h @@ -0,0 +1,189 @@ +/* + * Copyright (c) 2005 Adrian Page <adrian@pagenet.plus.com> + * + * 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_QPAINTDEVICE_CANVAS_PAINTER_H_ +#define KIS_QPAINTDEVICE_CANVAS_PAINTER_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <qwidget.h> +#include <qpainter.h> + +#include "kis_global.h" +#include "kis_canvas_painter.h" + +class KisQPaintDeviceCanvasPainter : public KisCanvasWidgetPainter { +public: + KisQPaintDeviceCanvasPainter(); + KisQPaintDeviceCanvasPainter(const QPaintDevice *paintDevice); + virtual ~KisQPaintDeviceCanvasPainter(); + + bool begin(const QPaintDevice* paintDevice, bool unclipped = false); + + virtual bool begin(KisCanvasWidget *canvasWidget, bool unclipped = false); + virtual bool end(); + + virtual void save(); + virtual void restore(); + + virtual QFontMetrics fontMetrics() const; + virtual QFontInfo fontInfo() const; + + virtual const QFont& font() const; + virtual void setFont(const QFont&); + virtual const QPen& pen() const; + virtual void setPen(const QPen&); + virtual void setPen(Qt::PenStyle); + virtual void setPen(const QColor&); + virtual const QBrush&brush() const; + virtual void setBrush(const QBrush&); + virtual void setBrush(Qt::BrushStyle); + virtual void setBrush(const QColor&); + virtual QPoint pos() const; + + virtual const QColor&backgroundColor() const; + virtual void setBackgroundColor(const QColor&); + virtual Qt::BGMode backgroundMode() const; + virtual void setBackgroundMode(Qt::BGMode); + virtual Qt::RasterOp rasterOp() const; + virtual void setRasterOp(Qt::RasterOp); + virtual const QPoint&brushOrigin() const; + virtual void setBrushOrigin(int x, int y); + virtual void setBrushOrigin(const QPoint&); + + virtual bool hasViewXForm() const; + virtual bool hasWorldXForm() const; + + virtual void setViewXForm(bool); + virtual QRect window() const; + virtual void setWindow(const QRect&); + virtual void setWindow(int x, int y, int w, int h); + virtual QRect viewport() const; + virtual void setViewport(const QRect&); + virtual void setViewport(int x, int y, int w, int h); + + virtual void setWorldXForm(bool); + virtual const QWMatrix&worldMatrix() const; + virtual void setWorldMatrix(const QWMatrix&, bool combine=FALSE); + + virtual void saveWorldMatrix(); + virtual void restoreWorldMatrix(); + + virtual void scale(double sx, double sy); + virtual void shear(double sh, double sv); + virtual void rotate(double a); + + virtual void translate(double dx, double dy); + virtual void resetXForm(); + virtual double translationX() const; + virtual double translationY() const; + + virtual QPoint xForm(const QPoint&) const; + virtual QRect xForm(const QRect&) const; + virtual QPointArray xForm(const QPointArray&) const; + virtual QPointArray xForm(const QPointArray&, int index, int npoints) const; + virtual QPoint xFormDev(const QPoint&) const; + virtual QRect xFormDev(const QRect&) const; + virtual QPointArray xFormDev(const QPointArray&) const; + virtual QPointArray xFormDev(const QPointArray&, int index, int npoints) const; + + virtual void setClipping(bool); + virtual bool hasClipping() const; + virtual QRegion clipRegion(QPainter::CoordinateMode = QPainter::CoordDevice) const; + virtual void setClipRect(const QRect&, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRect(int x, int y, int w, int h, QPainter::CoordinateMode = QPainter::CoordDevice); + virtual void setClipRegion(const QRegion&, QPainter::CoordinateMode = QPainter::CoordDevice); + + virtual void drawPoint(int x, int y); + virtual void drawPoint(const QPoint&); + virtual void drawPoints(const QPointArray& a, int index=0, int npoints=-1); + virtual void moveTo(int x, int y); + virtual void moveTo(const QPoint&); + virtual void lineTo(int x, int y); + virtual void lineTo(const QPoint&); + virtual void drawLine(int x1, int y1, int x2, int y2); + virtual void drawLine(const QPoint&, const QPoint&); + virtual void drawRect(int x, int y, int w, int h); + virtual void drawRect(const QRect&); + virtual void drawWinFocusRect(int x, int y, int w, int h); + virtual void drawWinFocusRect(int x, int y, int w, int h, const QColor&bgColor); + virtual void drawWinFocusRect(const QRect&); + virtual void drawWinFocusRect(const QRect&, const QColor&bgColor); + virtual void drawRoundRect(int x, int y, int w, int h, int = 25, int = 25); + virtual void drawRoundRect(const QRect&, int = 25, int = 25); + virtual void drawEllipse(int x, int y, int w, int h); + virtual void drawEllipse(const QRect&); + virtual void drawArc(int x, int y, int w, int h, int a, int alen); + virtual void drawArc(const QRect&, int a, int alen); + virtual void drawPie(int x, int y, int w, int h, int a, int alen); + virtual void drawPie(const QRect&, int a, int alen); + virtual void drawChord(int x, int y, int w, int h, int a, int alen); + virtual void drawChord(const QRect&, int a, int alen); + virtual void drawLineSegments(const QPointArray&, int index=0, int nlines=-1); + virtual void drawPolyline(const QPointArray&, int index=0, int npoints=-1); + virtual void drawPolygon(const QPointArray&, bool winding=FALSE, int index=0, int npoints=-1); + virtual void drawConvexPolygon(const QPointArray&, int index=0, int npoints=-1); + virtual void drawCubicBezier(const QPointArray&, int index=0); + virtual void drawPixmap(int x, int y, const QPixmap&, int sx=0, int sy=0, int sw=-1, int sh=-1); + virtual void drawPixmap(const QPoint&, const QPixmap&, const QRect&sr); + virtual void drawPixmap(const QPoint&, const QPixmap&); + virtual void drawPixmap(const QRect&, const QPixmap&); + virtual void drawImage(int x, int y, const QImage&, int sx = 0, int sy = 0, int sw = -1, int sh = -1, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, const QRect&sr, int conversionFlags = 0); + virtual void drawImage(const QPoint&, const QImage&, int conversion_flags = 0); + virtual void drawImage(const QRect&, const QImage&); + virtual void drawTiledPixmap(int x, int y, int w, int h, const QPixmap&, int sx=0, int sy=0); + virtual void drawTiledPixmap(const QRect&, const QPixmap&, const QPoint&); + virtual void drawTiledPixmap(const QRect&, const QPixmap&); + //virtual void drawPicture(const QPicture&); + //virtual void drawPicture(int x, int y, const QPicture&); + //virtual void drawPicture(const QPoint&, const QPicture&); + + virtual void fillRect(int x, int y, int w, int h, const QBrush&); + virtual void fillRect(const QRect&, const QBrush&); + virtual void eraseRect(int x, int y, int w, int h); + virtual void eraseRect(const QRect&); + + virtual void drawText(int x, int y, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&, const QString&, int len = -1, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + virtual void drawText(const QPoint&p, const QString&, int pos, int len, QPainter::TextDirection dir = QPainter::Auto); + + virtual void drawText(int x, int y, int w, int h, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + virtual void drawText(const QRect&, int flags, const QString&, int len = -1, QRect *br=0, QTextParag **intern=0); + + virtual void drawTextItem(int x, int y, const QTextItem&ti, int textflags = 0); + virtual void drawTextItem(const QPoint& p, const QTextItem&ti, int textflags = 0); + + virtual QRect boundingRect(int x, int y, int w, int h, int flags, const QString&, int len = -1, QTextParag **intern=0); + virtual QRect boundingRect(const QRect&, int flags, const QString&, int len = -1, QTextParag **intern=0); + + virtual int tabStops() const; + virtual void setTabStops(int); + virtual int *tabArray() const; + virtual void setTabArray(int *); + +protected: + QPainter m_painter; +}; + +#endif // KIS_QPAINTDEVICE_CANVAS_PAINTER_H_ + diff --git a/krita/ui/kis_resource_mediator.cc b/krita/ui/kis_resource_mediator.cc new file mode 100644 index 000000000..e4040cd2b --- /dev/null +++ b/krita/ui/kis_resource_mediator.cc @@ -0,0 +1,117 @@ +/* + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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 <koIconChooser.h> + +#include "kdebug.h" + +#include "kis_icon_item.h" +#include "kis_resource.h" +#include "kis_itemchooser.h" +#include "kis_resourceserver.h" +#include "kis_resource_mediator.h" + +KisResourceMediator::KisResourceMediator(KisItemChooser *chooser, + QObject *parent, + const char *name) : super(parent, name), m_chooser(chooser) +{ + Q_ASSERT(chooser); + m_activeItem = 0; + + connect(m_chooser, SIGNAL(selected(KoIconItem*)), SLOT(setActiveItem(KoIconItem*))); +} + +KisResourceMediator::~KisResourceMediator() +{ +} + +void KisResourceMediator::connectServer(KisResourceServerBase* rServer) +{ + // Add the initially loaded items + QValueList<KisResource*> resources = rServer->resources(); + QValueList<KisResource*>::iterator it; + for ( it = resources.begin(); it != resources.end(); ++it ) + rServerAddedResource( *it ); + + // And connect to the server permanently, so that we may recieve updates afterwards + connect(rServer, SIGNAL(resourceAdded(KisResource*)), + this, SLOT(rServerAddedResource(KisResource*))); +} + +KisResource *KisResourceMediator::currentResource() const +{ + if (m_activeItem) { + Q_ASSERT(dynamic_cast<KisIconItem*>(m_activeItem)); + return static_cast<KisIconItem*>(m_activeItem)->resource(); + } + + return 0; +} + +KisIconItem *KisResourceMediator::itemFor(KisResource *r) const +{ + if(m_items.contains(r)) + { + return m_items[r]; + } + return 0; +} + +KisResource *KisResourceMediator::resourceFor(KoIconItem *item) const +{ + KisIconItem *kisitem = dynamic_cast<KisIconItem*>(item); + + return kisitem ? kisitem->resource() : 0; +} + +KisResource *KisResourceMediator::resourceFor(KisIconItem *item) const +{ + return item ? item->resource() : 0; +} + +QWidget *KisResourceMediator::chooserWidget() const +{ + return m_chooser; +} + +void KisResourceMediator::setActiveItem(KoIconItem *item) +{ + KisIconItem *kisitem = dynamic_cast<KisIconItem*>(item); + + if (kisitem) { + m_activeItem = kisitem; + m_chooser->setCurrent(item); + emit activatedResource(kisitem ? kisitem->resource() : 0); + } +} + +void KisResourceMediator::rServerAddedResource(KisResource *resource) +{ + if (resource && resource->valid()) { + + KisIconItem *item = new KisIconItem(resource); + Q_CHECK_PTR(item); + + m_items[resource] = item; + + m_chooser->addItem(item); + if (m_activeItem == 0) setActiveItem(item); + } +} + +#include "kis_resource_mediator.moc" + diff --git a/krita/ui/kis_resource_mediator.h b/krita/ui/kis_resource_mediator.h new file mode 100644 index 000000000..55623a6e0 --- /dev/null +++ b/krita/ui/kis_resource_mediator.h @@ -0,0 +1,72 @@ +/* + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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_RESOURCE_MEDIATOR_H_ +#define KIS_RESOURCE_MEDIATOR_H_ + +#include <qobject.h> +#include <qmap.h> +#include <qwidget.h> + +class KoIconItem; +class KisItemChooser; +class KisIconItem; +class KisResource; +class KisResourceServerBase; + +/** + * A resource mediator manages access to resources like + * gradients. brushes, patterns and palettes. + * For every view, a new resource mediator is created for every + * resource type. + */ +class KisResourceMediator : public QObject { + Q_OBJECT + typedef QObject super; + +public: + KisResourceMediator(KisItemChooser *chooser, + QObject *parent = 0, + const char *name = 0); + virtual ~KisResourceMediator(); + +public: + void connectServer(KisResourceServerBase* rServer); + KisResource *currentResource() const; + KisIconItem *itemFor(KisResource *r) const; + KisResource *resourceFor(KoIconItem *item) const; + KisResource *resourceFor(KisIconItem *item) const; + QWidget *chooserWidget() const; + +public slots: + + void setActiveItem(KoIconItem *item); + +signals: + void activatedResource(KisResource *r); + +private slots: + void rServerAddedResource(KisResource *resource); + +private: + KisItemChooser *m_chooser; + QMap<KisResource*, KisIconItem*> m_items; + KoIconItem *m_activeItem; +}; + +#endif // KIS_RESOURCE_MEDIATOR_H_ + diff --git a/krita/ui/kis_resourceserver.cc b/krita/ui/kis_resourceserver.cc new file mode 100644 index 000000000..c72f9b80e --- /dev/null +++ b/krita/ui/kis_resourceserver.cc @@ -0,0 +1,199 @@ +/* + * kis_resourceserver.cc - part of KImageShop + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de> + * + * 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 <qfileinfo.h> +#include <qstringlist.h> +#include <qthread.h> +#include <qdir.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kstandarddirs.h> +#include <kinstance.h> + +#include "kis_resource.h" +#include "kis_factory.h" +#include "kis_generic_registry.h" +#include "kis_resourceserver.h" +#include "kis_brush.h" +#include "kis_imagepipe_brush.h" +#include "kis_gradient.h" +#include "kis_pattern.h" +#include "kis_palette.h" +#include <kogradientmanager.h> + +KisResourceServerBase::KisResourceServerBase(QString type) + : m_type(type), m_loaded(false) +{ +} + +KisResourceServerBase::~KisResourceServerBase() +{ +} + +void KisResourceServerBase::loadResources(QStringList filenames) +{ + QStringList uniqueFiles; + + while( !filenames.empty() ) + { + + QString front = *filenames.begin(); + filenames.pop_front(); + + QString fname = QFileInfo(front).fileName(); + //ebug() << "Loading " << fname << "\n"; + // 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.find(fname) == uniqueFiles.end()) { + uniqueFiles.append(fname); + KisResource *resource; + resource = createResource(front); + if(resource->load() && resource->valid()) + { + m_resources.append(resource); + Q_CHECK_PTR(resource); + emit resourceAdded(resource); + } + else { + delete resource; + } + } + } + m_loaded = true; +} + +QValueList<KisResource*> KisResourceServerBase::resources() +{ + if(!m_loaded) { + return QValueList<KisResource*>(); + } + + return m_resources; +} + +void KisResourceServerBase::addResource(KisResource* resource) +{ + if (!resource->valid()) { + kdWarning(41001) << "Tried to add an invalid resource!" << endl; + return; + } + + m_resources.append(resource); + emit resourceAdded(resource); +} + + +class ResourceLoaderThread : public QThread { + +public: + + ResourceLoaderThread(KisResourceServerBase * server, QStringList files) + : QThread() + , m_server(server) + , m_fileNames( files ) + { + } + + + void run() + { + m_server->loadResources(m_fileNames); + } + +private: + + KisResourceServerBase * m_server; + QStringList m_fileNames; + +}; + +QStringList getFileNames( QString extensions, QString type ) +{ + QStringList extensionList = QStringList::split(":", extensions); + QStringList fileNames; + + QStringList::Iterator it; + for ( it = extensionList.begin(); it != extensionList.end(); ++it ) { + QString s = (*it); + fileNames += KisFactory::instance()->dirs()->findAllResources(type.ascii(), (*it)); + } + return fileNames; +} + + +KisResourceServerRegistry *KisResourceServerRegistry::m_singleton = 0; + +KisResourceServerRegistry::KisResourceServerRegistry() +{ + + KisResourceServer<KisBrush>* brushServer = new KisResourceServer<KisBrush>("kis_brushes"); + ResourceLoaderThread t1 (brushServer, getFileNames( "*.gbr","kis_brushes" )); + t1.start(); + + KisResourceServer<KisImagePipeBrush>* imagePipeBrushServer = new KisResourceServer<KisImagePipeBrush>("kis_brushes"); + ResourceLoaderThread t2 (imagePipeBrushServer, getFileNames( "*.gih", "kis_brushes")); + t2.start(); + + KisResourceServer<KisPattern>* patternServer = new KisResourceServer<KisPattern>("kis_patterns"); + ResourceLoaderThread t3 (patternServer, getFileNames("*.pat", "kis_patterns")); + t3.start(); + + KisResourceServer<KisGradient>* gradientServer = new KisResourceServer<KisGradient>("kis_gradients"); + ResourceLoaderThread t4 (gradientServer, getFileNames(KoGradientManager::filters().join( ":" ), "kis_gradients")); + t4.start(); + + + KisResourceServer<KisPalette>* paletteServer = new KisResourceServer<KisPalette>("kis_palettes"); + ResourceLoaderThread t5 (paletteServer, getFileNames("*.gpl:*.pal:*.act", "kis_palettes") ); + t5.start(); + + t1.wait(); + t2.wait(); + t3.wait(); + t4.wait(); + t5.wait(); + + add( KisID( "BrushServer", ""), brushServer ); + add( KisID( "ImagePipeBrushServer", ""), imagePipeBrushServer ); + add( KisID( "PatternServer", ""), patternServer ); + add( KisID( "GradientServer", ""), gradientServer ); + add( KisID( "PaletteServer", ""), paletteServer ); + +} + +KisResourceServerRegistry::~KisResourceServerRegistry() +{ +} + +KisResourceServerRegistry* KisResourceServerRegistry::instance() +{ + if(KisResourceServerRegistry::m_singleton == 0) + { + KisResourceServerRegistry::m_singleton = new KisResourceServerRegistry(); + } + return KisResourceServerRegistry::m_singleton; +} + + +#include "kis_resourceserver.moc" + diff --git a/krita/ui/kis_resourceserver.h b/krita/ui/kis_resourceserver.h new file mode 100644 index 000000000..aa15f72e0 --- /dev/null +++ b/krita/ui/kis_resourceserver.h @@ -0,0 +1,90 @@ +/* + * kis_resourceserver.h - part of KImageShop + * + * Copyright (c) 1999 Matthias Elter <elter@kde.org> + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2005 Sven Langkamp <longamp@reallygood.de> + * + * 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_RESOURCESERVER_H_ +#define KIS_RESOURCESERVER_H_ + +#include <qstring.h> +#include <qstringlist.h> + +#include "kis_generic_registry.h" + +class KisResource; + +class KisResourceServerBase : public QObject { + Q_OBJECT +public: + KisResourceServerBase(QString type); + virtual ~KisResourceServerBase(); + + void loadResources(QStringList filenames); + /// Adds an already loaded resource to the server + void addResource(KisResource* resource); + QValueList<KisResource*> resources(); + QString type() { return m_type; }; + +signals: + void resourceAdded(KisResource*); + +protected: + virtual KisResource* createResource( QString filename ) = 0; + +private: + QValueList<KisResource*> m_resources; + QString m_type; + + bool m_loaded; + +}; + + +template <class T> class KisResourceServer : public KisResourceServerBase { + typedef KisResourceServerBase super; + +public: + KisResourceServer(QString type) :super( type ) {} + virtual ~KisResourceServer(){} + +private: + KisResource* createResource( QString filename ){return new T(filename);} +}; + + + + +class KisResourceServerRegistry : public KisGenericRegistry<KisResourceServerBase*> +{ + +public: + virtual ~KisResourceServerRegistry(); + + static KisResourceServerRegistry* instance(); + +private: + KisResourceServerRegistry(); + KisResourceServerRegistry(const KisResourceServerRegistry&); + KisResourceServerRegistry operator=(const KisResourceServerRegistry&); + + static KisResourceServerRegistry *m_singleton; +}; + + +#endif // KIS_RESOURCESERVER_H_ diff --git a/krita/ui/kis_ruler.cc b/krita/ui/kis_ruler.cc new file mode 100644 index 000000000..1da94b154 --- /dev/null +++ b/krita/ui/kis_ruler.cc @@ -0,0 +1,367 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000-2001 theKompany.com & Dave Marotti + * Copyright (C) 2002 Patrick Julien <freak@codepimps.org> + * + * 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 <qpainter.h> +#include <qstyle.h> + +#include "kdebug.h" + +#include "kis_ruler.h" + +#define MARKER_WIDTH 1 +#define MARKER_HEIGHT RULER_THICKNESS + +const char *KisRuler::m_nums[] = { + "70 7 2 1", + " c Black", + "X c None", + "XX XXXXXX XXXX XXXX XXXXXX XXX XXXX XXX XXX XXXX XX", + "X XXX XXXX XXX XXX XX XXX XXXX XXX XXXXXXX XXXXXXXXX XX XXX XX XXX X", + "X XXX XXXXX XXXXXXX XXXXXX XXX X XXX XXXXXX XXXXXXXXX XXX XXX XX XXX X", + "X XXX XXXXX XXXXX XXXXX XXX XX XXX XXX XXXXXX XXXX XXXX X", + "X XXX XXXXX XXXX XXXXXXXXX XX XXXXXX XX XXX XXXX XXXX XXX XXXXXX X", + "X XXX XXXXX XXX XXXXXX XXX XXXXX XXXXXXX XX XXX XXXX XXXX XXX XXXXX XX", + "XX XXXXXX XXX XXX XXXXXX XXX XXXX XXXXX XXXXX XXXX XXX" +}; + +KisRuler::KisRuler(Qt::Orientation o, QWidget *parent, const char *name) : super(parent, name, WRepaintNoErase | WResizeNoErase), m_pixmapNums(m_nums) +{ + setBackgroundMode(NoBackground); + setFrameStyle(Box | Sunken); + setLineWidth(1); + setMidLineWidth(0); + m_orientation = o; + m_unit = KoUnit::U_PT; + m_zoom = 1.0; + m_firstVisible = 0; + m_pixmapBuffer = 0; + m_currentPosition = -1; + + if (m_orientation == Qt::Horizontal) { + setFixedHeight(RULER_THICKNESS); + initMarker(MARKER_WIDTH, MARKER_HEIGHT); + } else { + setFixedWidth(RULER_THICKNESS); + initMarker(MARKER_HEIGHT, MARKER_WIDTH); + } +} + +KisRuler::~KisRuler() +{ + delete m_pixmapBuffer; +} + +void KisRuler::initMarker(Q_INT32 w, Q_INT32 h) +{ + QPainter p; + + m_pixmapMarker.resize(w, h); + p.begin(&m_pixmapMarker); + p.setPen(blue); + p.eraseRect(0, 0, w, h); + p.drawLine(0, 0, w - 1, h - 1); + p.end(); +} + +void KisRuler::recalculateSize() +{ + Q_INT32 w; + Q_INT32 h; + + if (m_pixmapBuffer) { + delete m_pixmapBuffer; + m_pixmapBuffer = 0; + } + + if (m_orientation == Qt::Horizontal) { + w = width(); + h = RULER_THICKNESS; + } else { + w = RULER_THICKNESS; + h = height(); + } + + m_pixmapBuffer = new QPixmap(w, h); + Q_CHECK_PTR(m_pixmapBuffer); + + drawRuler(); + updatePointer(m_currentPosition, m_currentPosition); +} + +KoUnit::Unit KisRuler::unit() const +{ + return m_unit; +} + +void KisRuler::setUnit(KoUnit::Unit u) +{ + m_unit = u; + drawRuler(); + updatePointer(m_currentPosition, m_currentPosition); + update(); +} + +void KisRuler::setZoom(double zoom) +{ + m_zoom = zoom; + recalculateSize(); + drawRuler(); + updatePointer(m_currentPosition, m_currentPosition); + update(); +} + +void KisRuler::updatePointer(Q_INT32 x, Q_INT32 y) +{ + if (m_pixmapBuffer) { + if (m_orientation == Qt::Horizontal) { + if (m_currentPosition != -1) + repaint(m_currentPosition, 1, MARKER_WIDTH, MARKER_HEIGHT); + + if (x != -1) { + bitBlt(this, x, 1, &m_pixmapMarker, 0, 0, MARKER_WIDTH, MARKER_HEIGHT); + m_currentPosition = x; + } + } else { + if (m_currentPosition != -1) + repaint(1, m_currentPosition, MARKER_HEIGHT, MARKER_WIDTH); + + if (y != -1) { + bitBlt(this, 1, y, &m_pixmapMarker, 0, 0, MARKER_HEIGHT, MARKER_WIDTH); + m_currentPosition = y; + } + } + } +} + +void KisRuler::updateVisibleArea(Q_INT32 xpos, Q_INT32 ypos) +{ + if (m_orientation == Qt::Horizontal) + m_firstVisible = xpos; + else + m_firstVisible = ypos; + + drawRuler(); + update(); + updatePointer(m_currentPosition, m_currentPosition); +} + +void KisRuler::paintEvent(QPaintEvent *e) +{ + if (m_pixmapBuffer) { + const QRect& rect = e->rect(); + + bitBlt(this, rect.topLeft(), m_pixmapBuffer, rect); + super::paintEvent(e); + } +} + +void KisRuler::drawRuler() +{ + QPainter p; + QString buf; + Q_INT32 st1 = 0; + Q_INT32 st2 = 0; + Q_INT32 st3 = 0; + Q_INT32 st4 = 0; + + if (!m_pixmapBuffer) + return; + + p.begin(m_pixmapBuffer); + p.setPen(colorGroup().text()); + p.setBackgroundColor(colorGroup().base()); + p.eraseRect(0, 0, m_pixmapBuffer->width(), m_pixmapBuffer->height()); + + switch (m_unit) { + case KoUnit::U_PT: + case KoUnit::U_MM: + case KoUnit::U_DD: + case KoUnit::U_CC: + st1 = 1; + st2 = 5; + st3 = 10; + st4 = 25; + break; + case KoUnit::U_CM: + case KoUnit::U_PI: + case KoUnit::U_INCH: + default: + st1 = 1; + st2 = 2; + st3 = 5; + st4 = 10; + } + + bool s1 = KoUnit::fromUserValue(st1, m_unit) * m_zoom > 3.0; + bool s2 = KoUnit::fromUserValue(st2, m_unit) * m_zoom > 3.0; + bool s3 = KoUnit::fromUserValue(st3, m_unit) * m_zoom > 3.0; + bool s4 = KoUnit::fromUserValue(st4, m_unit) * m_zoom > 3.0; + + float cx = KoUnit::fromUserValue(100, m_unit) / m_zoom; + Q_INT32 step = qRound(cx); + + if (step < 5) { + step = 1; + } else if (step < 10) { + step = 5; + } else if (step < 25) { + step = 10; + } else if (step < 50) { + step = 25; + } else if (step < 100) { + step = 50; + } else if (step < 250) { + step = 100; + } else if (step < 500) { + step = 250; + } else if (step < 1000) { + step = 500; + } else if (step < 2500) { + step = 1000; + } else if (step < 5000) { + step = 2500; + } else if (step < 10000) { + step = 5000; + } else if (step < 25000) { + step = 10000; + } else if (step < 50000) { + step = 25000; + } else if (step < 100000) { + step = 50000; + } else { + step = 100000; + } + + Q_INT32 start = (Q_INT32)(KoUnit::fromUserValue(m_firstVisible, m_unit) / m_zoom); + Q_INT32 pos = 0; + + if (m_orientation == Qt::Horizontal) { + do { + pos = (Q_INT32)(KoUnit::fromUserValue(start, m_unit) * m_zoom - m_firstVisible); + + if (!s3 && s4 && start % st4 == 0) + p.drawLine(pos, RULER_THICKNESS - 9, pos, RULER_THICKNESS); + + if (s3 && start % st3 == 0) + p.drawLine(pos, RULER_THICKNESS - 9, pos, RULER_THICKNESS); + + if (s2 && start % st2 == 0) + p.drawLine(pos, RULER_THICKNESS - 7, pos, RULER_THICKNESS); + + if (s1 && start % st1 == 0) + p.drawLine(pos, RULER_THICKNESS - 5, pos, RULER_THICKNESS); + + if (start % step == 0) { + buf.setNum(QABS(start)); + drawNums(&p, pos, 4, buf, true); + } + + start++; + } while (pos < m_pixmapBuffer->width()); + } else { + do { + pos = (Q_INT32)(KoUnit::fromUserValue(start, m_unit) * m_zoom - m_firstVisible); + + if (!s3 && s4 && start % st4 == 0) + p.drawLine(RULER_THICKNESS - 9, pos, RULER_THICKNESS, pos); + + if (s3 && start % st3 == 0) + p.drawLine(RULER_THICKNESS - 9, pos, RULER_THICKNESS, pos); + + if (s2 && start % st2 == 0) + p.drawLine(RULER_THICKNESS - 7, pos, RULER_THICKNESS, pos); + + if (s1 && start % st1 == 0) + p.drawLine(RULER_THICKNESS - 5, pos, RULER_THICKNESS, pos); + + if (start % step == 0) { + buf.setNum(QABS(start)); + drawNums(&p, 4, pos, buf, false); + } + + start++; + } while (pos < m_pixmapBuffer->height()); + } + + p.end(); +} + +void KisRuler::resizeEvent(QResizeEvent *) +{ + recalculateSize(); +} + +void KisRuler::styleChange(QStyle& oldStyle) +{ + Q_UNUSED(oldStyle); + updateGeometry(); + drawRuler(); +} + +void KisRuler::paletteChange(const QPalette& oldPalette) +{ + Q_UNUSED(oldPalette); + drawRuler(); +} + +void KisRuler::show() +{ + if (m_orientation == Qt::Horizontal) { + setFixedHeight(RULER_THICKNESS); + initMarker(MARKER_WIDTH, MARKER_HEIGHT); + } else { + setFixedWidth(RULER_THICKNESS); + initMarker(MARKER_HEIGHT, MARKER_WIDTH); + } + + super::show(); +} + +void KisRuler::hide() +{ + /* + if (m_orientation == Qt::Horizontal) + setFixedHeight(1); + else + setFixedWidth(1); + */ + super::hide(); +} + +void KisRuler::drawNums(QPainter *p, Q_INT32 x, Q_INT32 y, QString& num, bool orientationHoriz) +{ + if (orientationHoriz) + x -= 7; + else + y -= 8; + + for (Q_UINT32 k = 0; k < num.length(); k++) { + Q_INT32 st = num.at(k).digitValue() * 7; + + p->drawPixmap(x, y, m_pixmapNums, st, 0, 7, 7); + + if (orientationHoriz) + x += 7; + else + y += 8; + } +} + +#include "kis_ruler.moc" + diff --git a/krita/ui/kis_ruler.h b/krita/ui/kis_ruler.h new file mode 100644 index 000000000..511539127 --- /dev/null +++ b/krita/ui/kis_ruler.h @@ -0,0 +1,80 @@ +/* + * Kivio - Visual Modelling and Flowcharting + * Copyright (C) 2000-2001 theKompany.com & Dave Marotti + * Copyright (C) 2002 Patrick Julien <freak@codepimps.org> + * + * 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_RULER_H_ +#define KIS_RULER_H_ + +#include <qframe.h> +#include <qpixmap.h> +#include <KoUnit.h> + +// XXX: Make this look more like the KOffice ruler -- the KOffice +// ruler is not quite suited to Krita. Also: start units with 0, +// print every 100 units. + +#define RULER_THICKNESS 20 + +class QPainter; + +class KisRuler : public QFrame { + Q_OBJECT + typedef QFrame super; + +public: + KisRuler(Qt::Orientation, QWidget *parent = 0, const char *name = 0); + virtual ~KisRuler(); + +public: + KoUnit::Unit unit() const; + +public slots: + void setZoom(double zoom); + void updatePointer(Q_INT32 x, Q_INT32 y); + void updateVisibleArea(Q_INT32 xpos, Q_INT32 ypos); + void setUnit(KoUnit::Unit u); + void hide(); + void show(); + +protected: + virtual void paintEvent(QPaintEvent *e); + virtual void resizeEvent(QResizeEvent *e); + virtual void styleChange(QStyle& oldStyle); + virtual void paletteChange(const QPalette& oldPalette); + + void recalculateSize(); + void drawRuler(); + void initMarker(Q_INT32 w, Q_INT32 h); + void drawNums(QPainter *gc, Q_INT32 x, Q_INT32 y, QString& num, bool orientationHoriz); + +private: + KoUnit::Unit m_unit; + Qt::Orientation m_orientation; + Q_INT32 m_firstVisible; + Q_INT32 m_currentPosition; + QPixmap *m_pixmapBuffer; + QPixmap m_pixmapMarker; + QPixmap m_pixmapNums; + double m_zoom; + +private: + static const char *m_nums[]; +}; + +#endif // KIS_RULER_H_ + diff --git a/krita/ui/kis_save_visitor.h b/krita/ui/kis_save_visitor.h new file mode 100644 index 000000000..ceb07eb7f --- /dev/null +++ b/krita/ui/kis_save_visitor.h @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk> + * + * 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_SAVE_VISITOR_H_ +#define KIS_SAVE_VISITOR_H_ + +#include <qrect.h> +#include "kis_types.h" +#include "kis_layer_visitor.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_paint_layer.h" +#include "kis_group_layer.h" + +class KisSaveVisitor : public KisLayerVisitor { +public: + KisSaveVisitor(KisImageSP img, KoStore *store, Q_UINT32 &count) : + KisLayerVisitor(), + m_count(count) + { + m_external = false; + m_img = img; + m_store = store; + } + +public: + void setExternalUri(QString &uri) + { + m_external = true; + m_uri = uri; + } + + virtual bool visit(KisPaintLayer *layer) + { + //connect(*layer->paintDevice(), SIGNAL(ioProgress(Q_INT8)), m_img, SLOT(slotIOProgress(Q_INT8))); + + QString location = m_external ? QString::null : m_uri; + location += m_img->name() + QString("/layers/layer%1").arg(m_count); + + // Layer data + if (m_store->open(location)) { + if (!layer->paintDevice()->write(m_store)) { + layer->paintDevice()->disconnect(); + m_store->close(); + //IODone(); + return false; + } + + m_store->close(); + } + + if (layer->paintDevice()->colorSpace()->getProfile()) { + KisAnnotationSP annotation = layer->paintDevice()->colorSpace()->getProfile()->annotation(); + + if (annotation) { + // save layer profile + location = m_external ? QString::null : m_uri; + location += m_img->name() + QString("/layers/layer%1").arg(m_count) + ".icc"; + + if (m_store->open(location)) { + m_store->write(annotation->annotation()); + m_store->close(); + } + } + } + + if (layer->hasMask()) { + KisPaintDeviceSP mask = layer->getMask(); + + if (mask) { + // save layer profile + location = m_external ? QString::null : m_uri; + location += m_img->name() + QString("/layers/layer%1").arg(m_count) + ".mask"; + + if (m_store->open(location)) { + if (!mask->write(m_store)) { + mask->disconnect(); + m_store->close(); + return false; + } + + m_store->close(); + } + } + } + + m_count++; + return true; + } + + virtual bool visit(KisGroupLayer *layer) + { + KisSaveVisitor visitor(m_img, m_store, m_count); + + if(m_external) + visitor.setExternalUri(m_uri); + + KisLayerSP child = layer->firstChild(); + + while(child) + { + child->accept(visitor); + child = child->nextSibling(); + } + return true; + } + + virtual bool visit(KisPartLayer *) + { + return true; + } + + virtual bool visit(KisAdjustmentLayer* layer) + { + + if (layer->selection()) { + QString location = m_external ? QString::null : m_uri; + location += m_img->name() + QString("/layers/layer%1").arg(m_count) + ".selection"; + + // Layer data + if (m_store->open(location)) { + if (!layer->selection()->write(m_store)) { + layer->selection()->disconnect(); + m_store->close(); + //IODone(); + return false; + } + m_store->close(); + } + } + + if (layer->filter()) { + QString location = m_external ? QString::null : m_uri; + location = m_external ? QString::null : m_uri; + location += m_img->name() + QString("/layers/layer%1").arg(m_count) + ".filterconfig"; + + if (m_store->open(location)) { + QString s = layer->filter()->toString(); + m_store->write(s.utf8(), qstrlen(s.utf8())); + m_store->close(); + } + } + m_count++; + return true; + } + +private: + KisImageSP m_img; + KoStore *m_store; + bool m_external; + QString m_uri; + Q_UINT32 &m_count; +}; + +#endif // KIS_SAVE_VISITOR_H_ + diff --git a/krita/ui/kis_savexml_visitor.h b/krita/ui/kis_savexml_visitor.h new file mode 100644 index 000000000..f45466cd1 --- /dev/null +++ b/krita/ui/kis_savexml_visitor.h @@ -0,0 +1,144 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2005 Casper Boemann <cbr@boemann.dk> + * + * 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_SAVEXML_VISITOR_H_ +#define KIS_SAVEXML_VISITOR_H_ + +#include <qrect.h> + +#include "kis_adjustment_layer.h" +#include "kis_exif_info.h" +#include "kis_group_layer.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_layer_visitor.h" +#include "kis_paint_layer.h" +#include "kis_types.h" + +class KisSaveXmlVisitor : public KisLayerVisitor { +public: + KisSaveXmlVisitor(QDomDocument doc, QDomElement element, Q_UINT32 &count, bool root=false) : + KisLayerVisitor(), + m_doc(doc), + m_count(count), + m_root(root) + { + m_elem = element; + } + +public: + virtual bool visit(KisPaintLayer *layer) + { + QDomElement layerElement = m_doc.createElement("layer"); + + layerElement.setAttribute("name", layer->name()); + layerElement.setAttribute("x", layer->x()); + layerElement.setAttribute("y", layer->y()); + layerElement.setAttribute("opacity", layer->opacity()); + layerElement.setAttribute("compositeop", layer->compositeOp().id().id()); + layerElement.setAttribute("visible", layer->visible()); + layerElement.setAttribute("locked", layer->locked()); + layerElement.setAttribute("layertype", "paintlayer"); + layerElement.setAttribute("filename", QString("layer%1").arg(m_count)); + layerElement.setAttribute("colorspacename", layer->paintDevice()->colorSpace()->id().id()); + layerElement.setAttribute("hasmask", layer->hasMask()); + m_elem.appendChild(layerElement); + + if(layer->paintDevice()->hasExifInfo()) + { + QDomElement exifElmt = layer->paintDevice()->exifInfo()->save(m_doc); + layerElement.appendChild(exifElmt); + } + m_count++; + return true; + } + + virtual bool visit(KisGroupLayer *layer) + { + QDomElement layerElement; + + if(m_root) // if this is the root we fake so not to save it + layerElement = m_elem; + else + { + layerElement = m_doc.createElement("layer"); + + layerElement.setAttribute("name", layer->name()); + layerElement.setAttribute("x", layer->x()); + layerElement.setAttribute("y", layer->y()); + layerElement.setAttribute("opacity", layer->opacity()); + layerElement.setAttribute("compositeop", layer->compositeOp().id().id()); + layerElement.setAttribute("visible", layer->visible()); + layerElement.setAttribute("locked", layer->locked()); + layerElement.setAttribute("layertype", "grouplayer"); + + m_elem.appendChild(layerElement); + } + + QDomElement elem = m_doc.createElement("LAYERS"); + + layerElement.appendChild(elem); + + KisSaveXmlVisitor visitor(m_doc, elem, m_count); + + KisLayerSP child = layer->firstChild(); + + while(child) + { + child->accept(visitor); + child = child->nextSibling(); + } + return true; + } + + virtual bool visit(KisPartLayer* layer) + { + bool ok = layer->saveToXML(m_doc, m_elem); + return ok; + } + + virtual bool visit(KisAdjustmentLayer* layer) + { + QDomElement layerElement = m_doc.createElement("layer"); + + layerElement.setAttribute("name", layer->name()); + layerElement.setAttribute("filtername", layer->filter()->name()); + layerElement.setAttribute("filterversion", layer->filter()->version()); + layerElement.setAttribute("opacity", layer->opacity()); + layerElement.setAttribute("compositeop", layer->compositeOp().id().id()); + layerElement.setAttribute("visible", layer->visible()); + layerElement.setAttribute("locked", layer->locked()); + layerElement.setAttribute("layertype", "adjustmentlayer"); + layerElement.setAttribute("filename", QString("layer%1").arg(m_count)); + layerElement.setAttribute("x", layer->x()); + layerElement.setAttribute("y", layer->y()); + m_elem.appendChild(layerElement); + + m_count++; + return true; + } + +private: + QDomDocument m_doc; + QDomElement m_elem; + Q_UINT32 &m_count; + bool m_root; +}; + +#endif // KIS_SAVEXML_VISITOR_H_ + diff --git a/krita/ui/kis_selection_manager.cc b/krita/ui/kis_selection_manager.cc new file mode 100644 index 000000000..d97fca0cd --- /dev/null +++ b/krita/ui/kis_selection_manager.cc @@ -0,0 +1,1643 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qobject.h> +#include <qapplication.h> +#include <qclipboard.h> +#include <qcolor.h> +#include <qcursor.h> + +#include <kdebug.h> +#include <kaction.h> +#include <klocale.h> +#include <kstdaction.h> + +#include <KoDocument.h> +#include <KoMainWindow.h> +#include <KoQueryTrader.h> + +#include "kis_cursor.h" +#include "kis_part_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_clipboard.h" +#include "kis_types.h" +#include "kis_view.h" +#include "kis_doc.h" +#include "kis_image.h" +#include "kis_selection.h" +#include "kis_selection_manager.h" +#include "kis_painter.h" +#include "kis_iterators_pixel.h" +#include "kis_iteratorpixeltrait.h" +#include "kis_layer.h" +#include "kis_group_layer.h" +#include "kis_paint_layer.h" +#include "kis_paint_device.h" +#include "kis_channelinfo.h" +#include "kis_dlg_apply_profile.h" +#include "kis_config.h" +#include "kis_debug_areas.h" +#include "kis_transaction.h" +#include "kis_undo_adapter.h" +#include "kis_selected_transaction.h" +#include "kis_convolution_painter.h" +#include "kis_integer_maths.h" +#include "kis_fill_painter.h" +#include "kis_canvas.h" + +KisSelectionManager::KisSelectionManager(KisView * parent, KisDoc * doc) + : m_parent(parent), + m_doc(doc), + m_copy(0), + m_cut(0), + m_paste(0), + m_pasteNew(0), + m_cutToNewLayer(0), + m_selectAll(0), + m_deselect(0), + m_clear(0), + m_reselect(0), + m_invert(0), + m_toNewLayer(0), + m_feather(0), + m_border(0), + m_expand(0), + m_smooth(0), + m_contract(0), + m_similar(0), + m_transform(0), + m_load(0), + m_save(0), + m_fillForegroundColor(0), + m_fillBackgroundColor(0), + m_fillPattern(0) +{ + m_pluginActions.setAutoDelete(true); + m_clipboard = KisClipboard::instance(); +} + +KisSelectionManager::~KisSelectionManager() +{ + m_pluginActions.clear(); +} + + +void KisSelectionManager::setup(KActionCollection * collection) +{ + // XXX: setup shortcuts! + + m_cut = KStdAction::cut(this, + SLOT(cut()), + collection, + "cut"); + + m_copy = KStdAction::copy(this, + SLOT(copy()), + collection, + "copy"); + + m_paste = KStdAction::paste(this, + SLOT(paste()), + collection, + "paste"); + + m_pasteNew = new KAction(i18n("Paste into &New Image"), + 0, 0, + this, SLOT(pasteNew()), + collection, + "paste_new"); + + + m_selectAll = KStdAction::selectAll(this, + SLOT(selectAll()), + collection, + "select_all"); + + m_deselect = KStdAction::deselect(this, + SLOT(deselect()), + collection, + "deselect"); + + + m_clear = KStdAction::clear(this, + SLOT(clear()), + collection, + "clear"); + + m_reselect = new KAction(i18n("&Reselect"), + 0, "Ctrl+Shift+D", + this, SLOT(reselect()), + collection, "reselect"); + + m_invert = new KAction(i18n("&Invert"), + 0, "Ctrl+I", + this, SLOT(invert()), + collection, "invert"); + + + m_toNewLayer = new KAction(i18n("Copy Selection to New Layer"), + 0, "Ctrl+J", + this, SLOT(copySelectionToNewLayer()), + collection, "copy_selection_to_new_layer"); + + + m_cutToNewLayer = new KAction(i18n("Cut Selection to New Layer"), + 0, "Ctrl+Shift+J", + this, SLOT(cutToNewLayer()), + collection, "cut_selection_to_new_layer"); + + m_feather = new KAction(i18n("Feather"), + 0, "Ctrl+Alt+D", + this, SLOT(feather()), + collection, "feather"); + + m_fillForegroundColor = new KAction(i18n("Fill with Foreground Color"), + "Alt+backspace", this, + SLOT(fillForegroundColor()), + collection, + "fill_selection_foreground_color"); + m_fillBackgroundColor = new KAction(i18n("Fill with Background Color"), + "backspace", this, + SLOT(fillBackgroundColor()), + collection, + "fill_selection_background_color"); + m_fillPattern = new KAction(i18n("Fill with Pattern"), + 0, this, + SLOT(fillPattern()), + collection, + "fill_selection_pattern"); + + m_toggleDisplaySelection = new KToggleAction(i18n("Display Selection"), "Ctrl+h", this, SLOT(toggleDisplaySelection()), collection, "toggle_display_selection"); + m_toggleDisplaySelection->setCheckedState(KGuiItem(i18n("Hide Selection"))); + m_toggleDisplaySelection->setChecked(true); + + m_border = + new KAction(i18n("Border..."), + 0, 0, + this, SLOT(border()), + collection, "border"); + m_expand = + new KAction(i18n("Expand..."), + 0, 0, + this, SLOT(expand()), + collection, "expand"); + + m_smooth = + new KAction(i18n("Smooth..."), + 0, 0, + this, SLOT(smooth()), + collection, "smooth"); + + + m_contract = + new KAction(i18n("Contract..."), + 0, 0, + this, SLOT(contract()), + collection, "contract"); + m_similar = + new KAction(i18n("Similar"), + 0, 0, + this, SLOT(similar()), + collection, "similar"); + + + m_transform + = new KAction(i18n("Transform..."), + 0, 0, + this, SLOT(transform()), + collection, "transform_selection"); + + +// m_load +// = new KAction(i18n("Load..."), +// 0, 0, +// this, SLOT(load()), +// collection, "load_selection"); +// +// +// m_save +// = new KAction(i18n("Save As..."), +// 0, 0, +// this, SLOT(save()), +// collection, "save_selection"); + + QClipboard *cb = QApplication::clipboard(); + connect(cb, SIGNAL(dataChanged()), SLOT(clipboardDataChanged())); +} + +void KisSelectionManager::clipboardDataChanged() +{ + updateGUI(); +} + + +void KisSelectionManager::addSelectionAction(KAction * action) +{ + m_pluginActions.append(action); +} + + +void KisSelectionManager::updateGUI() +{ + Q_ASSERT(m_parent); + Q_ASSERT(m_clipboard); + + if (m_parent == 0) { + // "Eek, no parent! + return; + } + + if (m_clipboard == 0) { + // Eek, no clipboard! + return; + } + + KisImageSP img = m_parent->currentImg(); + KisLayerSP l = 0; + KisPaintDeviceSP dev = 0; + + bool enable = false; + if (img && img->activeDevice() && img->activeLayer()) { + l = img->activeLayer(); + dev = img->activeDevice(); + + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(l.data()); + KisAdjustmentLayer * adjLayer = dynamic_cast<KisAdjustmentLayer*>(l.data()); + + enable = l && dev&& dev->hasSelection() && !l->locked() && l->visible() && (partLayer==0); + + if(dev && !adjLayer) + m_reselect->setEnabled( dev->selectionDeselected() ); + if (adjLayer) // There's no reselect for adjustment layers + m_reselect->setEnabled(false); + } + + m_cut->setEnabled(enable); + m_cutToNewLayer->setEnabled(enable); + m_selectAll->setEnabled(img != 0); + m_deselect->setEnabled(enable); + m_clear->setEnabled(enable); + m_fillForegroundColor->setEnabled(enable); + m_fillBackgroundColor->setEnabled(enable); + m_fillPattern->setEnabled(enable); + m_invert->setEnabled(enable); + + m_feather->setEnabled(enable); + + m_border->setEnabled(enable); + m_expand->setEnabled(enable); + m_smooth->setEnabled(enable); + m_contract->setEnabled(enable); + m_similar->setEnabled(enable); + m_transform->setEnabled(enable); +// m_load->setEnabled(enable); +// m_save->setEnabled(enable); + + + KAction * a; + for (a = m_pluginActions.first(); a; a = m_pluginActions.next()) { + a->setEnabled(img != 0); + } + + // You can copy from locked layers and paste the clip into a new layer, even when + // the current layer is locked. + enable = false; + if (img && l && dev) { + enable = dev->hasSelection() && l->visible(); + } + + m_copy->setEnabled(enable); + m_paste->setEnabled(img != 0 && m_clipboard->hasClip()); + m_pasteNew->setEnabled(img != 0 && m_clipboard->hasClip()); + m_toNewLayer->setEnabled(enable); + + m_parent->updateStatusBarSelectionLabel(); + +} + +void KisSelectionManager::imgSelectionChanged(KisImageSP img) +{ + if (img == m_parent->currentImg()) { + updateGUI(); + } +} + +void KisSelectionManager::cut() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + copy(); + + KisSelectedTransaction *t = 0; + + if (img->undo()) { + t = new KisSelectedTransaction(i18n("Cut"), dev); + Q_CHECK_PTR(t); + } + + dev->clearSelection(); + dev->deselect(); + dev->emitSelectionChanged(); + + if (img->undo()) { + img->undoAdapter()->addCommand(t); + } +} + +void KisSelectionManager::copy() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisSelectionSP selection = dev->selection(); + + QRect r = selection->selectedExactRect(); + + KisPaintDeviceSP clip = new KisPaintDevice(dev->colorSpace(), "clip"); + Q_CHECK_PTR(clip); + + KisColorSpace * cs = clip->colorSpace(); + + // TODO if the source is linked... copy from all linked layers?!? + + // Copy image data + KisPainter gc; + gc.begin(clip); + gc.bitBlt(0, 0, COMPOSITE_COPY, dev, r.x(), r.y(), r.width(), r.height()); + gc.end(); + + // Apply selection mask. + + for (Q_INT32 y = 0; y < r.height(); y++) { + KisHLineIteratorPixel layerIt = clip->createHLineIterator(0, y, r.width(), true); + KisHLineIteratorPixel selectionIt = selection->createHLineIterator(r.x(), r.y() + y, r.width(), false); + + while (!layerIt.isDone()) { + + cs->applyAlphaU8Mask( layerIt.rawData(), selectionIt.rawData(), 1 ); + + + ++layerIt; + ++selectionIt; + } + } + + m_clipboard->setClip(clip); + imgSelectionChanged(m_parent->currentImg()); +} + + +KisLayerSP KisSelectionManager::paste() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return 0; + + KisPaintDeviceSP clip = m_clipboard->clip(); + + if (clip) { + QApplication::setOverrideCursor(KisCursor::waitCursor()); + KisPaintLayer *layer = new KisPaintLayer(img, img->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE); + Q_CHECK_PTR(layer); + + QRect r = clip->exactBounds(); + KisPainter gc; + gc.begin(layer->paintDevice()); + gc.bitBlt(0, 0, COMPOSITE_COPY, clip, r.x(), r.y(), r.width(), r.height()); + gc.end(); + + //figure out where to position the clip + KisCanvasController *cc = m_parent->getCanvasController(); + QPoint center = cc->viewToWindow(QPoint(cc->kiscanvas()->width()/2, cc->kiscanvas()->height()/2)); + QPoint bottomright = cc->viewToWindow(QPoint(cc->kiscanvas()->width(), cc->kiscanvas()->height())); + if(bottomright.x() > img->width()) + center.setX(img->width()/2); + if(bottomright.y() > img->height()) + center.setY(img->height()/2); + center -= QPoint(r.width()/2, r.height()/2); + layer->setX(center.x()); + layer->setY(center.y()); + +/*XXX CBR have an idea of asking the user if he is about to paste a clip ion another cs than that of + the image if that is what he want rather than silently converting + if (clip->colorSpace != img ->colorSpace()) + if (dlg->exec() == QDialog::Accepted) + layer->convertTo(img->colorSpace()); +*/ + QApplication::restoreOverrideCursor(); + if(img->addLayer(layer, img->activeLayer()->parent(), img->activeLayer())) + { + return layer; + } else { + return 0; + } + } + return 0; +} + +void KisSelectionManager::pasteNew() +{ + KisPaintDeviceSP clip = m_clipboard->clip(); + if (!clip) return; + + QRect r = clip->exactBounds(); + if (r.width() < 1 && r.height() < 1) { + // Don't paste empty clips + return; + } + + const QCString mimetype = KoDocument::readNativeFormatMimeType(); + KoDocumentEntry entry = KoDocumentEntry::queryByMimeType( mimetype ); + KisDoc * doc = (KisDoc*) entry.createDoc(); + + Q_ASSERT(doc->undoAdapter() != 0); + doc->undoAdapter()->setUndo(false); + + KisImageSP img = new KisImage(doc->undoAdapter(), r.width(), r.height(), clip->colorSpace(), "Pasted"); + KisPaintLayer *layer = new KisPaintLayer(img, clip->name(), OPACITY_OPAQUE, clip->colorSpace()); + + KisPainter p(layer->paintDevice()); + p.bitBlt(0, 0, COMPOSITE_COPY, clip, OPACITY_OPAQUE, r.x(), r.y(), r.width(), r.height()); + p.end(); + + img->addLayer(layer, img->rootLayer(), 0); + doc->setCurrentImage(img); + + doc->undoAdapter()->setUndo(true); + + KoMainWindow *win = new KoMainWindow( doc->instance() ); + win->show(); + win->setRootDocument( doc ); +} + +void KisSelectionManager::selectAll() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Select All"), dev); + Q_CHECK_PTR(t); + + // Make adjustment layers behave better + KisAdjustmentLayer* adj = dynamic_cast<KisAdjustmentLayer*>(img->activeLayer().data()); + if (adj) { + adj->clearSelection(); + adj->selection()->invert(); + } else { + dev->selection()->clear(); + dev->selection()->invert(); + } + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + +void KisSelectionManager::deselect() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Deselect"), dev); + Q_CHECK_PTR(t); + + // Make adjustment layers behave almost the same (except no reselect) + KisAdjustmentLayer* adj = dynamic_cast<KisAdjustmentLayer*>(img->activeLayer().data()); + if (adj) { + adj->clearSelection(); + } else { + dev->deselect(); + } + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + + +void KisSelectionManager::clear() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisTransaction * t = 0; + + if (img->undo()) { + t = new KisTransaction(i18n("Clear"), dev); + } + + dev->clearSelection(); + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) img->undoAdapter()->addCommand(t); +} + +void KisSelectionManager::fill(const KisColor& color, bool fillWithPattern, const QString& transactionText) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + + KisSelectionSP selection = dev->selection(); + + KisPaintDeviceSP filled = new KisPaintDevice(dev->colorSpace()); + KisFillPainter painter(filled); + + if (fillWithPattern) { + painter.fillRect(0, 0, img->width(), img->height(), + m_parent->currentPattern()); + } else { + painter.fillRect(0, 0, img->width(), img->height(), color); + } + + painter.end(); + + KisPainter painter2(dev); + + if (img->undo()) painter2.beginTransaction(transactionText); + painter2.bltSelection(0, 0, COMPOSITE_OVER, filled, OPACITY_OPAQUE, + 0, 0, img->width(), img->height()); + + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) { + img->undoAdapter()->addCommand(painter2.endTransaction()); + } +} + +void KisSelectionManager::fillForegroundColor() +{ + fill(m_parent->fgColor(), false, i18n("Fill with Foreground Color")); +} + +void KisSelectionManager::fillBackgroundColor() +{ + fill(m_parent->bgColor(), false, i18n("Fill with Background Color")); +} + +void KisSelectionManager::fillPattern() +{ + fill(KisColor(), true, i18n("Fill with Pattern")); +} + +void KisSelectionManager::reselect() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img ->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Reselect"), dev); + Q_CHECK_PTR(t); + + dev->reselect(); // sets hasSelection=true + dev->setDirty(); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); +} + + +void KisSelectionManager::invert() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (dev->hasSelection()) { + KisSelectionSP s = dev->selection(); + + KisSelectedTransaction * t = 0; + if (img->undo()) + { + t = new KisSelectedTransaction(i18n("Invert"), dev); + Q_CHECK_PTR(t); + } + + s->invert(); + dev->setDirty(); + dev->emitSelectionChanged(); + + if (t) { + img->undoAdapter()->addCommand(t); + } + } +} + +void KisSelectionManager::copySelectionToNewLayer() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + copy(); + paste(); +} + +void KisSelectionManager::cutToNewLayer() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + cut(); + paste(); +} + + +void KisSelectionManager::feather() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) { + // activate it, but don't do anything with it + dev->selection(); + return; + } + + KisSelectionSP selection = dev->selection(); + KisSelectedTransaction * t = 0; + if (img->undo()) t = new KisSelectedTransaction(i18n("Feather..."), dev); + Q_CHECK_PTR(t); + + + // XXX: we should let gaussian blur & others influence alpha channels as well + // (on demand of the caller) + + KisConvolutionPainter painter(selection.data()); + + KisKernelSP k = new KisKernel(); + k->width = 3; + k->height = 3; + k->factor = 16; + k->offset = 0; + k->data = new Q_INT32[9]; + k->data[0] = 1; + k->data[1] = 2; + k->data[2] = 1; + k->data[3] = 2; + k->data[4] = 4; + k->data[5] = 2; + k->data[6] = 1; + k->data[7] = 2; + k->data[8] = 1; + + QRect rect = selection->selectedRect(); + // Make sure we've got enough space around the edges. + rect = QRect(rect.x() - 3, rect.y() - 3, rect.width() + 6, rect.height() + 6); + rect &= QRect(0, 0, img->width(), img->height()); + + painter.applyMatrix(k, rect.x(), rect.y(), rect.width(), rect.height(), BORDER_AVOID, KisChannelInfo::FLAG_ALPHA); + painter.end(); + + dev->setDirty(rect); + dev->emitSelectionChanged(); + + if (img->undo()) + img->undoAdapter()->addCommand(t); + +} + +void KisSelectionManager::toggleDisplaySelection() +{ + m_parent->selectionDisplayToggled(displaySelection()); +} + +bool KisSelectionManager::displaySelection() +{ + return m_toggleDisplaySelection->isChecked(); +} +// XXX: Maybe move these esoteric functions to plugins? +void KisSelectionManager::border() {} +void KisSelectionManager::expand() {} +void KisSelectionManager::contract() {} +void KisSelectionManager::similar() {} +void KisSelectionManager::transform() {} +void KisSelectionManager::load() {} +void KisSelectionManager::save() {} + +#define MAX(a, b) ((a) > (b) ? (a) : (b)) +#define MIN(a, b) ((a) < (b) ? (a) : (b)) + +void KisSelectionManager::grow (Q_INT32 xradius, Q_INT32 yradius) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + /* + Any bugs in this fuction are probably also in thin_region + Blame all bugs in this function on jaycox@gimp.org + */ + + Q_UINT8 **buf; // caches the region's pixel data + Q_UINT8 **max; // caches the largest values for each column + + if (xradius <= 0 || yradius <= 0) + return; + + KisSelectedTransaction *t = 0; + + if (img->undo()) { + t = new KisSelectedTransaction(i18n("Grow"), dev); + Q_CHECK_PTR(t); + } + + max = new Q_UINT8* [layerSize.width() + 2 * xradius]; + buf = new Q_UINT8* [yradius + 1]; + for (Q_INT32 i = 0; i < yradius + 1; i++) + { + buf[i] = new Q_UINT8[layerSize.width()]; + } + Q_UINT8* buffer = new Q_UINT8[ ( layerSize.width() + 2 * xradius ) * ( yradius + 1 ) ]; + for (Q_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++) + { + if (i < xradius) + max[i] = buffer; + else if (i < layerSize.width() + xradius) + max[i] = &buffer[(yradius + 1) * (i - xradius)]; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)]; + + for (Q_INT32 j = 0; j < xradius + 1; j++) + max[i][j] = 0; + } + /* offset the max pointer by xradius so the range of the array + is [-xradius] to [region->w + xradius] */ + max += xradius; + + Q_UINT8* out = new Q_UINT8[ layerSize.width() ]; // holds the new scan line we are computing + + Q_INT32* circ = new Q_INT32[ 2 * xradius + 1 ]; // holds the y coords of the filter's mask + computeBorder (circ, xradius, yradius); + + /* offset the circ pointer by xradius so the range of the array + is [-xradius] to [xradius] */ + circ += xradius; + + memset (buf[0], 0, layerSize.width()); + for (Q_INT32 i = 0; i < yradius && i < layerSize.height(); i++) // load top of image + { + selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1); + } + + for (Q_INT32 x = 0; x < layerSize.width() ; x++) // set up max for top of image + { + max[x][0] = 0; // buf[0][x] is always 0 + max[x][1] = buf[1][x]; // MAX (buf[1][x], max[x][0]) always = buf[1][x] + for (Q_INT32 j = 2; j < yradius + 1; j++) + { + max[x][j] = MAX(buf[j][x], max[x][j-1]); + } + } + + for (Q_INT32 y = 0; y < layerSize.height(); y++) + { + rotatePointers (buf, yradius + 1); + if (y < layerSize.height() - (yradius)) + selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1); + else + memset (buf[yradius], 0, layerSize.width()); + for (Q_INT32 x = 0; x < layerSize.width(); x++) /* update max array */ + { + for (Q_INT32 i = yradius; i > 0; i--) + { + max[x][i] = MAX (MAX (max[x][i - 1], buf[i - 1][x]), buf[i][x]); + } + max[x][0] = buf[0][x]; + } + Q_INT32 last_max = max[0][circ[-1]]; + Q_INT32 last_index = 1; + for (Q_INT32 x = 0; x < layerSize.width(); x++) /* render scan line */ + { + last_index--; + if (last_index >= 0) + { + if (last_max == 255) + out[x] = 255; + else + { + last_max = 0; + for (Q_INT32 i = xradius; i >= 0; i--) + if (last_max < max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + else + { + last_index = xradius; + last_max = max[x + xradius][circ[xradius]]; + for (Q_INT32 i = xradius - 1; i >= -xradius; i--) + if (last_max < max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + /* undo the offsets to the pointers so we can free the malloced memmory */ + circ -= xradius; + max -= xradius; + //XXXX: replace delete by delete[] where it is necessary to avoid memory leaks! + delete[] circ; + delete[] buffer; + delete[] max; + for (Q_INT32 i = 0; i < yradius + 1; i++) + delete[] buf[i]; + delete[] buf; + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); + + if (t) { + img->undoAdapter()->addCommand(t); + } +} + +void KisSelectionManager::shrink (Q_INT32 xradius, Q_INT32 yradius, bool edge_lock) +{ + + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + /* + pretty much the same as fatten_region only different + blame all bugs in this function on jaycox@gimp.org + */ + /* If edge_lock is true we assume that pixels outside the region + we are passed are identical to the edge pixels. + If edge_lock is false, we assume that pixels outside the region are 0 + */ + Q_UINT8 **buf; // caches the the region's pixels + Q_UINT8 **max; // caches the smallest values for each column + Q_INT32 last_max, last_index; + + if (xradius <= 0 || yradius <= 0) + return; + + max = new Q_UINT8* [layerSize.width() + 2 * xradius]; + buf = new Q_UINT8* [yradius + 1]; + for (Q_INT32 i = 0; i < yradius + 1; i++) + { + buf[i] = new Q_UINT8[layerSize.width()]; + } + + Q_INT32 buffer_size = (layerSize.width() + 2 * xradius + 1) * (yradius + 1); + Q_UINT8* buffer = new Q_UINT8[buffer_size]; + + if (edge_lock) + memset(buffer, 255, buffer_size); + else + memset(buffer, 0, buffer_size); + + for (Q_INT32 i = 0; i < layerSize.width() + 2 * xradius; i++) + { + if (i < xradius) + if (edge_lock) + max[i] = buffer; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)]; + else if (i < layerSize.width() + xradius) + max[i] = &buffer[(yradius + 1) * (i - xradius)]; + else + if (edge_lock) + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius - 1)]; + else + max[i] = &buffer[(yradius + 1) * (layerSize.width() + xradius)]; + } + if (!edge_lock) + for (Q_INT32 j = 0 ; j < xradius + 1; j++) max[0][j] = 0; + + // offset the max pointer by xradius so the range of the array is [-xradius] to [region->w + xradius] + max += xradius; + + Q_UINT8* out = new Q_UINT8[layerSize.width()]; // holds the new scan line we are computing + + Q_INT32* circ = new Q_INT32[2 * xradius + 1]; // holds the y coords of the filter's mask + + computeBorder (circ, xradius, yradius); + + // offset the circ pointer by xradius so the range of the array is [-xradius] to [xradius] + circ += xradius; + + for (Q_INT32 i = 0; i < yradius && i < layerSize.height(); i++) // load top of image + selection->readBytes(buf[i + 1], layerSize.x(), layerSize.y() + i, layerSize.width(), 1); + + if (edge_lock) + memcpy (buf[0], buf[1], layerSize.width()); + else + memset (buf[0], 0, layerSize.width()); + + + for (Q_INT32 x = 0; x < layerSize.width(); x++) // set up max for top of image + { + max[x][0] = buf[0][x]; + for (Q_INT32 j = 1; j < yradius + 1; j++) + max[x][j] = MIN(buf[j][x], max[x][j-1]); + } + + for (Q_INT32 y = 0; y < layerSize.height(); y++) + { + rotatePointers (buf, yradius + 1); + if (y < layerSize.height() - yradius) + selection->readBytes(buf[yradius], layerSize.x(), layerSize.y() + y + yradius, layerSize.width(), 1); + else if (edge_lock) + memcpy (buf[yradius], buf[yradius - 1], layerSize.width()); + else + memset (buf[yradius], 0, layerSize.width()); + + for (Q_INT32 x = 0 ; x < layerSize.width(); x++) // update max array + { + for (Q_INT32 i = yradius; i > 0; i--) + { + max[x][i] = MIN (MIN (max[x][i - 1], buf[i - 1][x]), buf[i][x]); + } + max[x][0] = buf[0][x]; + } + last_max = max[0][circ[-1]]; + last_index = 0; + + for (Q_INT32 x = 0 ; x < layerSize.width(); x++) // render scan line + { + last_index--; + if (last_index >= 0) + { + if (last_max == 0) + out[x] = 0; + else + { + last_max = 255; + for (Q_INT32 i = xradius; i >= 0; i--) + if (last_max > max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + else + { + last_index = xradius; + last_max = max[x + xradius][circ[xradius]]; + for (Q_INT32 i = xradius - 1; i >= -xradius; i--) + if (last_max > max[x + i][circ[i]]) + { + last_max = max[x + i][circ[i]]; + last_index = i; + } + out[x] = last_max; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + + // undo the offsets to the pointers so we can free the malloced memmory + circ -= xradius; + max -= xradius; + //free the memmory + //XXXX: replace delete by delete[] where it is necessary to avoid memory leaks! + delete[] circ; + delete[] buffer; + delete[] max; + for (Q_INT32 i = 0; i < yradius + 1; i++) + delete buf[i]; + delete[] buf; + delete[] out; + + dev->setDirty(layerSize); + dev->emitSelectionChanged(); +} + +//Simple convolution filter to smooth a mask (1bpp) + +void KisSelectionManager::smooth() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + + Q_UINT8 *buf[3]; + + Q_INT32 width = layerSize.width(); + + for (Q_INT32 i = 0; i < 3; i++) buf[i] = new Q_UINT8[width + 2]; + + Q_UINT8* out = new Q_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (Q_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (Q_INT32 x = 0 ; x < width; x++) + { + Q_INT32 value = (buf[0][x] + buf[0][x+1] + buf[0][x+2] + + buf[1][x] + buf[2][x+1] + buf[1][x+2] + + buf[2][x] + buf[1][x+1] + buf[2][x+2]); + + out[x] = value / 9; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (Q_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +// Erode (radius 1 pixel) a mask (1bpp) + +void KisSelectionManager::erode() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + + Q_UINT8* buf[3]; + + + Q_INT32 width = layerSize.width(); + + for (Q_INT32 i = 0; i < 3; i++) + buf[i] = new Q_UINT8[width + 2]; + + Q_UINT8* out = new Q_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (Q_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (Q_INT32 x = 0 ; x < width; x++) + { + Q_INT32 min = 255; + + if (buf[0][x+1] < min) min = buf[0][x+1]; + if (buf[1][x] < min) min = buf[1][x]; + if (buf[1][x+1] < min) min = buf[1][x+1]; + if (buf[1][x+2] < min) min = buf[1][x+2]; + if (buf[2][x+1] < min) min = buf[2][x+1]; + + out[x] = min; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (Q_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +// dilate (radius 1 pixel) a mask (1bpp) + +void KisSelectionManager::dilate() +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + + Q_UINT8* buf[3]; + + Q_INT32 width = layerSize.width(); + + for (Q_INT32 i = 0; i < 3; i++) + buf[i] = new Q_UINT8[width + 2]; + + Q_UINT8* out = new Q_UINT8[width]; + + // load top of image + selection->readBytes(buf[0] + 1, layerSize.x(), layerSize.y(), width, 1); + + buf[0][0] = buf[0][1]; + buf[0][width + 1] = buf[0][width]; + + memcpy (buf[1], buf[0], width + 2); + + for (Q_INT32 y = 0; y < layerSize.height(); y++) + { + if (y + 1 < layerSize.height()) + { + selection->readBytes(buf[2] + 1, layerSize.x(), layerSize.y() + y + 1, width, 1); + + buf[2][0] = buf[2][1]; + buf[2][width + 1] = buf[2][width]; + } + else + { + memcpy (buf[2], buf[1], width + 2); + } + + for (Q_INT32 x = 0 ; x < width; x++) + { + Q_INT32 max = 0; + + if (buf[0][x+1] > max) max = buf[0][x+1]; + if (buf[1][x] > max) max = buf[1][x]; + if (buf[1][x+1] > max) max = buf[1][x+1]; + if (buf[1][x+2] > max) max = buf[1][x+2]; + if (buf[2][x+1] > max) max = buf[2][x+1]; + + out[x] = max; + } + + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, width, 1); + + rotatePointers (buf, 3); + } + + for (Q_INT32 i = 0; i < 3; i++) + delete[] buf[i]; + + delete[] out; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +void KisSelectionManager::border(Q_INT32 xradius, Q_INT32 yradius) +{ + KisImageSP img = m_parent->currentImg(); + if (!img) return; + + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (!dev->hasSelection()) return; + KisSelectionSP selection = dev->selection(); + + //determine the layerSize + QRect layerSize = dev->exactBounds(); + + /* + This function has no bugs, but if you imagine some you can + blame them on jaycox@gimp.org + */ + Q_UINT8 *buf[3]; + Q_UINT8 **density; + Q_UINT8 **transition; + + if (xradius == 1 && yradius == 1) // optimize this case specifically + { + Q_UINT8* source[3]; + + for (Q_INT32 i = 0; i < 3; i++) + source[i] = new Q_UINT8[layerSize.width()]; + + Q_UINT8* transition = new Q_UINT8[layerSize.width()]; + + selection->readBytes(source[0], layerSize.x(), layerSize.y(), layerSize.width(), 1); + memcpy (source[1], source[0], layerSize.width()); + if (layerSize.height() > 1) + selection->readBytes(source[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1); + else + memcpy (source[2], source[1], layerSize.width()); + + computeTransition (transition, source, layerSize.width()); + selection->writeBytes(transition, layerSize.x(), layerSize.y(), layerSize.width(), 1); + + for (Q_INT32 y = 1; y < layerSize.height(); y++) + { + rotatePointers (source, 3); + if (y + 1 < layerSize.height()) + selection->readBytes(source[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1); + else + memcpy(source[2], source[1], layerSize.width()); + computeTransition (transition, source, layerSize.width()); + selection->writeBytes(transition, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + + for (Q_INT32 i = 0; i < 3; i++) + delete[] source[i]; + delete[] transition; + return; + } + + Q_INT32* max = new Q_INT32[layerSize.width() + 2 * xradius]; + for (Q_INT32 i = 0; i < (layerSize.width() + 2 * xradius); i++) + max[i] = yradius + 2; + max += xradius; + + for (Q_INT32 i = 0; i < 3; i++) + buf[i] = new Q_UINT8[layerSize.width()]; + + transition = new Q_UINT8*[yradius + 1]; + for (Q_INT32 i = 0; i < yradius + 1; i++) + { + transition[i] = new Q_UINT8[layerSize.width() + 2 * xradius]; + memset(transition[i], 0, layerSize.width() + 2 * xradius); + transition[i] += xradius; + } + Q_UINT8* out = new Q_UINT8[layerSize.width()]; + density = new Q_UINT8*[2 * xradius + 1]; + density += xradius; + + for (Q_INT32 x = 0; x < (xradius + 1); x++) // allocate density[][] + { + density[ x] = new Q_UINT8[2 * yradius + 1]; + density[ x] += yradius; + density[-x] = density[x]; + } + for (Q_INT32 x = 0; x < (xradius + 1); x++) // compute density[][] + { + double tmpx, tmpy, dist; + Q_UINT8 a; + + if (x > 0) + tmpx = x - 0.5; + else if (x < 0) + tmpx = x + 0.5; + else + tmpx = 0.0; + + for (Q_INT32 y = 0; y < (yradius + 1); y++) + { + if (y > 0) + tmpy = y - 0.5; + else if (y < 0) + tmpy = y + 0.5; + else + tmpy = 0.0; + dist = ((tmpy * tmpy) / (yradius * yradius) + + (tmpx * tmpx) / (xradius * xradius)); + if (dist < 1.0) + a = 255 * (Q_UINT8)(1.0 - sqrt (dist)); + else + a = 0; + density[ x][ y] = a; + density[ x][-y] = a; + density[-x][ y] = a; + density[-x][-y] = a; + } + } + selection->readBytes(buf[0], layerSize.x(), layerSize.y(), layerSize.width(), 1); + memcpy (buf[1], buf[0], layerSize.width()); + if (layerSize.height() > 1) + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + 1, layerSize.width(), 1); + else + memcpy (buf[2], buf[1], layerSize.width()); + computeTransition (transition[1], buf, layerSize.width()); + + for (Q_INT32 y = 1; y < yradius && y + 1 < layerSize.height(); y++) // set up top of image + { + rotatePointers (buf, 3); + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + 1, layerSize.width(), 1); + computeTransition (transition[y + 1], buf, layerSize.width()); + } + for (Q_INT32 x = 0; x < layerSize.width(); x++) // set up max[] for top of image + { + max[x] = -(yradius + 7); + for (Q_INT32 j = 1; j < yradius + 1; j++) + if (transition[j][x]) + { + max[x] = j; + break; + } + } + for (Q_INT32 y = 0; y < layerSize.height(); y++) // main calculation loop + { + rotatePointers (buf, 3); + rotatePointers (transition, yradius + 1); + if (y < layerSize.height() - (yradius + 1)) + { + selection->readBytes(buf[2], layerSize.x(), layerSize.y() + y + yradius + 1, layerSize.width(), 1); + computeTransition (transition[yradius], buf, layerSize.width()); + } + else + memcpy (transition[yradius], transition[yradius - 1], layerSize.width()); + + for (Q_INT32 x = 0; x < layerSize.width(); x++) // update max array + { + if (max[x] < 1) + { + if (max[x] <= -yradius) + { + if (transition[yradius][x]) + max[x] = yradius; + else + max[x]--; + } + else + if (transition[-max[x]][x]) + max[x] = -max[x]; + else if (transition[-max[x] + 1][x]) + max[x] = -max[x] + 1; + else + max[x]--; + } + else + max[x]--; + if (max[x] < -yradius - 1) + max[x] = -yradius - 1; + } + Q_UINT8 last_max = max[0][density[-1]]; + Q_INT32 last_index = 1; + for (Q_INT32 x = 0 ; x < layerSize.width(); x++) // render scan line + { + last_index--; + if (last_index >= 0) + { + last_max = 0; + for (Q_INT32 i = xradius; i >= 0; i--) + if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x+i]] > last_max) + { + last_max = density[i][max[x + i]]; + last_index = i; + } + out[x] = last_max; + } + else + { + last_max = 0; + for (Q_INT32 i = xradius; i >= -xradius; i--) + if (max[x + i] <= yradius && max[x + i] >= -yradius && density[i][max[x + i]] > last_max) + { + last_max = density[i][max[x + i]]; + last_index = i; + } + out[x] = last_max; + } + if (last_max == 0) + { + Q_INT32 i; + for (i = x + 1; i < layerSize.width(); i++) + { + if (max[i] >= -yradius) + break; + } + if (i - x > xradius) + { + for (; x < i - xradius; x++) + out[x] = 0; + x--; + } + last_index = xradius; + } + } + selection->writeBytes(out, layerSize.x(), layerSize.y() + y, layerSize.width(), 1); + } + delete [] out; + + for (Q_INT32 i = 0; i < 3; i++) + delete buf[i]; + + max -= xradius; + delete[] max; + + for (Q_INT32 i = 0; i < yradius + 1; i++) + { + transition[i] -= xradius; + delete transition[i]; + } + delete[] transition; + + for (Q_INT32 i = 0; i < xradius + 1 ; i++) + { + density[i] -= yradius; + delete density[i]; + } + density -= xradius; + delete[] density; + + dev->setDirty(); + dev->emitSelectionChanged(); +} + +#define RINT(x) floor ((x) + 0.5) + +void KisSelectionManager::computeBorder (Q_INT32 *circ, Q_INT32 xradius, Q_INT32 yradius) +{ + Q_ASSERT(xradius != 0); + Q_INT32 i; + Q_INT32 diameter = xradius * 2 + 1; + double tmp; + + for (i = 0; i < diameter; i++) + { + if (i > xradius) + tmp = (i - xradius) - 0.5; + else if (i < xradius) + tmp = (xradius - i) - 0.5; + else + tmp = 0.0; + + circ[i] = (Q_INT32) RINT (yradius / (double) xradius * sqrt (xradius * xradius - tmp * tmp)); + } +} + +void KisSelectionManager::rotatePointers (Q_UINT8 **p, Q_UINT32 n) +{ + Q_UINT32 i; + Q_UINT8 *tmp; + + tmp = p[0]; + + for (i = 0; i < n - 1; i++) p[i] = p[i + 1]; + + p[i] = tmp; +} + +void KisSelectionManager::computeTransition (Q_UINT8* transition, Q_UINT8** buf, Q_INT32 width) +{ + Q_INT32 x = 0; + + if (width == 1) + { + if (buf[1][x] > 127 && (buf[0][x] < 128 || buf[2][x] < 128)) + transition[x] = 255; + else + transition[x] = 0; + return; + } + if (buf[1][x] > 127) + { + if ( buf[0][x] < 128 || buf[0][x + 1] < 128 || + buf[1][x + 1] < 128 || + buf[2][x] < 128 || buf[2][x + 1] < 128 ) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; + for (Q_INT32 x = 1; x < width - 1; x++) + { + if (buf[1][x] >= 128) + { + if (buf[0][x - 1] < 128 || buf[0][x] < 128 || buf[0][x + 1] < 128 || + buf[1][x - 1] < 128 || buf[1][x + 1] < 128 || + buf[2][x - 1] < 128 || buf[2][x] < 128 || buf[2][x + 1] < 128) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; + } + if (buf[1][x] >= 128) + { + if (buf[0][x - 1] < 128 || buf[0][x] < 128 || + buf[1][x - 1] < 128 || + buf[2][x - 1] < 128 || buf[2][x] < 128) + transition[x] = 255; + else + transition[x] = 0; + } + else + transition[x] = 0; +} + +#include "kis_selection_manager.moc" diff --git a/krita/ui/kis_selection_manager.h b/krita/ui/kis_selection_manager.h new file mode 100644 index 000000000..7e18a0d97 --- /dev/null +++ b/krita/ui/kis_selection_manager.h @@ -0,0 +1,136 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_SELECTION_MANAGER_ +#define KIS_SELECTION_MANAGER_ + +#include "qobject.h" +#include "qptrlist.h" + +#include "kis_image.h" +#include <koffice_export.h> + +class KAction; +class KisView; +class KisDoc; +class KisClipboard; + +/** + * The selection manager is responsible selections + * and the clipboard. + */ +class KRITACORE_EXPORT KisSelectionManager : public QObject { + + Q_OBJECT + +public: + + KisSelectionManager(KisView * parent, KisDoc * doc); + virtual ~KisSelectionManager(); + + void setup(KActionCollection * collection); + + void addSelectionAction(KAction * action); + +public: + /** + * This function return if the selection should be displayed + */ + bool displaySelection(); + +public slots: + + void updateGUI(); + void imgSelectionChanged(KisImageSP img); + void clipboardDataChanged(); + + void cut(); + void copy(); + KisLayerSP paste(); + void pasteNew(); + void cutToNewLayer(); + void selectAll(); + void deselect(); + void clear(); + void fillForegroundColor(); + void fillBackgroundColor(); + void fillPattern(); + void reselect(); + void invert(); + void copySelectionToNewLayer(); + void feather(); + void border(); + void expand(); + void contract(); + void smooth(); + void similar(); + void transform(); + void load(); + void save(); + void toggleDisplaySelection(); + +public: + void grow (Q_INT32 xradius, Q_INT32 yradius); + void shrink (Q_INT32 xradius, Q_INT32 yradius, bool edge_lock); + void border(Q_INT32 xradius, Q_INT32 yradius); + // the following functions are needed for the siox tool + // they might be also usefull on its own + void erode(); + void dilate(); + +private: + void fill(const KisColor& color, bool fillWithPattern, const QString& transactionText); + + void computeBorder (Q_INT32 *circ, Q_INT32 xradius, Q_INT32 yradius); + inline void rotatePointers (Q_UINT8 **p, Q_UINT32 n); + void computeTransition (Q_UINT8* transition, Q_UINT8** buf, Q_INT32 width); + + KisView * m_parent; + KisDoc * m_doc; + + KisClipboard * m_clipboard; + + KAction *m_copy; + KAction *m_cut; + KAction *m_paste; + KAction *m_pasteNew; + KAction *m_cutToNewLayer; + KAction *m_selectAll; + KAction *m_deselect; + KAction *m_clear; + KAction *m_reselect; + KAction *m_invert; + KAction *m_toNewLayer; + KAction *m_feather; + KAction *m_border; + KAction *m_expand; + KAction *m_smooth; + KAction *m_contract; + KAction *m_similar; + KAction *m_transform; + KAction *m_load; + KAction *m_save; + KAction *m_fillForegroundColor; + KAction *m_fillBackgroundColor; + KAction *m_fillPattern; + KToggleAction *m_toggleDisplaySelection; + + QPtrList<KAction> m_pluginActions; + +}; + +#endif // KIS_SELECTION_MANAGER_ diff --git a/krita/ui/kis_selection_options.cc b/krita/ui/kis_selection_options.cc new file mode 100644 index 000000000..7d8e62cb9 --- /dev/null +++ b/krita/ui/kis_selection_options.cc @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qwidget.h> +#include <qradiobutton.h> +#include <qcombobox.h> +#include <kcolorbtn.h> +#include <qlayout.h> + +#include "kis_canvas_controller.h" +#include "kis_canvas_subject.h" +#include "wdgselectionoptions.h" +#include "kis_selection_options.h" +#include "kis_types.h" +#include "kis_layer.h" +#include "kis_image.h" +#include "kis_selection.h" +#include "kis_paint_device.h" + +KisSelectionOptions::KisSelectionOptions(QWidget *parent, KisCanvasSubject * subject) + : super(parent), + m_subject(subject) +{ + m_page = new WdgSelectionOptions(this); + Q_CHECK_PTR(m_page); + + QVBoxLayout * l = new QVBoxLayout(this); + l->addWidget(m_page); + + connect(m_page->cmbAction, SIGNAL(activated(int)), this, SIGNAL(actionChanged(int))); +} + +KisSelectionOptions::~KisSelectionOptions() +{ +} + +int KisSelectionOptions::action() +{ + return m_page->cmbAction->currentItem(); +} + +void KisSelectionOptions::slotActivated() +{ + + if (!m_subject) return; + KisImageSP img = m_subject->currentImg(); + if (!img) return; + KisPaintDeviceSP dev = img->activeDevice(); + if (!dev) return; + + if (dev->hasSelection()) { + } +} + +#include "kis_selection_options.moc" diff --git a/krita/ui/kis_selection_options.h b/krita/ui/kis_selection_options.h new file mode 100644 index 000000000..7b6134109 --- /dev/null +++ b/krita/ui/kis_selection_options.h @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_SELECTION_OPTIONS_H__ +#define __KIS_SELECTION_OPTIONS_H__ + +#include <qwidget.h> + +#include "koffice_export.h" + +class KisCanvasSubject; +class WdgSelectionOptions; + +/** + */ +class KRITAUI_EXPORT KisSelectionOptions : public QWidget +{ + + Q_OBJECT + + typedef QWidget super; + +public: + KisSelectionOptions( QWidget *parent, KisCanvasSubject * subject); + virtual ~KisSelectionOptions(); + + int action(); + +signals: + void actionChanged(int); + +public slots: + void slotActivated(); + +private: + WdgSelectionOptions * m_page; + KisCanvasSubject* m_subject; +}; + +#endif + diff --git a/krita/ui/kis_text_brush.cc b/krita/ui/kis_text_brush.cc new file mode 100644 index 000000000..6285e503b --- /dev/null +++ b/krita/ui/kis_text_brush.cc @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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 <qfontmetrics.h> +#include <qpainter.h> +#include <qspinbox.h> +#include <qcheckbox.h> +#include <qlabel.h> + +#include <kfontdialog.h> + +#include <klineedit.h> +#include "kis_text_brush.h" + +void KisTextBrushResource::updateBrush() +{ + QFontMetrics metric(m_font); + int w = metric.width(m_txt); + int h = metric.height(); + QPixmap px(w,h); + QPainter p; + p.begin(&px); + p.setFont( m_font ); + p.fillRect(0,0, w, h, Qt::white); + p.setPen(Qt::black); + p.drawText(0, metric.ascent(), m_txt ); + p.end(); + setImage(px.convertToImage ()); +} + +KisTextBrush::KisTextBrush(QWidget *parent, const char* name, const QString& caption) + : KisWdgTextBrush(parent, name), + m_textBrushResource(new KisTextBrushResource()) +{ + setCaption(caption); + connect((QObject*)lineEdit, SIGNAL(textChanged(const QString&)), this, SLOT(rebuildTextBrush())); + connect((QObject*)bnFont, SIGNAL(clicked()), this, SLOT(getFont())); + m_font = font(); + rebuildTextBrush(); +} + + +void KisTextBrush::getFont() +{ + KFontDialog::getFont( m_font, false/*, QWidget* parent! */ ); + rebuildTextBrush(); +} + +void KisTextBrush::rebuildTextBrush() +{ + lblFont->setText(QString(m_font.family() + ", %1").arg(m_font.pointSize())); + lblFont->setFont(m_font); + m_textBrushResource->setFont(m_font); + m_textBrushResource->setText(lineEdit->text()); + m_textBrushResource->updateBrush(); + emit(activatedResource(m_textBrushResource)); +} + +#include "kis_text_brush.moc" diff --git a/krita/ui/kis_text_brush.h b/krita/ui/kis_text_brush.h new file mode 100644 index 000000000..c1cb07c64 --- /dev/null +++ b/krita/ui/kis_text_brush.h @@ -0,0 +1,70 @@ +/* + * Copyright (c) 2004 Cyrille Berger <cberger@cberger.net> + * + * 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_TEXT_BRUSH_H_ +#define _KIS_TEXT_BRUSH_H_ + +#include "wdgtextbrush.h" +#include "kis_brush.h" + +class KisTextBrushResource : public KisBrush +{ + public: + KisTextBrushResource() : KisBrush("") + { + setBrushType(MASK); + } + KisTextBrushResource(const QString& txt, const QFont& font) : KisBrush("") + { + setFont(font); + setText(txt); + updateBrush(); + setBrushType(MASK); + }; + public: + virtual bool load() { return false; }; + void setText(const QString& txt) { m_txt = txt; }; + void setFont(const QFont& font) { m_font = font; }; + void updateBrush(); + private: + QFont m_font; + QString m_txt; +}; + +class KisTextBrush : public KisWdgTextBrush +{ + Q_OBJECT +public: + KisTextBrush(QWidget *parent, const char* name, const QString& caption); + +signals: + void activatedResource(KisResource *r); + +private slots: + void rebuildTextBrush(); + void getFont(); + +private: + KisTextBrushResource* m_textBrushResource; + QFont m_font; +}; + + + + +#endif diff --git a/krita/ui/kis_tool.cc b/krita/ui/kis_tool.cc new file mode 100644 index 000000000..7ea39e3c7 --- /dev/null +++ b/krita/ui/kis_tool.cc @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2002, 2003 Patrick Julien <freak@codepimps.org> + * + * 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 <qwidget.h> +#include <qstring.h> +#include <kaction.h> +#include <qlabel.h> + +#include <klocale.h> +#include <kdebug.h> + +#include "kis_tool.h" +#include "kis_tool.moc" + + +class KisTool::KisToolPrivate +{ +public: + QString uiname; + QLabel * optionWidget; +}; + +KisTool::KisTool(const QString & name) +{ + m_action = 0; + m_ownAction = false; + d = new KisToolPrivate(); + d->uiname = name; + d->optionWidget = 0; +} + +KisTool::~KisTool() +{ + if (m_ownAction) { + delete m_action; + m_action = 0; + } + delete d; +} + +QWidget* KisTool::createOptionWidget(QWidget* parent) +{ + + d->optionWidget = new QLabel(i18n("No options for %1.").arg(d->uiname), parent); + d->optionWidget->setCaption(d->uiname); + d->optionWidget->setAlignment(Qt::AlignCenter); + return d->optionWidget; +} + +QWidget* KisTool::optionWidget() +{ + return d->optionWidget; +} + diff --git a/krita/ui/kis_tool.h b/krita/ui/kis_tool.h new file mode 100644 index 000000000..570ec3432 --- /dev/null +++ b/krita/ui/kis_tool.h @@ -0,0 +1,143 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * Copyright (c) 2002, 2003 Patrick Julien <freak@codepimps.org> + * + * 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_TOOL_H_ +#define KIS_TOOL_H_ + +#include <qobject.h> +#include <qstring.h> + +#include <ksharedptr.h> +#include <kaction.h> + +#include "kis_shared_ptr_vector.h" +#include "kis_canvas_observer.h" + +class QCursor; +class QEvent; +class QKeyEvent; +class QRect; +class QWidget; +class KActionCollection; +class KRadioAction; +class KDialog; +class KisBrush; +class KisGradient; +class KisPattern; +class KisButtonPressEvent; +class KisButtonReleaseEvent; +class KisDoubleClickEvent; +class KisMoveEvent; +class KisCanvasPainter; + +enum enumToolType { + TOOL_SHAPE = 0, // Geometric shapes like ellipses and lines + TOOL_FREEHAND = 1, // Freehand drawing tools + TOOL_TRANSFORM = 2, // Tools that transform the layer + TOOL_FILL = 3, // Tools that fill parts of the canvas + TOOL_VIEW = 4, // Tools that affect the canvas: pan, zoom, etc. + TOOL_SELECT = 5 + +}; + +const Q_UINT8 NUMBER_OF_TOOLTYPES = 6; + +class KisTool : public QObject, public KisCanvasObserver, public KShared { + Q_OBJECT + +public: + KisTool(const QString & name); + virtual ~KisTool(); + +public: + + virtual void paint(KisCanvasPainter& gc) = 0; + virtual void paint(KisCanvasPainter& gc, const QRect& rc) = 0; + + /** + * This function is called after the creation of a tool to create the KAction corresponding + * to the tool. + * + * The code should look like : + * @code + * + * @endcode + */ + virtual void setup(KActionCollection *collection) = 0; + + virtual void buttonPress(KisButtonPressEvent *e) = 0; + virtual void move(KisMoveEvent *e) = 0; + virtual void buttonRelease(KisButtonReleaseEvent *e) = 0; + virtual void doubleClick(KisDoubleClickEvent *e) = 0; + virtual void keyPress(QKeyEvent *e) = 0; + virtual void keyRelease(QKeyEvent *e) = 0; + + virtual QCursor cursor() = 0; + virtual void setCursor(const QCursor& cursor) = 0; + /** + * This function is called to create the configuration widget of the tool. + * @param parent the parent of the widget + */ + virtual QWidget* createOptionWidget(QWidget* parent); + /** + * @return the current configuration widget. + */ + virtual QWidget* optionWidget(); + KRadioAction *action() const { return m_action; } + + /** + * Return true if this tool wants auto canvas-scrolling to + * work when this tool is active. + */ + virtual bool wantsAutoScroll() const { return true; } + + // Methods for integration with karbon-style toolbox + virtual Q_UINT32 priority() { return 0; } + virtual enumToolType toolType() { return TOOL_FREEHAND; } + virtual QString icon() { return m_action->icon(); } + virtual QString quickHelp() const { return ""; } + +public slots: + /** + * This slot is called when the tool is selected in the toolbox + */ + virtual void activate() = 0; + + /** + * deactivate is called when the tool gets deactivated because another + * tool is selected. Tools can then clean up after themselves. + */ + virtual void deactivate() = 0; + +private: + KisTool(const KisTool&); + KisTool& operator=(const KisTool&); + +protected: + KRadioAction *m_action; + bool m_ownAction; + +private: + class KisToolPrivate; + KisToolPrivate * d; + +}; + +#endif // KIS_TOOL_H_ + diff --git a/krita/ui/kis_tool_controller.h b/krita/ui/kis_tool_controller.h new file mode 100644 index 000000000..f135b86eb --- /dev/null +++ b/krita/ui/kis_tool_controller.h @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2003 Patrick Julien <freak@codepimps.org> + * + * 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_TOOL_CONTROLLER_H_ +#define KIS_TOOL_CONTROLLER_H_ + +class KisTool; + +class KisToolControllerInterface { +public: + KisToolControllerInterface() {}; + virtual ~KisToolControllerInterface() {}; + +public: + virtual void setCurrentTool(KisTool *tool) = 0; + virtual KisTool *currentTool() const = 0; + +private: + KisToolControllerInterface(const KisToolControllerInterface&); + KisToolControllerInterface& operator=(const KisToolControllerInterface&); +}; + +#endif // KIS_TOOL_CONTROLLER_H_ + diff --git a/krita/ui/kis_tool_dummy.cc b/krita/ui/kis_tool_dummy.cc new file mode 100644 index 000000000..8cb126957 --- /dev/null +++ b/krita/ui/kis_tool_dummy.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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 <qwidget.h> +#include <qstring.h> +#include <kaction.h> +#include <qlabel.h> + +#include <kaction.h> +#include <klocale.h> + +#include "kis_canvas_controller.h" +#include "kis_canvas_subject.h" +#include "kis_cursor.h" +#include "kis_tool_dummy.h" +#include "kis_button_press_event.h" +#include "kis_button_release_event.h" +#include "kis_move_event.h" + +KisToolDummy::KisToolDummy() + : super(i18n("No Active Tool")) +{ + setName("tool_dummy"); + m_subject = 0; + m_dragging = false; + m_optionWidget = 0; + setCursor(QCursor::forbiddenCursor); +} + +KisToolDummy::~KisToolDummy() +{ +} + +void KisToolDummy::update(KisCanvasSubject *subject) +{ + m_subject = subject; + super::update(m_subject); +} + +void KisToolDummy::buttonPress(KisButtonPressEvent *e) +{ + if (m_subject && !m_dragging && e->button() == Qt::LeftButton) { + KisCanvasController *controller = m_subject->canvasController(); + + m_origScrollX = controller->horzValue(); + m_origScrollY = controller->vertValue(); + m_dragPos = controller->windowToView(e->pos()); + m_dragging = true; + } +} + +void KisToolDummy::move(KisMoveEvent *e) +{ + if (m_subject && m_dragging) { + KisCanvasController *controller = m_subject->canvasController(); + + KisPoint currPos = controller->windowToView(e->pos()); + KisPoint delta = currPos - m_dragPos; + controller->scrollTo(m_origScrollX - delta.floorX(), m_origScrollY - delta.floorY()); + } +} + +void KisToolDummy::buttonRelease(KisButtonReleaseEvent *e) +{ + if (m_subject && m_dragging && e->button() == Qt::LeftButton) { + m_dragging = false; + } +} + +void KisToolDummy::setup(KActionCollection *collection) +{ + m_action = static_cast<KRadioAction *>(collection->action(name())); + + if (m_action == 0) { + m_action = new KRadioAction(i18n("&Dummy"), "tool_dummy", Qt::SHIFT+Qt::Key_H, this, SLOT(activate()), collection, name()); + m_action->setExclusiveGroup("tools"); + m_ownAction = true; + } +} + + +QWidget* KisToolDummy::createOptionWidget(QWidget* parent) +{ + m_optionWidget = new QLabel(i18n("Layer is locked or invisible."), parent); + m_optionWidget->setCaption(i18n("No Active Tool")); + m_optionWidget->setAlignment(Qt::AlignCenter); + return m_optionWidget; +} + +QWidget* KisToolDummy::optionWidget() +{ + return m_optionWidget; +} + + +#include "kis_tool_dummy.moc" diff --git a/krita/ui/kis_tool_dummy.h b/krita/ui/kis_tool_dummy.h new file mode 100644 index 000000000..3eb57ac4b --- /dev/null +++ b/krita/ui/kis_tool_dummy.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2004 Adrian Page <adrian@pagenet.plus.com> + * + * 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_TOOL_DUMMY_H_ +#define KIS_TOOL_DUMMY_H_ + +#include "kis_tool_non_paint.h" +#include "kis_tool_factory.h" +#include <koffice_export.h> + +#include "kis_point.h" + +class QLabel; +class KisCanvasSubject; + +/** + * The dummy tool is activated when a layer does not permit painting + * or any other destructive action. It shows a forbidden cursor, making + * it clear that you really cannot do anything here. + * + * Furthermore, it implements more or less the same things as the pan tool, + * so we can at least move the canvas around. + */ +class KRITATOOL_EXPORT KisToolDummy : public KisToolNonPaint { + + typedef KisToolNonPaint super; + Q_OBJECT + +public: + KisToolDummy(); + virtual ~KisToolDummy(); + + virtual void update(KisCanvasSubject *subject); + + virtual void setup(KActionCollection *collection); + virtual void buttonPress(KisButtonPressEvent *e); + virtual void move(KisMoveEvent *e); + virtual void buttonRelease(KisButtonReleaseEvent *e); + + virtual QWidget* createOptionWidget(QWidget* parent); + virtual QWidget* optionWidget(); + +private: + QLabel * m_optionWidget; + KisCanvasSubject *m_subject; + KisPoint m_dragPos; + Q_INT32 m_origScrollX; + Q_INT32 m_origScrollY; + bool m_dragging; +}; + +class KisToolDummyFactory : public KisToolFactory { + typedef KisToolFactory super; +public: + KisToolDummyFactory() : super() {}; + virtual ~KisToolDummyFactory() {}; + + virtual KisTool * createTool(KActionCollection * ac) { + KisTool * t = new KisToolDummy(); + Q_CHECK_PTR(t); + t->setup(ac); + return t; + } + virtual KisID id() { return KisID("dummy", i18n("Dummy Tool")); } +}; + + +#endif // KIS_TOOL_DUMMY_H_ + diff --git a/krita/ui/kis_tool_factory.h b/krita/ui/kis_tool_factory.h new file mode 100644 index 000000000..da1239e33 --- /dev/null +++ b/krita/ui/kis_tool_factory.h @@ -0,0 +1,41 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_TOOL_FACTORY_H_ +#define KIS_TOOL_FACTORY_H_ + +#include <klocale.h> + +#include "kis_id.h" +#include "kis_types.h" +#include "kactioncollection.h" + +class KisToolFactory : public KShared +{ + +public: + KisToolFactory() {} + virtual ~KisToolFactory() {}; + + virtual KisTool * createTool(KActionCollection * ac) = 0; + virtual KisID id() { return KisID("Abstract Tool", i18n("Abstract Tool")); } + +}; + +#endif // KIS_TOOL_FACTORY_H_ + diff --git a/krita/ui/kis_tool_freehand.cc b/krita/ui/kis_tool_freehand.cc new file mode 100644 index 000000000..0909ad9b3 --- /dev/null +++ b/krita/ui/kis_tool_freehand.cc @@ -0,0 +1,354 @@ +/* + * kis_tool_brush.cc - part of Krita + * + * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org> + * Copyright (c) 2004 Bart Coppens <kde@bartcoppens.be> + * + * 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 <qevent.h> +#include <qlabel.h> +#include <qlayout.h> +#include <qwidget.h> +#include <qrect.h> + +#include <kdebug.h> +#include <kaction.h> +#include <kcommand.h> +#include <klocale.h> + +#include "kis_canvas_subject.h" +#include "kis_undo_adapter.h" +#include "kis_selection.h" +#include "kis_painter.h" +#include "kis_fill_painter.h" +#include "kis_tool_freehand.h" +#include "kis_cursor.h" +#include "kis_button_press_event.h" +#include "kis_button_release_event.h" +#include "kis_move_event.h" +#include "kis_layer.h" +#include "kis_group_layer.h" +#include "kis_paint_layer.h" +#include "kis_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_boundary_painter.h" +#include "kis_brush.h" + +KisToolFreehand::KisToolFreehand(QString transactionText) + : super(transactionText), + m_dragDist ( 0 ), + m_transactionText(transactionText), + m_mode( HOVER ) +{ + m_painter = 0; + m_currentImage = 0; + m_tempLayer = 0; + m_paintIncremental = true; + m_paintOnSelection = false; + m_paintedOutline = false; +} + +KisToolFreehand::~KisToolFreehand() +{ +} + +void KisToolFreehand::update(KisCanvasSubject *subject) +{ + super::update(subject); + m_currentImage = m_subject->currentImg(); +} + +void KisToolFreehand::buttonPress(KisButtonPressEvent *e) +{ + if (!m_subject) return; + + if (!m_subject->currentBrush()) return; + + if (!m_currentImage || !m_currentImage->activeDevice()) return; + + if (e->button() == QMouseEvent::LeftButton) { + + m_currentImage->activeDevice()->lock( true ); + kdDebug() << ">>>>>>>>>>>>>>>>>>>Locking paint device\n"; + + // People complain that they can't start brush strokes outside of the image boundaries. + // This makes sense, especially when combined with BUG:132759, so commenting out the + // next line makes sense. + //if (!m_currentImage->bounds().contains(e->pos().floorQPoint())) return; + + initPaint(e); + paintAt(e->pos(), e->pressure(), e->xTilt(), e->yTilt()); + + m_prevPos = e->pos(); + m_prevPressure = e->pressure(); + m_prevXTilt = e->xTilt(); + m_prevYTilt = e->yTilt(); + + QRect r = m_painter->dirtyRect(); + if ( r.isValid() ) { + m_dirtyRect = r; + + r = QRect(r.left()-1, r.top()-1, r.width()+2, r.height()+2); //needed to update selectionvisualization + if (!m_paintOnSelection) { + m_currentImage->activeLayer()->setDirty(r); + } + else { + m_target->setDirty(r); + // Just update the canvas. XXX: After 1.5, find a better way to make sure tools don't set dirty what they didn't touch. + m_subject->canvasController()->updateCanvas( r ); + } + } + } +} + +void KisToolFreehand::buttonRelease(KisButtonReleaseEvent* e) +{ + if (e->button() == QMouseEvent::LeftButton && m_mode == PAINT) { + endPaint(); + m_currentImage->activeDevice()->lock( false ); + kdDebug() << ">>>>>>>>>>>>>>>>>>>UNLocking paint device\n"; + + } + KisToolPaint::buttonRelease(e); +} + +void KisToolFreehand::move(KisMoveEvent *e) +{ + if (m_mode == PAINT) { + + paintLine(m_prevPos, m_prevPressure, m_prevXTilt, m_prevYTilt, e->pos(), e->pressure(), e->xTilt(), e->yTilt()); + + m_prevPos = e->pos(); + m_prevPressure = e->pressure(); + m_prevXTilt = e->xTilt(); + m_prevYTilt = e->yTilt(); + + QRect r = m_painter->dirtyRect(); + + if (r.isValid()) { + m_dirtyRect |= r; + + if (!m_paintOnSelection) { + m_currentImage->activeLayer()->setDirty(r); + } + else { + // Just update the canvas + r = QRect(r.left()-1, r.top()-1, r.width()+2, r.height()+2); //needed to update selectionvisualization + m_target->setDirty(r); + m_subject->canvasController()->updateCanvas( r ); + } + } + } +} + +void KisToolFreehand::initPaint(KisEvent *) +{ + if (!m_currentImage || !m_currentImage->activeDevice()) return; + + m_mode = PAINT; + m_dragDist = 0; + + // Create painter + KisPaintDeviceSP device; + if (m_currentImage && (device = m_currentImage->activeDevice())) { + + if (m_painter) + delete m_painter; + + if (!m_paintIncremental) { + if (m_currentImage->undo()) + m_currentImage->undoAdapter()->beginMacro(m_transactionText); + + KisLayerSupportsIndirectPainting* layer; + if ((layer = dynamic_cast<KisLayerSupportsIndirectPainting*>( + m_currentImage->activeLayer().data()))) { + + // Hack for the painting of single-layered layers using indirect painting, + // because the group layer would not have a correctly synched cache ( + // because of an optimization that would happen, having this layer as + // projection). + KisLayer* l = layer->layer(); + KisPaintLayer* pl = dynamic_cast<KisPaintLayer*>(l); + if (l->parent() && (l->parent()->parent() == 0) + && (l->parent()->childCount() == 1) + && l->parent()->paintLayerInducesProjectionOptimization(pl)) { + // If there's a mask, device could've been the mask. The induce function + // should catch this, but better safe than sorry + l->parent()->resetProjection(pl->paintDevice()); + } + + m_target = new KisPaintDevice(m_currentImage->activeLayer(), + device->colorSpace()); + layer->setTemporaryTarget(m_target); + layer->setTemporaryCompositeOp(m_compositeOp); + layer->setTemporaryOpacity(m_opacity); + + if (device->hasSelection()) + m_target->setSelection(device->selection()); + } + } else { + m_target = device; + } + if(m_target->hasSelection()) m_target->selection()->startCachingExactRect(); + m_painter = new KisPainter( m_target ); + Q_CHECK_PTR(m_painter); + m_source = device; + if (currentImage()->undo()) m_painter->beginTransaction(m_transactionText); + } + + m_painter->setPaintColor(m_subject->fgColor()); + m_painter->setBackgroundColor(m_subject->bgColor()); + m_painter->setBrush(m_subject->currentBrush()); + + + // if you're drawing on a temporary layer, the layer already sets this + if (m_paintIncremental) { + m_painter->setCompositeOp(m_compositeOp); + m_painter->setOpacity(m_opacity); + } else { + m_painter->setCompositeOp(COMPOSITE_ALPHA_DARKEN); + m_painter->setOpacity( OPACITY_OPAQUE ); + + } + +/* kdDebug() << "target: " << m_target << "( " << m_target->name() << " )" + << " source: " << m_source << "( " << m_source->name() << " )" + << ", incremental " << m_paintIncremental + << ", paint on selection: " << m_paintOnSelection + << ", active device has selection: " << device->hasSelection() + << ", target has selection: " << m_target->hasSelection() + << endl; +*/ +} + +void KisToolFreehand::endPaint() +{ + m_mode = HOVER; + if (m_currentImage) { + + if (m_painter) { + // If painting in mouse release, make sure painter + // is destructed or end()ed + if (!m_paintIncremental) { + if (m_currentImage->undo()) + m_painter->endTransaction(); + KisPainter painter( m_source ); + painter.setCompositeOp(m_compositeOp); + if (m_currentImage->undo()) + painter.beginTransaction(m_transactionText); + painter.bitBlt(m_dirtyRect.x(), m_dirtyRect.y(), m_compositeOp, m_target, + m_opacity, + m_dirtyRect.x(), m_dirtyRect.y(), + m_dirtyRect.width(), m_dirtyRect.height()); + + KisLayerSupportsIndirectPainting* layer = + dynamic_cast<KisLayerSupportsIndirectPainting*>(m_source->parentLayer()); + layer->setTemporaryTarget(0); + m_source->parentLayer()->setDirty(m_dirtyRect); + + if (m_currentImage->undo()) { + m_currentImage->undoAdapter()->addCommand(painter.endTransaction()); + m_currentImage->undoAdapter()->endMacro(); + } + } else { + if (m_currentImage->undo()) + m_currentImage->undoAdapter()->addCommand(m_painter->endTransaction()); + } + } + delete m_painter; + m_painter = 0; + notifyModified(); + if(m_target->hasSelection()) m_target->selection()->stopCachingExactRect(); + } +} + +void KisToolFreehand::paintAt(const KisPoint &pos, + const double pressure, + const double xTilt, + const double yTilt) +{ + painter()->paintAt(pos, pressure, xTilt, yTilt); +} + +void KisToolFreehand::paintLine(const KisPoint & pos1, + const double pressure1, + const double xtilt1, + const double ytilt1, + const KisPoint & pos2, + const double pressure2, + const double xtilt2, + const double ytilt2) +{ + m_dragDist = painter()->paintLine(pos1, pressure1, xtilt1, ytilt1, pos2, pressure2, xtilt2, ytilt2, m_dragDist); +} + + +KisImageSP KisToolFreehand::currentImage() +{ + return m_currentImage; +} + + +void KisToolFreehand::paintOutline(const KisPoint& point) { + if (!m_subject) { + return; + } + + KisCanvasController *controller = m_subject->canvasController(); + + if (currentImage() && !currentImage()->bounds().contains(point.floorQPoint())) { + if (m_paintedOutline) { + controller->kiscanvas()->update(); + m_paintedOutline = false; + } + return; + } + + KisCanvas *canvas = controller->kiscanvas(); + canvas->repaint(); + + KisBrush *brush = m_subject->currentBrush(); + // There may not be a brush present, and we shouldn't crash in that case + if (brush) { + KisCanvasPainter gc(canvas); + QPen pen(Qt::SolidLine); + + KisPoint hotSpot = brush->hotSpot(); + + gc.setRasterOp(Qt::NotROP); + gc.setPen(pen); + gc.setViewport(0, 0, static_cast<Q_INT32>(canvas->width() * m_subject->zoomFactor()), + static_cast<Q_INT32>(canvas->height() * m_subject->zoomFactor())); + gc.translate((- controller->horzValue()) / m_subject->zoomFactor(), + (- controller->vertValue()) / m_subject->zoomFactor()); + + KisPoint topLeft = point - hotSpot; + + if (m_subject->currentPaintop().id() == "pen") { + // Pen paints on whole pixels only. + topLeft = topLeft.roundQPoint(); + } + + gc.translate(topLeft.x(), topLeft.y()); + + KisBoundaryPainter::paint(brush->boundary(), gc); + m_paintedOutline = true; + } +} + + +#include "kis_tool_freehand.moc" + diff --git a/krita/ui/kis_tool_freehand.h b/krita/ui/kis_tool_freehand.h new file mode 100644 index 000000000..1d29a9b7a --- /dev/null +++ b/krita/ui/kis_tool_freehand.h @@ -0,0 +1,102 @@ +/* + * kis_tool_brush.h - part of Krita + * + * Copyright (c) 2003-2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_TOOL_FREEHAND_H_ +#define KIS_TOOL_FREEHAND_H_ + +#include "kis_types.h" +#include "kis_tool_paint.h" +#include "kis_point.h" +#include "koffice_export.h" + +class KisPainter; +class KisBrush; +class KisEvent; +class KisPaintLayer; + + +class KRITACORE_EXPORT KisToolFreehand : public KisToolPaint { + Q_OBJECT + typedef KisToolPaint super; + +public: + KisToolFreehand(const QString transactionText); + virtual ~KisToolFreehand(); + + virtual void update(KisCanvasSubject *subject); + + virtual void buttonPress(KisButtonPressEvent *e); + virtual void move(KisMoveEvent *e); + virtual void buttonRelease(KisButtonReleaseEvent *e); + + virtual enumToolType toolType() { return TOOL_FREEHAND; } + +protected: + virtual void paintAt(const KisPoint &pos, + const double pressure, + const double xTilt, + const double yTilt); + + virtual void paintLine(const KisPoint & pos1, + const double pressure1, + const double xtilt1, + const double ytilt1, + const KisPoint & pos2, + const double pressure2, + const double xtilt2, + const double ytilt2); + + // XXX: why not make this a protected member attribute for the + // use of subclasses? BSAR. + inline KisPainter * painter() { return m_painter; }; + virtual void initPaint(KisEvent *e); + virtual void endPaint(); + + KisImageSP currentImage(); + + void paintOutline(const KisPoint& point); + +protected: + KisPoint m_prevPos; + double m_prevPressure; + double m_prevXTilt; + double m_prevYTilt; + double m_dragDist; + + bool m_paintIncremental; + bool m_paintOnSelection; + + KisPaintDeviceSP m_target; + KisLayerSP m_tempLayer; + KisPaintDeviceSP m_source; + + QString m_transactionText; + enumBrushMode m_mode; + KisPainter *m_painter; + + KisImageSP m_currentImage; +private: + bool m_paintedOutline; +}; + + + +#endif // KIS_TOOL_FREEHAND_H_ + diff --git a/krita/ui/kis_tool_manager.cc b/krita/ui/kis_tool_manager.cc new file mode 100644 index 000000000..663907404 --- /dev/null +++ b/krita/ui/kis_tool_manager.cc @@ -0,0 +1,303 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 "kopalettemanager.h" + +#include "kis_part_layer.h" +#include "kis_tool_manager.h" +#include "kis_tool_registry.h" +#include "kis_tool_dummy.h" +#include "kis_canvas_subject.h" +#include "kis_tool_controller.h" +#include "kis_view.h" +#include "kis_canvas.h" +#include "kis_cursor.h" +#include "KoToolBox.h" +#include "kis_image.h" +#include "kis_layer.h" +#include "kis_input_device.h" + + +KisToolManager::KisToolManager(KisCanvasSubject * parent, KisCanvasController * controller) + : m_subject(parent), + m_controller(controller) +{ + m_toolBox = 0; + m_oldTool = 0; + m_dummyTool = 0; + m_paletteManager = 0; + m_actionCollection = 0; + m_tools_disabled = false; + setup = false; +} + +KisToolManager::~KisToolManager() +{ + delete m_dummyTool; +} + +void KisToolManager::setUp(KoToolBox * toolbox, KoPaletteManager * paletteManager, KActionCollection * actionCollection) +{ + if (setup) { + resetToolBox( toolbox ); + return; + } + + m_toolBox = toolbox; + m_paletteManager = paletteManager; + m_actionCollection = actionCollection; + + // Dummy tool for when the layer is locked or invisible + if (!m_dummyTool) + m_dummyTool = KisToolDummyFactory().createTool(actionCollection); + + QValueVector<KisInputDevice> inputDevices = KisInputDevice::inputDevices(); + + for (Q_UINT32 inputDevice = 0; inputDevice < inputDevices.count(); inputDevice++) { + m_inputDeviceToolSetMap[inputDevices[inputDevice]] = KisToolRegistry::instance()->createTools(actionCollection, m_subject); + } + + m_tools = m_inputDeviceToolSetMap[KisInputDevice::mouse()]; + for (vKisTool_it it = m_tools.begin(); it != m_tools.end(); ++it) { + KisTool * t = *it; + if (!t) continue; + toolbox->registerTool( t->action(), t->toolType(), t->priority() ); + } + + toolbox->setupTools(); + + KisTool * t = findTool("tool_brush"); + if (t) { + t->activate(); + setCurrentTool(t); + } + setup = true; + +} + + + +void KisToolManager::youAintGotNoToolBox() +{ + m_toolBox = 0; + m_oldTool = currentTool(); +} + +void KisToolManager::resetToolBox(KoToolBox * toolbox) +{ + m_toolBox = toolbox; + + m_tools = m_inputDeviceToolSetMap[KisInputDevice::mouse()]; + for (vKisTool_it it = m_tools.begin(); it != m_tools.end(); ++it) { + KisTool * t = *it; + if (!t) continue; + m_toolBox->registerTool( t->action(), t->toolType(), t->priority() ); + } + + toolbox->setupTools(); + +#if 0 // Because I cannot find out how to reset the toolbox so the button is depressed, we reset the tool to brush + setCurrentTool(findTool("tool_brush")); +#else + if (m_oldTool) { + // restore the old current tool + setCurrentTool(m_oldTool); + m_oldTool = 0; + } +#endif + +} + +void KisToolManager::updateGUI() +{ + Q_ASSERT(m_subject); + if (m_subject == 0) { + // "Eek, no parent! + return; + } + + if (!m_toolBox) return; + + KisImageSP img = m_subject->currentImg(); + KisLayerSP l = 0; + + bool enable = false; + + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(l.data()); + + if (img) { + l = img->activeLayer(); + enable = l && !l->locked() && l->visible() && (partLayer == 0); + } + + m_toolBox->enableTools( enable ); + + KisTool * current = currentTool(); + + // XXX: Fix this properly: changing the visibility of a layer causes this cause to be executed twice! + if (!enable && current != m_dummyTool) { + // Store the current tool + m_oldTool = currentTool(); + // Set the dummy tool + if (!m_dummyTool) { + m_dummyTool = KisToolDummyFactory().createTool(m_actionCollection); + } + setCurrentTool(m_dummyTool); + m_tools_disabled = true; + } + else if (enable && m_tools_disabled) { + m_tools_disabled = false; + if (m_oldTool) { + // restore the old current tool + setCurrentTool(m_oldTool); + m_oldTool = 0; + } + else { + m_oldTool = 0; + KisTool * t = findTool("tool_brush"); + setCurrentTool(t); + } + } +} + +void KisToolManager::setCurrentTool(KisTool *tool) +{ + KisTool *oldTool = currentTool(); + KisCanvas * canvas = (KisCanvas*)m_controller->kiscanvas(); + + + if (oldTool) + { + oldTool->deactivate(); + oldTool->action()->setChecked( false ); + + m_paletteManager->removeWidget(krita::TOOL_OPTION_WIDGET); + } + + if (tool) { + + if (!tool->optionWidget()) { + tool->createOptionWidget(0); + } + QWidget * w = tool->optionWidget(); + + if (w) + m_paletteManager->addWidget(w, krita::TOOL_OPTION_WIDGET, krita::CONTROL_PALETTE ); + + m_inputDeviceToolMap[m_controller->currentInputDevice()] = tool; + m_controller->setCanvasCursor(tool->cursor()); + + canvas->enableMoveEventCompressionHint(dynamic_cast<KisToolNonPaint *>(tool) != NULL); + + m_subject->notifyObservers(); + + tool->action()->setChecked( true ); + tool->action()->activate(); + m_toolBox->slotSetTool(tool->name()); + } else { + m_inputDeviceToolMap[m_controller->currentInputDevice()] = 0; + m_controller->setCanvasCursor(KisCursor::arrowCursor()); + } + +} + +void KisToolManager::setCurrentTool( const QString & toolName ) +{ + setCurrentTool(findTool(toolName)); +} + +KisTool * KisToolManager::currentTool() const +{ + InputDeviceToolMap::const_iterator it = m_inputDeviceToolMap.find(m_controller->currentInputDevice()); + + if (it != m_inputDeviceToolMap.end()) { + return (*it).second; + } else { + return 0; + } +} + + +void KisToolManager::setToolForInputDevice(KisInputDevice oldDevice, KisInputDevice newDevice) +{ + InputDeviceToolSetMap::iterator vit = m_inputDeviceToolSetMap.find(oldDevice); + + if (vit != m_inputDeviceToolSetMap.end()) { + vKisTool& oldTools = (*vit).second; + for (vKisTool::iterator it = oldTools.begin(); it != oldTools.end(); ++it) { + KisTool *tool = *it; + KAction *toolAction = tool->action(); + toolAction->disconnect(SIGNAL(activated()), tool, SLOT(activate())); + } + } + KisTool *oldTool = currentTool(); + if (oldTool) + { + m_paletteManager->removeWidget(krita::TOOL_OPTION_WIDGET); + oldTool->deactivate(); + } + + + vit = m_inputDeviceToolSetMap.find(newDevice); + + Q_ASSERT(vit != m_inputDeviceToolSetMap.end()); + + vKisTool& tools = (*vit).second; + + for (vKisTool::iterator it = tools.begin(); it != tools.end(); ++it) { + KisTool *tool = *it; + KAction *toolAction = tool->action(); + connect(toolAction, SIGNAL(activated()), tool, SLOT(activate())); + } +} + +void KisToolManager::activateCurrentTool() +{ + KisTool * t = currentTool(); + if (t && t->action()) { + t->action()->activate(); + } +} + +KisTool * KisToolManager::findTool(const QString &toolName, KisInputDevice inputDevice) const +{ + if (inputDevice == KisInputDevice::unknown()) { + inputDevice = m_controller->currentInputDevice(); + } + + KisTool *tool = 0; + + InputDeviceToolSetMap::const_iterator vit = m_inputDeviceToolSetMap.find(inputDevice); + + Q_ASSERT(vit != m_inputDeviceToolSetMap.end()); + + const vKisTool& tools = (*vit).second; + + for (vKisTool::const_iterator it = tools.begin(); it != tools.end(); ++it) { + KisTool *t = *it; + if (t->name() == toolName) { + tool = t; + break; + } + } + + return tool; +} + + +#include "kis_tool_manager.moc" diff --git a/krita/ui/kis_tool_manager.h b/krita/ui/kis_tool_manager.h new file mode 100644 index 000000000..d56b16f93 --- /dev/null +++ b/krita/ui/kis_tool_manager.h @@ -0,0 +1,102 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_TOOL_MANAGER +#define KIS_TOOL_MANAGER + +#include <map> + +#include <qobject.h> + +#include "kis_tool_controller.h" +#include "kis_global.h" +#include "kis_tool_types.h" +#include "kis_input_device.h" + +class KoView; +class KisCanvasSubject; +class KisView; +class KisTool; +class KisToolRegistry; +class KisCanvasController; +class KoPaletteManager; +class KoToolBox; + +/** + * This class manages the activation and deactivation of tools for + * each input device. + */ +class KisToolManager : public QObject, public KisToolControllerInterface { + + Q_OBJECT + +public: + + KisToolManager(KisCanvasSubject * parent, KisCanvasController * controller); + ~KisToolManager(); + +public: + + void setUp(KoToolBox * toolbox, KoPaletteManager * paletteManager, KActionCollection * collection); + + // Called when the toolbox is deleted because the view was made inactive in favour of another view + void youAintGotNoToolBox(); + + void updateGUI(); + + virtual void setCurrentTool(KisTool *tool); + virtual void setCurrentTool(const QString & toolName); + + virtual KisTool *currentTool() const; + + void setToolForInputDevice(KisInputDevice oldDevice, KisInputDevice newDevice); + + KisTool *findTool(const QString &toolName, KisInputDevice inputDevice = KisInputDevice::unknown()) const; + + void activateCurrentTool(); + +private: + + void resetToolBox(KoToolBox * toolbox); + +private: + + typedef std::map<KisInputDevice, KisTool *> InputDeviceToolMap; + typedef std::map<KisInputDevice, vKisTool> InputDeviceToolSetMap; + + InputDeviceToolMap m_inputDeviceToolMap; + InputDeviceToolSetMap m_inputDeviceToolSetMap; + + KisCanvasSubject * m_subject; + KisCanvasController * m_controller; + + KoPaletteManager * m_paletteManager; + KActionCollection * m_actionCollection; + + KoToolBox * m_toolBox; + + KisTool * m_oldTool; + KisTool * m_dummyTool; + + vKisTool m_tools; + + bool m_tools_disabled; + bool setup; +}; + + +#endif diff --git a/krita/ui/kis_tool_non_paint.cc b/krita/ui/kis_tool_non_paint.cc new file mode 100644 index 000000000..efba4950e --- /dev/null +++ b/krita/ui/kis_tool_non_paint.cc @@ -0,0 +1,115 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <kdebug.h> + +#include "kis_image.h" +#include "kis_canvas_subject.h" +#include "kis_canvas_controller.h" +#include "kis_tool_controller.h" +#include "kis_tool_non_paint.h" + +KisToolNonPaint::KisToolNonPaint(const QString & UIName) + : super(UIName) +{ + m_subject = 0; +} + +KisToolNonPaint::~KisToolNonPaint() +{ +} + +void KisToolNonPaint::update(KisCanvasSubject *subject) +{ + m_subject = subject; +} + +void KisToolNonPaint::paint(KisCanvasPainter&) +{ +} + +void KisToolNonPaint::paint(KisCanvasPainter&, const QRect&) +{ +} + +void KisToolNonPaint::deactivate() +{ +} + +void KisToolNonPaint::buttonPress(KisButtonPressEvent *) +{ +} + +void KisToolNonPaint::move(KisMoveEvent *) +{ +} + +void KisToolNonPaint::buttonRelease(KisButtonReleaseEvent *) +{ +} + +void KisToolNonPaint::doubleClick(KisDoubleClickEvent *) +{ +} + +void KisToolNonPaint::keyPress(QKeyEvent *) +{ +} + +void KisToolNonPaint::keyRelease(QKeyEvent *) +{ +} + +QCursor KisToolNonPaint::cursor() +{ + return m_cursor; +} + +void KisToolNonPaint::setCursor(const QCursor& cursor) +{ + m_cursor = cursor; + + if (m_subject) { + KisToolControllerInterface *controller = m_subject->toolController(); + + if (controller && controller->currentTool() == this) { + m_subject->canvasController()->setCanvasCursor(m_cursor); + } + } +} + +void KisToolNonPaint::activate() +{ + if (m_subject) { + KisToolControllerInterface *controller = m_subject->toolController(); + + if (controller) + controller->setCurrentTool(this); + } +} + +void KisToolNonPaint::notifyModified() const +{ + if (m_subject && m_subject->currentImg()) { + + m_subject->currentImg()->setModified(); + } +} + +#include "kis_tool_non_paint.moc" diff --git a/krita/ui/kis_tool_non_paint.h b/krita/ui/kis_tool_non_paint.h new file mode 100644 index 000000000..21726627a --- /dev/null +++ b/krita/ui/kis_tool_non_paint.h @@ -0,0 +1,84 @@ +/* + * Copyright (c) 2002 Patrick Julien <freak@codepimps.org> + * + * 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_TOOL_NON_PAINT_H_ +#define KIS_TOOL_NON_PAINT_H_ + +#include <qcursor.h> +#include <qcolor.h> +#include <qwidget.h> + +#include "kis_global.h" +#include "kis_types.h" +#include "kis_tool.h" +#include <koffice_export.h> + +class QEvent; +class QKeyEvent; +class QPaintEvent; +class QRect; +class KDialog; +class KisCanvasSubject; + + +class KRITACORE_EXPORT KisToolNonPaint : public KisTool { + + Q_OBJECT + typedef KisTool super; + +public: + KisToolNonPaint(const QString & UIName); + virtual ~KisToolNonPaint(); + +// CanvasObserver +public: + virtual void update(KisCanvasSubject *subject); + +// KisTool +public: + virtual void paint(KisCanvasPainter& gc); + virtual void paint(KisCanvasPainter& gc, const QRect& rc); + + virtual void buttonPress(KisButtonPressEvent *e); + virtual void move(KisMoveEvent *e); + virtual void buttonRelease(KisButtonReleaseEvent *e); + virtual void doubleClick(KisDoubleClickEvent *e); + virtual void keyPress(QKeyEvent *e); + virtual void keyRelease(QKeyEvent *e); + + virtual QCursor cursor(); + virtual void setCursor(const QCursor& cursor); + + virtual enumToolType toolType() { return TOOL_VIEW; } + +public slots: + virtual void activate(); + virtual void deactivate(); + +protected: + void notifyModified() const; + +protected: + KisCanvasSubject *m_subject; + +private: + QCursor m_cursor; +}; + +#endif // KIS_TOOL_NON_PAINT_H_ + diff --git a/krita/ui/kis_tool_paint.cc b/krita/ui/kis_tool_paint.cc new file mode 100644 index 000000000..25129a829 --- /dev/null +++ b/krita/ui/kis_tool_paint.cc @@ -0,0 +1,260 @@ +/* + * Copyright (c) 2003 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 <qwidget.h> +#include <qrect.h> +#include <qlayout.h> +#include <qlabel.h> +#include <qpushbutton.h> +#include <qwhatsthis.h> +#include <qcheckbox.h> + +#include <kdebug.h> +#include <klocale.h> +#include <knuminput.h> +#include <kiconloader.h> + +#include "kis_button_release_event.h" +#include "kis_canvas_subject.h" +#include "kis_cmb_composite.h" +#include "kis_colorspace.h" +#include "kis_config.h" +#include "kis_cursor.h" +#include "kis_global.h" +#include "kis_image.h" +#include "kis_int_spinbox.h" +#include "kis_paint_device.h" +#include "kis_tool_controller.h" +#include "kis_tool_paint.h" + +KisToolPaint::KisToolPaint(const QString& UIName) + : super(UIName) +{ + m_subject = 0; + + m_UIName = UIName; + + m_optionWidget = 0; + m_optionWidgetLayout = 0; + + m_lbOpacity = 0; + m_slOpacity = 0; + m_lbComposite= 0; + m_cmbComposite = 0; + + m_opacity = OPACITY_OPAQUE; + m_compositeOp = COMPOSITE_OVER; +} + +KisToolPaint::~KisToolPaint() +{ +} + +void KisToolPaint::update(KisCanvasSubject *subject) +{ + m_subject = subject; + updateCompositeOpComboBox(); +} + +void KisToolPaint::paint(KisCanvasPainter&) +{ +} + +void KisToolPaint::paint(KisCanvasPainter&, const QRect&) +{ +} + +void KisToolPaint::deactivate() +{ +} + +void KisToolPaint::buttonPress(KisButtonPressEvent *) +{ +} + +void KisToolPaint::move(KisMoveEvent *) +{ +} + +void KisToolPaint::buttonRelease(KisButtonReleaseEvent * e) +{ + kdDebug() << "buttonRelease" << endl; + if(e->button() == Qt::MidButton) + { + kdDebug() << "switch" << endl; + KisColor bg = m_subject->bgColor(); + m_subject->setBGColor(m_subject->fgColor()); + m_subject->setFGColor(bg); + } +} + +void KisToolPaint::doubleClick(KisDoubleClickEvent *) +{ +} + +void KisToolPaint::keyPress(QKeyEvent *) +{ +} + +void KisToolPaint::keyRelease(QKeyEvent *) +{ +} + +QWidget* KisToolPaint::createOptionWidget(QWidget* parent) +{ + m_optionWidget = new QWidget(parent); + m_optionWidget->setCaption(m_UIName); + + m_lbOpacity = new QLabel(i18n("Opacity:"), m_optionWidget); + m_slOpacity = new KisIntSpinbox( m_optionWidget, "int_m_optionwidget"); + m_slOpacity->setRange( 0, 100); + m_slOpacity->setValue(m_opacity / OPACITY_OPAQUE * 100); + connect(m_slOpacity, SIGNAL(valueChanged(int)), this, SLOT(slotSetOpacity(int))); + + m_lbComposite = new QLabel(i18n("Mode:"), m_optionWidget); + m_cmbComposite = new KisCmbComposite(m_optionWidget); + connect(m_cmbComposite, SIGNAL(activated(const KisCompositeOp&)), this, SLOT(slotSetCompositeMode(const KisCompositeOp&))); + + QVBoxLayout* verticalLayout = new QVBoxLayout(m_optionWidget); + verticalLayout->setMargin(0); + verticalLayout->setSpacing(3); + + m_optionWidgetLayout = new QGridLayout(verticalLayout, 2, 3, 6); + + m_optionWidgetLayout->addWidget(m_lbOpacity, 0, 0); + m_optionWidgetLayout->addWidget(m_slOpacity, 0, 1); + + m_optionWidgetLayout->addWidget(m_lbComposite, 1, 0); + m_optionWidgetLayout->addWidget(m_cmbComposite, 1, 1); + + verticalLayout->addItem(new QSpacerItem(0,0,QSizePolicy::Fixed,QSizePolicy::Expanding)); + + if (!quickHelp().isEmpty()) { + QPushButton* push = new QPushButton(SmallIconSet( "help" ), "", m_optionWidget); + connect(push, SIGNAL(clicked()), this, SLOT(slotPopupQuickHelp())); + + QHBoxLayout* hLayout = new QHBoxLayout(m_optionWidget); + hLayout->addWidget(push); + hLayout->addItem(new QSpacerItem(0,0,QSizePolicy::Expanding,QSizePolicy::Fixed)); + verticalLayout->addLayout(hLayout); + } + return m_optionWidget; +} + +QWidget* KisToolPaint::optionWidget() +{ + return m_optionWidget; +} + +void KisToolPaint::addOptionWidgetLayout(QLayout *layout) +{ + Q_ASSERT(m_optionWidget != 0); + Q_ASSERT(m_optionWidgetLayout != 0); + int rowCount = m_optionWidgetLayout->numRows(); + m_optionWidgetLayout->addMultiCellLayout(layout, rowCount, rowCount, 0, 1); +} + +void KisToolPaint::addOptionWidgetOption(QWidget *control, QWidget *label) +{ + Q_ASSERT(m_optionWidget != 0); + Q_ASSERT(m_optionWidgetLayout != 0); + if(label) + { + m_optionWidgetLayout->addWidget(label, m_optionWidgetLayout->numRows(), 0); + m_optionWidgetLayout->addWidget(control, m_optionWidgetLayout->numRows()-1, 1); + } + else + m_optionWidgetLayout->addMultiCellWidget(control, m_optionWidgetLayout->numRows(), m_optionWidgetLayout->numRows(), 0, 1); +} + +void KisToolPaint::slotSetOpacity(int opacityPerCent) +{ + m_opacity = opacityPerCent * OPACITY_OPAQUE / 100; +} + +void KisToolPaint::slotSetCompositeMode(const KisCompositeOp& compositeOp) +{ + m_compositeOp = compositeOp; +} + +QCursor KisToolPaint::cursor() +{ + return m_cursor; +} + +void KisToolPaint::setCursor(const QCursor& cursor) +{ + m_cursor = cursor; + + if (m_subject) { + KisToolControllerInterface *controller = m_subject->toolController(); + + if (controller && controller->currentTool() == this) { + m_subject->canvasController()->setCanvasCursor(m_cursor); + } + } +} + +void KisToolPaint::activate() +{ + if (m_subject) { + KisToolControllerInterface *controller = m_subject->toolController(); + + if (controller) + controller->setCurrentTool(this); + + updateCompositeOpComboBox(); + + KisConfig cfg; + m_paintOutline = (cfg.cursorStyle() == CURSOR_STYLE_OUTLINE); + } +} + +void KisToolPaint::notifyModified() const +{ + if (m_subject && m_subject->currentImg()) { + m_subject->currentImg()->setModified(); + } +} + +void KisToolPaint::updateCompositeOpComboBox() +{ + if (m_optionWidget && m_subject) { + KisImageSP img = m_subject->currentImg(); + + if (img) { + KisPaintDeviceSP device = img->activeDevice(); + + if (device) { + KisCompositeOpList compositeOps = device->colorSpace()->userVisiblecompositeOps(); + m_cmbComposite->setCompositeOpList(compositeOps); + + if (compositeOps.find(m_compositeOp) == compositeOps.end()) { + m_compositeOp = COMPOSITE_OVER; + } + m_cmbComposite->setCurrentItem(m_compositeOp); + } + } + } +} + +void KisToolPaint::slotPopupQuickHelp() { + QWhatsThis::display(quickHelp()); +} + +#include "kis_tool_paint.moc" diff --git a/krita/ui/kis_tool_paint.h b/krita/ui/kis_tool_paint.h new file mode 100644 index 000000000..9aae6516f --- /dev/null +++ b/krita/ui/kis_tool_paint.h @@ -0,0 +1,118 @@ +/* + * Copyright (c) 2003 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_TOOL_PAINT_H_ +#define KIS_TOOL_PAINT_H_ + +#include <qcursor.h> +#include <qlayout.h> + +#include <koffice_export.h> + +#include "kis_tool.h" +#include "kis_composite_op.h" + +class QCheckBox; +class QEvent; +class QKeyEvent; +class QComboBox; +class QPaintEvent; +class QRect; +class QGridLayout; +class KDialog; +class KisCanvasSubject; +class QLabel; +class KisCmbComposite; +class KisIntSpinbox; + +enum enumBrushMode { + PAINT, + PAINT_STYLUS, + ERASE, + ERASE_STYLUS, + HOVER +}; + +class KRITACORE_EXPORT KisToolPaint : public KisTool { + + Q_OBJECT + typedef KisTool super; + +public: + KisToolPaint(const QString& UIName); + virtual ~KisToolPaint(); + +public: + virtual void update(KisCanvasSubject *subject); + + virtual void paint(KisCanvasPainter& gc); + virtual void paint(KisCanvasPainter& gc, const QRect& rc); + + virtual void buttonPress(KisButtonPressEvent *e); + virtual void move(KisMoveEvent *e); + virtual void buttonRelease(KisButtonReleaseEvent *e); + virtual void doubleClick(KisDoubleClickEvent *e); + virtual void keyPress(QKeyEvent *e); + virtual void keyRelease(QKeyEvent *e); + + virtual QCursor cursor(); + virtual void setCursor(const QCursor& cursor); + virtual QWidget* createOptionWidget(QWidget* parent); + virtual QWidget* optionWidget(); + virtual void addOptionWidgetOption(QWidget *control, QWidget *label = 0); + +public slots: + virtual void activate(); + virtual void deactivate(); + + void slotSetOpacity(int opacityPerCent); + void slotSetCompositeMode(const KisCompositeOp& compositeOp); + void slotPopupQuickHelp(); + +protected: + void notifyModified() const; + + // Add the tool-specific layout to the default option widget's layout. + void addOptionWidgetLayout(QLayout *layout); + +private: + void updateCompositeOpComboBox(); + +protected: + KisCanvasSubject *m_subject; + QRect m_dirtyRect; + Q_UINT8 m_opacity; + KisCompositeOp m_compositeOp; + bool m_paintOutline; + +private: + QString m_UIName; + + QCursor m_cursor; + + QWidget *m_optionWidget; + QGridLayout *m_optionWidgetLayout; + + QLabel *m_lbOpacity; + KisIntSpinbox *m_slOpacity; + QLabel *m_lbComposite; + KisCmbComposite *m_cmbComposite; +}; + +#endif // KIS_TOOL_PAINT_H_ + diff --git a/krita/ui/kis_tool_registry.cc b/krita/ui/kis_tool_registry.cc new file mode 100644 index 000000000..5e5e17d49 --- /dev/null +++ b/krita/ui/kis_tool_registry.cc @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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 "kdebug.h" +#include <kaction.h> +#include <kparts/plugin.h> +#include <kservice.h> +#include <ktrader.h> +#include <kparts/componentfactory.h> + +#include "kis_generic_registry.h" +#include "kis_types.h" +#include "kis_tool_registry.h" +#include "kis_tool.h" +#include "kis_tool_factory.h" +#include "kis_canvas_subject.h" +#include "kis_id.h" +#include "kis_debug_areas.h" + +KisToolRegistry *KisToolRegistry::m_singleton = 0; + +KisToolRegistry::KisToolRegistry() +{ + // Load all modules: color models, paintops, filters + KTrader::OfferList offers = KTrader::self()->query(QString::fromLatin1("Krita/Tool"), + QString::fromLatin1("(Type == 'Service') and " + "([X-Krita-Version] == 2)")); + + KTrader::OfferList::ConstIterator iter; + + for(iter = offers.begin(); iter != offers.end(); ++iter) + { + KService::Ptr service = *iter; + int errCode = 0; + KParts::Plugin* plugin = + KParts::ComponentFactory::createInstanceFromService<KParts::Plugin> ( service, this, 0, QStringList(), &errCode); + if ( plugin ) + kdDebug(DBG_AREA_PLUGINS) << "found plugin " << service->property("Name").toString() << "\n"; + else { + kdDebug(41006) << "found plugin " << service->property("Name").toString() << ", " << errCode << "\n"; + if( errCode == KParts::ComponentFactory::ErrNoLibrary) + { + kdWarning(41006) << " Error loading plugin was : ErrNoLibrary " << KLibLoader::self()->lastErrorMessage() << endl; + } + } + + } + +} + +KisToolRegistry::~KisToolRegistry() +{ +} + +KisToolRegistry* KisToolRegistry::instance() +{ + if(KisToolRegistry::m_singleton == 0) + { + KisToolRegistry::m_singleton = new KisToolRegistry(); + } + return KisToolRegistry::m_singleton; +} + + + +vKisTool KisToolRegistry::createTools(KActionCollection * ac, KisCanvasSubject *subject) const +{ + Q_ASSERT(subject); + + vKisTool tools; + + KisIDList factories = listKeys(); + + for (KisIDList::Iterator it = factories.begin(); it != factories.end(); ++it ) + { + KisToolFactorySP f = get(*it); + + KisTool * tool = f->createTool(ac); + subject->attach(tool); + tools.push_back(tool); + } + + subject->notifyObservers(); + + return tools; +} + +KisTool * KisToolRegistry::createTool(KActionCollection * ac, KisCanvasSubject * subject, KisID & id) const +{ + KisToolFactorySP f = get(id); + KisTool * t = f->createTool(ac); + subject->attach(t); + return t; +} + +#include "kis_tool_registry.moc" diff --git a/krita/ui/kis_tool_registry.h b/krita/ui/kis_tool_registry.h new file mode 100644 index 000000000..2fef3d1e5 --- /dev/null +++ b/krita/ui/kis_tool_registry.h @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2004 Boudewijn Rempt <boud@valdyas.org> + * + * 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_TOOL_REGISTRY_H_ +#define KIS_TOOL_REGISTRY_H_ + +#include <qobject.h> + +#include "kis_tool_types.h" +#include "kis_generic_registry.h" +#include <koffice_export.h> + +class KActionCollection; +class KisCanvasSubject; +class QStringList; + +/** + * A registry, similar to the tool and colormodel registry + * where new tool plugins can register themselves. KisToolRegistry + * in contrast to the paintop and colormodel registries, creates + * a vector containing instances of all registered tools. + */ +class KRITACORE_EXPORT KisToolRegistry : public QObject, public KisGenericRegistry<KisToolFactorySP>{ + + Q_OBJECT + +public: + virtual ~KisToolRegistry(); + + static KisToolRegistry* instance(); + + vKisTool createTools(KActionCollection * ac, KisCanvasSubject *subject) const; + KisTool * createTool(KActionCollection * ac, KisCanvasSubject * subject, KisID & id) const; + +private: + KisToolRegistry(); + KisToolRegistry(const KisToolRegistry&); + KisToolRegistry operator=(const KisToolRegistry&); + + static KisToolRegistry *m_singleton; +}; + +#endif // KIS_TOOL_REGISTRY_H_ + diff --git a/krita/ui/kis_tool_shape.cc b/krita/ui/kis_tool_shape.cc new file mode 100644 index 000000000..06c854a7c --- /dev/null +++ b/krita/ui/kis_tool_shape.cc @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2005 Adrian Page + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include <qwidget.h> +#include <qlayout.h> +#include <qcombobox.h> +#include <qlabel.h> + +#include <kdebug.h> +#include <klocale.h> + +#include "kis_tool_shape.h" +#include "wdgshapeoptions.h" + +KisToolShape::KisToolShape(const QString& UIName) : super(UIName) +{ + m_shapeOptionsWidget = 0; + m_optionLayout = 0; +} + +KisToolShape::~KisToolShape() +{ +} + +QWidget* KisToolShape::createOptionWidget(QWidget* parent) +{ + QWidget *widget = super::createOptionWidget(parent); + + m_shapeOptionsWidget = new WdgGeometryOptions(0); + Q_CHECK_PTR(m_shapeOptionsWidget); + + m_optionLayout = new QGridLayout(widget, 2, 1); + // super::addOptionWidgetLayout(m_optionLayout); + + m_shapeOptionsWidget->cmbFill->reparent(widget, QPoint(0,0), true); + m_shapeOptionsWidget->textLabel3->reparent(widget, QPoint(0,0), true); + addOptionWidgetOption(m_shapeOptionsWidget->cmbFill, m_shapeOptionsWidget->textLabel3); + + return widget; +} + +KisPainter::FillStyle KisToolShape::fillStyle(void) +{ + if (m_shapeOptionsWidget) { + return static_cast<KisPainter::FillStyle>(m_shapeOptionsWidget->cmbFill->currentItem()); + } else { + return KisPainter::FillStyleNone; + } +} + +#include "kis_tool_shape.moc" + diff --git a/krita/ui/kis_tool_shape.h b/krita/ui/kis_tool_shape.h new file mode 100644 index 000000000..b6c1b2db3 --- /dev/null +++ b/krita/ui/kis_tool_shape.h @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2005 Adrian Page + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef KIS_TOOL_SHAPE_H_ +#define KIS_TOOL_SHAPE_H_ + +#include <koffice_export.h> + +#include "kis_tool_paint.h" +#include "kis_painter.h" + +class QGridLayout; +class WdgGeometryOptions; + +class KRITACORE_EXPORT KisToolShape : public KisToolPaint { + + Q_OBJECT + typedef KisToolPaint super; + +public: + KisToolShape(const QString& UIName); + virtual ~KisToolShape(); + + virtual enumToolType toolType() { return TOOL_SHAPE; } + +protected: + virtual QWidget* createOptionWidget(QWidget* parent); + + KisPainter::FillStyle fillStyle(); + +private: + QGridLayout *m_optionLayout; + WdgGeometryOptions *m_shapeOptionsWidget; +}; + +#endif // KIS_TOOL_SHAPE_H_ + diff --git a/krita/ui/kis_tool_types.h b/krita/ui/kis_tool_types.h new file mode 100644 index 000000000..4811f75e5 --- /dev/null +++ b/krita/ui/kis_tool_types.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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_TOOL_TYPES_H_ +#define KIS_TOOL_TYPES_H_ + +#include <ksharedptr.h> +#include "kis_shared_ptr_vector.h" + + +class KisTool; +typedef KSharedPtr<KisTool> KisToolSP; +typedef KisSharedPtrVector<KisTool> vKisTool; +typedef vKisTool::iterator vKisTool_it; +typedef vKisTool::const_iterator vKisTool_cit; + +class KisToolFactory; +typedef KSharedPtr<KisToolFactory> KisToolFactorySP; + +#endif // KIS_TOOL_TYPES_H_ diff --git a/krita/ui/kis_view.cc b/krita/ui/kis_view.cc new file mode 100644 index 000000000..4bd4a2b17 --- /dev/null +++ b/krita/ui/kis_view.cc @@ -0,0 +1,4018 @@ +/* This file is part of KimageShop^WKrayon^WKrita + * + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * 1999 Michael Koch <koch@kde.org> + * 1999 Carsten Pfeiffer <pfeiffer@kde.org> + * 2002 Patrick Julien <freak@codepimps.org> + * 2003-2005 Boudewijn Rempt <boud@valdyas.org> + * 2004 Clarence Dang <dang@kde.org> + * + * 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 <algorithm> +#include <cmath> + +// Qt +#include <qapplication.h> +#include <qbutton.h> +#include <qcursor.h> +#include <qevent.h> +#include <qpainter.h> +#include <qscrollbar.h> +#include <qspinbox.h> +#include <qdockarea.h> +#include <qstringlist.h> +#include <qstyle.h> +#include <qpopupmenu.h> +#include <qvaluelist.h> +#include <qstringlist.h> +#include <qobjectlist.h> + +// KDE +#include <kis_meta_registry.h> +#include <kglobalsettings.h> +#include <dcopobject.h> +#include <kaction.h> +#include <kcolordialog.h> +#include <kiconloader.h> +#include <kfiledialog.h> +#include <klocale.h> +#include <kmessagebox.h> +#include <knotifyclient.h> +#include <kprinter.h> +#include <kpushbutton.h> +#include <kstatusbar.h> +#include <kstdaction.h> +#include <kinputdialog.h> +#include <kurldrag.h> +#include <kpopupmenu.h> +#include <kdebug.h> +#include <ksharedptr.h> +#include <ktoolbar.h> +#include <kparts/plugin.h> +#include <kservice.h> +#include <ktrader.h> +#include <kparts/componentfactory.h> +#include <kparts/event.h> + +// KOffice +#include <KoPartSelectAction.h> +#include <KoFilterManager.h> +#include <KoMainWindow.h> +#include <KoView.h> +#include <KoTabBar.h> +#include <ko_gray_widget.h> +#include <ko_hsv_widget.h> +#include <ko_rgb_widget.h> +#include <kopalettemanager.h> +#include <kopalette.h> + +// Local +#include "kis_brush.h" +#include "kis_button_press_event.h" +#include "kis_button_release_event.h" +#include "kis_canvas.h" +#include "kis_canvas_painter.h" +#include "kis_color.h" +#include "kis_colorspace_factory_registry.h" +#include "kis_config.h" +#include "kis_controlframe.h" +#include "kis_cursor.h" +#include "kis_doc.h" +#include "kis_double_click_event.h" +#include "kis_factory.h" +#include "kis_filter_strategy.h" +#include "kis_gradient.h" +#include "kis_group_layer.h" +#include "kis_adjustment_layer.h" +#include "kis_paint_device.h" +#include "kis_tool_freehand.h" +//#include "kis_guide.h" +#include "kis_layerbox.h" +#include "kis_import_catcher.h" +#include "kis_layer.h" +#include "kis_paint_layer.h" +#include "kis_move_event.h" +#include "kis_paint_device.h" +#include "kis_painter.h" +#include "kis_paintop_registry.h" +#include "kis_part_layer.h" +#include "kis_part_layer_handler.h" +#include "kis_pattern.h" +#include "kis_profile.h" +#include "kis_rect.h" +#include "kis_resource.h" +#include "kis_palette.h" +#include "kis_ruler.h" +#include "kis_selection.h" +#include "KoToolBox.h" +#include "kis_tool.h" +#include "kis_tool_manager.h" +#include "kis_transaction.h" +#include "kis_selected_transaction.h" +#include "kis_types.h" +#include "kis_undo_adapter.h" +#include "kis_view.h" +#include "kis_view_iface.h" +#include "kis_label_progress.h" +#include "kis_opengl_image_context.h" +#include "kis_background.h" +#include "kis_paint_device_action.h" +#include "kis_filter_configuration.h" +#include "kis_transform_worker.h" +#include "kis_shear_visitor.h" + +#include <kis_resourceserver.h> +#include <kis_resource_mediator.h> + +#include "kis_icon_item.h" +#include "kis_palette_widget.h" +#include "kis_birdeye_box.h" +#include "kis_color.h" +#include "kis_factory.h" + +// Dialog boxes +#include "kis_dlg_new_layer.h" +#include "kis_dlg_layer_properties.h" +#include "kis_dlg_preferences.h" +#include "kis_dlg_image_properties.h" +#include "kis_dlg_adjustment_layer.h" +#include "kis_dlg_adj_layer_props.h" + +// Action managers +#include "kis_selection_manager.h" +#include "kis_filter_manager.h" +#include "kis_grid_manager.h" +#include "kis_perspective_grid_manager.h" + +#include "kis_custom_palette.h" +#include "wdgpalettechooser.h" + +#include <fixx11h.h> + +// Time in ms that must pass after a tablet event before a mouse event is allowed to +// change the input device to the mouse. This is needed because mouse events are always +// sent to a receiver if it does not accept the tablet event. +#define MOUSE_CHANGE_EVENT_DELAY 100 + +KisView::KisView(KisDoc *doc, KisUndoAdapter *adapter, QWidget *parent, const char *name) + : super(doc, parent, name) + , KXMLGUIBuilder( shell() ) + , m_panning( false ) + , m_oldTool( 0 ) + , m_doc( doc ) + , m_canvas( 0 ) + , m_partHandler( 0 ) + , m_gridManager( 0 ) + , m_perspectiveGridManager( 0 ) + , m_selectionManager( 0 ) + , m_filterManager( 0 ) + , m_paletteManager( 0 ) + , m_toolManager( 0 ) + , m_actLayerVis( false ) + , m_hRuler( 0 ) + , m_vRuler( 0 ) + , m_imgFlatten( 0 ) + , m_imgMergeLayer( 0 ) + , m_imgRename( 0 ) + , m_imgResizeToLayer( 0 ) + , m_imgScan( 0 ) + , m_actionPartLayer( 0 ) + , m_layerAdd( 0 ) + , m_layerBottom( 0 ) + , m_layerDup( 0 ) + , m_layerHide( 0 ) + , m_layerLower( 0 ) + , m_layerProperties( 0 ) + , m_layerRaise( 0 ) + , m_layerRm( 0 ) + , m_layerSaveAs( 0 ) + , m_layerTop( 0 ) + , m_zoomIn( 0 ) + , m_zoomOut( 0 ) + , m_actualPixels( 0 ) + , m_actualSize( 0 ) + , m_fitToCanvas( 0 ) + , m_fullScreen( 0 ) + , m_imgProperties( 0 ) + , m_RulerAction( 0 ) + , m_guideAction( 0 ) + , m_dcop( 0 ) + , m_hScroll( 0 ) + , m_vScroll( 0 ) + , m_scrollX( 0 ) + , m_scrollY( 0 ) + , m_canvasXOffset( 0) + , m_canvasYOffset( 0) + , m_paintViewEnabled( false ) + , m_guiActivateEventReceived( false ) + , m_showEventReceived( false ) + , m_imageLoaded( false ) +// , m_currentGuide( 0 ) + , m_adapter( adapter ) + , m_statusBarZoomLabel( 0 ) + , m_statusBarSelectionLabel( 0 ) + , m_statusBarProfileLabel( 0 ) + , m_progress( 0 ) + , m_layerBox( 0 ) + , m_toolBox( 0 ) + , m_brush( 0 ) + , m_pattern( 0 ) + , m_gradient( 0 ) + , m_toolIsPainting( false ) + , m_monitorProfile( 0 ) + , m_HDRExposure( 0 ) +{ + + Q_ASSERT(doc); + Q_ASSERT(adapter); + Q_ASSERT(parent); + + KisConfig cfg; + + m_currentColorChooserDisplay = KisID("BLA"); + setFocusPolicy( QWidget::StrongFocus ); + + // Must come before input devices are referenced as this detects them. +#ifdef Q_WS_X11 + KisCanvasWidget::initX11Support(); +#endif + // Install event filter before we create any child widgets so they can see + // the tablet events. + qApp->installEventFilter(this); + + m_tabletEventTimer.start(); + m_inputDevice = KisInputDevice::mouse(); + + connect(&m_initialZoomTimer, SIGNAL(timeout()), SLOT(slotInitialZoomTimeout())); + + m_paletteManager = new KoPaletteManager(this, actionCollection(), "Krita palette manager"); + if (cfg.fixDockerWidth()) m_paletteManager->setFixedWidth( 360 ); + + m_paletteManager->createPalette( krita::CONTROL_PALETTE, i18n("Control box")); + m_paletteManager->createPalette( krita::COLORBOX, i18n("Colors")); + m_paletteManager->createPalette( krita::LAYERBOX, i18n("Layers")); + + m_selectionManager = new KisSelectionManager(this, doc); + m_filterManager = new KisFilterManager(this, doc); + m_toolManager = new KisToolManager(canvasSubject(), getCanvasController()); + m_gridManager = new KisGridManager(this); + m_perspectiveGridManager = new KisPerspectiveGridManager(this); + + // This needs to be set before the dockers are created. + m_image = m_doc->currentImage(); + KisColorSpace * cs = KisMetaRegistry::instance()->csRegistry()->getRGB8(); + m_fg = KisColor(Qt::black, cs); + m_bg = KisColor(Qt::white, cs); + + createDockers(); + + setInstance(KisFactory::instance(), false); + setClientBuilder( this ); + + if (!doc->isReadWrite()) + setXMLFile("krita_readonly.rc"); + else + setXMLFile("krita.rc"); + + KStdAction::keyBindings( mainWindow()->guiFactory(), SLOT( configureShortcuts() ), actionCollection() ); + + createLayerBox(); + + setupCanvas(); + m_canvas->hide(); + setupRulers(); + setupScrollBars(); + setupStatusBar(); + + setupActions(); + dcopObject(); + + + connect(this, SIGNAL(autoScroll(const QPoint &)), SLOT(slotAutoScroll(const QPoint &))); + + setMouseTracking(true); + + resetMonitorProfile(); + + layersUpdated(); + + m_brushesAndStuffToolBar = new KisControlFrame(mainWindow(), this); + + // Load all plugins + KTrader::OfferList offers = KTrader::self()->query(QString::fromLatin1("Krita/ViewPlugin"), + QString::fromLatin1("(Type == 'Service') and " + "([X-Krita-Version] == 2)")); + KTrader::OfferList::ConstIterator iter; + for(iter = offers.begin(); iter != offers.end(); ++iter) + { + KService::Ptr service = *iter; + int errCode = 0; + KParts::Plugin* plugin = + KParts::ComponentFactory::createInstanceFromService<KParts::Plugin> ( service, this, 0, QStringList(), &errCode); + if ( plugin ) { + kdDebug(41006) << "found plugin " << service->property("Name").toString() << "\n"; + insertChildClient(plugin); + } + else { + kdDebug(41006) << "found plugin " << service->property("Name").toString() << ", " << errCode << "\n"; + if( errCode == KParts::ComponentFactory::ErrNoLibrary) + { + kdWarning(41006) << " Error loading plugin was : ErrNoLibrary " << KLibLoader::self()->lastErrorMessage() << endl; + } + } + } + + if(!doc->isLoading()) + { + slotLoadingFinished(); + } else { + connect(doc, SIGNAL(loadingFinished()), this, SLOT(slotLoadingFinished())); + } + + setFocus(); +} + +KisView::~KisView() +{ + KisConfig cfg; + cfg.setShowRulers( m_RulerAction->isChecked() ); + + delete m_dcop; + delete m_paletteManager; + delete m_selectionManager; + delete m_filterManager; + delete m_toolManager; + +} + + +static Qt::Dock stringToDock( const QString& attrPosition ) +{ + KToolBar::Dock dock = KToolBar::DockTop; + if ( !attrPosition.isEmpty() ) { + if ( attrPosition == "top" ) + dock = Qt::DockTop; + else if ( attrPosition == "left" ) + dock = Qt::DockLeft; + else if ( attrPosition == "right" ) + dock = Qt::DockRight; + else if ( attrPosition == "bottom" ) + dock = Qt::DockBottom; + else if ( attrPosition == "floating" ) + dock = Qt::DockTornOff; + else if ( attrPosition == "flat" ) + dock = Qt::DockMinimized; + } + return dock; +} + +QWidget * KisView::createContainer( QWidget *parent, int index, const QDomElement &element, int &id ) +{ + if( element.attribute( "name" ) == "ToolBox" ) + { + m_toolBox = new KoToolBox(mainWindow(), "ToolBox", KisFactory::instance(), NUMBER_OF_TOOLTYPES); + m_toolBox->setLabel(i18n("Krita")); + m_toolManager->setUp(m_toolBox, m_paletteManager, actionCollection()); + + Dock dock = stringToDock( element.attribute( "position" ).lower() ); + + mainWindow()->addDockWindow( m_toolBox, dock, false); + mainWindow()->moveDockWindow( m_toolBox, dock, false, 0, 0 ); + } + + return KXMLGUIBuilder::createContainer( parent, index, element, id ); + +} + +void KisView::removeContainer( QWidget *container, QWidget *parent, QDomElement &element, int id ) +{ + Q_ASSERT(container); + + if( shell() && container == m_toolBox ) + { + delete m_toolBox; + m_toolManager->youAintGotNoToolBox(); + } + else { + KXMLGUIBuilder::removeContainer( container, parent, element, id ); + } +} + +KoPaletteManager * KisView::paletteManager() +{ + if (!m_paletteManager) { + m_paletteManager = new KoPaletteManager(this, actionCollection(), "Krita palette manager"); + Q_CHECK_PTR(m_paletteManager); + } + return m_paletteManager; +} + +void KisView::createLayerBox() +{ + m_layerBox = new KisLayerBox(this); + m_layerBox->setCaption(i18n("Layers")); + + connect(m_layerBox, SIGNAL(sigRequestLayer(KisGroupLayerSP, KisLayerSP)), + this, SLOT(addLayer(KisGroupLayerSP, KisLayerSP))); + connect(m_layerBox, SIGNAL(sigRequestGroupLayer(KisGroupLayerSP, KisLayerSP)), + this, SLOT(addGroupLayer(KisGroupLayerSP, KisLayerSP))); + connect(m_layerBox, SIGNAL(sigRequestAdjustmentLayer(KisGroupLayerSP, KisLayerSP)), + this, SLOT(addAdjustmentLayer(KisGroupLayerSP, KisLayerSP))); + connect(m_layerBox, SIGNAL(sigRequestPartLayer(KisGroupLayerSP, KisLayerSP, const KoDocumentEntry&)), + this, SLOT(addPartLayer(KisGroupLayerSP, KisLayerSP, const KoDocumentEntry&))); + connect(m_layerBox, SIGNAL(sigRequestLayerProperties(KisLayerSP)), + this, SLOT(showLayerProperties(KisLayerSP))); + connect(m_layerBox, SIGNAL(sigOpacityChanged(int, bool)), this, SLOT(layerOpacity(int, bool))); + connect(m_layerBox, SIGNAL(sigOpacityFinishedChanging(int, int)), + this, SLOT(layerOpacityFinishedChanging(int, int))); + connect(m_layerBox, SIGNAL(sigItemComposite(const KisCompositeOp&)), this, SLOT(layerCompositeOp(const KisCompositeOp&))); + + paletteManager()->addWidget(m_layerBox, "layerbox", krita::LAYERBOX, 0); + +} + +DCOPObject* KisView::dcopObject() +{ + if (!m_dcop) { + m_dcop = new KisViewIface(this); + Q_CHECK_PTR(m_dcop); + } + return m_dcop; +} + +void KisView::setupScrollBars() +{ + m_scrollX = 0; + m_scrollY = 0; + m_vScroll = new QScrollBar(QScrollBar::Vertical, this); + Q_CHECK_PTR(m_vScroll); + + m_hScroll = new QScrollBar(QScrollBar::Horizontal, this); + Q_CHECK_PTR(m_hScroll); + + m_vScroll->setGeometry(width() - 16, 20, 16, height() - 36); + m_hScroll->setGeometry(20, height() - 16, width() - 36, 16); + m_hScroll->setValue(0); + m_vScroll->setValue(0); + QObject::connect(m_vScroll, SIGNAL(valueChanged(int)), this, SLOT(scrollV(int))); + QObject::connect(m_hScroll, SIGNAL(valueChanged(int)), this, SLOT(scrollH(int))); +} + +void KisView::setupRulers() +{ + m_hRuler = new KisRuler(Qt::Horizontal, this); + Q_CHECK_PTR(m_hRuler); + + m_vRuler = new KisRuler(Qt::Vertical, this); + Q_CHECK_PTR(m_vRuler); + + m_hRuler->setGeometry(20, 0, width() - 20, 20); + m_vRuler->setGeometry(0, 20, 20, height() - 20); + + if (statusBar()) { + m_hRuler->installEventFilter(this); + m_vRuler->installEventFilter(this); + } +} + +#define EPSILON 1e-6 + +void KisView::updateStatusBarZoomLabel () +{ + if (zoom() < 1 - EPSILON) { + m_statusBarZoomLabel->setText(i18n("Zoom %1%").arg(zoom() * 100, 0, 'g', 4)); + } else { + m_statusBarZoomLabel->setText(i18n("Zoom %1%").arg(zoom() * 100, 0, 'f', 0)); + } + m_statusBarZoomLabel->setMaximumWidth(m_statusBarZoomLabel->fontMetrics().width(i18n("Zoom %1%").arg("0.8888 "))); +} + +void KisView::updateStatusBarSelectionLabel() +{ + if (m_statusBarSelectionLabel == 0) { + return; + } + + KisImageSP img = currentImg(); + if (img) { + KisPaintDeviceSP dev = img->activeDevice(); + if (dev) { + if (dev->hasSelection()) { + QRect r = dev->selection()->selectedExactRect(); + m_statusBarSelectionLabel->setText( i18n("Selection Active: x = %1 y = %2 width = %3 height = %4").arg(r.x()).arg(r.y()).arg( r.width()).arg( r.height())); + return; + } + } + } + + m_statusBarSelectionLabel->setText(i18n("No Selection")); +} + +void KisView::updateStatusBarProfileLabel() +{ + if (m_statusBarProfileLabel == 0) { + return; + } + + KisImageSP img = currentImg(); + if (!img) return; + + if (img->getProfile() == 0) { + m_statusBarProfileLabel->setText(i18n("No profile")); + } + else { + m_statusBarProfileLabel->setText(img->colorSpace()->id().name() + " " + img->getProfile()->productName()); + } +} + + +KisProfile * KisView::monitorProfile() +{ + if (m_monitorProfile == 0) { + resetMonitorProfile(); + } + return m_monitorProfile; +} + + +void KisView::resetMonitorProfile() +{ + m_monitorProfile = KisProfile::getScreenProfile(); + + if (m_monitorProfile == 0) { + KisConfig cfg; + QString monitorProfileName = cfg.monitorProfile(); + m_monitorProfile = KisMetaRegistry::instance()->csRegistry()->getProfileByName(monitorProfileName); + } + +} + +void KisView::setupStatusBar() +{ + KStatusBar *sb = statusBar(); + + if (sb) { + m_statusBarZoomLabel = new QLabel(sb); + addStatusBarItem(m_statusBarZoomLabel,1); + updateStatusBarZoomLabel(); + + m_statusBarSelectionLabel = new KSqueezedTextLabel(sb); + addStatusBarItem(m_statusBarSelectionLabel,2); + updateStatusBarSelectionLabel(); + + m_statusBarProfileLabel = new KSqueezedTextLabel(sb); + addStatusBarItem(m_statusBarProfileLabel,3); + updateStatusBarProfileLabel(); + + //int height = m_statusBarProfileLabel->height(); + + m_progress = new KisLabelProgress(this); + m_progress->setMaximumWidth(225); + m_progress->setMinimumWidth(225); + m_progress->setMaximumHeight(fontMetrics().height() ); + addStatusBarItem(m_progress, 2, true); + + m_progress->hide(); + } +} + +void KisView::setupActions() +{ + KisConfig cfg; + + m_selectionManager->setup(actionCollection()); + m_filterManager->setup(actionCollection()); + m_gridManager->setup(actionCollection()); + m_perspectiveGridManager->setup(actionCollection()); + + + m_fullScreen = KStdAction::fullScreen( NULL, NULL, actionCollection(), this ); + connect( m_fullScreen, SIGNAL( toggled( bool )), this, SLOT( slotUpdateFullScreen( bool ))); + + m_imgProperties = new KAction(i18n("Image Properties"), 0, this, SLOT(slotImageProperties()), actionCollection(), "img_properties"); + m_imgScan = 0; // How the hell do I get a KAction to the scan plug-in?!? + m_imgResizeToLayer = new KAction(i18n("Resize Image to Size of Current Layer"), 0, this, SLOT(imgResizeToActiveLayer()), actionCollection(), "resizeimgtolayer"); + + // view actions + m_zoomIn = KStdAction::zoomIn(this, SLOT(slotZoomIn()), actionCollection(), "zoom_in"); + m_zoomOut = KStdAction::zoomOut(this, SLOT(slotZoomOut()), actionCollection(), "zoom_out"); + m_actualPixels = new KAction(i18n("Actual Pixels"), "Ctrl+0", this, SLOT(slotActualPixels()), actionCollection(), "actual_pixels"); + m_actualSize = KStdAction::actualSize(this, SLOT(slotActualSize()), actionCollection(), "actual_size"); + m_actualSize->setEnabled(false); + m_fitToCanvas = KStdAction::fitToPage(this, SLOT(slotFitToCanvas()), actionCollection(), "fit_to_canvas"); + + // layer actions + m_layerAdd = new KAction(i18n("&Add..."), "Ctrl+Shift+N", this, SLOT(layerAdd()), actionCollection(), "insert_layer"); + + m_actionPartLayer = new KoPartSelectAction( i18n( "&Object Layer" ), "frame_query", + this, SLOT( addPartLayer() ), + actionCollection(), "insert_part_layer" ); + + + m_actionAdjustmentLayer = new KAction( i18n( "&Adjustment Layer" ), 0, + this, SLOT( addAdjustmentLayer() ), + actionCollection(), "insert_adjustment_layer" ); + + + m_layerRm = new KAction(i18n("&Remove"), 0, this, SLOT(layerRemove()), actionCollection(), "remove_layer"); + m_layerDup = new KAction(i18n("Duplicate"), 0, this, SLOT(layerDuplicate()), actionCollection(), "duplicate_layer"); + m_layerHide = new KToggleAction(i18n("&Hide"), 0, this, SLOT(layerToggleVisible()), actionCollection(), "hide_layer"); + m_layerHide->setCheckedState(KGuiItem(i18n("&Show"))); + m_layerHide->setChecked(false); + + m_layerRaise = new KAction(i18n("Raise"), "raise", "Ctrl+]", this, SLOT(layerRaise()), actionCollection(), "raiselayer"); + m_layerLower = new KAction(i18n("Lower"), "lower", "Ctrl+[", this, SLOT(layerLower()), actionCollection(), "lowerlayer"); + m_layerTop = new KAction(i18n("To Top"), "bring_forward", "Ctrl+Shift+]", this, SLOT(layerFront()), actionCollection(), "toplayer"); + m_layerBottom = new KAction(i18n("To Bottom"), "send_backward", "Ctrl+Shift+[", this, SLOT(layerBack()), actionCollection(), "bottomlayer"); + m_layerProperties = new KAction(i18n("Properties"), 0, this, SLOT(layerProperties()), actionCollection(), "layer_properties"); + (void)new KAction(i18n("I&nsert Image as Layer..."), 0, this, SLOT(slotInsertImageAsLayer()), actionCollection(), "insert_image_as_layer"); + m_layerSaveAs = new KAction(i18n("Save Layer as Image..."), "filesave", this, SLOT(saveLayerAsImage()), actionCollection(), "save_layer_as_image"); + (void)new KAction(i18n("Flip on &X Axis"), "view_left_right", 0, this, SLOT(mirrorLayerX()), actionCollection(), "mirrorLayerX"); + (void)new KAction(i18n("Flip on &Y Axis"), "view_top_bottom", 0, this, SLOT(mirrorLayerY()), actionCollection(), "mirrorLayerY"); + + m_createMask = new KAction(i18n("Create Mask"), 0, this, + SLOT(slotCreateMask()), actionCollection(), "create_mask"); + m_maskFromSelection = new KAction(i18n("Mask From Selection"), 0, this, + SLOT(slotMaskFromSelection()), actionCollection(), + "mask_fromsel"); + m_maskToSelection = new KAction(i18n("Mask to Selection"), 0, this, + SLOT(slotMaskToSelection()), actionCollection(), "mask_tosel"); + m_applyMask = new KAction(i18n("Apply Mask"), 0, this, SLOT(slotApplyMask()), + actionCollection(), "apply_mask"); + m_removeMask = new KAction(i18n("Remove Mask"), 0, this, + SLOT(slotRemoveMask()), actionCollection(), "remove_mask"); + m_showMask = new KToggleAction(i18n( "Show Mask" ), 0, this, + SLOT(slotShowMask()), actionCollection(), "show_mask"); + m_editMask = new KToggleAction(i18n( "Edit Mask" ), 0, this, + SLOT(slotEditMask()), actionCollection(), "edit_mask"); + + // image actions + m_imgFlatten = new KAction(i18n("&Flatten Image"), "Ctrl+Shift+E", this, SLOT(flattenImage()), actionCollection(), "flatten_image"); + m_imgMergeLayer = new KAction(i18n("&Merge with Layer Below"), "Ctrl+E", this, SLOT(mergeLayer()), actionCollection(), "merge_layer"); + + // setting actions + KStdAction::preferences(this, SLOT(preferences()), actionCollection(), "preferences"); + + m_RulerAction = new KToggleAction( i18n( "Show Rulers" ), "Ctrl+R", this, SLOT( showRuler() ), actionCollection(), "view_ruler" ); + m_RulerAction->setChecked(cfg.showRulers()); + m_RulerAction->setCheckedState(i18n("Hide Rulers")); + m_RulerAction->setWhatsThis( i18n("The rulers show the horizontal and vertical positions of the mouse on the image " + "and can be used to position your mouse at the right place on the canvas. <p>Uncheck this to disable " + "the rulers from being displayed." ) ); + + //m_guideAction = new KToggleAction( i18n( "Guide Lines" ), 0, this, SLOT( viewGuideLines() ), actionCollection(), "view_guidelines" ); + + // Add new palette + new KAction(i18n("Add New Palette..."), 0, this, SLOT(slotAddPalette()), + actionCollection(), "add_palette"); + new KAction(i18n("Edit Palette..."), 0, this, SLOT(slotEditPalette()), + actionCollection(), "edit_palette"); + + // XXX: This triggers a repaint of the image, but way too early + //showRuler(); + +} + +void KisView::resizeEvent(QResizeEvent *) +{ + if (!m_paintViewEnabled) { + startInitialZoomTimerIfReady(); + } + + KisImageSP img = currentImg(); + Q_INT32 scrollBarExtent = style().pixelMetric(QStyle::PM_ScrollBarExtent); + Q_INT32 drawH; + Q_INT32 drawW; + Q_INT32 docW; + Q_INT32 docH; + +// if (img) { +// KisGuideMgr *mgr = img->guides(); +// mgr->resize(size()); +// } + + docW = static_cast<Q_INT32>(ceil(docWidth() * zoom())); + docH = static_cast<Q_INT32>(ceil(docHeight() * zoom())); + + m_rulerThickness = m_RulerAction->isChecked() ? RULER_THICKNESS : 0; + drawH = height() - m_rulerThickness; + drawW = width() - m_rulerThickness; + + if (drawH < docH) { + // Will need vert scrollbar + drawW -= scrollBarExtent; + if (drawW < docW) + // Will need horiz scrollbar + drawH -= scrollBarExtent; + } else if (drawW < docW) { + // Will need horiz scrollbar + drawH -= scrollBarExtent; + if (drawH < docH) + // Will need vert scrollbar + drawW -= scrollBarExtent; + } + + m_vScroll->setEnabled(docH > drawH); + m_hScroll->setEnabled(docW > drawW); + + if (docH <= drawH && docW <= drawW) { + // we need no scrollbars + m_vScroll->hide(); + m_hScroll->hide(); + m_vScroll->setValue(0); + m_hScroll->setValue(0); + m_vScrollBarExtent = 0; + m_hScrollBarExtent = 0; + } else if (docH <= drawH) { + // we need a horizontal scrollbar only + m_vScroll->hide(); + m_vScroll->setValue(0); + m_hScroll->setRange(0, docW - drawW); + m_hScroll->setGeometry(m_rulerThickness, + height() - scrollBarExtent, + width() - m_rulerThickness, + scrollBarExtent); + m_hScroll->show(); + m_hScrollBarExtent = scrollBarExtent; + m_hScrollBarExtent = scrollBarExtent; + } else if(docW <= drawW) { + // we need a vertical scrollbar only + m_hScroll->hide(); + m_hScroll->setValue(0); + m_vScroll->setRange(0, docH - drawH); + m_vScroll->setGeometry(width() - scrollBarExtent, m_rulerThickness, scrollBarExtent, height() - m_rulerThickness); + m_vScroll->show(); + m_vScrollBarExtent = scrollBarExtent; + } else { + // we need both scrollbars + m_vScroll->setRange(0, docH - drawH); + m_vScroll->setGeometry(width() - scrollBarExtent, + m_rulerThickness, + scrollBarExtent, + height() -2* m_rulerThickness); + m_hScroll->setRange(0, docW - drawW); + m_hScroll->setGeometry(m_rulerThickness, + height() - scrollBarExtent, + width() - 2*m_rulerThickness, + scrollBarExtent); + m_vScroll->show(); + m_hScroll->show(); + m_vScrollBarExtent = scrollBarExtent; + m_hScrollBarExtent = scrollBarExtent; + } + + Q_INT32 oldCanvasXOffset = m_canvasXOffset; + Q_INT32 oldCanvasYOffset = m_canvasYOffset; + + if (docW < drawW) { + m_canvasXOffset = (drawW - docW) / 2; + } else { + m_canvasXOffset = 0; + } + + if (docH < drawH) { + m_canvasYOffset = (drawH - docH) / 2; + } else { + m_canvasYOffset = 0; + } + + //Check if rulers are visible + if( m_RulerAction->isChecked() ) + m_canvas->setGeometry(m_rulerThickness, m_rulerThickness, drawW, drawH); + else + m_canvas->setGeometry(0, 0, drawW, drawH); + m_canvas->show(); + + if (!m_canvas->isOpenGLCanvas()) { + + if (m_canvasPixmap.size() != QSize(drawW, drawH)) { + + Q_INT32 oldCanvasWidth = m_canvasPixmap.width(); + Q_INT32 oldCanvasHeight = m_canvasPixmap.height(); + + Q_INT32 newCanvasWidth = drawW; + Q_INT32 newCanvasHeight = drawH; + + QRegion exposedRegion = QRect(0, 0, newCanvasWidth, newCanvasHeight); + + // Increase size first so that we can copy the old image area to the new one. + m_canvasPixmap.resize(QMAX(oldCanvasWidth, newCanvasWidth), QMAX(oldCanvasHeight, newCanvasHeight)); + + if (!m_canvasPixmap.isNull()) { + + if (oldCanvasXOffset != m_canvasXOffset || oldCanvasYOffset != m_canvasYOffset) { + + Q_INT32 srcX; + Q_INT32 srcY; + Q_INT32 srcWidth; + Q_INT32 srcHeight; + Q_INT32 dstX; + Q_INT32 dstY; + + if (oldCanvasXOffset <= m_canvasXOffset) { + // Move to the right + srcX = 0; + dstX = m_canvasXOffset - oldCanvasXOffset; + srcWidth = oldCanvasWidth; + } else { + // Move to the left + srcX = oldCanvasXOffset - m_canvasXOffset; + dstX = 0; + srcWidth = newCanvasWidth; + } + + if (oldCanvasYOffset <= m_canvasYOffset) { + // Move down + srcY = 0; + dstY = m_canvasYOffset - oldCanvasYOffset; + srcHeight = oldCanvasHeight; + } else { + // Move up + srcY = oldCanvasYOffset - m_canvasYOffset; + dstY = 0; + srcHeight = newCanvasHeight; + } + + bitBlt(&m_canvasPixmap, dstX, dstY, &m_canvasPixmap, srcX, srcY, srcWidth, srcHeight); + exposedRegion -= QRegion(QRect(dstX, dstY, srcWidth, srcHeight)); + } else { + exposedRegion -= QRegion(QRect(0, 0, oldCanvasWidth, oldCanvasHeight)); + } + } + + m_canvasPixmap.resize(newCanvasWidth, newCanvasHeight); + + if (!m_canvasPixmap.isNull() && !exposedRegion.isEmpty()) { + + QMemArray<QRect> rects = exposedRegion.rects(); + + for (unsigned int i = 0; i < rects.count(); i++) { + QRect r = rects[i]; + updateQPaintDeviceCanvas(viewToWindow(r)); + } + } + } + } + + int fontheight = QFontMetrics(KGlobalSettings::generalFont()).height() * 3; + m_vScroll->setPageStep(drawH); + m_vScroll->setLineStep(fontheight); + m_hScroll->setPageStep(drawW); + m_hScroll->setLineStep(fontheight); + + m_hRuler->setGeometry(m_rulerThickness + m_canvasXOffset, 0, QMIN(docW, drawW), m_rulerThickness); + m_vRuler->setGeometry(0, m_rulerThickness + m_canvasYOffset, m_rulerThickness, QMIN(docH, drawH)); + + if (m_vScroll->isVisible()) + m_vRuler->updateVisibleArea(0, m_vScroll->value()); + else + m_vRuler->updateVisibleArea(0, 0); + + if (m_hScroll->isVisible()) + m_hRuler->updateVisibleArea(m_hScroll->value(), 0); + else + m_hRuler->updateVisibleArea(0, 0); + + if( m_RulerAction->isChecked() ) + { + m_hRuler->show(); + m_vRuler->show(); + } + else { + m_hRuler->hide(); + m_vRuler->hide(); + } + + emit viewTransformationsChanged(); +} + +void KisView::styleChange(QStyle& oldStyle) +{ + Q_UNUSED(oldStyle); + m_canvas->updateGeometry(); + refreshKisCanvas(); +} + +void KisView::paletteChange(const QPalette& oldPalette) +{ + Q_UNUSED(oldPalette); + refreshKisCanvas(); +} + +void KisView::showEvent(QShowEvent *) +{ + if (!m_showEventReceived) { + m_showEventReceived = true; + startInitialZoomTimerIfReady(); + } +} + +void KisView::updateReadWrite(bool readwrite) +{ + layerUpdateGUI(readwrite); +} + +Q_INT32 KisView::horzValue() const +{ + return m_hScroll->value() - m_canvasXOffset; +} + +Q_INT32 KisView::vertValue() const +{ + return m_vScroll->value() - m_canvasYOffset; +} + +void KisView::updateQPaintDeviceCanvas(const QRect& imageRect) +{ + QRect vr = windowToView(imageRect); + vr &= QRect(0, 0, m_canvas->width(), m_canvas->height()); + + if (!vr.isEmpty()) { + + QPainter gc; + + if (gc.begin(&m_canvasPixmap)) { + + KisImageSP img = currentImg(); + + if (img && m_paintViewEnabled) { + + QRect wr = viewToWindow(vr); + + if (wr.left() < 0 || wr.right() >= img->width() || wr.top() < 0 || wr.bottom() >= img->height()) { + // Erase areas outside document + QRegion rg(vr); + rg -= QRegion(windowToView(QRect(0, 0, img->width(), img->height()))); + + QMemArray<QRect> rects = rg.rects(); + + for (unsigned int i = 0; i < rects.count(); i++) { + QRect er = rects[i]; + gc.fillRect(er, colorGroup().mid()); + } + wr &= QRect(0, 0, img->width(), img->height()); + } + + if (!wr.isEmpty()) { + + KisImage::PaintFlags paintFlags = (KisImage::PaintFlags)KisImage::PAINT_BACKGROUND; + + if (m_actLayerVis) { + paintFlags = (KisImage::PaintFlags)(paintFlags|KisImage::PAINT_MASKINACTIVELAYERS); + } + + if (m_selectionManager->displaySelection()) + { + paintFlags = (KisImage::PaintFlags)(paintFlags|KisImage::PAINT_SELECTION); + } + + if (zoom() > 1.0 - EPSILON) { + + gc.setWorldXForm(true); + gc.translate(-horzValue(), -vertValue()); + gc.scale(zoomFactor(), zoomFactor()); + + m_image->renderToPainter(wr.left(), wr.top(), + wr.right(), wr.bottom(), gc, monitorProfile(), + paintFlags, HDRExposure()); + } else { + + QRect canvasRect = windowToView(wr); + QRect scaledImageRect = canvasRect; + scaledImageRect.moveBy(horzValue(), vertValue()); + + QSize scaledImageSize(static_cast<Q_INT32>(ceil(docWidth() * zoom())), + static_cast<Q_INT32>(ceil(docHeight() * zoom()))); + + QImage image = m_image->convertToQImage(scaledImageRect, scaledImageSize, + monitorProfile(), paintFlags, HDRExposure()); + + gc.drawImage(canvasRect.topLeft(), image, image.rect()); + + // Set up for the grid drawer. + gc.setWorldXForm(true); + gc.translate(-horzValue(), -vertValue()); + gc.scale(zoomFactor(), zoomFactor()); + } + + m_gridManager->drawGrid( wr, &gc ); + m_perspectiveGridManager->drawGrid( wr, &gc ); + } +// paintGuides(); + } else { + gc.fillRect(vr, colorGroup().mid()); + } + } + } +} + +void KisView::paintQPaintDeviceView(const QRegion& canvasRegion) +{ + Q_ASSERT(m_canvas->QPaintDeviceWidget() != 0); + + if (m_canvas->QPaintDeviceWidget() != 0 && !m_canvasPixmap.isNull()) { + QMemArray<QRect> rects = canvasRegion.rects(); + + for (unsigned int i = 0; i < rects.count(); i++) { + QRect r = rects[i]; + + bitBlt(m_canvas->QPaintDeviceWidget(), r.x(), r.y(), &m_canvasPixmap, + r.x(), r.y(), r.width(), r.height()); + } + + paintToolOverlay(canvasRegion); + } +} + +void KisView::updateOpenGLCanvas(const QRect& imageRect) +{ +#ifdef HAVE_GL + KisImageSP img = currentImg(); + + if (img && m_paintViewEnabled) { + Q_ASSERT(m_OpenGLImageContext != 0); + + if (m_OpenGLImageContext != 0) { + m_OpenGLImageContext->update(imageRect); + } + } +#else + Q_UNUSED(imageRect); +#endif +} + +void KisView::paintOpenGLView(const QRect& canvasRect) +{ +#ifdef HAVE_GL + if (!m_canvas->isUpdatesEnabled()) { + return; + } + + m_canvas->OpenGLWidget()->makeCurrent(); + + glDrawBuffer(GL_BACK); + + QColor widgetBackgroundColor = colorGroup().mid(); + + glClearColor(widgetBackgroundColor.red() / 255.0, widgetBackgroundColor.green() / 255.0, widgetBackgroundColor.blue() / 255.0, 1.0); + glClear(GL_COLOR_BUFFER_BIT); + + KisImageSP img = currentImg(); + + if (img && m_paintViewEnabled) { + + QRect vr = canvasRect; + vr &= QRect(0, 0, m_canvas->width(), m_canvas->height()); + + if (!vr.isNull()) { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glViewport(0, 0, m_canvas->width(), m_canvas->height()); + glOrtho(0, m_canvas->width(), m_canvas->height(), 0, -1, 1); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + glBindTexture(GL_TEXTURE_2D, m_OpenGLImageContext->backgroundTexture()); + + glTranslatef(m_canvasXOffset, m_canvasYOffset, 0.0); + + glEnable(GL_TEXTURE_2D); + glBegin(GL_QUADS); + + glTexCoord2f(0.0, 0.0); + glVertex2f(0.0, 0.0); + + glTexCoord2f((img->width() * zoom()) / KisOpenGLImageContext::BACKGROUND_TEXTURE_WIDTH, 0.0); + glVertex2f(img->width() * zoom(), 0.0); + + glTexCoord2f((img->width() * zoom()) / KisOpenGLImageContext::BACKGROUND_TEXTURE_WIDTH, + (img->height() * zoom()) / KisOpenGLImageContext::BACKGROUND_TEXTURE_HEIGHT); + glVertex2f(img->width() * zoom(), img->height() * zoom()); + + glTexCoord2f(0.0, (img->height() * zoom()) / KisOpenGLImageContext::BACKGROUND_TEXTURE_HEIGHT); + glVertex2f(0.0, img->height() * zoom()); + + glEnd(); + + glTranslatef(-m_canvasXOffset, -m_canvasYOffset, 0.0); + + glTranslatef(-horzValue(), -vertValue(), 0.0); + glScalef(zoomFactor(), zoomFactor(), 1.0); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + QRect wr = viewToWindow(QRect(0, 0, m_canvas->width(), m_canvas->height())); + wr &= QRect(0, 0, img->width(), img->height()); + + m_OpenGLImageContext->setHDRExposure(HDRExposure()); + + m_canvas->OpenGLWidget()->makeCurrent(); + + for (int x = (wr.left() / m_OpenGLImageContext->imageTextureTileWidth()) * m_OpenGLImageContext->imageTextureTileWidth(); + x <= wr.right(); + x += m_OpenGLImageContext->imageTextureTileWidth()) { + for (int y = (wr.top() / m_OpenGLImageContext->imageTextureTileHeight()) * m_OpenGLImageContext->imageTextureTileHeight(); + y <= wr.bottom(); + y += m_OpenGLImageContext->imageTextureTileHeight()) { + + glBindTexture(GL_TEXTURE_2D, m_OpenGLImageContext->imageTextureTile(x, y)); + + glBegin(GL_QUADS); + + glTexCoord2f(0.0, 0.0); + glVertex2f(x, y); + + glTexCoord2f(1.0, 0.0); + glVertex2f(x + m_OpenGLImageContext->imageTextureTileWidth(), y); + + glTexCoord2f(1.0, 1.0); + glVertex2f(x + m_OpenGLImageContext->imageTextureTileWidth(), y + m_OpenGLImageContext->imageTextureTileHeight()); + + glTexCoord2f(0.0, 1.0); + glVertex2f(x, y + m_OpenGLImageContext->imageTextureTileHeight()); + + glEnd(); + } + } + + glDisable(GL_TEXTURE_2D); + glDisable(GL_BLEND); + + m_gridManager->drawGrid(wr, 0, true); + m_perspectiveGridManager->drawGrid( wr, 0, true ); + + // Unbind the texture otherwise the ATI driver crashes when the canvas context is + // made current after the textures are deleted following an image resize. + glBindTexture(GL_TEXTURE_2D, 0); + + //paintGuides(); + } + } + + m_canvas->OpenGLWidget()->swapBuffers(); + + paintToolOverlay(QRegion(canvasRect)); + +#else + Q_UNUSED(canvasRect); +#endif +} + +void KisView::setInputDevice(KisInputDevice inputDevice) +{ + if (inputDevice != m_inputDevice) { + m_inputDevice = inputDevice; + + m_toolManager->setToolForInputDevice(m_inputDevice, inputDevice); + + if (m_toolManager->currentTool() == 0) { + m_toolManager->setCurrentTool(m_toolManager->findTool("tool_brush", m_inputDevice)); + } + else { + m_toolManager->setCurrentTool(m_toolManager->currentTool()); + } + m_toolManager->activateCurrentTool(); + + emit sigInputDeviceChanged(inputDevice); + } + +} + +KisInputDevice KisView::currentInputDevice() const +{ + return m_inputDevice; +} + + +KisCanvas *KisView::kiscanvas() const +{ + return m_canvas; +} + +void KisView::updateCanvas() +{ + if (m_image) { + updateCanvas(m_image->bounds()); + } +} + +void KisView::updateCanvas(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h) +{ + updateCanvas(QRect(x, y, w, h)); +} + +void KisView::updateCanvas(const QRect& imageRect) +{ + if (m_canvas->isOpenGLCanvas()) { + updateOpenGLCanvas(imageRect); + paintOpenGLView(windowToView(imageRect)); + } else { + updateQPaintDeviceCanvas(imageRect); + //m_canvas->update(windowToView(imageRect)); + m_canvas->repaint(windowToView(imageRect)); + } +} + +void KisView::refreshKisCanvas() +{ + QRect imageRect = viewToWindow(QRect(0, 0, m_canvas->width(), m_canvas->height())); + + if (m_image) { + imageRect |= m_image->bounds(); + } + + updateCanvas(imageRect); + + // Enable this if updateCanvas does an m_canvas->update() + //m_canvas->repaint(); +} + +void KisView::selectionDisplayToggled(bool displaySelection) +{ +#ifdef HAVE_GL + if (m_canvas->isOpenGLCanvas()) { + if (m_OpenGLImageContext) { + m_OpenGLImageContext->setSelectionDisplayEnabled(displaySelection); + } + } +#else + Q_UNUSED(displaySelection); +#endif + updateCanvas(); +} + +void KisView::layerUpdateGUI(bool enable) +{ + KisImageSP img = currentImg(); + + KisLayerSP layer; + Q_INT32 nlayers = 0; + Q_INT32 nvisible = 0; + + + + if (img) { + layer = img->activeLayer(); + nlayers = img->nlayers(); + nvisible = nlayers - img->nHiddenLayers(); + } + + KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>(layer.data()); + + if (pl && ( m_currentColorChooserDisplay != KisID("BLA") || + pl->paintDevice()->colorSpace()->id() != m_currentColorChooserDisplay)) { + if (pl->paintDevice()->colorSpace()->id() == KisID("WET")) { + m_paletteManager->hideWidget( "hsvwidget" ); + m_paletteManager->hideWidget( "rgbwidget" ); + m_paletteManager->hideWidget( "graywidget" ); + m_paletteManager->hideWidget( "palettewidget" ); + m_paletteManager->showWidget( "watercolor docker" ); + } + else { + m_paletteManager->hideWidget( "watercolor docker" ); + m_paletteManager->showWidget( "palettewidget" ); + m_paletteManager->showWidget( "graywidget" ); + m_paletteManager->showWidget( "rgbwidget" ); + m_paletteManager->showWidget( "hsvwidget" ); + } + m_currentColorChooserDisplay = pl->paintDevice()->colorSpace()->id(); + } + + enable = enable && img && layer && layer->visible() && !layer->locked(); + m_layerDup->setEnabled(enable); + m_layerRm->setEnabled(enable); + m_layerHide->setEnabled(img && layer); + m_layerProperties->setEnabled(enable); + m_layerSaveAs->setEnabled(enable); + m_layerRaise->setEnabled(enable && layer->prevSibling()); + m_layerLower->setEnabled(enable && layer->nextSibling()); + m_layerTop->setEnabled(enable && nlayers > 1 && layer != img->rootLayer()->firstChild()); + m_layerBottom->setEnabled(enable && nlayers > 1 && layer != img->rootLayer()->lastChild()); + + // XXX these should be named layer instead of img + m_imgFlatten->setEnabled(nlayers > 1); + m_imgMergeLayer->setEnabled(nlayers > 1 && layer && layer->nextSibling()); + + + m_selectionManager->updateGUI(); + m_filterManager->updateGUI(); + m_toolManager->updateGUI(); + m_gridManager->updateGUI(); + m_perspectiveGridManager->updateGUI(); + + + KisPartLayer * partLayer = dynamic_cast<KisPartLayer*>(layer.data()); + if (partLayer) { + setCanvasCursor( KisCursor::arrowCursor() ); + } + + if (img && img->activeDevice()) + emit currentColorSpaceChanged(img->activeDevice()->colorSpace()); + + imgUpdateGUI(); +} + + +void KisView::imgUpdateGUI() +{ + KisImageSP img = currentImg(); + + m_imgResizeToLayer->setEnabled(img && img->activeLayer()); + + updateStatusBarProfileLabel(); +} + +static const double zoomLevels[] = { + 1.0 / 500, + 1.0 / 333.333333, + 1.0 / 250, + 1.0 / 200, + 1.0 / 150, + 1.0 / 100, + 1.0 / 66.666667, + 1.0 / 50, + 1.0 / 33.333333, + 1.0 / 25, + 1.0 / 20, + 1.0 / 16, + 1.0 / 12, + 1.0 / 8, + 1.0 / 6, + 1.0 / 4, + 1.0 / 3, + 1.0 / 2, + 1.0 / 1.5, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 12, + 16 +}; + +#define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) +#define NUM_ZOOM_LEVELS ARRAY_SIZE(zoomLevels) + +#define FIRST_ZOOM_LEVEL_INDEX 0 +#define LAST_ZOOM_LEVEL_INDEX (NUM_ZOOM_LEVELS - 1) + +#define KISVIEW_MIN_ZOOM (zoomLevels[FIRST_ZOOM_LEVEL_INDEX]) +#define KISVIEW_MAX_ZOOM (zoomLevels[LAST_ZOOM_LEVEL_INDEX]) + +double KisView::nextZoomInLevel() const +{ + uint zoomLevelIndex = FIRST_ZOOM_LEVEL_INDEX; + + while (zoom() >= zoomLevels[zoomLevelIndex] && zoomLevelIndex < LAST_ZOOM_LEVEL_INDEX) { + zoomLevelIndex++; + } + + return zoomLevels[zoomLevelIndex]; +} + +double KisView::nextZoomOutLevel(double zoomLevel) const +{ + int zoomLevelIndex = LAST_ZOOM_LEVEL_INDEX; + + while (zoomLevel <= zoomLevels[zoomLevelIndex] && zoomLevelIndex > FIRST_ZOOM_LEVEL_INDEX) { + zoomLevelIndex--; + } + + return zoomLevels[zoomLevelIndex]; +} + +double KisView::nextZoomOutLevel() const +{ + return nextZoomOutLevel(zoom()); +} + +void KisView::zoomAroundPoint(double x, double y, double zf) +{ + // Disable updates while we change the scrollbar settings. + m_canvas->setUpdatesEnabled(false); + m_hScroll->setUpdatesEnabled(false); + m_vScroll->setUpdatesEnabled(false); + + if (x < 0 || y < 0) { + // Zoom about the centre of the current display + KisImageSP img = currentImg(); + + if (img) { + if (m_hScroll->isVisible()) { + KisPoint c = viewToWindow(KisPoint(m_canvas->width() / 2.0, m_canvas->height() / 2.0)); + x = c.x(); + } + else { + x = img->width() / 2.0; + } + + if (m_vScroll->isVisible()) { + KisPoint c = viewToWindow(KisPoint(m_canvas->width() / 2.0, m_canvas->height() / 2.0)); + y = c.y(); + } + else { + y = img->height() / 2.0; + } + } + else { + x = 0; + y = 0; + } + } + + setZoom(zf); + + Q_ASSERT(m_zoomIn); + Q_ASSERT(m_zoomOut); + + updateStatusBarZoomLabel (); + + m_zoomIn->setEnabled(zf < KISVIEW_MAX_ZOOM); + m_zoomOut->setEnabled(zf > KISVIEW_MIN_ZOOM); + resizeEvent(0); + + m_hRuler->setZoom(zf); + m_vRuler->setZoom(zf); + + if (m_hScroll->isVisible()) { + double vcx = m_canvas->width() / 2.0; + Q_INT32 scrollX = qRound(x * zoom() - vcx); + m_hScroll->setValue(scrollX); + } + + if (m_vScroll->isVisible()) { + double vcy = m_canvas->height() / 2.0; + Q_INT32 scrollY = qRound(y * zoom() - vcy); + m_vScroll->setValue(scrollY); + } + + // Now update everything. + m_canvas->setUpdatesEnabled(true); + m_hScroll->setUpdatesEnabled(true); + m_vScroll->setUpdatesEnabled(true); + m_hScroll->update(); + m_vScroll->update(); + + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(QRect(0, 0, m_canvas->width(), m_canvas->height())); + } else { + refreshKisCanvas(); + } + + emit viewTransformationsChanged(); +} + +void KisView::zoomTo(const KisRect& r) +{ + if (!r.isNull()) { + + double wZoom = fabs(m_canvas->width() / r.width()); + double hZoom = fabs(m_canvas->height() / r.height()); + + double zf = kMin(wZoom, hZoom); + + if (zf < KISVIEW_MIN_ZOOM) { + zf = KISVIEW_MIN_ZOOM; + } + else + if (zf > KISVIEW_MAX_ZOOM) { + zf = KISVIEW_MAX_ZOOM; + } + + zoomAroundPoint(r.center().x(), r.center().y(), zf); + } +} + +void KisView::zoomTo(const QRect& r) +{ + zoomTo(KisRect(r)); +} + +void KisView::zoomTo(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h) +{ + zoomTo(KisRect(x, y, w, h)); +} + +void KisView::zoomIn(Q_INT32 x, Q_INT32 y) +{ + zoomAroundPoint(x, y, nextZoomInLevel()); +} + +void KisView::zoomOut(Q_INT32 x, Q_INT32 y) +{ + zoomAroundPoint(x, y, nextZoomOutLevel()); +} + +void KisView::zoomIn() +{ + slotZoomIn(); +} + +void KisView::zoomOut() +{ + slotZoomOut(); +} + +void KisView::slotZoomIn() +{ + zoomIn(-1, -1); +} + +void KisView::slotZoomOut() +{ + zoomOut(-1, -1); +} + +void KisView::slotActualPixels() +{ + zoomAroundPoint(-1, -1, 1.0); +} + +void KisView::slotActualSize() +{ + //XXX later this should be update to take screen res and image res into consideration + zoomAroundPoint(-1, -1, 1.0); +} + +double KisView::fitToCanvasZoomLevel() const +{ + int fullCanvasWidth = width(); + + if (m_vRuler->isVisible()) { + fullCanvasWidth -= m_vRuler->width(); + } + + int fullCanvasHeight = height(); + + if (m_hRuler->isVisible()) { + fullCanvasHeight -= m_hRuler->height(); + } + + KisImageSP img = currentImg(); + if (img) { + double xZoomLevel = static_cast<double>(fullCanvasWidth) / img->width(); + double yZoomLevel = static_cast<double>(fullCanvasHeight) / img->height(); + + return QMIN(xZoomLevel, yZoomLevel); + } + else { + return 1; + } +} + +void KisView::slotFitToCanvas() +{ + zoomAroundPoint(-1, -1, fitToCanvasZoomLevel()); +} + +void KisView::setInitialZoomLevel() +{ + double zoomLevel = fitToCanvasZoomLevel(); + + if (zoomLevel > 1) { + zoomLevel = 1; + } else { + zoomLevel = nextZoomOutLevel(zoomLevel); + } + + zoomAroundPoint(-1, -1, zoomLevel); +} + +void KisView::imgResizeToActiveLayer() +{ + KisImageSP img = currentImg(); + KisLayerSP layer; + + if (img && (layer = img->activeLayer())) { + + if (m_adapter && m_adapter->undo()) { + m_adapter->beginMacro(i18n("Resize Image to Size of Current Layer")); + } + + img->lock(); + + QRect r = layer->exactBounds(); + img->resize(r.width(), r.height(), r.x(), r.y(), true); + + img->unlock(); + + if (m_adapter && m_adapter->undo()) { + m_adapter->endMacro(); + } + } +} + +void KisView::slotImageProperties() +{ + KisImageSP img = currentImg(); + + if (!img) return; + + KisDlgImageProperties dlg(img, this); + + if (dlg.exec() == QDialog::Accepted) { + if (dlg.imageWidth() != img->width() || + dlg.imageHeight() != img->height()) { + + resizeCurrentImage(dlg.imageWidth(), + dlg.imageHeight()); + } + Q_INT32 opacity = dlg.opacity(); + opacity = opacity * 255 / 100; + img->setName(dlg.imageName()); + img->setColorSpace(dlg.colorSpace()); + img->setResolution(dlg.resolution(), dlg.resolution()); + img->setDescription(dlg.description()); + img->setProfile(dlg.profile()); + } +} + +void KisView::slotInsertImageAsLayer() +{ + if (importImage() > 0) + m_doc->setModified(true); +} + +void KisView::slotAddPalette() +{ + KDialogBase* base = new KDialogBase(this, 0, true, i18n("Add Palette"), KDialogBase::Ok | KDialogBase::Cancel); + KisCustomPalette* p = new KisCustomPalette(base, "add palette", i18n("Add Palette"), this); + base->setMainWidget(p); + base->show(); +} + +void KisView::slotEditPalette() +{ + KisPaletteChooser chooser(this); + KisResourceServerBase* srv = KisResourceServerRegistry::instance()->get("PaletteServer"); + if (!srv) { + return; + } + QValueList<KisResource*> resources = srv->resources(); + QValueList<KisPalette*> palettes; + + for(uint i = 0; i < resources.count(); i++) { + KisPalette* palette = dynamic_cast<KisPalette*>(*resources.at(i)); + + chooser.paletteList->insertItem(palette->name()); + palettes.append(palette); + } + + if (chooser.exec() != QDialog::Accepted ) { + return; + } + + int index = chooser.paletteList->currentItem(); + if (index < 0) { + KMessageBox::error(this, i18n("No palette selected."), i18n("Palette")); + return; + } + + KDialogBase* base = new KDialogBase(this, 0, true, i18n("Edit Palette") , KDialogBase::Ok); + KisCustomPalette* cp = new KisCustomPalette(base, "edit palette", + i18n("Edit Palette"), this); + cp->setEditMode(true); + cp->setPalette(*palettes.at(index)); + base->setMainWidget(cp); + base->show(); +} + +void KisView::saveLayerAsImage() +{ + QStringList listMimeFilter = KoFilterManager::mimeFilter("application/x-krita", KoFilterManager::Export); + QString mimelist = listMimeFilter.join(" "); + + KFileDialog fd (QString::null, mimelist, this, "Export Layer", true); + fd.setCaption(i18n("Export Layer")); + fd.setMimeFilter(listMimeFilter); + fd.setOperationMode(KFileDialog::Saving); + + if (!fd.exec()) return; + + KURL url = fd.selectedURL(); + QString mimefilter = fd.currentMimeFilter(); + + if (url.isEmpty()) + return; + + + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP l = img->activeLayer(); + if (!l) return; + + QRect r = l->exactBounds(); + + KisDoc d; + d.prepareForImport(); + + KisImageSP dst = new KisImage(d.undoAdapter(), r.width(), r.height(), img->colorSpace(), l->name()); + d.setCurrentImage( dst ); + dst->addLayer(l->clone(),dst->rootLayer(),0); + + d.setOutputMimeType(mimefilter.latin1()); + d.exp0rt(url); +} + + + +Q_INT32 KisView::importImage(const KURL& urlArg) +{ + KisImageSP currentImage = currentImg(); + + if (!currentImage) { + return 0; + } + + KURL::List urls; + Q_INT32 rc = 0; + + if (urlArg.isEmpty()) { + QString mimelist = KoFilterManager::mimeFilter("application/x-krita", KoFilterManager::Import).join(" "); + urls = KFileDialog::getOpenURLs(QString::null, mimelist, 0, i18n("Import Image")); + } else { + urls.push_back(urlArg); + } + + if (urls.empty()) + return 0; + + for (KURL::List::iterator it = urls.begin(); it != urls.end(); ++it) { + new KisImportCatcher( *it, currentImage ); + } + + updateCanvas(); + + return rc; +} + +void KisView::rotateLayer180() +{ + rotateLayer( M_PI ); +} + +void KisView::rotateLayerLeft90() +{ + rotateLayer( M_PI/2 - 2*M_PI ); +} + +void KisView::rotateLayerRight90() +{ + rotateLayer( M_PI/2 ); +} + +void KisView::mirrorLayerX() +{ + if (!currentImg()) return; + KisPaintDeviceSP dev = currentImg()->activeDevice(); + if (!dev) return; + + KisTransaction * t = 0; + if (undoAdapter() && undoAdapter()->undo()) { + t = new KisTransaction(i18n("Mirror Layer X"), dev); + Q_CHECK_PTR(t); + } + + dev->mirrorX(); + + if (t) undoAdapter()->addCommand(t); + + m_doc->setModified(true); + layersUpdated(); + updateCanvas(); +} + +void KisView::mirrorLayerY() +{ + if (!currentImg()) return; + KisPaintDeviceSP dev = currentImg()->activeDevice(); + if (!dev) return; + + KisTransaction * t = 0; + if (undoAdapter() && undoAdapter()->undo()) { + t = new KisTransaction(i18n("Mirror Layer Y"), dev); + Q_CHECK_PTR(t); + } + + dev->mirrorY(); + + if (t) undoAdapter()->addCommand(t); + + m_doc->setModified(true); + layersUpdated(); + updateCanvas(); +} + +void KisView::scaleLayer(double sx, double sy, KisFilterStrategy *filterStrategy) +{ + if (!currentImg()) return; + + KisPaintDeviceSP dev = currentImg()->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (undoAdapter() && undoAdapter()->undo()) { + t = new KisSelectedTransaction(i18n("Scale Layer"), dev); + Q_CHECK_PTR(t); + } + + KisTransformWorker worker(dev, sx, sy, 0, 0, 0.0, 0, 0, m_progress, filterStrategy); + worker.run(); + + if (t) undoAdapter()->addCommand(t); + currentImg()->rootLayer()->setDirty(false); + m_doc->setModified(true); + layersUpdated(); + updateCanvas(); +} + +void KisView::rotateLayer(double radians) +{ + if (!currentImg()) return; + + KisPaintDeviceSP dev = currentImg()->activeDevice(); + if (!dev) return; + + KisSelectedTransaction * t = 0; + if (undoAdapter() && undoAdapter()->undo()) { + t = new KisSelectedTransaction(i18n("Rotate Layer"), dev); + Q_CHECK_PTR(t); + } + + KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->get(KisID("Triangle")); + QRect r; + if(dev->hasSelection()) + r = dev->selection()->selectedExactRect(); + else + r = dev->exactBounds(); + double cx = r.x()+r.width()/2.0; + double cy = r.y()+r.height()/2.0; + Q_INT32 tx = Q_INT32(cx*cos(radians) - cy*sin(radians) - cx + 0.5); + Q_INT32 ty = Q_INT32(cy*cos(radians) + cx*sin(radians) - cy + 0.5); + + KisTransformWorker tw(dev, 1.0, 1.0, 0, 0, radians, -tx, -ty, m_progress, filter); + tw.run(); + + if (t) undoAdapter()->addCommand(t); + + m_doc->setModified(true); + layersUpdated(); + updateCanvas(); +} + +void KisView::shearLayer(double angleX, double angleY) +{ + if (!currentImg()) return; + + KisLayerSP layer = currentImg()->activeLayer(); + if (!layer) return; + + KisUndoAdapter * undo = 0; + if ((undo = currentImg()->undoAdapter())) { + undo->beginMacro(i18n("Shear layer")); + } + + KisShearVisitor v(angleX, angleY, m_progress); + v.setUndoAdapter(undo); + layer->accept(v); + + if (undo) undo->endMacro(); + + m_doc->setModified(true); + layersUpdated(); + updateCanvas(); +} + +void KisView::flattenImage() +{ + KisImageSP img = currentImg(); + + if (img) { + bool doIt = true; + + if (img->nHiddenLayers() > 0) { + int answer = KMessageBox::warningYesNo(this, + i18n("The image contains hidden layers that will be lost."), + i18n("Flatten Image"), + i18n("&Flatten Image"), + KStdGuiItem::cancel()); + + if (answer != KMessageBox::Yes) { + doIt = false; + } + } + + if (doIt) { + img->flatten(); + } + } +} + +void KisView::mergeLayer() +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + img->mergeLayer(layer); +} + +void KisView::preferences() +{ +#ifdef HAVE_GL + bool canvasWasOpenGL = m_canvas->isOpenGLCanvas(); +#endif + + if (PreferencesDialog::editPreferences()) + { + KisConfig cfg; + m_paletteManager->slotResetFont(); + resetMonitorProfile(); + +#ifdef HAVE_GL + if (cfg.useOpenGL() != canvasWasOpenGL) { + + disconnectCurrentImg(); + + //XXX: Need to notify other views that this global setting has changed. + if (cfg.useOpenGL()) { + m_OpenGLImageContext = KisOpenGLImageContext::getImageContext(m_image, monitorProfile()); + m_canvas->createOpenGLCanvas(m_OpenGLImageContext->sharedContextWidget()); + } else + { + m_OpenGLImageContext = 0; + m_canvas->createQPaintDeviceCanvas(); + } + + connectCurrentImg(); + + resizeEvent(0); + } + + if (cfg.useOpenGL()) { + m_OpenGLImageContext->setMonitorProfile(monitorProfile()); + } +#endif + + refreshKisCanvas(); + + if (m_toolManager->currentTool()) { + setCanvasCursor(m_toolManager->currentTool()->cursor()); + } + +#if defined(EXTENDED_X11_TABLET_SUPPORT) + m_canvas->selectTabletDeviceEvents(); +#endif + + } +} + +void KisView::layerCompositeOp(const KisCompositeOp& compositeOp) +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + if (img->undo()) { + KNamedCommand *cmd = layer->setCompositeOpCommand(compositeOp); + cmd->execute(); + undoAdapter()->addCommand(cmd); + } +} + +// range: 0 - 100 +void KisView::layerOpacity(int opacity, bool dontundo) +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + opacity = int(float(opacity * 255) / 100 + 0.5); + if (opacity > 255) + opacity = 255; + + if (opacity == layer->opacity()) return; + + if (dontundo) + layer->setOpacity( opacity ); + else + { + if (img->undo()) { + KNamedCommand *cmd = layer->setOpacityCommand(opacity); + cmd->execute(); + undoAdapter()->addCommand(cmd); + } + } +} + +void KisView::layerOpacityFinishedChanging( int previous, int opacity ) +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + opacity = int(float(opacity * 255) / 100 + 0.5); + if (opacity > 255) + opacity = 255; + + previous = int(float(previous * 255) / 100 + 0.5); + if (previous > 255) + previous = 255; + + if (previous == opacity) return; + + if (img->undo()) { + KNamedCommand *cmd = layer->setOpacityCommand(previous, opacity); + m_adapter->addCommand(cmd); + } +} + + +void KisView::showRuler() +{ + if( m_RulerAction->isChecked() ) + { + m_hRuler->show(); + m_vRuler->show(); + } + else + { + m_hRuler->hide(); + m_vRuler->hide(); + } + + resizeEvent(0); + refreshKisCanvas(); +} + +void KisView::slotUpdateFullScreen(bool toggle) +{ + if (KoView::shell()) { + + uint newState = KoView::shell()->windowState(); + + if (toggle) { + newState |= Qt::WindowFullScreen; + } else { + newState &= ~Qt::WindowFullScreen; + } + + KoView::shell()->setWindowState(newState); + } +} + +Q_INT32 KisView::docWidth() const +{ + return currentImg() ? currentImg()->width() : 0; +} + +Q_INT32 KisView::docHeight() const +{ + return currentImg() ? currentImg()->height() : 0; +} + +void KisView::scrollTo(Q_INT32 x, Q_INT32 y) +{ + if (m_hScroll->isVisible()) { + m_hScroll->setValue(x); + } + if (m_vScroll->isVisible()) { + m_vScroll->setValue(y); + } +} + +void KisView::brushActivated(KisResource *brush) +{ + + m_brush = dynamic_cast<KisBrush*>(brush); + + if (m_brush ) + { + emit brushChanged(m_brush); + notifyObservers(); + } +} + +void KisView::patternActivated(KisResource *pattern) +{ + m_pattern = dynamic_cast<KisPattern*>(pattern); + + if (m_pattern) { + emit patternChanged(m_pattern); + notifyObservers(); + } +} + +void KisView::gradientActivated(KisResource *gradient) +{ + + m_gradient = dynamic_cast<KisGradient*>(gradient); + + if (m_gradient) { + emit gradientChanged(m_gradient); + notifyObservers(); + } +} + +void KisView::paintopActivated(const KisID & paintop, const KisPaintOpSettings *paintopSettings) +{ + if (paintop.id().isNull() || paintop.id().isEmpty()) { + return; + } + + m_paintop = paintop; + m_paintopSettings = paintopSettings; + emit paintopChanged(m_paintop, paintopSettings); + notifyObservers(); +} + +void KisView::setBGColor(const KisColor& c) +{ + m_bg = c; + notifyObservers(); + emit sigBGQColorChanged( c.toQColor() ); +} + +void KisView::setFGColor(const KisColor& c) +{ + m_fg = c; + notifyObservers(); + emit sigFGQColorChanged( c.toQColor() ); +} + +void KisView::slotSetFGColor(const KisColor& c) +{ + + m_fg = c; + notifyObservers(); +} + +void KisView::slotSetBGColor(const KisColor& c) +{ + + m_bg = c; + notifyObservers(); +} + +void KisView::slotSetFGQColor(const QColor& c) +{ + KisColorSpace * monitorSpace = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA"), m_monitorProfile); + setFGColor(KisColor(c, monitorSpace)); + emit sigFGQColorChanged(c); +} + +void KisView::slotSetBGQColor(const QColor& c) +{ + KisColorSpace * monitorSpace = KisMetaRegistry::instance()->csRegistry()->getColorSpace(KisID("RGBA"), m_monitorProfile); + setBGColor(KisColor(c, monitorSpace)); + emit sigBGQColorChanged(c); +} + + +void KisView::setupPrinter(KPrinter& printer) +{ + KisImageSP img = currentImg(); + + if (img) { + printer.setPageSelection(KPrinter::ApplicationSide); + printer.setPageSize(KPrinter::A4); + printer.setOrientation(KPrinter::Portrait); + } +} + +void KisView::print(KPrinter& printer) +{ + QPainter gc(&printer); + + KisImageSP img = currentImg(); + if (!img) return; + + printer.setFullPage(true); + gc.setClipping(false); + + KisConfig cfg; + QString printerProfileName = cfg.printerProfile(); + KisProfile * printerProfile = KisMetaRegistry::instance()->csRegistry() ->getProfileByName(printerProfileName); + + QRect r = img->bounds(); + img->renderToPainter(r.x(), r.y(), r.width(), r.height(), gc, printerProfile, KisImage::PAINT_IMAGE_ONLY, HDRExposure()); +} + +void KisView::paintToolOverlay(const QRegion& region) +{ + if (!region.isEmpty() && m_toolManager->currentTool() && !m_toolIsPainting) { + KisCanvasPainter gc(m_canvas); + + gc.setClipRegion(region); + gc.setClipping(true); + + // Prevent endless loop if the tool needs to have the canvas repainted + m_toolIsPainting = true; + m_toolManager->currentTool()->paint(gc, region.boundingRect()); + m_toolIsPainting = false; + } +} + +void KisView::canvasGotPaintEvent(QPaintEvent *event) +{ + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(event->rect()); + } else { + paintQPaintDeviceView(event->region()); + } +} + +void KisView::canvasGotButtonPressEvent(KisButtonPressEvent *e) +{ +#if defined(EXTENDED_X11_TABLET_SUPPORT) + // The event filter doesn't see tablet events going to the canvas. + if (e->device() != KisInputDevice::mouse()) { + m_tabletEventTimer.start(); + } +#endif // EXTENDED_X11_TABLET_SUPPORT + + if (e->device() != currentInputDevice()) { + if (e->device() == KisInputDevice::mouse()) { + if (m_tabletEventTimer.elapsed() > MOUSE_CHANGE_EVENT_DELAY) { + setInputDevice(KisInputDevice::mouse()); + } + } else { + setInputDevice(e->device()); + } + } + + KisImageSP img = currentImg(); + +// if (img) { +// QPoint pt = mapToScreen(e->pos().floorQPoint()); +// KisGuideMgr *mgr = img->guides(); +// +// m_lastGuidePoint = mapToScreen(e->pos().floorQPoint()); +// m_currentGuide = 0; +// +// if ((e->state() & ~Qt::ShiftButton) == Qt::NoButton) { +// KisGuideSP gd = mgr->find(static_cast<Q_INT32>(pt.x() / zoom()), static_cast<Q_INT32>(pt.y() / zoom()), QMAX(2.0, 2.0 / zoom())); +// +// if (gd) { +// m_currentGuide = gd; +// +// if ((e->button() == Qt::RightButton) || ((e->button() & Qt::ShiftButton) == Qt::ShiftButton)) { +// if (gd->isSelected()) +// mgr->unselect(gd); +// else +// mgr->select(gd); +// } else { +// if (!gd->isSelected()) { +// mgr->unselectAll(); +// mgr->select(gd); +// } +// } +// +// updateGuides(); +// return; +// } +// } +// } + if (e->button() == Qt::RightButton) { + QPopupMenu * m_popup = 0; + if (factory()) { + Q_ASSERT(factory()); + m_popup = (QPopupMenu *)factory()->container("image_popup", this); + } + if (m_popup) { + m_popup->popup(e->globalPos().roundQPoint()); + } + } + else if (e->device() == currentInputDevice() && m_toolManager->currentTool()) { + KisPoint p = viewToWindow(e->pos()); + // somewhat of a hack: we should actually test if we intersect with the scrollers, + // but the globalPos seems to be off by a few pixels + if (m_vScroll->draggingSlider() || m_hScroll->draggingSlider()) + return; + + if (m_toolManager->currentTool()->wantsAutoScroll()) { + enableAutoScroll(); + } + + KisButtonPressEvent ev(e->device(), p, e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->button(), e->state()); + m_toolManager->currentTool()->buttonPress(&ev); + } +} + +void KisView::canvasGotMoveEvent(KisMoveEvent *e) +{ +#if defined(EXTENDED_X11_TABLET_SUPPORT) + // The event filter doesn't see tablet events going to the canvas. + if (e->device() != KisInputDevice::mouse()) { + m_tabletEventTimer.start(); + } +#endif // EXTENDED_X11_TABLET_SUPPORT + + if (e->device() != currentInputDevice()) { + if (e->device() == KisInputDevice::mouse()) { + if (m_tabletEventTimer.elapsed() > MOUSE_CHANGE_EVENT_DELAY) { + setInputDevice(KisInputDevice::mouse()); + } + } else { + setInputDevice(e->device()); + } + } + + KisImageSP img = currentImg(); + + m_hRuler->updatePointer(e->pos().floorX() - m_canvasXOffset, e->pos().floorY() - m_canvasYOffset); + m_vRuler->updatePointer(e->pos().floorX() - m_canvasXOffset, e->pos().floorY() - m_canvasYOffset); + + KisPoint wp = viewToWindow(e->pos()); + +#if 0 + if (img && m_currentGuide) { + QPoint p = mapToScreen(e->pos().floorQPoint()); + KisGuideMgr *mgr = img->guides(); + + if (((e->state() & Qt::LeftButton) == Qt::LeftButton) && mgr->hasSelected()) { + eraseGuides(); + p -= m_lastGuidePoint; + + if (p.x()) + mgr->moveSelectedByX(p.x() / zoom()); + + if (p.y()) + mgr->moveSelectedByY(p.y() / zoom()); + + m_doc->setModified(true); + paintGuides(); + } + } else +#endif + if (e->device() == currentInputDevice() && m_toolManager->currentTool()) { + KisMoveEvent ev(e->device(), wp, e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->state()); + + m_toolManager->currentTool()->move(&ev); + } + +// m_lastGuidePoint = mapToScreen(e->pos().floorQPoint()); + emit cursorPosition(wp.floorX(), wp.floorY()); +} + +int KisView::leftBorder() const +{ + return m_rulerThickness; +} + +int KisView::rightBorder() const +{ + return m_hScrollBarExtent; +} + +int KisView::topBorder() const +{ + return m_rulerThickness; +} + +int KisView::bottomBorder() const +{ + return m_vScrollBarExtent; +} + +void KisView::mouseMoveEvent(QMouseEvent *e) +{ + KisMoveEvent ke(currentInputDevice(), e->pos(), e->globalPos(), PRESSURE_DEFAULT, 0, 0, e->state()); + canvasGotMoveEvent(&ke); +} + +void KisView::slotAutoScroll(const QPoint &p) +{ + scrollTo(horzValue()+p.x(), vertValue()+p.y()); +} + +void KisView::canvasGotButtonReleaseEvent(KisButtonReleaseEvent *e) +{ +#if defined(EXTENDED_X11_TABLET_SUPPORT) + // The event filter doesn't see tablet events going to the canvas. + if (e->device() != KisInputDevice::mouse()) { + m_tabletEventTimer.start(); + } +#endif // EXTENDED_X11_TABLET_SUPPORT + + if (e->device() != currentInputDevice()) { + if (e->device() == KisInputDevice::mouse()) { + if (m_tabletEventTimer.elapsed() > MOUSE_CHANGE_EVENT_DELAY) { + setInputDevice(KisInputDevice::mouse()); + } + } else { + setInputDevice(e->device()); + } + } + + KisImageSP img = currentImg(); + +// if (img && m_currentGuide) { +// m_currentGuide = 0; +// } else + if (e->device() == currentInputDevice() && m_toolManager->currentTool()) { + KisPoint p = viewToWindow(e->pos()); + KisButtonReleaseEvent ev(e->device(), p, e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->button(), e->state()); + + disableAutoScroll(); + if (m_toolManager->currentTool()) { + m_toolManager->currentTool()->buttonRelease(&ev); + } + } +} + +void KisView::canvasGotDoubleClickEvent(KisDoubleClickEvent *e) +{ +#if defined(EXTENDED_X11_TABLET_SUPPORT) + // The event filter doesn't see tablet events going to the canvas. + if (e->device() != KisInputDevice::mouse()) { + m_tabletEventTimer.start(); + } +#endif // EXTENDED_X11_TABLET_SUPPORT + + if (e->device() != currentInputDevice()) { + if (e->device() == KisInputDevice::mouse()) { + if (m_tabletEventTimer.elapsed() > MOUSE_CHANGE_EVENT_DELAY) { + setInputDevice(KisInputDevice::mouse()); + } + } else { + setInputDevice(e->device()); + } + } + + if (e->device() == currentInputDevice() && m_toolManager->currentTool()) { + KisPoint p = viewToWindow(e->pos()); + KisDoubleClickEvent ev(e->device(), p, e->globalPos(), e->pressure(), e->xTilt(), e->yTilt(), e->button(), e->state()); + + if (m_toolManager->currentTool()) { + m_toolManager->currentTool()->doubleClick(&ev); + } + } +} + +void KisView::canvasGotEnterEvent(QEvent *e) +{ + Q_UNUSED( e ); +} + +void KisView::canvasGotLeaveEvent (QEvent *e) +{ + Q_UNUSED( e ); +} + +void KisView::canvasGotMouseWheelEvent(QWheelEvent *event) +{ + //if(event->state() == ControlButton ) + //{ + if(event->delta() / 120 != 0) + { + if(event->delta() > 0) + { + zoomIn(); + } else { + zoomOut(); + } + if (m_oldTool) { + KisCanvasPainter gc(m_canvas); + m_oldTool->paint(gc); + } + } + //} else { + // QApplication::sendEvent(m_vScroll, event); + //} +} + +void KisView::canvasGotKeyPressEvent(QKeyEvent *event) +{ + if (!m_toolManager->currentTool()) { + event->ignore(); + return; + } + + if (event->key() == Qt::Key_Space) { + if (!m_panning) { + // Set tool temporarily to pan + m_panning = true; + m_oldTool = m_toolManager->currentTool(); + m_toolManager->setCurrentTool( "tool_pan" ); + } + else { + // Unset panning + m_panning = false; + m_toolManager->setCurrentTool( m_oldTool ); + m_oldTool = 0; + } + } + if (m_toolManager->currentTool()) + m_toolManager->currentTool()->keyPress(event); +} + +void KisView::canvasGotKeyReleaseEvent(QKeyEvent *event) +{ + if (m_toolManager->currentTool()) + m_toolManager->currentTool()->keyRelease(event); +} + +void KisView::canvasGotDragEnterEvent(QDragEnterEvent *event) +{ + bool accept = false; + + // Only accept drag if we're not busy, particularly as we may + // be showing a progress bar and calling qApp->processEvents(). + if (KURLDrag::canDecode(event) && QApplication::overrideCursor() == 0) { + accept = true; + } + + event->accept(accept); +} + +void KisView::canvasGotDropEvent(QDropEvent *event) +{ + KURL::List urls; + + if (KURLDrag::decode(event, urls)) + { + if (urls.count() > 0) { + enum enumActionId { + addLayerId = 1, + addDocumentId = 2, + cancelId + }; + + KPopupMenu popup(this, "drop_popup"); + + if (urls.count() == 1) { + if (currentImg() != 0) { + popup.insertItem(i18n("Insert as New Layer"), addLayerId); + } + popup.insertItem(i18n("Open in New Document"), addDocumentId); + } + else { + if (currentImg() != 0) { + popup.insertItem(i18n("Insert as New Layers"), addLayerId); + } + popup.insertItem(i18n("Open in New Documents"), addDocumentId); + } + + popup.insertSeparator(); + popup.insertItem(i18n("Cancel"), cancelId); + + int actionId = popup.exec(QCursor::pos()); + + if (actionId >= 0 && actionId != cancelId) { + for (KURL::List::ConstIterator it = urls.begin (); it != urls.end (); ++it) { + KURL url = *it; + + switch (actionId) { + case addLayerId: + importImage(url); + break; + case addDocumentId: + if (shell() != 0) { + shell()->openDocument(url); + } + break; + } + } + } + } + } +} + +void KisView::layerProperties() +{ + if (currentImg() && currentImg()->activeLayer()) + showLayerProperties(currentImg()->activeLayer()); +} + +namespace { + class KisChangeFilterCmd : public KNamedCommand { + typedef KNamedCommand super; + + public: + // The QStrings are the _serialized_ configs + KisChangeFilterCmd(KisAdjustmentLayerSP layer, + KisFilterConfiguration* config, + const QString& before, + const QString& after) : super(i18n("Change Filter")) + { + m_layer = layer; + m_config = config; + m_before = before; + m_after = after; + } + public: + virtual void execute() + { + QApplication::setOverrideCursor(KisCursor::waitCursor()); + m_config->fromXML(m_after); + //Q_ASSERT(m_after == m_config->toString()); + m_layer->setFilter(m_config); + m_layer->setDirty(); + QApplication::restoreOverrideCursor(); + } + + virtual void unexecute() + { + QApplication::setOverrideCursor(KisCursor::waitCursor()); + m_config->fromXML(m_before); + //Q_ASSERT(m_before == m_config->toString()); + m_layer->setFilter(m_config); + m_layer->setDirty(); + QApplication::restoreOverrideCursor(); + } + private: + KisAdjustmentLayerSP m_layer; + KisFilterConfiguration* m_config; + QString m_before; + QString m_after; + }; +} + +void KisView::showLayerProperties(KisLayerSP layer) +{ + Q_ASSERT( layer ); + if ( !layer ) return; + + KisColorSpace * cs = 0; + KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>( layer.data() ); + if ( pl ) { + cs = pl->paintDevice()->colorSpace(); + } + else { + cs = layer->image()->colorSpace(); + } + + + if (KisAdjustmentLayerSP alayer = dynamic_cast<KisAdjustmentLayer*>(layer.data())) + { + KisDlgAdjLayerProps dlg(alayer, alayer->name(), i18n("Adjustment Layer Properties"), this, "dlgadjlayerprops"); + QString before = dlg.filterConfiguration()->toString(); + if (dlg.exec() == QDialog::Accepted) + { + KisChangeFilterCmd * cmd = new KisChangeFilterCmd(alayer, + dlg.filterConfiguration(), + before, + dlg.filterConfiguration()->toString()); + cmd->execute(); + m_adapter->addCommand(cmd); + m_doc->setModified( true ); + } + } + else + { + KisDlgLayerProperties dlg(layer->name(), + layer->opacity(), + layer->compositeOp(), + cs); + if (dlg.exec() == QDialog::Accepted) + { + if (layer->name() != dlg.getName() || + layer->opacity() != dlg.getOpacity() || + layer->compositeOp() != dlg.getCompositeOp()) + { + QApplication::setOverrideCursor(KisCursor::waitCursor()); + m_adapter->beginMacro(i18n("Property Changes")); + layer->image()->setLayerProperties(layer, dlg.getOpacity(), dlg.getCompositeOp(), dlg.getName()); + layer->setDirty(); + m_adapter->endMacro(); + QApplication::restoreOverrideCursor(); + m_doc->setModified( true ); + } + } + } +} + +void KisView::layerAdd() +{ + KisImageSP img = currentImg(); + if (img && img->activeLayer()) { + addLayer(img->activeLayer()->parent(), img->activeLayer()); + } + else if (img) + addLayer(static_cast<KisGroupLayer*>(img->rootLayer().data()), 0); +} + +void KisView::addLayer(KisGroupLayerSP parent, KisLayerSP above) +{ + KisImageSP img = currentImg(); + if (img) { + KisConfig cfg; + QString profilename; + if(img->colorSpace()->getProfile()) + profilename = img->colorSpace()->getProfile()->productName(); + NewLayerDialog dlg(img->colorSpace()->id(), profilename, img->nextLayerName(), this); + + if (dlg.exec() == QDialog::Accepted) { + KisColorSpace* cs = KisMetaRegistry::instance()-> csRegistry() -> + getColorSpace(dlg.colorSpaceID(),dlg.profileName()); + KisLayerSP layer = new KisPaintLayer(img, dlg.layerName(), dlg.opacity(), cs); + if (layer) { + layer->setCompositeOp(dlg.compositeOp()); + img->addLayer(layer, parent.data(), above); + updateCanvas(); + } else { + KMessageBox::error(this, i18n("Could not add layer to image."), i18n("Layer Error")); + } + } + else { + img->rollBackLayerName(); + } + } +} + +void KisView::addGroupLayer(KisGroupLayerSP parent, KisLayerSP above) +{ + KisImageSP img = currentImg(); + if (img) { + QString profilename; + if(img->colorSpace()->getProfile()) + profilename = img->colorSpace()->getProfile()->productName(); + KisConfig cfg; + NewLayerDialog dlg(img->colorSpace()->id(), profilename, img->nextLayerName(), this); + dlg.setColorSpaceEnabled(false); + + if (dlg.exec() == QDialog::Accepted) { + KisLayerSP layer = new KisGroupLayer(img, dlg.layerName(), dlg.opacity()); + if (layer) { + layer->setCompositeOp(dlg.compositeOp()); + img->addLayer(layer, parent.data(), above); + updateCanvas(); + } else { + KMessageBox::error(this, i18n("Could not add layer to image."), i18n("Layer Error")); + } + } + } +} + +void KisView::addPartLayer() +{ + KisImageSP img = currentImg(); + if (!img) return; + + addPartLayer(img->rootLayer(), img->rootLayer()->firstChild(), m_actionPartLayer->documentEntry()); +} + +void KisView::addPartLayer(KisGroupLayerSP parent, KisLayerSP above, const KoDocumentEntry& entry) +{ + delete m_partHandler; // Only one at a time + m_partHandler = new KisPartLayerHandler(this, entry, parent, above); + + disconnect(m_canvas, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent*)), this, 0); + disconnect(m_canvas, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent*)), this, 0); + disconnect(m_canvas, SIGNAL(sigGotMoveEvent(KisMoveEvent*)), this, 0); + disconnect(m_canvas, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), this, 0); + + connect(m_canvas, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent*)), + m_partHandler, SLOT(gotButtonPressEvent(KisButtonPressEvent*))); + connect(m_canvas, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent*)), + m_partHandler, SLOT(gotButtonReleaseEvent(KisButtonReleaseEvent*))); + connect(m_canvas, SIGNAL(sigGotMoveEvent(KisMoveEvent*)), + m_partHandler, SLOT(gotMoveEvent(KisMoveEvent*))); + connect(m_canvas, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), + m_partHandler, SLOT(gotKeyPressEvent(QKeyEvent*))); + + connect(m_partHandler, SIGNAL(sigGotMoveEvent(KisMoveEvent*)), + this, SLOT(canvasGotMoveEvent(KisMoveEvent*))); + connect(m_partHandler, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), + this, SLOT(canvasGotKeyPressEvent(QKeyEvent*))); + connect(m_partHandler, SIGNAL(handlerDone()), + this, SLOT(reconnectAfterPartInsert())); +} + +void KisView::insertPart(const QRect& viewRect, const KoDocumentEntry& entry, + KisGroupLayerSP parent, KisLayerSP above) { + KisImageSP img = currentImg(); + if (!img) return; + + KoDocument* doc = entry.createDoc(m_doc); + if ( !doc ) + return; + + if ( !doc->showEmbedInitDialog(this) ) + return; + + QRect rect = viewToWindow(viewRect); + + KisChildDoc * childDoc = m_doc->createChildDoc(rect, doc); + + KisPartLayerImpl* partLayer = new KisPartLayerImpl(img, childDoc); + partLayer->setDocType(entry.service()->genericName()); + img->addLayer(partLayer, parent, above); + m_doc->setModified(true); + + reconnectAfterPartInsert(); +} + +void KisView::reconnectAfterPartInsert() { + connect(m_canvas, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent*)), + this, SLOT(canvasGotButtonPressEvent(KisButtonPressEvent*))); + connect(m_canvas, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent*)), + this, SLOT(canvasGotButtonReleaseEvent(KisButtonReleaseEvent*))); + connect(m_canvas, SIGNAL(sigGotMoveEvent(KisMoveEvent*)), + this, SLOT(canvasGotMoveEvent(KisMoveEvent*))); + connect(m_canvas, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), + this, SLOT(canvasGotKeyPressEvent(QKeyEvent*))); + + delete m_partHandler; + m_partHandler = 0; +} + +void KisView::addAdjustmentLayer() +{ + KisImageSP img = currentImg(); + if (!img) return; + + addAdjustmentLayer( img->activeLayer()->parent(), img->activeLayer() ); +} + +void KisView::addAdjustmentLayer(KisGroupLayerSP parent, KisLayerSP above) +{ + Q_ASSERT(parent); + Q_ASSERT(above); + + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP l = img->activeLayer(); + + KisPaintDeviceSP dev; + + // Argh! I hate having to cast, cast and cast again to see what kind of a layer I've got! + KisPaintLayer * pl = dynamic_cast<KisPaintLayer*>(l.data()); + if (pl) { + dev = pl->paintDevice(); + } + else { + KisGroupLayer * gl = dynamic_cast<KisGroupLayer*>(l.data()); + if (gl) { + dev = gl->projection(img->bounds()); + } + else { + KisAdjustmentLayer * al = dynamic_cast<KisAdjustmentLayer*>(l.data()); + if (al) { + dev = al->cachedPaintDevice(); + } + else { + return; + } + } + } + + KisDlgAdjustmentLayer dlg(img, img->nextLayerName(), i18n("New Adjustment Layer"), this, "dlgadjustmentlayer"); + if (dlg.exec() == QDialog::Accepted) { + KisSelectionSP selection = 0; + if (dev->hasSelection()) { + selection = dev->selection(); + } + KisFilterConfiguration * filter = dlg.filterConfiguration(); + QString name = dlg.layerName(); + + addAdjustmentLayer( parent, above, name, filter, selection); + + } +} + +void KisView::addAdjustmentLayer(KisGroupLayerSP parent, KisLayerSP above, const QString & name, + KisFilterConfiguration * filter, KisSelectionSP selection) +{ + Q_ASSERT(parent); + Q_ASSERT(above); + Q_ASSERT(filter); + + KisImageSP img = currentImg(); + if (!img) return; + + KisAdjustmentLayer * l = new KisAdjustmentLayer(img, name, filter, selection); + img->addLayer(l, parent, above); +} + +void KisView::slotChildActivated(bool a) { + // It should be so that the only part (child) we can activate, is the current layer: + if (currentImg() && currentImg()->activeLayer()) + { + if (a) { + currentImg()->activeLayer()->activate(); + } else { + currentImg()->activeLayer()->deactivate(); + } + } + + super::slotChildActivated(a); +} + +void KisView::layerRemove() +{ + KisImageSP img = currentImg(); + + if (img) { + KisLayerSP layer = img->activeLayer(); + + if (layer) { + + + img->removeLayer(layer); + + if (layer->parent()) + layer->parent()->setDirty(layer->extent()); + + updateCanvas(); + layerUpdateGUI(img->activeLayer() != 0); + } + } +} + +void KisView::layerDuplicate() +{ + KisImageSP img = currentImg(); + + if (!img) + return; + + KisLayerSP active = img->activeLayer(); + + if (!active) + return; + + KisLayerSP dup = active->clone(); + dup->setName(i18n("Duplicate of '%1'").arg(active->name())); + img->addLayer(dup, active->parent().data(), active); + if (dup) { + img->activate( dup ); + updateCanvas(); + } else { + KMessageBox::error(this, i18n("Could not add layer to image."), i18n("Layer Error")); + } +} + +void KisView::layerRaise() +{ + KisImageSP img = currentImg(); + KisLayerSP layer; + + if (!img) + return; + + layer = img->activeLayer(); + + img->raiseLayer(layer); +} + +void KisView::layerLower() +{ + KisImageSP img = currentImg(); + KisLayerSP layer; + + if (!img) + return; + + layer = img->activeLayer(); + + img->lowerLayer(layer); +} + +void KisView::layerFront() +{ + KisImageSP img = currentImg(); + KisLayerSP layer; + + if (!img) + return; + + layer = img->activeLayer(); + img->toTop(layer); +} + +void KisView::layerBack() +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer; + + layer = img->activeLayer(); + img->toBottom(layer); +} + +void KisView::layersUpdated() +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + + layerUpdateGUI(img && layer); + + notifyObservers(); +} + +void KisView::layerToggleVisible() +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + layer->setVisible(!layer->visible()); +} + +void KisView::layerToggleLocked() +{ + KisImageSP img = currentImg(); + if (!img) return; + + KisLayerSP layer = img->activeLayer(); + if (!layer) return; + + layer->setLocked(!layer->locked()); +} + +void KisView::actLayerVisChanged(int show) +{ + m_actLayerVis = (show != 0); +} + +bool KisView::activeLayerHasSelection() +{ + return m_image && m_image->activeDevice() && m_image->activeDevice()->hasSelection(); +} + +void KisView::scrollH(int value) +{ + m_hRuler->updateVisibleArea(value, 0); + + int xShift = m_scrollX - value; + m_scrollX = value; + + if (m_canvas->isUpdatesEnabled()) { + if (xShift > 0) { + + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(QRect(0, 0, m_canvas->width(), m_canvas->height())); + } else { + QRect drawRect(0, 0, xShift, m_canvasPixmap.height()); + + bitBlt(&m_canvasPixmap, xShift, 0, &m_canvasPixmap, 0, 0, m_canvasPixmap.width() - xShift, m_canvasPixmap.height()); + + updateQPaintDeviceCanvas(viewToWindow(drawRect)); + m_canvas->repaint(); + } + } else if (xShift < 0) { + + QRect drawRect(m_canvasPixmap.width() + xShift, 0, -xShift, m_canvasPixmap.height()); + + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(QRect(0, 0, m_canvas->width(), m_canvas->height())); + } else { + bitBlt(&m_canvasPixmap, 0, 0, &m_canvasPixmap, -xShift, 0, m_canvasPixmap.width() + xShift, m_canvasPixmap.height()); + + updateQPaintDeviceCanvas(viewToWindow(drawRect)); + m_canvas->repaint(); + } + } + if (m_oldTool) { + KisCanvasPainter gc(m_canvas); + m_oldTool->paint(gc); + } + } + + if (xShift != 0) { + // XXX do sth with the childframe or so + } + emit viewTransformationsChanged(); +} + +void KisView::scrollV(int value) +{ + m_vRuler->updateVisibleArea(0, value); + + int yShift = m_scrollY - value; + m_scrollY = value; + + if (m_canvas->isUpdatesEnabled()) { + if (yShift > 0) { + + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(QRect(0, 0, m_canvas->width(), m_canvas->height())); + } else { + QRect drawRect(0, 0, m_canvasPixmap.width(), yShift); + + bitBlt(&m_canvasPixmap, 0, yShift, &m_canvasPixmap, 0, 0, m_canvasPixmap.width(), m_canvasPixmap.height() - yShift); + + updateQPaintDeviceCanvas(viewToWindow(drawRect)); + m_canvas->repaint(); + } + } else if (yShift < 0) { + + if (m_canvas->isOpenGLCanvas()) { + paintOpenGLView(QRect(0, 0, m_canvas->width(), m_canvas->height())); + } else { + QRect drawRect(0, m_canvasPixmap.height() + yShift, m_canvasPixmap.width(), -yShift); + + bitBlt(&m_canvasPixmap, 0, 0, &m_canvasPixmap, 0, -yShift, m_canvasPixmap.width(), m_canvasPixmap.height() + yShift); + + updateQPaintDeviceCanvas(viewToWindow(drawRect)); + m_canvas->repaint(); + } + } + if (m_oldTool) { + KisCanvasPainter gc(m_canvas); + m_oldTool->paint(gc); + } + } + + if (yShift != 0) { + // XXX do sth with the childframe or so + } + emit viewTransformationsChanged(); +} + +void KisView::setupCanvas() +{ + m_canvas = new KisCanvas(this, "kis_canvas"); + m_canvas->setFocusPolicy( QWidget::StrongFocus ); + QObject::connect(m_canvas, SIGNAL(sigGotButtonPressEvent(KisButtonPressEvent*)), this, SLOT(canvasGotButtonPressEvent(KisButtonPressEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotButtonReleaseEvent(KisButtonReleaseEvent*)), this, SLOT(canvasGotButtonReleaseEvent(KisButtonReleaseEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotDoubleClickEvent(KisDoubleClickEvent*)), this, SLOT(canvasGotDoubleClickEvent(KisDoubleClickEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotMoveEvent(KisMoveEvent*)), this, SLOT(canvasGotMoveEvent(KisMoveEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotPaintEvent(QPaintEvent*)), this, SLOT(canvasGotPaintEvent(QPaintEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotEnterEvent(QEvent*)), this, SLOT(canvasGotEnterEvent(QEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotLeaveEvent(QEvent*)), this, SLOT(canvasGotLeaveEvent(QEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotMouseWheelEvent(QWheelEvent*)), this, SLOT(canvasGotMouseWheelEvent(QWheelEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotKeyPressEvent(QKeyEvent*)), this, SLOT(canvasGotKeyPressEvent(QKeyEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotKeyReleaseEvent(QKeyEvent*)), this, SLOT(canvasGotKeyReleaseEvent(QKeyEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotDragEnterEvent(QDragEnterEvent*)), this, SLOT(canvasGotDragEnterEvent(QDragEnterEvent*))); + QObject::connect(m_canvas, SIGNAL(sigGotDropEvent(QDropEvent*)), this, SLOT(canvasGotDropEvent(QDropEvent*))); +} + +void KisView::connectCurrentImg() +{ + if (m_image) { + connect(m_image, SIGNAL(sigActiveSelectionChanged(KisImageSP)), m_selectionManager, SLOT(imgSelectionChanged(KisImageSP))); + connect(m_image, SIGNAL(sigActiveSelectionChanged(KisImageSP)), this, SLOT(updateCanvas())); + connect(m_image, SIGNAL(sigColorSpaceChanged(KisColorSpace *)), this, SLOT(updateStatusBarProfileLabel())); + connect(m_image, SIGNAL(sigProfileChanged(KisProfile * )), SLOT(profileChanged(KisProfile * ))); + + connect(m_image, SIGNAL(sigLayersChanged(KisGroupLayerSP)), SLOT(layersUpdated())); + connect(m_image, SIGNAL(sigMaskInfoChanged()), SLOT(maskUpdated())); + connect(m_image, SIGNAL(sigLayerAdded(KisLayerSP)), SLOT(layersUpdated())); + connect(m_image, SIGNAL(sigLayerRemoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), SLOT(layersUpdated())); + connect(m_image, SIGNAL(sigLayerMoved(KisLayerSP, KisGroupLayerSP, KisLayerSP)), SLOT(layersUpdated())); + connect(m_image, SIGNAL(sigLayerActivated(KisLayerSP)), SLOT(layersUpdated())); + connect(m_image, SIGNAL(sigLayerActivated(KisLayerSP)), SLOT(updateCanvas())); + connect(m_image, SIGNAL(sigLayerPropertiesChanged(KisLayerSP)), SLOT(layersUpdated())); + + KisConnectPartLayerVisitor v(m_image, this, true); + m_image->rootLayer()->accept(v); + connect(m_image, SIGNAL(sigLayerAdded(KisLayerSP)), + SLOT(handlePartLayerAdded(KisLayerSP))); + + maskUpdated(); +#ifdef HAVE_GL + if (m_OpenGLImageContext != 0) { + connect(m_OpenGLImageContext, SIGNAL(sigImageUpdated(QRect)), SLOT(slotOpenGLImageUpdated(QRect))); + connect(m_OpenGLImageContext, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), SLOT(slotImageSizeChanged(Q_INT32, Q_INT32))); + } else +#endif + { + connect(m_image, SIGNAL(sigImageUpdated(QRect)), SLOT(imgUpdated(QRect))); + connect(m_image, SIGNAL(sigSizeChanged(Q_INT32, Q_INT32)), SLOT(slotImageSizeChanged(Q_INT32, Q_INT32))); + } + } + + m_layerBox->setImage(m_image); + m_birdEyeBox->setImage(m_image); +} + +void KisView::disconnectCurrentImg() +{ + if (m_image) { + m_image->disconnect(this); + m_layerBox->setImage(0); + m_birdEyeBox->setImage(0); + + KisConnectPartLayerVisitor v(m_image, this, false); + m_image->rootLayer()->accept(v); + } + +#ifdef HAVE_GL + if (m_OpenGLImageContext != 0) { + m_OpenGLImageContext->disconnect(this); + } +#endif +} + +void KisView::handlePartLayerAdded(KisLayerSP layer) +{ + KisPartLayer* l = dynamic_cast<KisPartLayer*>(layer.data()); + if (!l) + return; + + connect(this, SIGNAL(childActivated(KoDocumentChild*)), + layer, SLOT(childActivated(KoDocumentChild*))); +} + +void KisView::imgUpdated(QRect rc) +{ + updateCanvas(rc); +} + +void KisView::slotOpenGLImageUpdated(QRect rc) +{ + paintOpenGLView(windowToView(rc)); +} + +void KisView::profileChanged(KisProfile * /*profile*/) +{ + updateStatusBarProfileLabel(); +} + +void KisView::slotImageSizeChanged(Q_INT32 /*w*/, Q_INT32 /*h*/) +{ + resizeEvent(0); + refreshKisCanvas(); +} + +void KisView::resizeCurrentImage(Q_INT32 w, Q_INT32 h, bool cropLayers) +{ + if (!currentImg()) return; + + currentImg()->resize(w, h, cropLayers); + m_doc->setModified(true); + layersUpdated(); +} + +void KisView::scaleCurrentImage(double sx, double sy, KisFilterStrategy *filterStrategy) +{ + if (!currentImg()) return; + currentImg()->scale(sx, sy, m_progress, filterStrategy); + m_doc->setModified(true); + layersUpdated(); +} + +void KisView::rotateCurrentImage(double radians) +{ + if (!currentImg()) return; + currentImg()->rotate(radians, m_progress); + m_doc->setModified(true); + layersUpdated(); +} + +void KisView::shearCurrentImage(double angleX, double angleY) +{ + if (!currentImg()) return; + currentImg()->shear(angleX, angleY, m_progress); + m_doc->setModified(true); + layersUpdated(); +} + + +QPoint KisView::viewToWindow(const QPoint& pt) +{ + QPoint converted; + + converted.rx() = static_cast<int>((pt.x() + horzValue()) / zoom()); + converted.ry() = static_cast<int>((pt.y() + vertValue()) / zoom()); + + return converted; +} + +QPoint KisView::viewToWindow(const QPoint& pt) const +{ + QPoint converted; + + converted.rx() = static_cast<int>((pt.x() + horzValue()) / zoom()); + converted.ry() = static_cast<int>((pt.y() + vertValue()) / zoom()); + + return converted; +} + +KisPoint KisView::viewToWindow(const KisPoint& pt) +{ + KisPoint converted; + + converted.setX((pt.x() + horzValue()) / zoom()); + converted.setY((pt.y() + vertValue()) / zoom()); + + return converted; +} + +QRect KisView::viewToWindow(const QRect& rc) +{ + QRect r; + + r.setTopLeft(viewToWindow(rc.topLeft())); + r.setRight((int)(ceil((rc.right() + 1.0 + horzValue()) / zoom()) - 1)); + r.setBottom((int)(ceil((rc.bottom() + 1.0 + vertValue()) / zoom()) - 1)); + + return r; +} + +KisRect KisView::viewToWindow(const KisRect& rc) +{ + KisRect r; + KisPoint p = viewToWindow(KisPoint(rc.x(), rc.y())); + r.setX(p.x()); + r.setY(p.y()); + r.setWidth(rc.width() / zoom()); + r.setHeight(rc.height() / zoom()); + + return r; +} + +void KisView::viewToWindow(Q_INT32 *x, Q_INT32 *y) +{ + if (x && y) { + QPoint p = viewToWindow(QPoint(*x, *y)); + *x = p.x(); + *y = p.y(); + } +} + +QPoint KisView::windowToView(const QPoint& pt) +{ + QPoint p; + p.setX(static_cast<int>(pt.x() * zoom() - horzValue())); + p.setY(static_cast<int>(pt.y() * zoom() - vertValue())); + + return p; +} + +QPoint KisView::windowToView(const QPoint& pt) const +{ + QPoint p; + p.setX(static_cast<int>(pt.x() * zoom() - horzValue())); + p.setY(static_cast<int>(pt.y() * zoom() - vertValue())); + + return p; +} + +KisPoint KisView::windowToView(const KisPoint& pt) +{ + KisPoint p; + p.setX(pt.x() * zoom() - horzValue()); + p.setY(pt.y() * zoom() - vertValue()); + + return p; +} + +QRect KisView::windowToView(const QRect& rc) +{ + QRect r; + + r.setTopLeft(windowToView(rc.topLeft())); + r.setRight((int)(ceil((rc.right() + 1.0) * zoom()) - horzValue() - 1)); + r.setBottom((int)(ceil((rc.bottom() + 1.0) * zoom()) - vertValue() - 1)); + + return r; +} + +KisRect KisView::windowToView(const KisRect& rc) +{ + KisRect r; + KisPoint p = windowToView(KisPoint(rc.x(), rc.y())); + r.setX(p.x()); + r.setY(p.y()); + r.setWidth(rc.width() * zoom()); + r.setHeight(rc.height() * zoom()); + + return r; +} + +void KisView::windowToView(Q_INT32 *x, Q_INT32 *y) +{ + if (x && y) { + QPoint p = windowToView(QPoint(*x, *y)); + *x = p.x(); + *y = p.y(); + } +} + +void KisView::guiActivateEvent(KParts::GUIActivateEvent *event) +{ + Q_ASSERT(event); + + if (event->activated()) { + + KStatusBar *sb = statusBar(); + if (sb) { + sb->show(); + } + + if (!m_guiActivateEventReceived) { + m_guiActivateEventReceived = true; + startInitialZoomTimerIfReady(); + } + } + + super::guiActivateEvent(event); +} + +bool KisView::eventFilter(QObject *o, QEvent *e) +{ + Q_ASSERT(o); + Q_ASSERT(e); + + switch (e->type()) { + case QEvent::TabletMove: + case QEvent::TabletPress: + case QEvent::TabletRelease: + { + QTabletEvent *te = static_cast<QTabletEvent *>(e); + KisInputDevice device; + + switch (te->device()) { + default: + case QTabletEvent::Stylus: + case QTabletEvent::NoDevice: + device = KisInputDevice::stylus(); + break; + case QTabletEvent::Puck: + device = KisInputDevice::puck(); + break; + case QTabletEvent::Eraser: + device = KisInputDevice::eraser(); + break; + } + + setInputDevice(device); + + // We ignore device change due to mouse events for a short duration + // after a tablet event, since these are almost certainly mouse events + // sent to receivers that don't accept the tablet event. + m_tabletEventTimer.start(); + break; + } + case QEvent::MouseButtonPress: + case QEvent::MouseMove: + case QEvent::MouseButtonRelease: + { +#ifdef EXTENDED_X11_TABLET_SUPPORT + KisInputDevice device = KisCanvasWidget::findActiveInputDevice(); + + if (device != KisInputDevice::mouse()) { + setInputDevice(device); + m_tabletEventTimer.start(); + } else +#endif + { + if (currentInputDevice() != KisInputDevice::mouse() && m_tabletEventTimer.elapsed() > MOUSE_CHANGE_EVENT_DELAY) { + setInputDevice(KisInputDevice::mouse()); + } + } + break; + } + case QEvent::KeyPress: + case QEvent::KeyRelease: + { + if (m_canvas->cursorIsOverCanvas()) { + m_canvas->handleKeyEvent(e); + return true; + } + break; + } +#if 0 + // This code is unnecessary now that there's an application event filter + // This eventFilter is called for all widgets already, no need to install event filters multiple times + // Even worse: with multiple views, they would all install event filters on each other's widgets, + // due to the qapp event filter triggering in all views! + case QEvent::ChildInserted: + { + QChildEvent *childEvent = static_cast<QChildEvent *>(e); + QObject *child = childEvent->child(); + if ( child->isWidgetType() ) { + + child->installEventFilter(this); + + QObjectList *objectList = child->queryList("QWidget"); + QObjectListIt it(*objectList); + QObject *obj; + while ((obj = it.current()) != 0) { + obj->installEventFilter(this); + ++it; + } + delete objectList; + } + } +#endif + default: + // Ignore + break; + } + +#if 0 + if ((o == m_hRuler || o == m_vRuler) && (e->type() == QEvent::MouseMove || e->type() == QEvent::MouseButtonRelease)) { + QMouseEvent *me = dynamic_cast<QMouseEvent*>(e); + QPoint pt = mapFromGlobal(me->globalPos()); + KisImageSP img = currentImg(); + KisGuideMgr *mgr; + + if (!img) + return super::eventFilter(o, e); + + mgr = img->guides(); + + if (e->type() == QEvent::MouseMove && (me->state() & Qt::LeftButton)) { + bool flag = geometry().contains(pt); + KisGuideSP gd; + + if (m_currentGuide == 0 && flag) { + // No guide is being edited and moving mouse over the canvas. + // Create a new guide. + enterEvent(0); + eraseGuides(); + mgr->unselectAll(); + + if (o == m_vRuler) + gd = mgr->add((pt.x() - m_vRuler->width() + horzValue()) / zoom(), Qt::Vertical); + else + gd = mgr->add((pt.y() - m_hRuler->height() + vertValue()) / zoom(), Qt::Horizontal); + + m_currentGuide = gd; + mgr->select(gd); + m_lastGuidePoint = mapToScreen(pt); + } else if (m_currentGuide) { + if (flag) { + // moved an existing guide. + KisMoveEvent kme(currentInputDevice(), pt, me->globalPos(), PRESSURE_DEFAULT, 0, 0, me->state()); + canvasGotMoveEvent(&kme); + } else { + // moved a guide out of the frame, destroy it + leaveEvent(0); + eraseGuides(); + mgr->remove(m_currentGuide); + paintGuides(); + m_currentGuide = 0; + } + } + } else if (e->type() == QEvent::MouseButtonRelease && m_currentGuide) { + eraseGuides(); + mgr->unselect(m_currentGuide); + paintGuides(); + m_currentGuide = 0; + enterEvent(0); + KisMoveEvent kme(currentInputDevice(), pt, me->globalPos(), PRESSURE_DEFAULT, 0, 0, Qt::NoButton); + canvasGotMoveEvent(&kme); + } + } +#endif + + return super::eventFilter(o, e); +} + +#if 0 +void KisView::eraseGuides() +{ + KisImageSP img = currentImg(); + + if (img) { + KisGuideMgr *mgr = img->guides(); + + if (mgr) + mgr->erase(&m_canvasPixmap, this, horzValue(), vertValue(), zoom()); + } +} + +void KisView::paintGuides() +{ + KisImageSP img = currentImg(); + + if (img) { + KisGuideMgr *mgr = img->guides(); + + if (mgr) + mgr->paint(&m_canvasPixmap, this, horzValue(), vertValue(), zoom()); + } +} + +void KisView::updateGuides() +{ + eraseGuides(); + paintGuides(); +} +#endif + +//void KisView::viewGuideLines() +//{ +//} + +QPoint KisView::mapToScreen(const QPoint& pt) +{ + QPoint converted; + + converted.rx() = pt.x() + horzValue(); + converted.ry() = pt.y() + vertValue(); + return converted; +} + +void KisView::attach(KisCanvasObserver *observer) +{ + Q_ASSERT(observer); + if (observer) + m_observers.push_back(observer); +} + +void KisView::detach(KisCanvasObserver *observer) +{ + Q_ASSERT(observer); + if (observer) { + vKisCanvasObserver_it it = std::find(m_observers.begin(), m_observers.end(), observer); + + if (it != m_observers.end()) + m_observers.erase(it); + } +} + +void KisView::notifyObservers() +{ + for (vKisCanvasObserver_it it = m_observers.begin(); it != m_observers.end(); ++it) { + (*it)->update(this); + } +} + +KisImageSP KisView::currentImg() const +{ + return m_image; +} + +void KisView::setCurrentImage(KisImageSP image) +{ + if(!image) return; + + disconnectCurrentImg(); + m_image = image; + + KisConfig cfg; + +#ifdef HAVE_GL + if (cfg.useOpenGL()) { + m_OpenGLImageContext = KisOpenGLImageContext::getImageContext(image, monitorProfile()); + m_canvas->createOpenGLCanvas(m_OpenGLImageContext->sharedContextWidget()); + } +#endif + connectCurrentImg(); + m_layerBox->setImage(currentImg()); + + zoomAroundPoint(0, 0, 1.0); + + if (!currentImg()) + layersUpdated(); + + imgUpdateGUI(); + + image->blockSignals(false); +} + +KisColor KisView::bgColor() const +{ + return m_bg; +} + +KisColor KisView::fgColor() const +{ + return m_fg; +} + +KisBrush *KisView::currentBrush() const +{ + return m_brush; +} + +KisPattern *KisView::currentPattern() const +{ + return m_pattern; +} + +KisGradient *KisView::currentGradient() const +{ + return m_gradient; +} + +KisID KisView::currentPaintop() const +{ + return m_paintop; +} + +const KisPaintOpSettings *KisView::currentPaintopSettings() const +{ + return m_paintopSettings; +} + +double KisView::zoomFactor() const +{ + return zoom(); +} + +KisUndoAdapter *KisView::undoAdapter() const +{ + return m_adapter; +} + +KisCanvasController *KisView::canvasController() const +{ + return const_cast<KisCanvasController*>(static_cast<const KisCanvasController*>(this)); +} + +KisToolControllerInterface *KisView::toolController() const +{ + return const_cast<KisToolControllerInterface*>(static_cast<const KisToolControllerInterface*>(m_toolManager)); +} + +KisDoc *KisView::document() const +{ + return m_doc; +} + +KisProgressDisplayInterface *KisView::progressDisplay() const +{ + return m_progress; +} + +QCursor KisView::setCanvasCursor(const QCursor & cursor) +{ + QCursor oldCursor = m_canvas->cursor(); + QCursor newCursor; + + KisConfig cfg; + + switch (cfg.cursorStyle()) { + case CURSOR_STYLE_TOOLICON: + newCursor = cursor; + break; + case CURSOR_STYLE_CROSSHAIR: + newCursor = KisCursor::crossCursor(); + break; + case CURSOR_STYLE_POINTER: + newCursor = KisCursor::arrowCursor(); + break; + case CURSOR_STYLE_OUTLINE: + newCursor = cursor; + break; + default: + newCursor = cursor; + } + + m_canvas->setCursor(newCursor); + return oldCursor; +} + +float KisView::HDRExposure() const +{ + return m_HDRExposure; +} + +void KisView::setHDRExposure(float exposure) +{ + if (exposure != m_HDRExposure) { + m_HDRExposure = exposure; + notifyObservers(); + updateCanvas(); + } +} + +void KisView::createDockers() +{ + + m_birdEyeBox = new KisBirdEyeBox(this); + m_birdEyeBox->setCaption(i18n("Overview")); + m_paletteManager->addWidget( m_birdEyeBox, "birdeyebox", krita::CONTROL_PALETTE); + + m_hsvwidget = new KoHSVWidget(this, "hsv"); + m_hsvwidget->setCaption(i18n("HSV")); + + connect(m_hsvwidget, SIGNAL(sigFgColorChanged(const QColor &)), this, SLOT(slotSetFGQColor(const QColor &))); + connect(m_hsvwidget, SIGNAL(sigBgColorChanged(const QColor &)), this, SLOT(slotSetBGQColor(const QColor &))); + connect(this, SIGNAL(sigFGQColorChanged(const QColor &)), m_hsvwidget, SLOT(setFgColor(const QColor &))); + connect(this, SIGNAL(sigBGQColorChanged(const QColor &)), m_hsvwidget, SLOT(setBgColor(const QColor &))); + m_paletteManager->addWidget( m_hsvwidget, "hsvwidget", krita::COLORBOX, 0, PALETTE_DOCKER, true); + + m_rgbwidget = new KoRGBWidget(this, "rgb"); + m_rgbwidget->setCaption(i18n("RGB")); + connect(m_rgbwidget, SIGNAL(sigFgColorChanged(const QColor &)), this, SLOT(slotSetFGQColor(const QColor &))); + connect(m_rgbwidget, SIGNAL(sigBgColorChanged(const QColor &)), this, SLOT(slotSetBGQColor(const QColor &))); + connect(this, SIGNAL(sigFGQColorChanged(const QColor &)), m_rgbwidget, SLOT(setFgColor(const QColor &))); + connect(this, SIGNAL(sigBGQColorChanged(const QColor &)), m_rgbwidget, SLOT(setBgColor(const QColor &))); + m_paletteManager->addWidget( m_rgbwidget, "rgbwidget", krita::COLORBOX); + + m_graywidget = new KoGrayWidget(this, "gray"); + m_graywidget->setCaption(i18n("Gray")); + connect(m_graywidget, SIGNAL(sigFgColorChanged(const QColor &)), this, SLOT(slotSetFGQColor(const QColor &))); + connect(m_graywidget, SIGNAL(sigBgColorChanged(const QColor &)), this, SLOT(slotSetBGQColor(const QColor &))); + connect(this, SIGNAL(sigFGQColorChanged(const QColor &)), m_graywidget, SLOT(setFgColor(const QColor &))); + connect(this, SIGNAL(sigBGQColorChanged(const QColor &)), m_graywidget, SLOT(setBgColor(const QColor &))); + m_paletteManager->addWidget( m_graywidget, "graywidget", krita::COLORBOX); + + //make sure the color chooser get right default values + emit sigFGQColorChanged(m_fg.toQColor()); + emit sigBGQColorChanged(m_bg.toQColor()); + + m_palettewidget = new KisPaletteWidget(this); + m_palettewidget->setCaption(i18n("Palettes")); + connect(m_palettewidget, SIGNAL(colorSelected(const QColor &)), + this, SLOT(slotSetFGQColor(const QColor &))); + // No BGColor or reverse slotFGChanged->palette connections, since that's not useful here + + KisResourceServerBase* rServer; + rServer = KisResourceServerRegistry::instance()->get("PaletteServer"); + QValueList<KisResource*> resources = rServer->resources(); + QValueList<KisResource*>::iterator it; + for ( it = resources.begin(); it != resources.end(); ++it ) { + m_palettewidget->slotAddPalette( *it ); + } + connect(m_palettewidget, SIGNAL(colorSelected(const KisColor &)), this, SLOT(slotSetFGColor(const KisColor &))); + m_paletteManager->addWidget( m_palettewidget, "palettewidget", krita::COLORBOX, 10, PALETTE_DOCKER, true); +} + +QPoint KisView::applyViewTransformations(const QPoint& p) const { + QPoint point(windowToView(p)); + + if (m_hRuler->isShown()) + point.ry() += m_hRuler->height(); + if (m_vRuler -> isShown()) + point.rx() += m_vRuler->width(); + + return point; +} + +QPoint KisView::reverseViewTransformations(const QPoint& p) const { + // Since we now zoom ourselves, the only thing super::~ does is nothing anymore. + // Hence, zoom ourselves, like super would + // viewToWindow doesn't take the rulers into account, do that ourselves + QPoint point(p); + if (m_hRuler -> isShown()) + point.ry() -= m_hRuler -> height(); + if (m_vRuler -> isShown()) + point.rx() -= m_vRuler -> width(); + + return viewToWindow(point); +} + +void KisView::canvasAddChild(KoViewChild *child) { + super::canvasAddChild(child); + connect(this, SIGNAL(viewTransformationsChanged()), child, SLOT(reposition())); + m_vScroll->raise(); + m_hScroll->raise(); + m_vScroll->raise(); + m_hRuler->raise(); + m_vRuler->raise(); +} + +void KisView::slotLoadingFinished() +{ + // Set the current image for real now everything is ready to go. + setCurrentImage(document()->currentImage()); + m_paletteManager->showWidget( "layerbox" ); + m_canvas->show(); + disconnect(document(), SIGNAL(loadingFinished()), this, SLOT(slotLoadingFinished())); + + m_imageLoaded = true; + startInitialZoomTimerIfReady(); +} + +void KisView::startInitialZoomTimerIfReady() +{ + if (m_imageLoaded && m_showEventReceived && m_guiActivateEventReceived) { + m_initialZoomTimer.start(250, true); + } +} + +void KisView::slotInitialZoomTimeout() +{ + Q_ASSERT(!m_paintViewEnabled); + + m_paintViewEnabled = true; + setInitialZoomLevel(); +} + + +void KisView::slotCreateMask() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + KNamedCommand *cmd = layer->createMaskCommand(); + cmd->execute(); + if (undoAdapter() && undoAdapter()->undo()) { + undoAdapter()->addCommand(cmd); + } +} + +void KisView::slotMaskFromSelection() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + KNamedCommand *cmd = layer->maskFromSelectionCommand(); + cmd->execute(); + if (undoAdapter() && undoAdapter()->undo()) { + undoAdapter()->addCommand(cmd); + } +} + +void KisView::slotMaskToSelection() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + KNamedCommand *cmd = layer->maskToSelectionCommand(); + cmd->execute(); + if (undoAdapter() && undoAdapter()->undo()) { + undoAdapter()->addCommand(cmd); + } +} + +void KisView::slotApplyMask() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + KNamedCommand *cmd = layer->applyMaskCommand(); + cmd->execute(); + if (undoAdapter() && undoAdapter()->undo()) { + undoAdapter()->addCommand(cmd); + } +} + +void KisView::slotRemoveMask() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + KNamedCommand *cmd = layer->removeMaskCommand(); + cmd->execute(); + if (undoAdapter() && undoAdapter()->undo()) { + undoAdapter()->addCommand(cmd); + } +} + +void KisView::slotEditMask() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + layer->setEditMask(m_editMask->isChecked()); +} + +void KisView::slotShowMask() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) + return; + + layer->setRenderMask(m_showMask->isChecked()); +} + +void KisView::maskUpdated() { + KisPaintLayer* layer = dynamic_cast<KisPaintLayer*>(currentImg()->activeLayer().data()); + if (!layer) { + m_createMask->setEnabled(false); + m_applyMask->setEnabled(false); + m_removeMask->setEnabled(false); + m_editMask->setEnabled(false); + m_showMask->setEnabled(false); + return; + } + m_createMask->setEnabled(!layer->hasMask()); + m_maskFromSelection->setEnabled(true); // Perhaps also update this to false when no selection? + m_maskToSelection->setEnabled(layer->hasMask()); + m_applyMask->setEnabled(layer->hasMask()); + m_removeMask->setEnabled(layer->hasMask()); + + m_editMask->setEnabled(layer->hasMask()); + m_editMask->setChecked(layer->editMask()); + m_showMask->setEnabled(layer->hasMask()); + m_showMask->setChecked(layer->renderMask()); +} + +#include "kis_view.moc" + diff --git a/krita/ui/kis_view.h b/krita/ui/kis_view.h new file mode 100644 index 000000000..71d970178 --- /dev/null +++ b/krita/ui/kis_view.h @@ -0,0 +1,663 @@ +/* + * Copyright (c) 1999 Matthias Elter <me@kde.org> + * 1999 Michael Koch <koch@kde.org> + * 1999 Carsten Pfeiffer <pfeiffer@kde.org> + * 2002 Patrick Julien <freak@codepimps.org> + * 2004 Clarence Dang <dang@kde.org> + * + * 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_H_ +#define KIS_VIEW_H_ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <list> + +#include <qdatetime.h> +#include <qpixmap.h> +#include <qstringlist.h> +#include <qtimer.h> + +#include <ksqueezedtextlabel.h> +#include <kdebug.h> +#include <kxmlguibuilder.h> +#include <kxmlguiclient.h> +#include <KoView.h> + +#include "kis_canvas_controller.h" +#include "kis_canvas_subject.h" +#include "kis_global.h" +// #include "kis_debug_areas.h" +#include "kis_types.h" +#include "kis_profile.h" +#include "kis_opengl_image_context.h" +#include "kis_id.h" +#include "koffice_export.h" +#include "kis_color.h" +#include "kis_input_device.h" + +class QButton; +class QLabel; +class QPaintEvent; +class QScrollBar; +class QWidget; +class QPopup; +class QPopupMenu; + +class DCOPObject; +class KAction; +class KActionMenu; +class KPrinter; +class KToggleAction; +class KToolBar; + +class KoPartSelectAction; +class KoDocumentEntry; +class KoIconItem; +class KoTabBar; +class KoPaletteManager; +class KoGrayWidget; +class KoHSVWidget; +class KoRGBWidget; + +class KisBirdEyeBox; +class KisBrush; +class KisButtonPressEvent; +class KisButtonReleaseEvent; +class KisCanvas; +class KisCanvasObserver; +class KisCompositeOp; +class KisControlFrame; +class KisDoc; +class KisDoubleClickEvent; +class KisFilterManager; +class KisFilterStrategy; +class KisGradient; +class KisGridManager; +class KisPerspectiveGridManager; +class KisLabelProgress; +class KisLayerBox; +class KisMoveEvent; +class KisPaletteWidget; +class KisPattern; +class KisPoint; +class KisRect; +class KisResource; +class KisResourceMediator; +class KisRuler; +class KisSelectionManager; +class KoToolBox; +class KisToolControllerInterface; +class KisToolManager; +class KisUndoAdapter; +class KisFilterConfiguration; +class KisPartLayerHandler; +class KisPaintOpSettings; + +class KRITA_EXPORT KisView + : public KoView, + public KisCanvasSubject, + public KXMLGUIBuilder, + private KisCanvasController +{ + + Q_OBJECT + + typedef KoView super; + + typedef std::list<KisCanvasObserver*> vKisCanvasObserver; + typedef vKisCanvasObserver::iterator vKisCanvasObserver_it; + typedef vKisCanvasObserver::const_iterator vKisCanvasObserver_cit; + +public: + KisView(KisDoc *doc, KisUndoAdapter *adapter, QWidget *parent = 0, const char *name = 0); + virtual ~KisView(); + +public: // KXMLGUIBuilder implementation + + virtual QWidget *createContainer( QWidget *parent, int index, const QDomElement &element, int &id ); + virtual void removeContainer( QWidget *container, QWidget *parent, QDomElement &element, int id ); + +public: // KoView implementation + virtual bool eventFilter(QObject *o, QEvent *e); + + virtual DCOPObject* dcopObject(); + + virtual void print(KPrinter &printer); + virtual void setupPrinter(KPrinter &printer); + + virtual void updateReadWrite(bool readwrite); + virtual void guiActivateEvent(KParts::GUIActivateEvent *event); + + virtual int leftBorder() const; + virtual int rightBorder() const; + virtual int topBorder() const; + virtual int bottomBorder() const; + + Q_INT32 docWidth() const; + Q_INT32 docHeight() const; + + void updateStatusBarSelectionLabel(); + + virtual QPoint applyViewTransformations(const QPoint& p) const; + virtual QPoint reverseViewTransformations( const QPoint& p) const; + virtual void canvasAddChild(KoViewChild *child); + +signals: + + void brushChanged(KisBrush * brush); + void gradientChanged(KisGradient * gradient); + void patternChanged(KisPattern * pattern); + void paintopChanged(KisID paintop, const KisPaintOpSettings *paintopSettings); + /** + * Indicates when the current layer changed so that the current colorspace could have + * changed. + **/ + void currentColorSpaceChanged(KisColorSpace* cs); + void cursorPosition(Q_INT32 xpos, Q_INT32 ypos); + + void sigFGQColorChanged(const QColor &); + void sigBGQColorChanged(const QColor &); + + void sigInputDeviceChanged(const KisInputDevice& inputDevice); + + /* + * Emitted whenever the zoom or scroll values change. + */ + void viewTransformationsChanged(); + +public slots: + + void slotSetFGColor(const KisColor& c); + void slotSetBGColor(const KisColor& c); + + void rotateLayer180(); + void rotateLayerLeft90(); + void rotateLayerRight90(); + void mirrorLayerX(); + void mirrorLayerY(); + void scaleLayer(double sx, double sy, KisFilterStrategy *filterStrategy); + void rotateLayer(double radians); + void shearLayer(double angleX, double angleY); + + void slotCreateMask(); + void slotMaskFromSelection(); + void slotMaskToSelection(); + void slotApplyMask(); + void slotRemoveMask(); + void slotEditMask(); + void slotShowMask(); + + void brushActivated(KisResource *brush); + void patternActivated(KisResource *pattern); + void gradientActivated(KisResource *gradient); + void paintopActivated(const KisID & paintop, const KisPaintOpSettings *paintopSettings); + + +public: + virtual void mouseMoveEvent(QMouseEvent *e); + + void resizeCurrentImage(Q_INT32 w, Q_INT32 h, bool cropLayers = false); + void scaleCurrentImage(double sx, double sy, KisFilterStrategy *filterStrategy); + void rotateCurrentImage(double radians); + void shearCurrentImage(double angleX, double angleY); + + void insertPart(const QRect& viewRect, const KoDocumentEntry& entry, + KisGroupLayerSP parent, KisLayerSP above); + + /** + * Import an image as a layer. If there is more than + * one layer in the image, import all of them as separate + * layers. + * + * @param url the url to the image file + * @return the number of layers added + */ + Q_INT32 importImage(const KURL& url = KURL()); +protected: + + virtual void resizeEvent(QResizeEvent*); // From QWidget + virtual void styleChange(QStyle& oldStyle); // From QWidget + virtual void paletteChange(const QPalette& oldPalette); // From QWidget + virtual void showEvent(QShowEvent *); + +protected slots: + virtual void slotChildActivated(bool a); // from KoView + +// -------------------------------------------------------------------------// +// KisCanvasSubject implementation +// -------------------------------------------------------------------------// +public: + + KisCanvasSubject * canvasSubject() { return this; }; + +private: + + virtual KisImageSP currentImg() const; + + virtual void attach(KisCanvasObserver *observer); + virtual void detach(KisCanvasObserver *observer); + virtual void notifyObservers(); + + virtual KisColor bgColor() const; + virtual void setBGColor(const KisColor& c); + + virtual KisColor fgColor() const; + virtual void setFGColor(const KisColor& c); + + float HDRExposure() const; + void setHDRExposure(float exposure); + + virtual KisBrush *currentBrush() const; + virtual KisPattern *currentPattern() const; + virtual KisGradient *currentGradient() const; + virtual KisID currentPaintop() const; + virtual const KisPaintOpSettings *currentPaintopSettings() const; + + virtual double zoomFactor() const; + + virtual KisUndoAdapter *undoAdapter() const; + + virtual KisCanvasController *canvasController() const; + virtual KisToolControllerInterface *toolController() const; + + virtual KisProgressDisplayInterface *progressDisplay() const; + + virtual KisDoc * document() const; + + inline KisGridManager * gridManager() { return m_gridManager; } + inline KisPerspectiveGridManager* perspectiveGridManager() { return m_perspectiveGridManager; } + + inline KisSelectionManager * selectionManager() { return m_selectionManager; } + + KoPaletteManager * paletteManager(); + + KisProfile * monitorProfile(); + + +// -------------------------------------------------------------------------// +// KisCanvasController implementation +// -------------------------------------------------------------------------// + +public: + + KisCanvasController * getCanvasController() { return this; }; + + +private slots: + virtual void updateCanvas(); + + void updateStatusBarZoomLabel(); + void updateStatusBarProfileLabel(); + +private: + virtual KisCanvas *kiscanvas() const; + + virtual Q_INT32 horzValue() const; + virtual Q_INT32 vertValue() const; + + virtual void scrollTo(Q_INT32 x, Q_INT32 y); + + virtual void updateCanvas(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h); + virtual void updateCanvas(const QRect& imageRect); + + virtual void zoomIn(); + virtual void zoomIn(Q_INT32 x, Q_INT32 y); + + virtual void zoomOut(); + virtual void zoomOut(Q_INT32 x, Q_INT32 y); + + virtual void zoomTo(Q_INT32 x, Q_INT32 y, Q_INT32 w, Q_INT32 h); + virtual void zoomTo(const QRect& r); + virtual void zoomTo(const KisRect& r); + virtual void zoomAroundPoint(double x, double y, double zf); + + virtual QPoint viewToWindow(const QPoint& pt); + virtual QPoint viewToWindow(const QPoint& pt) const; + virtual KisPoint viewToWindow(const KisPoint& pt); + virtual QRect viewToWindow(const QRect& rc); + virtual KisRect viewToWindow(const KisRect& rc); + virtual void viewToWindow(Q_INT32 *x, Q_INT32 *y); + + virtual QPoint windowToView(const QPoint& pt); + virtual QPoint windowToView(const QPoint& pt) const; + virtual KisPoint windowToView(const KisPoint& pt); + virtual QRect windowToView(const QRect& rc); + virtual KisRect windowToView(const KisRect& rc); + virtual void windowToView(Q_INT32 *x, Q_INT32 *y); + + virtual QCursor setCanvasCursor(const QCursor & cursor); + + void setInputDevice(KisInputDevice inputDevice); + KisInputDevice currentInputDevice() const; + +// -------------------------------------------------------------------------// +// KisView internals +// -------------------------------------------------------------------------// + +private: + + void connectCurrentImg(); + void disconnectCurrentImg(); +// void eraseGuides(); +// void paintGuides(); +// void updateGuides(); +// void viewGuideLines(); + + void imgUpdateGUI(); + + void layerUpdateGUI(bool enable); + void createLayerBox(); + void createDockers(); + + void paintToolOverlay(const QRegion& region); + + void paintQPaintDeviceView(const QRegion& canvasRegion); + void paintOpenGLView(const QRect& canvasRect); + + void updateQPaintDeviceCanvas(const QRect& imageRect); + void updateOpenGLCanvas(const QRect& imageRect); + + /** + * Update the whole of the KisCanvas, including areas outside the image. + */ + void refreshKisCanvas(); + + void selectionDisplayToggled(bool displaySelection); + + bool activeLayerHasSelection(); + + /** + * Reset the monitor profile to the new settings. + */ + void resetMonitorProfile(); + + void setupActions(); + void setupCanvas(); + void setupRulers(); + void setupScrollBars(); + void setupStatusBar(); + + + KisFilterManager * filterManager() { return m_filterManager; } + void setCurrentImage(KisImageSP image); + + /** + * Returns the next zoom level when zooming in from the current level. + */ + double nextZoomInLevel() const; + + /** + * Returns the next zoom level when zooming out from the current level. + */ + double nextZoomOutLevel() const; + + /** + * Returns the next zoom level when zooming out from the given level. + */ + double nextZoomOutLevel(double zoomLevel) const; + + /** + * Returns the zoom level that fits the image to the canvas. + */ + double fitToCanvasZoomLevel() const; + + /** + * Set the zoom level on first creating the view. + */ + void setInitialZoomLevel(); + + void startInitialZoomTimerIfReady(); + +private slots: + void layersUpdated(); // Used in the channel separation to notify the view that we have added a few layers. + void maskUpdated(); // To update the enabled or disabled status of the mask entries + + void slotSetFGQColor(const QColor & c); + void slotSetBGQColor(const QColor & c); + + void imgUpdated(QRect rc); + void slotOpenGLImageUpdated(QRect rc); + + void imgResizeToActiveLayer(); + + void canvasGotMoveEvent(KisMoveEvent *e); + void canvasGotButtonPressEvent(KisButtonPressEvent *e); + void canvasGotButtonReleaseEvent(KisButtonReleaseEvent *e); + void canvasGotDoubleClickEvent(KisDoubleClickEvent *e); + void canvasGotPaintEvent(QPaintEvent *e); + void canvasGotEnterEvent(QEvent *e); + void canvasGotLeaveEvent(QEvent *e); + void canvasGotMouseWheelEvent(QWheelEvent *e); + void canvasGotKeyPressEvent(QKeyEvent*); + void canvasGotKeyReleaseEvent(QKeyEvent*); + void canvasGotDragEnterEvent(QDragEnterEvent*); + void canvasGotDropEvent(QDropEvent*); + + void reconnectAfterPartInsert(); + + QPoint mapToScreen(const QPoint& pt); + void slotImageProperties(); + + void layerCompositeOp(const KisCompositeOp& compositeOp); + void layerOpacity(int opacity, bool dontundo); + void layerOpacityFinishedChanging(int previous, int opacity); + + void layerToggleVisible(); + void layerToggleLocked(); + void actLayerVisChanged(int show); + void layerProperties(); + void showLayerProperties(KisLayerSP layer); + void layerAdd(); + void addLayer(KisGroupLayerSP parent, KisLayerSP above); + void addGroupLayer(KisGroupLayerSP parent, KisLayerSP above); + void addPartLayer(); + void addPartLayer(KisGroupLayerSP parent, KisLayerSP above, const KoDocumentEntry& entry); + void addAdjustmentLayer(); + void addAdjustmentLayer(KisGroupLayerSP parent, KisLayerSP above); + void addAdjustmentLayer(KisGroupLayerSP parent, KisLayerSP above, const QString & name, KisFilterConfiguration * filter, KisSelectionSP selection = 0); + void layerRemove(); + void layerDuplicate(); + void layerRaise(); + void layerLower(); + void layerFront(); + void layerBack(); + void flattenImage(); + void mergeLayer(); + void saveLayerAsImage(); + + void slotUpdateFullScreen(bool toggle); + void showRuler(); + + void slotZoomIn(); + void slotZoomOut(); + void slotActualPixels(); + void slotActualSize(); + void slotFitToCanvas(); + + void slotImageSizeChanged(Q_INT32 w, Q_INT32 h); + + void scrollH(int value); + void scrollV(int value); + + void slotInsertImageAsLayer(); + void profileChanged(KisProfile * profile); + + void slotAddPalette(); + void slotEditPalette(); + + void preferences(); + + void slotAutoScroll(const QPoint &p); + + void handlePartLayerAdded(KisLayerSP layer); + + /// Is called when the file is loaded + void slotLoadingFinished(); + + void slotInitialZoomTimeout(); + +private: + + bool m_panning; + + KisTool * m_oldTool; + + KisDoc *m_doc; + KisCanvas *m_canvas; + KisPartLayerHandler* m_partHandler; + + KisGridManager * m_gridManager; + KisPerspectiveGridManager * m_perspectiveGridManager; + KisSelectionManager * m_selectionManager; + KisFilterManager * m_filterManager; + KoPaletteManager * m_paletteManager; + KisToolManager * m_toolManager; + bool m_actLayerVis; + + // Fringe benefits + KisRuler *m_hRuler; + KisRuler *m_vRuler; + Q_INT32 m_rulerThickness; + Q_INT32 m_vScrollBarExtent; + Q_INT32 m_hScrollBarExtent; + + // Actions + KAction *m_imgFlatten; + KAction *m_imgMergeLayer; + KAction *m_imgRename; + KAction *m_imgResizeToLayer; + KAction *m_imgScan; + + KoPartSelectAction * m_actionPartLayer; + KAction * m_actionAdjustmentLayer; + KAction *m_layerAdd; + KAction *m_layerBottom; + KAction *m_layerDup; + KToggleAction *m_layerHide; + KAction *m_layerLower; + KAction *m_layerProperties; + KAction *m_layerRaise; + KAction *m_layerRm; + KAction *m_layerSaveAs; + KAction *m_layerTop; + + KAction *m_createMask; + KAction *m_maskFromSelection; + KAction *m_maskToSelection; + KAction *m_applyMask; + KAction *m_removeMask; + KToggleAction *m_editMask; + KToggleAction *m_showMask; + + KAction *m_zoomIn; + KAction *m_zoomOut; + KAction *m_actualPixels; + KAction *m_actualSize; + KAction *m_fitToCanvas; + + KAction *m_fullScreen; + KAction *m_imgProperties; + + KToggleAction *m_RulerAction; + KToggleAction *m_guideAction; + + DCOPObject *m_dcop; + + // Widgets + QScrollBar *m_hScroll; // XXX: the sizing of the scrollthumbs + QScrollBar *m_vScroll; // is not right yet. + int m_scrollX; + int m_scrollY; + int m_canvasXOffset; + int m_canvasYOffset; + + bool m_paintViewEnabled; + bool m_guiActivateEventReceived; + bool m_showEventReceived; + bool m_imageLoaded; + + QTimer m_initialZoomTimer; + + +// KisGuideSP m_currentGuide; +// QPoint m_lastGuidePoint; + KisUndoAdapter *m_adapter; + vKisCanvasObserver m_observers; + QLabel *m_statusBarZoomLabel; + KSqueezedTextLabel *m_statusBarSelectionLabel; + KSqueezedTextLabel *m_statusBarProfileLabel; + KisLabelProgress *m_progress; + + + KisLayerBox *m_layerBox; + KoToolBox * m_toolBox; + KisControlFrame * m_brushesAndStuffToolBar; + + // Current colours, brushes, patterns etc. + + KisColor m_fg; + KisColor m_bg; + + KisBrush *m_brush; + KisPattern *m_pattern; + KisGradient *m_gradient; + + KisID m_paintop; + const KisPaintOpSettings *m_paintopSettings; + + QTime m_tabletEventTimer; + QTabletEvent::TabletDevice m_lastTabletEventDevice; + + QPixmap m_canvasPixmap; + bool m_toolIsPainting; + +#ifdef HAVE_GL + // OpenGL context for the current image, containing textures + // shared between multiple views. + KisOpenGLImageContextSP m_OpenGLImageContext; +#endif + + // Monitorprofile for this view + KisProfile * m_monitorProfile; + + float m_HDRExposure; + + // Currently active input device (mouse, stylus, eraser...) + KisInputDevice m_inputDevice; + + KisBirdEyeBox * m_birdEyeBox; + KoHSVWidget *m_hsvwidget; + KoRGBWidget *m_rgbwidget; + KoGrayWidget *m_graywidget; + KisPaletteWidget *m_palettewidget; + KisID m_currentColorChooserDisplay; + +private: + KisImageSP m_image; + +protected: + + friend class KisSelectionManager; + friend class KisFilterManager; + friend class KisGridManager; + friend class KisPerspectiveGridManager; +}; + +#endif // KIS_VIEW_H_ diff --git a/krita/ui/kis_view_iface.cc b/krita/ui/kis_view_iface.cc new file mode 100644 index 000000000..7de36c483 --- /dev/null +++ b/krita/ui/kis_view_iface.cc @@ -0,0 +1,98 @@ +/* + * This file is part of the KDE project + * + * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com> + * + * 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_view_iface.h" + +#include "kis_view.h" + +#include <dcopclient.h> + +KisViewIface::KisViewIface( KisView *view_ ) + : KoViewIface( view_ ) +{ + m_view = view_; +} + +void KisViewIface::copy() +{ +// m_view->copy(); +} + +void KisViewIface::cut() +{ +// m_view->cut(); +} + +void KisViewIface::removeSelection() +{ +// m_view->removeSelection(); +} + +void KisViewIface::paste() +{ +// m_view->paste(); +} + +void KisViewIface::copySelectionToNewLayer() +{ +// m_view->copySelectionToNewLayer(); +} + +void KisViewIface::selectAll() +{ +// m_view->selectAll(); +} + +void KisViewIface::unSelectAll() +{ +// m_view->unSelectAll(); +} + + + +void KisViewIface::slotImportImage() +{ +} + + +void KisViewIface::rotateLayer180() +{ + m_view->rotateLayer180(); +} + +void KisViewIface::rotateLayerLeft90() +{ + m_view->rotateLayerLeft90(); +} + +void KisViewIface::rotateLayerRight90() +{ + m_view->rotateLayerRight90(); +} + +void KisViewIface::mirrorLayerX() +{ + m_view->mirrorLayerX(); +} + +void KisViewIface::mirrorLayerY() +{ + m_view->mirrorLayerY(); +} diff --git a/krita/ui/kis_view_iface.h b/krita/ui/kis_view_iface.h new file mode 100644 index 000000000..0cc9b79da --- /dev/null +++ b/krita/ui/kis_view_iface.h @@ -0,0 +1,58 @@ +/* This file is part of the KDE project + * Copyright (C) 2002 Laurent Montel <lmontel@mandrakesoft.com> + * + * 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 KRAYON_VIEW_IFACE_H +#define KRAYON_VIEW_IFACE_H + +#include <KoViewIface.h> + +#include <qstring.h> + +class KisView; + +/** + * This is the definition of the interface Krita presents to + * dcop. + */ +class KisViewIface : public KoViewIface +{ + K_DCOP +public: + KisViewIface( KisView *view_ ); +k_dcop: + void copy(); + void cut(); + void removeSelection(); + void paste(); + void copySelectionToNewLayer(); + void selectAll(); + void unSelectAll(); + + void slotImportImage(); + + void rotateLayer180(); + void rotateLayerLeft90(); + void rotateLayerRight90(); + void mirrorLayerX(); + void mirrorLayerY(); + +private: + KisView *m_view; +}; + +#endif diff --git a/krita/ui/kobirdeyepanel.cpp b/krita/ui/kobirdeyepanel.cpp new file mode 100644 index 000000000..fda959453 --- /dev/null +++ b/krita/ui/kobirdeyepanel.cpp @@ -0,0 +1,619 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 <qpixmap.h> +#include <qimage.h> +#include <qlayout.h> +#include <qpainter.h> +#include <qframe.h> +#include <qlabel.h> +#include <qtoolbutton.h> +#include <qslider.h> +#include <qcursor.h> + +#include <kdebug.h> +#include <kglobalsettings.h> +#include <kaction.h> +#include <ktoolbar.h> +#include <knuminput.h> +#include <klocale.h> + +#include <KoDocument.h> + +#include "wdgbirdeye.h" +#include "kobirdeyepanel.h" +#include "kis_int_spinbox.h" + +KoCanvasAdapter::KoCanvasAdapter() {} +KoCanvasAdapter::~KoCanvasAdapter() {} + +KoZoomAdapter::KoZoomAdapter() {} +KoZoomAdapter::~KoZoomAdapter() {} + +KoThumbnailAdapter::KoThumbnailAdapter() {} +KoThumbnailAdapter::~KoThumbnailAdapter() {} + +KoBirdEyePanel::KoBirdEyePanel( KoZoomAdapter * zoomListener, + KoThumbnailAdapter * thumbnailProvider, + KoCanvasAdapter * canvas, + QWidget * parent, + const char * name, + WFlags f) + : QWidget(parent, name, f) + , m_zoomListener(zoomListener) + , m_thumbnailProvider(thumbnailProvider) + , m_canvas(canvas) + , m_dragging(false) +{ + QHBoxLayout * l = new QHBoxLayout(this); + m_page = new WdgBirdEye(this); + m_page->zoom->setRange((int) (QMAX(1, 100 * zoomListener->getMinZoom())), (int) (100 * zoomListener->getMaxZoom())); + m_page->zoom->setValue(100); + m_page->zoom->setSuffix("%"); + + m_page->toolbar->setIconSize(16); + m_page->view->installEventFilter(this); + m_page->view->setBackgroundMode(Qt::NoBackground); + + m_zoomIn = new KAction( i18n("Zoom In"), "birdeye_zoom_plus", 0, this, SLOT(zoomPlus()), this, "zoomIn" ); + m_zoomOut = new KAction( i18n("Zoom Out"), "birdeye_zoom_minus", 0, this, SLOT(zoomMinus()), this, "zoomOut" ); + + l->addWidget(m_page); + + connect(m_page->zoom, SIGNAL(valueChanged(int)), SLOT(zoomValueChanged(int))); + connect(m_page->bn100, SIGNAL(clicked()), SLOT(zoom100())); + connect(m_page->slZoom, SIGNAL(valueChanged(int)), SLOT(sliderChanged( int ))); +} + +KoBirdEyePanel::~KoBirdEyePanel() +{ + delete m_canvas; + delete m_thumbnailProvider; + delete m_zoomListener; +} + +void KoBirdEyePanel::setZoom(int zoom) +{ + m_page->zoom->blockSignals(true); + m_page->slZoom->blockSignals(true); + + m_page->zoom->setValue(zoom); + + if (zoom < 10) { + m_page->slZoom->setValue(0); + } + else if (zoom > 10 && zoom < 100) { + m_page->slZoom->setValue(zoom / 10); + } + else if (zoom >= 100 && zoom < 150) { + m_page->slZoom->setValue(10); + } + else if (zoom >= 150 && zoom < 250) { + m_page->slZoom->setValue(11); + } + else if (zoom >= 250 && zoom < 350) { + m_page->slZoom->setValue(12); + } + else if (zoom >= 350 && zoom < 450) { + m_page->slZoom->setValue(13); + } + else if (zoom >= 450 && zoom < 550) { + m_page->slZoom->setValue(14); + } + else if (zoom >= 550 && zoom < 650) { + m_page->slZoom->setValue(15); + } + else if (zoom >= 650 && zoom < 875) { + m_page->slZoom->setValue(16); + } + else if (zoom >= 875 && zoom < 1150) { + m_page->slZoom->setValue(17); + } + else if (zoom >= 1150 && zoom < 1450) { + m_page->slZoom->setValue(18); + } + else if (zoom >= 1450) { + m_page->slZoom->setValue(19); + } + + + m_page->zoom->blockSignals(false); + m_page->slZoom->blockSignals(false); + + +} + +void KoBirdEyePanel::zoomValueChanged(int zoom) +{ + KoPoint center; + center = m_canvas->visibleArea().center(); + m_zoomListener->zoomTo(center.x(), center.y(), zoom / 100.0); + setZoom(zoom); +} + +void KoBirdEyePanel::zoom100() +{ + zoomValueChanged( 100 ); +} + +void KoBirdEyePanel::sliderChanged( int v ) +{ + if (v < 10) { + zoomValueChanged((v + 1) * 10); + } + else { + switch(v) { + case 10: + zoomValueChanged(100); + break; + case 11: + zoomValueChanged(200); + break; + case 12: + zoomValueChanged(300); + case 13: + zoomValueChanged(400); + break; + case 14: + zoomValueChanged(500); + break; + case 15: + zoomValueChanged(600); + break; + case 16: + zoomValueChanged(750); + break; + case 17: + zoomValueChanged(1000); + break; + case 18: + zoomValueChanged(1300); + break; + case 19: + zoomValueChanged(1600); + break; + } + } +} + +void KoBirdEyePanel::cursorPosChanged(Q_INT32 xpos, Q_INT32 ypos) +{ + m_page->txtX->setText(QString("%L1").arg(xpos, 5)); + m_page->txtY->setText(QString("%L1").arg(ypos, 5)); +} + +void KoBirdEyePanel::setThumbnailProvider(KoThumbnailAdapter * thumbnailProvider) +{ + delete m_thumbnailProvider; + m_thumbnailProvider = thumbnailProvider; +} + +void KoBirdEyePanel::slotViewTransformationChanged() +{ + updateVisibleArea(); + renderView(); + m_page->view->update(); + setZoom(qRound(m_canvas->zoomFactor() * 100)); +} + +void KoBirdEyePanel::slotUpdate(const QRect & r) +{ + QRect updateRect = r; + + if (m_thumbnailProvider->pixelSize() != m_documentSize) { + m_documentSize = m_thumbnailProvider->pixelSize(); + fitThumbnailToView(); + updateRect = QRect(0, 0, m_documentSize.width(), m_documentSize.height()); + } + + updateRect &= QRect(0, 0, m_documentSize.width(), m_documentSize.height()); + + if (!updateRect.isEmpty() && !m_documentSize.isEmpty()) { + + QRect thumbnailRect = documentToThumbnail(KoRect::fromQRect(updateRect)); + + if (!thumbnailRect.isEmpty()) { + + QImage thumbnailImage = m_thumbnailProvider->image(thumbnailRect, m_thumbnail.size()); + + if (!thumbnailImage.isNull()) { + + Q_ASSERT(thumbnailImage.size() == thumbnailRect.size()); + + QPainter painter(&m_thumbnail); + + painter.fillRect(thumbnailRect, colorGroup().mid()); + painter.drawImage(thumbnailRect.x(), thumbnailRect.y(), thumbnailImage); + } + } + } + + renderView(); + m_page->view->update(); +} + +QRect KoBirdEyePanel::documentToThumbnail(const KoRect& docRect) +{ + if (docRect.isEmpty() || m_documentSize.isEmpty() || m_thumbnail.isNull()) { + return QRect(); + } + + Q_INT32 thumbnailLeft = static_cast<Q_INT32>((docRect.left() * m_thumbnail.width()) / m_documentSize.width()); + Q_INT32 thumbnailRight = static_cast<Q_INT32>(((docRect.right() + 1) * m_thumbnail.width()) / m_documentSize.width()); + Q_INT32 thumbnailTop = static_cast<Q_INT32>((docRect.top() * m_thumbnail.height()) / m_documentSize.height()); + Q_INT32 thumbnailBottom = static_cast<Q_INT32>(((docRect.bottom() + 1) * m_thumbnail.height()) / m_documentSize.height()); + + QRect thumbnailRect(thumbnailLeft, thumbnailTop, thumbnailRight - thumbnailLeft + 1, thumbnailBottom - thumbnailTop + 1); + thumbnailRect &= m_thumbnail.rect(); + + return thumbnailRect; +} + +KoRect KoBirdEyePanel::thumbnailToDocument(const QRect& thumbnailRect) +{ + if (thumbnailRect.isEmpty() || m_documentSize.isEmpty() || m_thumbnail.isNull()) { + return KoRect(); + } + + double docLeft = (static_cast<double>(thumbnailRect.left()) * m_documentSize.width()) / m_thumbnail.width(); + double docRight = (static_cast<double>(thumbnailRect.right() + 1) * m_documentSize.width()) / m_thumbnail.width(); + double docTop = (static_cast<double>(thumbnailRect.top()) * m_documentSize.height()) / m_thumbnail.height(); + double docBottom = (static_cast<double>(thumbnailRect.bottom() + 1) * m_documentSize.height()) / m_thumbnail.height(); + + KoRect docRect(docLeft, docTop, docRight - docLeft + 1, docBottom - docTop + 1); + docRect &= KoRect(0, 0, m_documentSize.width(), m_documentSize.height()); + + return docRect; +} + +QPoint KoBirdEyePanel::viewToThumbnail(const QPoint& viewPoint) +{ + int thumbnailX = (m_viewBuffer.width() - m_thumbnail.width()) / 2; + int thumbnailY = (m_viewBuffer.height() - m_thumbnail.height()) / 2; + + return QPoint(viewPoint.x() - thumbnailX, viewPoint.y() - thumbnailY); +} + + +void KoBirdEyePanel::zoomMinus() +{ +} + +void KoBirdEyePanel::zoomPlus() +{ +} + +void KoBirdEyePanel::updateVisibleArea() +{ + m_visibleAreaInThumbnail = documentToThumbnail(m_canvas->visibleArea()); +} + + +bool KoBirdEyePanel::eventFilter(QObject* o, QEvent* ev) +{ + if (o == m_page->view && ev->type() == QEvent::Resize) { + resizeViewEvent(static_cast<QResizeEvent *>(ev)->size()); + } + + if (o == m_page->view && ev->type() == QEvent::Paint) { + paintViewEvent(static_cast<QPaintEvent *>(ev)); + } + + if (o == m_page->view && ev->type() == QEvent::MouseMove) { + + QMouseEvent* me = (QMouseEvent*)ev; + QPoint thumbnailPos = viewToThumbnail(me->pos()); + + if (m_dragging) { + handleMouseMoveAction(thumbnailPos); + } else { + handleMouseMove(thumbnailPos); + } + + return true; + } + + if (o == m_page->view && ev->type() == QEvent::MouseButtonPress) { + + QMouseEvent* me = (QMouseEvent*)ev; + QPoint thumbnailPos = viewToThumbnail(me->pos()); + + if (me->button() == LeftButton) { + handleMousePress(thumbnailPos); + } + + return true; + } + + if (o == m_page->view && ev->type() == QEvent::MouseButtonRelease) { + + QMouseEvent* me = (QMouseEvent*)ev; + + if (me->button() == LeftButton) { + m_dragging = false; + } + + return true; + } + + return m_page->eventFilter(o, ev); +} + +KoBirdEyePanel::enumDragHandle KoBirdEyePanel::dragHandleAt(QPoint p) +{ + QRect left = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.top()-1, 3, m_visibleAreaInThumbnail.height()+2); + QRect right = QRect(m_visibleAreaInThumbnail.right()-1, m_visibleAreaInThumbnail.top()-1, 3, m_visibleAreaInThumbnail.height()+2); + QRect top = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.top()-1, m_visibleAreaInThumbnail.width()+2, 3); + QRect bottom = QRect(m_visibleAreaInThumbnail.left()-1, m_visibleAreaInThumbnail.bottom()-1, m_visibleAreaInThumbnail.width()+2, 3); + + if (left.contains(p)) { + return DragHandleLeft; + } + + if (right.contains(p)) { + return DragHandleRight; + } + + if (top.contains(p)) { + return DragHandleTop; + } + + if (bottom.contains(p)) { + return DragHandleBottom; + } + + if (m_visibleAreaInThumbnail.contains(p)) { + return DragHandleCentre; + } + + return DragHandleNone; +} + +void KoBirdEyePanel::handleMouseMove(QPoint p) +{ + QCursor cursor; + + switch (dragHandleAt(p)) { + case DragHandleLeft: + case DragHandleRight: + cursor = Qt::sizeHorCursor; + break; + case DragHandleTop: + case DragHandleBottom: + cursor = Qt::sizeVerCursor; + break; + case DragHandleCentre: + cursor = Qt::sizeAllCursor; + break; + default: + case DragHandleNone: + if (m_thumbnail.rect().contains(p)) { + cursor = Qt::PointingHandCursor; + } else { + cursor = Qt::arrowCursor; + } + break; + } + + m_page->view->setCursor(cursor); +} + +void KoBirdEyePanel::handleMouseMoveAction(QPoint p) +{ + if (m_dragging) { + + Q_INT32 dx = p.x() - m_lastDragPos.x(); + Q_INT32 dy = p.y() - m_lastDragPos.y(); + + m_lastDragPos = p; + + QRect thumbnailRect = m_visibleAreaInThumbnail; + + switch (m_dragHandle) { + case DragHandleLeft: { + thumbnailRect.setLeft(thumbnailRect.left()+dx); + break; + } + case DragHandleRight: { + thumbnailRect.setRight(thumbnailRect.right()+dx); + break; + } + case DragHandleTop: { + thumbnailRect.setTop(thumbnailRect.top()+dy); + break; + } + case DragHandleBottom: { + thumbnailRect.setBottom(thumbnailRect.bottom()+dy); + break; + } + case DragHandleCentre: { + thumbnailRect.moveBy(dx, dy); + break; + } + default: + case DragHandleNone: + break; + } + + makeThumbnailRectVisible(thumbnailRect); + } +} + +void KoBirdEyePanel::handleMousePress(QPoint p) +{ + if (!m_dragging) { + + enumDragHandle dragHandle = dragHandleAt(p); + + if (dragHandle == DragHandleNone) { + if (m_thumbnail.rect().contains(p)) { + + // Snap visible area centre to p and begin a centre drag. + + QRect thumbnailRect = m_visibleAreaInThumbnail; + thumbnailRect.moveCenter(p); + makeThumbnailRectVisible(thumbnailRect); + + m_dragHandle = DragHandleCentre; + m_page->view->setCursor(Qt::sizeAllCursor); + m_dragging = true; + } + } else { + m_dragHandle = dragHandle; + m_dragging = true; + } + m_lastDragPos = p; + } +} + +void KoBirdEyePanel::makeThumbnailRectVisible(const QRect& r) +{ + if (r.isEmpty()) { + return; + } + + QRect thumbnailRect = r; + + if (thumbnailRect.left() < m_thumbnail.rect().left()) { + thumbnailRect.moveLeft(m_thumbnail.rect().left()); + } + if (thumbnailRect.right() > m_thumbnail.rect().right()) { + thumbnailRect.moveRight(m_thumbnail.rect().right()); + } + if (thumbnailRect.top() < m_thumbnail.rect().top()) { + thumbnailRect.moveTop(m_thumbnail.rect().top()); + } + if (thumbnailRect.bottom() > m_thumbnail.rect().bottom()) { + thumbnailRect.moveBottom(m_thumbnail.rect().bottom()); + } + + if (thumbnailRect.width() > m_thumbnail.rect().width()) { + thumbnailRect.setLeft(m_thumbnail.rect().left()); + thumbnailRect.setRight(m_thumbnail.rect().right()); + } + if (thumbnailRect.height() > m_thumbnail.rect().height()) { + thumbnailRect.setTop(m_thumbnail.rect().top()); + thumbnailRect.setBottom(m_thumbnail.rect().bottom()); + } + + double zoomFactor = m_canvas->zoomFactor(); + + if (thumbnailRect.size() == m_visibleAreaInThumbnail.size()) { + // No change to zoom + } else if (thumbnailRect.width() != m_visibleAreaInThumbnail.width()) { + + Q_ASSERT(thumbnailRect.height() == m_visibleAreaInThumbnail.height()); + + zoomFactor *= static_cast<double>(m_visibleAreaInThumbnail.width()) / thumbnailRect.width(); + } else { + + Q_ASSERT(thumbnailRect.width() == m_visibleAreaInThumbnail.width()); + + zoomFactor *= static_cast<double>(m_visibleAreaInThumbnail.height()) / thumbnailRect.height(); + } + + if (zoomFactor < m_zoomListener->getMinZoom()) { + zoomFactor = m_zoomListener->getMinZoom(); + } else if (zoomFactor > m_zoomListener->getMaxZoom()) { + zoomFactor = m_zoomListener->getMaxZoom(); + } + + KoRect docRect = thumbnailToDocument(thumbnailRect); + m_zoomListener->zoomTo(docRect.center().x(), docRect.center().y(), zoomFactor); +} + +void KoBirdEyePanel::resizeViewEvent(QSize size) +{ + m_viewBuffer.resize(size); + fitThumbnailToView(); + slotUpdate(QRect(0, 0, m_documentSize.width(), m_documentSize.height())); +} + +void KoBirdEyePanel::fitThumbnailToView() +{ + QRect docRect = QRect(0, 0, m_thumbnailProvider->pixelSize().width(), m_thumbnailProvider->pixelSize().height()); + Q_INT32 thumbnailWidth; + Q_INT32 thumbnailHeight; + + if (docRect.isEmpty()) { + thumbnailWidth = 0; + thumbnailHeight = 0; + } else { + const int thumbnailBorderPixels = 4; + + double xScale = double(m_page->view->contentsRect().width() - thumbnailBorderPixels) / docRect.width(); + double yScale = double(m_page->view->contentsRect().height() - thumbnailBorderPixels) / docRect.height(); + + if (xScale < yScale) { + thumbnailWidth = m_page->view->contentsRect().width() - thumbnailBorderPixels; + thumbnailHeight = Q_INT32(ceil(docRect.height() * xScale)); + } else { + thumbnailWidth = Q_INT32(ceil(docRect.width() * yScale)); + thumbnailHeight = m_page->view->contentsRect().height() - thumbnailBorderPixels; + } + } + + m_thumbnail.resize(thumbnailWidth, thumbnailHeight); + updateVisibleArea(); +} + +void KoBirdEyePanel::renderView() +{ + Q_ASSERT(!m_viewBuffer.isNull()); + + if (!m_viewBuffer.isNull()) { + + updateVisibleArea(); + + QPainter painter(&m_viewBuffer); + + painter.fillRect(0, 0, m_viewBuffer.width(), m_viewBuffer.height(), colorGroup().mid()); + + if (!m_thumbnail.isNull()) { + + int thumbnailX = (m_viewBuffer.width() - m_thumbnail.width()) / 2; + int thumbnailY = (m_viewBuffer.height() - m_thumbnail.height()) / 2; + + painter.drawPixmap(thumbnailX, thumbnailY, m_thumbnail); + + painter.setPen(Qt::red); + painter.drawRect(thumbnailX + m_visibleAreaInThumbnail.x() - 1, + thumbnailY + m_visibleAreaInThumbnail.y() - 1, + m_visibleAreaInThumbnail.width() + 2, + m_visibleAreaInThumbnail.height() + 2); + painter.setPen(Qt::red.light()); + painter.drawRect(thumbnailX + m_visibleAreaInThumbnail.x() - 2, + thumbnailY + m_visibleAreaInThumbnail.y() - 2, + m_visibleAreaInThumbnail.width() + 4, + m_visibleAreaInThumbnail.height() + 4); + } + } +} + +void KoBirdEyePanel::paintViewEvent(QPaintEvent *e) +{ + Q_ASSERT(!m_viewBuffer.isNull()); + + if (!m_viewBuffer.isNull()) { + bitBlt(m_page->view, e->rect().x(), e->rect().y(), &m_viewBuffer, + e->rect().x(), e->rect().y(), e->rect().width(), e->rect().height()); + } +} + +#include "kobirdeyepanel.moc" diff --git a/krita/ui/kobirdeyepanel.h b/krita/ui/kobirdeyepanel.h new file mode 100644 index 000000000..0b625c993 --- /dev/null +++ b/krita/ui/kobirdeyepanel.h @@ -0,0 +1,262 @@ +/* + * This file is part of the KDE project + * + * Copyright (c) 2005 Boudewijn Rempt <boud@valdyas.org> + * + * 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 KO_BIRD_EYE_PANEL +#define KO_BIRD_EYE_PANEL + +#include <qrect.h> +#include <qwidget.h> + +#include <KoPoint.h> +#include <KoRect.h> + +class QPixmap; +class KAction; +class KoDocument; +class WdgBirdEye; + + +class KoCanvasAdapter { + +public: + + KoCanvasAdapter(); + virtual ~KoCanvasAdapter(); + + /** + * Returns the area of the document that is visible, in pixels + */ + virtual KoRect visibleArea() = 0; + + /** + * Returns the total area of the document in pixels. Use KoPageLayout and KoZoomhandler + * to take care of zoom, points and whatnot when computing this. + */ + virtual QRect size() = 0; + + /** + * Return the current canvas zoom factor. + */ + virtual double zoomFactor() = 0; + + /** + * Show pt in the center of the view + */ + virtual void setViewCenterPoint(double x, double y) = 0; +}; + +/** + * The zoom listener interface defines methods that the bird eye + * panel will call whenever the zoomlevel is changed through one + * of the panel actions. + */ +class KoZoomAdapter { + +public: + + KoZoomAdapter(); + virtual ~KoZoomAdapter(); + + /** + * Zoom to the specified factor around the point x and y + */ + virtual void zoomTo(double x, double y, double factor ) = 0; + + /** + * Zoom one step in. + */ + virtual void zoomIn() = 0; + + /** + * Zoom one step out. + */ + virtual void zoomOut() = 0; + + /** + * Get the minimum zoom factor that this listener supports. + */ + virtual double getMinZoom() = 0; + + /** + * Get the maximum zoom factor that this listener supports. + */ + virtual double getMaxZoom() = 0; + +}; + + +class KoThumbnailAdapter +{ + public: + + KoThumbnailAdapter(); + ~KoThumbnailAdapter(); + + /** + * Returns the size of the document in pixels. + * If the document is a KoDocument that uses a KoPageLayout, the same + * formula as in the generatePreview() method should be used to go from points + * to pixels. + * + * @returns the size in pixels. + */ + virtual QSize pixelSize() = 0; + + /** + * Returns the specified rectangle of the thumbnail as a QImage. thumbnailSize + * gives the dimensions of the whole document thumbnail, and r specifies a rectangle + * within that. + * + * @param r the rectangle in the thumbnail to be rendered + * @param thumbnailSize the size in pixels of the full thumbnail + */ + virtual QImage image(QRect r, QSize thumbnailSize) = 0; +}; + +/** + * A complex widget that provides an overview of a document + * with a red panning rectangle to and a zoom slider and a toolbar + * with a couple of useful functions. + */ +class KoBirdEyePanel : public QWidget { + + Q_OBJECT + +public: + + /** + * Create a new bird eye panel. + * + * @param zoomListener the object that listens to the zoom instructions we give + * @param thumbnailProvider the class that creates the small image at the right + * zoomlevel + * @param canvas the place the document is painted. + * @param parent the parent widget + * @param name the QObject name of this bird eye widget + * @param f the widget flags (@see QWidget) + */ + KoBirdEyePanel( KoZoomAdapter * zoomListener, + KoThumbnailAdapter * thumbnailProvider, + KoCanvasAdapter * canvas, + QWidget * parent, + const char * name = 0, + WFlags f = 0 ); + + virtual ~KoBirdEyePanel(); + + bool eventFilter(QObject*, QEvent*); + +public slots: + + void setZoomListener( KoZoomAdapter * zoomListener) { m_zoomListener = zoomListener; } + + /** + * Set a new thumbnail provider. This will first delete the existing provider. + **/ + void setThumbnailProvider( KoThumbnailAdapter * thumbnailProvider ); + + /** + * Connect to this slot to inform the bird's eye view of changes in + * the view transformation, i.e. zoom level or scroll changes. + */ + void slotViewTransformationChanged(); + + void cursorPosChanged(Q_INT32 xpos, Q_INT32 ypos); + + void zoomMinus(); + void zoomPlus(); + + /** + * Connect to this slot if a (rectangular) area of your document is changed. + * + * @param r The rect that has been changed: this is unzoomed. + */ + void slotUpdate(const QRect & r); + +protected slots: + + void updateVisibleArea(); + void zoomValueChanged(int zoom); + void zoom100(); + void sliderChanged(int); + +protected: + void setZoom(int zoom); + + void handleMouseMove(QPoint); + void handleMouseMoveAction(QPoint); + void handleMousePress(QPoint); + void fitThumbnailToView(); + void renderView(); + void resizeViewEvent(QSize size); + void paintViewEvent(QPaintEvent *e); + void makeThumbnailRectVisible(const QRect& r); + + enum enumDragHandle { + DragHandleNone, + DragHandleLeft, + DragHandleCentre, + DragHandleRight, + DragHandleTop, + DragHandleBottom + }; + + /* + * Returns the drag handle type at point p in thumbnail coordinates. + */ + enumDragHandle dragHandleAt(QPoint p); + + /** + * Returns the rectangle in the thumbnail covered by the given document rectangle. + */ + QRect documentToThumbnail(const KoRect& docRect); + + /** + * Returns the rectangle in the document covered by the given thumbnail rectangle. + */ + KoRect thumbnailToDocument(const QRect& thumbnailRect); + + /** + * Converts a point in the view to a point in the thumbnail. + */ + QPoint viewToThumbnail(const QPoint& viewPoint); + +private: + + WdgBirdEye * m_page; + + KoZoomAdapter * m_zoomListener; + KoThumbnailAdapter * m_thumbnailProvider; + KoCanvasAdapter * m_canvas; + + KAction* m_zoomIn; + KAction* m_zoomOut; + QPixmap m_viewBuffer; + QPixmap m_thumbnail; + + QSize m_documentSize; + QRect m_visibleAreaInThumbnail; + bool m_dragging; + enumDragHandle m_dragHandle; + QPoint m_lastDragPos; + +}; + +#endif diff --git a/krita/ui/layerlist.cpp b/krita/ui/layerlist.cpp new file mode 100644 index 000000000..5246896d1 --- /dev/null +++ b/krita/ui/layerlist.cpp @@ -0,0 +1,1325 @@ +/* + Copyright (c) 2005 Gábor Lehel <illissius@gmail.com> + + 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 "layerlist.h" + +#include <qtooltip.h> +#include <qbitmap.h> +#include <qcursor.h> +#include <qimage.h> +#include <qheader.h> +#include <qpainter.h> +#include <qpixmap.h> +#include <qsimplerichtext.h> +#include <qtimer.h> + +#include <kapplication.h> +#include <kdebug.h> +#include <kglobal.h> +#include <kglobalsettings.h> +#include <kiconloader.h> +#include <klineedit.h> +#include <klocale.h> +#include <kpopupmenu.h> +#include <kstringhandler.h> + +class LayerItemIterator: public QListViewItemIterator +{ +public: + LayerItemIterator( LayerList *list ): QListViewItemIterator( list ) { } + LayerItemIterator( LayerList *list, IteratorFlag flags ): QListViewItemIterator( list, flags ) { } + LayerItemIterator( LayerItem *item ): QListViewItemIterator( item ) { } + LayerItemIterator( LayerItem *item, IteratorFlag flags ): QListViewItemIterator( item, flags ) { } + LayerItem *operator*() { return static_cast<LayerItem*>( QListViewItemIterator::operator*() ); } +}; + +struct LayerProperty +{ + QString name; + QString displayName; + QPixmap enabledIcon; + QPixmap disabledIcon; + bool defaultValue; + bool validForFolders; + + LayerProperty(): defaultValue( false ), validForFolders( true ) { } + LayerProperty( const QString &pname, const QString &pdisplayName, const QPixmap &enabled, const QPixmap &disabled, + bool pdefaultValue, bool pvalidForFolders ) + : name( pname ), + displayName( pdisplayName ), + enabledIcon( enabled ), + disabledIcon( disabled ), + defaultValue( pdefaultValue ), + validForFolders( pvalidForFolders ) + { } +}; + +class LayerToolTip; +class LayerList::Private +{ +public: + LayerItem *activeLayer; + bool foldersCanBeActive; + bool previewsShown; + int itemHeight; + QValueList<LayerProperty> properties; + KPopupMenu contextMenu; + LayerToolTip *tooltip; + + Private( QWidget *parent, LayerList *list ); + ~Private(); +}; + +class LayerItem::Private +{ +public: + bool isFolder; + int id; + QValueList<bool> properties; + QImage *previewImage; + bool previewChanged; + QPixmap scaledPreview; + QSize previewSize; + QPoint previewOffset; + + Private( int pid ): isFolder( false ), id( pid ), previewImage( 0 ), previewChanged( false ) + { } +}; + +static const int MAX_SIZE = 256; +class LayerToolTip: public QToolTip, public QFrame +{ + LayerList *m_list; + LayerItem *m_item; + QPoint m_pos; + QTimer m_timer; + QImage m_img; + +public: + LayerToolTip( QWidget *parent, LayerList *list ) + : QToolTip( parent ), + QFrame( 0, 0, WStyle_Customize | WStyle_NoBorder | WStyle_Tool | WStyle_StaysOnTop | WX11BypassWM | WNoAutoErase ), + m_list( list ) + { + QFrame::setPalette( QToolTip::palette() ); + connect( &m_timer, SIGNAL( timeout() ), m_list, SLOT( hideTip() ) ); + qApp->installEventFilter( this ); + } + + virtual void maybeTip( const QPoint &pos ) + { + m_pos = pos; + LayerItem *prev = m_item; + m_item = static_cast<LayerItem*>(m_list->itemAt( m_pos )); + if( QToolTip::parentWidget() && m_list->showToolTips() && m_item ) + { + if( m_item != prev ) + hideTip(); + showTip(); + } + else + hideTip(); + } + + void showTip() + { + m_img = m_item->tooltipPreview(); + m_timer.start( 15000, true ); + if( !isVisible() || sizeHint() != size() ) + { + resize( sizeHint() ); + position(); + } + if( !isVisible() ) + show(); + else + update(); + } + + void hideTip() + { + if( !isVisible() ) + return; + QFrame::hide(); + QToolTip::hide(); + m_timer.stop(); + m_img.reset(); + m_list->triggerUpdate(); + } + + virtual void drawContents( QPainter *painter ) + { + QPixmap buf( width(), height() ); + QPainter p( &buf ); + buf.fill( colorGroup().background() ); + p.setPen( colorGroup().foreground() ); + p.drawRect( buf.rect() ); + + QSimpleRichText text( m_item->tooltip(), QToolTip::font() ); + text.setWidth( QCOORD_MAX ); + + p.translate( 5, 5 ); + if( !m_img.isNull() ) + { + if( m_img.width() > MAX_SIZE || m_img.height() > MAX_SIZE ) + m_img = m_img.scale( MAX_SIZE, MAX_SIZE, QImage::ScaleMin ); + int y = 0; + if( m_img.height() < text.height() ) + y = text.height()/2 - m_img.height()/2; + p.drawImage( 0, y, m_img ); + p.drawRect( -1, y-1, m_img.width()+2, m_img.height()+2 ); + p.translate( m_img.width() + 10, 0 ); + } + + text.draw( &p, 0, 0, rect(), colorGroup() ); + + painter->drawPixmap( 0, 0, buf ); + } + + virtual QSize sizeHint() const + { + if( !m_item ) + return QSize( 0, 0 ); + + QSimpleRichText text( m_item->tooltip(), QToolTip::font() ); + text.setWidth( QCOORD_MAX ); + + int width = text.widthUsed(); + if( !m_img.isNull() ) + width += kMin( m_img.width(), MAX_SIZE ) + 10; + width += 10; + + int height = text.height(); + if( !m_img.isNull() && kMin( m_img.height(), MAX_SIZE ) > height ) + height = kMin( m_img.height(), MAX_SIZE ); + height += 10; + + return QSize( width, height ); + } + + void position() + { + const QRect drect = QApplication::desktop()->availableGeometry( QToolTip::parentWidget() ); + const QSize size = sizeHint(); + const int width = size.width(), height = size.height(); + const QRect tmp = m_item->rect(); + const QRect irect( m_list->viewport()->mapToGlobal( m_list->contentsToViewport(tmp.topLeft()) ), tmp.size() ); + + int y; + if( irect.bottom() + height < drect.bottom() ) + y = irect.bottom(); + else + y = kMax( drect.top(), irect.top() - height ); + + int x = kMax( drect.x(), QToolTip::parentWidget()->mapToGlobal( m_pos ).x() - width/2 ); + if( x + width > drect.right() ) + x = drect.right() - width; + + move( x, y ); + } + + virtual bool eventFilter( QObject *, QEvent *e ) + { + if( isVisible() ) + switch ( e->type() ) + { + case QEvent::KeyPress: + case QEvent::KeyRelease: + case QEvent::MouseButtonPress: + case QEvent::MouseButtonRelease: + //case QEvent::MouseMove: + case QEvent::FocusIn: + case QEvent::FocusOut: + case QEvent::Wheel: + case QEvent::Leave: + hideTip(); + default: break; + } + + return false; + } +}; + +LayerList::Private::Private( QWidget *parent, LayerList *list ) + : activeLayer( 0 ), foldersCanBeActive( false ), previewsShown( false ), itemHeight( 32 ), + tooltip( new LayerToolTip( parent, list ) ) { } + +LayerList::Private::~Private() +{ + delete tooltip; + tooltip = 0; +} + +static int getID() +{ + static int id = -2; + return id--; +} + +static QSize iconSize() { return QIconSet::iconSize( QIconSet::Small ); } + + +/////////////// +// LayerList // +/////////////// + +LayerList::LayerList( QWidget *parent, const char *name ) + : super( parent, name ), d( new Private( viewport(), this ) ) +{ + setSelectionMode( QListView::Extended ); + setRootIsDecorated( true ); + setSorting( -1 ); + setSortColumn( -1 ); + setAllColumnsShowFocus( true ); + setFullWidth( true ); + setItemsRenameable( false ); + setDropHighlighter( true ); + setDefaultRenameAction( QListView::Accept ); + setDragEnabled( true ); + setAcceptDrops( true ); + setItemsMovable( true ); + addColumn( QString() ); + header()->hide(); + + QToolTip::add(this, i18n("Right-click to create folders. Click on the layername to change the layer's name. Click and drag to move layers.")); + + setNumRows( 2 ); + + connect( this, SIGNAL( itemRenamed( QListViewItem*, const QString&, int ) ), + SLOT( slotItemRenamed( QListViewItem*, const QString&, int ) ) ); + connect( this, SIGNAL( moved( QPtrList<QListViewItem>&, QPtrList<QListViewItem>&, QPtrList<QListViewItem>& ) ), + SLOT( slotItemMoved( QPtrList<QListViewItem>&, QPtrList<QListViewItem>&, QPtrList<QListViewItem>& ) ) ); + connect( this, SIGNAL( onItem( QListViewItem* ) ), SLOT( hideTip() ) ); + connect( this, SIGNAL( onViewport() ), SLOT( hideTip() ) ); +} + +LayerList::~LayerList() +{ + delete d; +} + +void LayerList::addProperty( const QString &name, const QString &displayName, const QIconSet &icon, + bool defaultValue, bool validForFolders ) +{ + addProperty( name, displayName, icon.pixmap( QIconSet::Small, QIconSet::Normal ), icon.pixmap( QIconSet::Small, QIconSet::Disabled ), defaultValue, validForFolders ); +} + +void LayerList::addProperty( const QString &name, const QString &displayName, QPixmap enabled, QPixmap disabled, + bool defaultValue, bool validForFolders ) +{ + d->properties.append( LayerProperty( name, displayName, enabled, disabled, defaultValue, validForFolders ) ); + + for( LayerItemIterator it( this ); *it; ++it ) + (*it)->d->properties.append( defaultValue ); + + //we do this only afterwards in case someone wants to access the other items in a connected slot... + for( LayerItemIterator it( this ); *it; ++it ) + if( validForFolders || !(*it)->isFolder() ) + { + emit propertyChanged( *it, name, defaultValue ); + emit propertyChanged( (*it)->id(), name, defaultValue ); + } + + triggerUpdate(); +} + +LayerItem *LayerList::layer( int id ) const +{ + if( !firstChild() || id == -1 ) + return 0; + + for( LayerItemIterator it( firstChild() ); *it; ++it ) + if( (*it)->id() == id ) + return (*it); + + return 0; +} + +LayerItem *LayerList::folder( int id ) const +{ + if( !firstChild() || id == -1 ) + return 0; + + for( LayerItemIterator it( firstChild() ); *it; ++it ) + if( (*it)->id() == id && (*it)->isFolder() ) + return (*it); + + return 0; +} + +LayerItem *LayerList::activeLayer() const +{ + return d->activeLayer; +} + +int LayerList::activeLayerID() const +{ + if( activeLayer() ) + return activeLayer()->id(); + return -1; +} + +QValueList<LayerItem*> LayerList::selectedLayers() const +{ + if( !firstChild() ) + return QValueList<LayerItem*>(); + + QValueList<LayerItem*> layers; + for( LayerItemIterator it( firstChild() ); *it; ++it ) + if( (*it)->isSelected() ) + layers.append( *it ); + + return layers; +} + +QValueList<int> LayerList::selectedLayerIDs() const +{ + const QValueList<LayerItem*> layers = selectedLayers(); + QValueList<int> ids; + for( int i = 0, n = layers.count(); i < n; ++i ) + ids.append( layers[i]->id() ); + + return ids; +} + +bool LayerList::foldersCanBeActive() const +{ + return d->foldersCanBeActive; +} + +bool LayerList::previewsShown() const +{ + return d->previewsShown; +} + +int LayerList::itemHeight() const +{ + return d->itemHeight; +} + +int LayerList::numRows() const +{ + if( itemHeight() < kMax( fontMetrics().height(), iconSize().height() ) ) + return 0; + + return ( itemHeight() - fontMetrics().height() ) / iconSize().height() + 1; +} + +void LayerList::makeFolder( int id ) +{ + LayerItem* const l = layer( id ); + if( l ) + l->makeFolder(); +} + +bool LayerList::isFolder( int id ) const +{ + LayerItem* const l = layer( id ); + if( !l ) + return false; + + return l->isFolder(); +} + +QString LayerList::displayName( int id ) const +{ + LayerItem* const l = layer( id ); + if( !l ) + return QString::null; //should be more severe... + + return l->displayName(); +} + +bool LayerList::property( int id, const QString &name ) const +{ + LayerItem* const l = layer( id ); + if( !l ) + return false; //should be more severe... + + return l->property( name ); +} + +KPopupMenu *LayerList::contextMenu() const +{ + return &( d->contextMenu ); +} + +void LayerList::setFoldersCanBeActive( bool can ) //SLOT +{ + d->foldersCanBeActive = can; + if( !can && activeLayer() && activeLayer()->isFolder() ) + { + d->activeLayer = 0; + emit activated( static_cast<LayerItem*>( 0 ) ); + emit activated( -1 ); + } +} + +void LayerList::setPreviewsShown( bool show ) //SLOT +{ + d->previewsShown = show; + triggerUpdate(); +} + +void LayerList::setItemHeight( int height ) //SLOT +{ + d->itemHeight = height; + for( LayerItemIterator it( this ); *it; ++it ) + (*it)->setup(); + triggerUpdate(); +} + +void LayerList::setNumRows( int rows ) +{ + if( rows < 1 ) + return; + + if( rows == 1 ) + setItemHeight( kMax( fontMetrics().height(), iconSize().height() ) ); + else + setItemHeight( fontMetrics().height() + ( rows - 1 ) * iconSize().height() ); +} + +void LayerList::setActiveLayer( LayerItem *layer ) //SLOT +{ + if( !foldersCanBeActive() && layer && layer->isFolder() ) + return; + + ensureItemVisible( layer ); + + if( d->activeLayer == layer ) + return; + + d->activeLayer = layer; + + if( currentItem() != layer ) + setCurrentItem( layer ); + else + { + int n = 0; + for( LayerItemIterator it( this, LayerItemIterator::Selected ); n < 2 && (*it); ++it ) { n++; } + if( n == 1 ) + (*LayerItemIterator( this, LayerItemIterator::Selected ))->setSelected( false ); + if( layer ) + layer->setSelected( true ); + } + + emit activated( layer ); + if( layer ) + emit activated( layer->id() ); + else + emit activated( -1 ); +} + +void LayerList::setActiveLayer( int id ) //SLOT +{ + setActiveLayer( layer( id ) ); +} + +void LayerList::setLayerDisplayName( LayerItem *layer, const QString &displayName ) +{ + if( !layer ) + return; + + layer->setDisplayName( displayName ); +} + +void LayerList::setLayerDisplayName( int id, const QString &displayName ) +{ + setLayerDisplayName( layer( id ), displayName ); +} + +void LayerList::setLayerProperty( LayerItem *layer, const QString &name, bool on ) //SLOT +{ + if( !layer ) + return; + + layer->setProperty( name, on ); +} + +void LayerList::setLayerProperty( int id, const QString &name, bool on ) //SLOT +{ + setLayerProperty( layer( id ), name, on ); +} + +void LayerList::toggleLayerProperty( LayerItem *layer, const QString &name ) //SLOT +{ + if( !layer ) + return; + + layer->toggleProperty( name ); +} + +void LayerList::toggleLayerProperty( int id, const QString &name ) //SLOT +{ + toggleLayerProperty( layer( id ), name ); +} + +void LayerList::setLayerPreviewImage( LayerItem *layer, QImage *image ) +{ + if( !layer ) + return; + + layer->setPreviewImage( image ); +} + +void LayerList::setLayerPreviewImage( int id, QImage *image ) +{ + setLayerPreviewImage( layer( id ), image ); +} + +void LayerList::layerPreviewChanged( LayerItem *layer ) +{ + if( !layer ) + return; + + layer->previewChanged(); +} + +void LayerList::layerPreviewChanged( int id ) +{ + layerPreviewChanged( layer( id ) ); +} + +LayerItem *LayerList::addLayer( const QString &displayName, LayerItem *after, int id ) //SLOT +{ + return new LayerItem( displayName, this, after, id ); +} + +LayerItem *LayerList::addLayer( const QString &displayName, int afterID, int id ) //SLOT +{ + return new LayerItem( displayName, this, layer( afterID ), id ); +} + +//SLOT +LayerItem *LayerList::addLayerToParent( const QString &displayName, LayerItem *parent, LayerItem *after, int id ) +{ + if( parent && parent->isFolder() ) + return parent->addLayer( displayName, after, id ); + else + return 0; +} + +LayerItem *LayerList::addLayerToParent( const QString &displayName, int parentID, int afterID, int id ) //SLOT +{ + return addLayerToParent( displayName, folder( parentID ), layer( afterID ), id ); +} + +void LayerList::moveLayer( LayerItem *layer, LayerItem *parent, LayerItem *after ) //SLOT +{ + if( !layer ) + return; + + if( parent && !parent->isFolder() ) + parent = 0; + + if( layer->parent() == parent && layer->prevSibling() == after ) + return; + + QListViewItem *current = currentItem(); + + moveItem( layer, parent, after ); + + emit layerMoved( layer, parent, after ); + emit layerMoved( layer->id(), parent ? parent->id() : -1, after ? after->id() : -1 ); + + setCurrentItem( current ); //HACK, sometimes Qt changes this under us +} + +void LayerList::moveLayer( int id, int parentID, int afterID ) //SLOT +{ + moveLayer( layer( id ), folder( parentID ), layer( afterID ) ); +} + +void LayerList::removeLayer( LayerItem *layer ) //SLOT +{ + delete layer; +} + +void LayerList::removeLayer( int id ) //SLOT +{ + delete layer( id ); +} + +void LayerList::contentsMousePressEvent( QMouseEvent *e ) +{ + LayerItem *item = static_cast<LayerItem*>( itemAt( contentsToViewport( e->pos() ) ) ); + + if( item ) + { + QMouseEvent m( QEvent::MouseButtonPress, item->mapFromListView( e->pos() ), e->button(), e->state() ); + if( !item->mousePressEvent( &m ) ) + super::contentsMousePressEvent( e ); + } + else + { + super::contentsMousePressEvent( e ); + if( e->button() == Qt::RightButton ) + showContextMenu(); + } +} + +void LayerList::contentsMouseDoubleClickEvent( QMouseEvent *e ) +{ + super::contentsMouseDoubleClickEvent( e ); + if( LayerItem *layer = static_cast<LayerItem*>( itemAt( contentsToViewport( e->pos() ) ) ) ) + { + if( !layer->iconsRect().contains( layer->mapFromListView( e->pos() ) ) ) + { + emit requestLayerProperties( layer ); + emit requestLayerProperties( layer->id() ); + } + } + else + { + emit requestNewLayer( static_cast<LayerItem*>( 0 ), static_cast<LayerItem*>( 0 ) ); + emit requestNewLayer( -1, -1 ); + } +} + +void LayerList::findDrop( const QPoint &pos, QListViewItem *&parent, QListViewItem *&after ) +{ + LayerItem *item = static_cast<LayerItem*>( itemAt( contentsToViewport( pos ) ) ); + if( item && item->isFolder() ) + { + parent = item; + after = 0; + } + else + super::findDrop( pos, parent, after ); +} + +void LayerList::showContextMenu() +{ + LayerItem *layer = static_cast<LayerItem*>( itemAt( viewport()->mapFromGlobal( QCursor::pos() ) ) ); + if( layer ) + setCurrentItem( layer ); + d->contextMenu.clear(); + constructMenu( layer ); + menuActivated( d->contextMenu.exec( QCursor::pos() ), layer ); +} + +void LayerList::hideTip() +{ + d->tooltip->hideTip(); +} + +void LayerList::maybeTip() +{ + d->tooltip->maybeTip( d->tooltip->QToolTip::parentWidget()->mapFromGlobal( QCursor::pos() ) ); +} + +void LayerList::constructMenu( LayerItem *layer ) +{ + if( layer ) + { + for( int i = 0, n = d->properties.count(); i < n; ++i ) + if( !layer->isFolder() || d->properties[i].validForFolders ) + d->contextMenu.insertItem( layer->d->properties[i] ? d->properties[i].enabledIcon : d->properties[i].disabledIcon, d->properties[i].displayName, MenuItems::COUNT + i ); + d->contextMenu.insertItem( SmallIconSet( "info" ), i18n( "&Properties" ), MenuItems::LayerProperties ); + d->contextMenu.insertSeparator(); + d->contextMenu.insertItem( SmallIconSet( "editdelete" ), + selectedLayers().count() > 1 ? i18n( "Remove Layers" ) + : layer->isFolder() ? i18n( "&Remove Folder" ) + : i18n( "&Remove Layer" ), MenuItems::RemoveLayer ); + } + d->contextMenu.insertItem( SmallIconSet( "filenew" ), i18n( "&New Layer" ), MenuItems::NewLayer ); + d->contextMenu.insertItem( SmallIconSet( "folder" ), i18n( "New &Folder" ), MenuItems::NewFolder ); +} + +void LayerList::menuActivated( int id, LayerItem *layer ) +{ + const QValueList<LayerItem*> selected = selectedLayers(); + + LayerItem *parent = ( layer && layer->isFolder() ) ? layer : 0; + LayerItem *after = 0; + if( layer && !parent ) + { + parent = layer->parent(); + after = layer->prevSibling(); + } + switch( id ) + { + case MenuItems::NewLayer: + emit requestNewLayer( parent, after ); + emit requestNewLayer( parent ? parent->id() : -1, after ? after->id() : -1 ); + break; + case MenuItems::NewFolder: + emit requestNewFolder( parent, after ); + emit requestNewFolder( parent ? parent->id() : -1, after ? after->id() : -1 ); + break; + case MenuItems::RemoveLayer: + { + QValueList<int> ids; + for( int i = 0, n = selected.count(); i < n; ++i ) + { + ids.append( selected[i]->id() ); + emit requestRemoveLayer( selected[i]->id() ); + } + emit requestRemoveLayers( ids ); + } + for( int i = 0, n = selected.count(); i < n; ++i ) + emit requestRemoveLayer( selected[i] ); + emit requestRemoveLayers( selected ); + break; + case MenuItems::LayerProperties: + if( layer ) + { + emit requestLayerProperties( layer ); + emit requestLayerProperties( layer->id() ); + } + break; + default: + if( id >= MenuItems::COUNT && layer ) + for( int i = 0, n = selected.count(); i < n; ++i ) + selected[i]->toggleProperty( d->properties[ id - MenuItems::COUNT ].name ); + } +} + +void LayerList::slotItemRenamed( QListViewItem *item, const QString &text, int col ) +{ + if( !item || col != 0 ) + return; + + emit displayNameChanged( static_cast<LayerItem*>( item ), text ); + emit displayNameChanged( static_cast<LayerItem*>( item )->id(), text ); +} + +void LayerList::slotItemMoved( QPtrList<QListViewItem> &items, QPtrList<QListViewItem> &/*afterBefore*/, QPtrList<QListViewItem> &afterNow ) +{ + for( int i = 0, n = items.count(); i < n; ++i ) + { + LayerItem *l = static_cast<LayerItem*>( items.at(i) ), *a = static_cast<LayerItem*>( afterNow.at(i) ); + if( !l ) + continue; + + if( l->parent() ) + l->parent()->setOpen( true ); + + emit layerMoved( l, l->parent(), a ); + emit layerMoved( l->id(), l->parent() ? l->parent()->id() : -1, a ? a->id() : -1 ); + } +} + +void LayerList::setCurrentItem( QListViewItem *item ) +{ + if( !item ) + return; + + super::setCurrentItem( item ); + ensureItemVisible( item ); + int n = 0; + for( LayerItemIterator it( this, LayerItemIterator::Selected ); n < 2 && (*it); ++it ) { n++; } + if( n == 1 ) + (*LayerItemIterator( this, LayerItemIterator::Selected ))->setSelected( false ); + item->setSelected( true ); + if( activeLayer() != item ) + setActiveLayer( static_cast<LayerItem*>(item) ); +} + + +/////////////// +// LayerItem // +/////////////// + +LayerItem::LayerItem( const QString &displayName, LayerList *p, LayerItem *after, int id ) + : super( p, after ), d( new Private( id ) ) +{ + init(); + setDisplayName( displayName ); +} + +LayerItem::LayerItem( const QString &displayName, LayerItem *p, LayerItem *after, int id ) + : super( ( p && p->isFolder() ) ? p : 0, after ), d( new Private( id ) ) +{ + init(); + setDisplayName( displayName ); +} + +void LayerItem::init() +{ + if( d->id < 0 ) + d->id = getID(); + + for( int i = 0, n = listView()->d->properties.count(); i < n; ++i ) + d->properties.append( listView()->d->properties[i].defaultValue ); + + if( parent()) + parent()->setOpen( true ); +} + +LayerItem::~LayerItem() +{ + if (listView() && (listView()->activeLayer() == this || contains(listView()->activeLayer()))) + listView()->setActiveLayer( static_cast<LayerItem*>( 0 ) ); + delete d; +} + +void LayerItem::makeFolder() +{ + d->isFolder = true; + setPixmap( 0, SmallIcon( "folder", 16 ) ); + if( isActive() && !listView()->foldersCanBeActive() ) + listView()->setActiveLayer( static_cast<LayerItem*>( 0 ) ); +} + +bool LayerItem::isFolder() const +{ + return d->isFolder; +} + +bool LayerItem::contains(const LayerItem *item) +{ + QListViewItemIterator it(this); + + while (it.current()) { + if (static_cast<const LayerItem *>(it.current()) == item) { + return true; + } + ++it; + } + return false; +} + +int LayerItem::id() const +{ + return d->id; +} + +QString LayerItem::displayName() const +{ + return text( 0 ); +} + +void LayerItem::setDisplayName( const QString &s ) +{ + if( displayName() == s ) + return; + setText( 0, s ); + emit listView()->displayNameChanged( this, s ); + emit listView()->displayNameChanged( id(), s ); +} + +bool LayerItem::isActive() const +{ + return listView()->activeLayer() == this; +} + +void LayerItem::setActive() +{ + listView()->setActiveLayer( this ); +} + +bool LayerItem::property( const QString &name ) const +{ + int i = listView()->d->properties.count() - 1; + while( i && listView()->d->properties[i].name != name ) + --i; + + if( i < 0 ) + return false; //should do something more severe... but what? + + return d->properties[i]; +} + +void LayerItem::setProperty( const QString &name, bool on ) +{ + int i = listView()->d->properties.count() - 1; + while( i && listView()->d->properties[i].name != name ) + --i; + + if( i < 0 || ( isFolder() && !listView()->d->properties[i].validForFolders ) ) + return; + + const bool notify = ( on != d->properties[i] ); + d->properties[i] = on; + if( notify ) + { + emit listView()->propertyChanged( this, name, on ); + emit listView()->propertyChanged( id(), name, on ); + } + + update(); +} + +void LayerItem::toggleProperty( const QString &name ) +{ + int i = listView()->d->properties.count() - 1; + while( i && listView()->d->properties[i].name != name ) + --i; + + if( i < 0 || ( isFolder() && !listView()->d->properties[i].validForFolders ) ) + return; + + d->properties[i] = !(d->properties[i]); + emit listView()->propertyChanged( this, name, d->properties[i] ); + emit listView()->propertyChanged( id(), name, d->properties[i] ); + + update(); +} + +void LayerItem::setPreviewImage( QImage *image ) +{ + d->previewImage = image; + previewChanged(); +} + +void LayerItem::previewChanged() +{ + d->previewChanged = true; + update(); +} + +LayerItem *LayerItem::addLayer( const QString &displayName, LayerItem *after, int id ) +{ + if( !isFolder() ) + return 0; + return new LayerItem( displayName, this, after, id ); +} + +LayerItem *LayerItem::prevSibling() const +{ + LayerItem *item = parent() ? parent()->firstChild() : listView()->firstChild(); + if( !item || this == item ) + return 0; + for(; item && this != item->nextSibling(); item = item->nextSibling() ); + return item; +} + +int LayerItem::mapXFromListView( int x ) const +{ + return x - rect().left(); +} + +int LayerItem::mapYFromListView( int y ) const +{ + return y - rect().top(); +} + +QPoint LayerItem::mapFromListView( const QPoint &point ) const +{ + return QPoint( mapXFromListView( point.x() ), mapYFromListView( point.y() ) ); +} + +QRect LayerItem::mapFromListView( const QRect &rect ) const +{ + return QRect( mapFromListView( rect.topLeft() ), rect.size() ); +} + +int LayerItem::mapXToListView( int x ) const +{ + return x + rect().left(); +} + +int LayerItem::mapYToListView( int y ) const +{ + return y + rect().top(); +} + +QPoint LayerItem::mapToListView( const QPoint &point ) const +{ + return QPoint( mapXToListView( point.x() ), mapYToListView( point.y() ) ); +} + +QRect LayerItem::mapToListView( const QRect &rect ) const +{ + return QRect( mapToListView( rect.topLeft() ), rect.size() ); +} + +QRect LayerItem::rect() const +{ + const int indent = listView()->treeStepSize() * ( depth() + 1 ); + return QRect( listView()->header()->sectionPos( 0 ) + indent, itemPos(), + listView()->header()->sectionSize( 0 ) - indent, height() ); +} + +QRect LayerItem::textRect() const +{ + static QFont f; + static int minbearing = 1337 + 666; //can be 0 or negative, 2003 is less likely + if( minbearing == 2003 || f != font() ) + { + f = font(); //getting your bearings can be expensive, so we cache them + minbearing = fontMetrics().minLeftBearing() + fontMetrics().minRightBearing(); + } + + const int margin = listView()->itemMargin(); + int indent = previewRect().right() + margin; + if( pixmap( 0 ) ) + indent += pixmap( 0 )->width() + margin; + + const int width = ( multiline() ? rect().right() : iconsRect().left() ) - indent - margin + minbearing; + + return QRect( indent, 0, width, fontMetrics().height() ); +} + +QRect LayerItem::iconsRect() const +{ + const QValueList<LayerProperty> &lp = listView()->d->properties; + int propscount = 0; + for( int i = 0, n = lp.count(); i < n; ++i ) + if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) ) + propscount++; + + const int iconswidth = propscount * iconSize().width() + (propscount - 1) * listView()->itemMargin(); + + const int x = multiline() ? previewRect().right() + listView()->itemMargin() : rect().width() - iconswidth; + const int y = multiline() ? fontMetrics().height() : 0; + + return QRect( x, y, iconswidth, iconSize().height() ); +} + +QRect LayerItem::previewRect() const +{ + return QRect( 0, 0, listView()->previewsShown() ? height() : 0, height() ); +} + +void LayerItem::drawText( QPainter *p, const QColorGroup &cg, const QRect &r ) +{ + p->translate( r.left(), r.top() ); + + p->setPen( isSelected() ? cg.highlightedText() : cg.text() ); + + const QString text = KStringHandler::rPixelSqueeze( displayName(), p->fontMetrics(), r.width() ); + p->drawText( listView()->itemMargin(), 0, r.width(), r.height(), Qt::AlignAuto | Qt::AlignTop, text ); + + p->translate( -r.left(), -r.top() ); +} + +void LayerItem::drawIcons( QPainter *p, const QColorGroup &/*cg*/, const QRect &r ) +{ + p->translate( r.left(), r.top() ); + + int x = 0; + const QValueList<LayerProperty> &lp = listView()->d->properties; + for( int i = 0, n = lp.count(); i < n; ++i ) + if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) ) + { + if( !isFolder() || lp[i].validForFolders ) + p->drawPixmap( x, 0, d->properties[i] ? lp[i].enabledIcon : lp[i].disabledIcon ); + x += iconSize().width() + listView()->itemMargin(); + } + + p->translate( -r.left(), -r.top() ); +} + +void LayerItem::drawPreview( QPainter *p, const QColorGroup &/*cg*/, const QRect &r ) +{ + if( !showPreview() ) + return; + + if( d->previewChanged || r.size() != d->previewSize ) + { //TODO handle width() != height() + const int size = kMin( r.width(), kMax( previewImage()->width(), previewImage()->height() ) ); + const QImage i = previewImage()->smoothScale( size, size, QImage::ScaleMin ); + d->scaledPreview.convertFromImage( i ); + d->previewOffset.setX( r.width()/2 - i.width()/2 ); + d->previewOffset.setY( r.height()/2 - i.height()/2 ); + + d->previewChanged = false; + d->previewSize = r.size(); + } + + p->drawPixmap( r.topLeft() + d->previewOffset, d->scaledPreview ); +} + +bool LayerItem::showPreview() const +{ + return listView()->previewsShown() && previewImage() && !previewImage()->isNull(); +} + +bool LayerItem::multiline() const +{ + return height() >= fontMetrics().height() + iconSize().height(); +} + +QFont LayerItem::font() const +{ + if( isActive() ) + { + QFont f = listView()->font(); + f.setBold( !f.bold() ); + f.setItalic( !f.italic() ); + return f; + } + else + return listView()->font(); +} + +QFontMetrics LayerItem::fontMetrics() const +{ + return QFontMetrics( font() ); +} + +bool LayerItem::mousePressEvent( QMouseEvent *e ) +{ + if( e->button() == Qt::RightButton ) + { + if ( !(e->state() & Qt::ControlButton) && !(e->state() & Qt::ShiftButton) ) + setActive(); + QTimer::singleShot( 0, listView(), SLOT( showContextMenu() ) ); + return false; + } + + const QRect ir = iconsRect(), tr = textRect(); + + if( ir.contains( e->pos() ) ) + { + const int iconWidth = iconSize().width(); + int x = e->pos().x() - ir.left(); + if( x % ( iconWidth + listView()->itemMargin() ) < iconWidth ) //it's on an icon, not a margin + { + const QValueList<LayerProperty> &lp = listView()->d->properties; + int p = -1; + for( int i = 0, n = lp.count(); i < n; ++i ) + { + if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) ) + x -= iconWidth + listView()->itemMargin(); + p += 1; + if( x < 0 ) + break; + } + toggleProperty( lp[p].name ); + } + return true; + } + + else if( tr.contains( e->pos() ) && isSelected() && !listView()->renameLineEdit()->isVisible() ) + { + listView()->rename( this, 0 ); + QRect r( listView()->contentsToViewport( mapToListView( tr.topLeft() ) ), tr.size() ); + listView()->renameLineEdit()->setGeometry( r ); + return true; + } + + if ( !(e->state() & Qt::ControlButton) && !(e->state() & Qt::ShiftButton) ) + setActive(); + + return false; +} + +QString LayerItem::tooltip() const +{ + QString tip; + tip += "<table cellspacing=\"0\" cellpadding=\"0\">"; + tip += QString("<tr><td colspan=\"2\" align=\"center\"><b>%1</b></td></tr>").arg( displayName() ); + QString row = "<tr><td>%1</td><td>%2</td></tr>"; + for( int i = 0, n = listView()->d->properties.count(); i < n; ++i ) + if( !isFolder() || listView()->d->properties[i].validForFolders ) + { + if( d->properties[i] ) + tip += row.arg( i18n( "%1:" ).arg( listView()->d->properties[i].displayName ) ).arg( i18n( "Yes" ) ); + else + tip += row.arg( i18n( "%1:" ).arg( listView()->d->properties[i].displayName ) ).arg( i18n( "No" ) ); + } + tip += "</table>"; + return tip; +} + +QImage *LayerItem::previewImage() const +{ + return d->previewImage; +} + +QImage LayerItem::tooltipPreview() const +{ + if( previewImage() ) + return *previewImage(); + return QImage(); +} + +int LayerItem::width( const QFontMetrics &fm, const QListView *lv, int c ) const +{ + if( c != 0 ) + return super::width( fm, lv, c ); + + const QValueList<LayerProperty> &lp = listView()->d->properties; + int propscount = 0; + for( int i = 0, n = d->properties.count(); i < n; ++i ) + if( !lp[i].enabledIcon.isNull() && ( !multiline() || !isFolder() || lp[i].validForFolders ) ) + propscount++; + + const int iconswidth = propscount * iconSize().width() + (propscount - 1) * listView()->itemMargin(); + + if( multiline() ) + return kMax( super::width( fm, lv, 0 ), iconswidth ); + else + return super::width( fm, lv, 0 ) + iconswidth; +} + +void LayerItem::paintCell( QPainter *painter, const QColorGroup &cg, int column, int width, int align ) +{ + if( column != 0 ) + { + super::paintCell( painter, cg, column, width, align ); + return; + } + + QPixmap buf( width, height() ); + QPainter p( &buf ); + + p.setFont( font() ); + + const QColorGroup cg_ = isEnabled() ? listView()->palette().active() : listView()->palette().disabled(); + + const QColor bg = isSelected() ? cg_.highlight() + : isAlternate() ? listView()->alternateBackground() + : listView()->viewport()->backgroundColor(); + + buf.fill( bg ); + + if( pixmap( 0 ) ) + p.drawPixmap( previewRect().right() + listView()->itemMargin(), 0, *pixmap( 0 ) ); + + drawText( &p, cg_, textRect() ); + drawIcons( &p, cg_, iconsRect() ); + drawPreview( &p, cg_, previewRect() ); + + painter->drawPixmap( 0, 0, buf ); +} + +void LayerItem::setup() +{ + super::setup(); + setHeight( listView()->d->itemHeight ); +} + +void LayerItem::setSelected( bool selected ) +{ + if( !selected && ( isActive() || this == listView()->currentItem() ) ) + return; + super::setSelected( selected ); +} + + +///////////////////////// +// Convenience Methods // +///////////////////////// + +LayerItem *LayerList::firstChild() const { return static_cast<LayerItem*>( super::firstChild() ); } +LayerItem *LayerList::lastChild() const { return static_cast<LayerItem*>( super::lastChild() ); } +LayerList *LayerItem::listView() const { return static_cast<LayerList*>( super::listView() ); } +void LayerItem::update() const { listView()->repaintItem( this ); } +LayerItem *LayerItem::firstChild() const { return static_cast<LayerItem*>( super::firstChild() ); } +LayerItem *LayerItem::nextSibling() const { return static_cast<LayerItem*>( super::nextSibling() ); } +LayerItem *LayerItem::parent() const { return static_cast<LayerItem*>( super::parent() ); } + + +#include "layerlist.moc" diff --git a/krita/ui/layerlist.h b/krita/ui/layerlist.h new file mode 100644 index 000000000..b981b266e --- /dev/null +++ b/krita/ui/layerlist.h @@ -0,0 +1,268 @@ +/* + Copyright (c) 2005 Gábor Lehel <illissius@gmail.com> + + 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 LAYERLIST_H +#define LAYERLIST_H + +#include <qiconset.h> +#include <klistview.h> + +class QMouseEvent; +class QString; +class KPopupMenu; +class LayerItem; +class LayerFolder; +template<class T> class QPtrList; + +class LayerList: public KListView +{ + Q_OBJECT + +public: + LayerList( QWidget *parent = 0, const char *name = 0 ); + virtual ~LayerList(); + + void addProperty( const QString &name, const QString &displayName, const QIconSet &icon = QIconSet(), + bool defaultValue = false, bool validForFolders = true ); + void addProperty( const QString &name, const QString &displayName, QPixmap enabled, QPixmap disabled, + bool defaultValue = false, bool validForFolders = true ); + + bool foldersCanBeActive() const; + bool previewsShown() const; + int itemHeight() const; + int numRows() const; + + LayerItem *layer( int id ) const; + LayerItem *folder( int id ) const; //returns 0 if not a folder + + LayerItem *activeLayer() const; + int activeLayerID() const; + + QValueList<LayerItem*> selectedLayers() const; + QValueList<int> selectedLayerIDs() const; + + void makeFolder( int id ); + bool isFolder( int id ) const; + QString displayName( int id ) const; + bool property( int id, const QString &name ) const; + + struct MenuItems + { + enum { NewLayer = 0, NewFolder, RemoveLayer, LayerProperties, COUNT }; + }; + KPopupMenu *contextMenu() const; + +public slots: + void setFoldersCanBeActive( bool can ); + void setPreviewsShown( bool show ); + void setItemHeight( int height ); + void setNumRows( int rows ); //how many rows of property icons can fit + + void setActiveLayer( LayerItem *layer ); + void setActiveLayer( int id ); + + void setLayerDisplayName( LayerItem *layer, const QString &displayName ); + void setLayerDisplayName( int id, const QString &displayName ); + + void setLayerProperty( LayerItem *layer, const QString &name, bool on ); + void setLayerProperty( int id, const QString &name, bool on ); + + void toggleLayerProperty( LayerItem *layer, const QString &name ); + void toggleLayerProperty( int id, const QString &name ); + + void setLayerPreviewImage( LayerItem *layer, QImage *image ); + void setLayerPreviewImage( int id, QImage *image ); + + void layerPreviewChanged( LayerItem *layer ); + void layerPreviewChanged( int id ); + + LayerItem *addLayer( const QString &displayName, LayerItem *after = 0, int id = -1 ); + LayerItem *addLayer( const QString &displayName, int afterID, int id = -1 ); + + LayerItem *addLayerToParent( const QString &displayName, LayerItem *parent, LayerItem *after = 0, int id = -1 ); + LayerItem *addLayerToParent( const QString &displayName, int parentID, int afterID = -1, int id = -1 ); + + void moveLayer( LayerItem *layer, LayerItem *parent, LayerItem *after ); + void moveLayer( int id, int parentID, int afterID ); + + void removeLayer( LayerItem *layer ); + void removeLayer( int id ); + +signals: + void activated( LayerItem *layer ); + void activated( int id ); + + void displayNameChanged( LayerItem *layer, const QString &displayName ); + void displayNameChanged( int id, const QString &displayName ); + + void propertyChanged( LayerItem *layer, const QString &name, bool on ); + void propertyChanged( int id, const QString &name, bool on ); + + void layerMoved( LayerItem *layer, LayerItem *parent, LayerItem *after ); + void layerMoved( int id, int parentID, int afterID ); + + void requestNewLayer( LayerItem *parent, LayerItem *after ); + void requestNewLayer( int parentID, int afterID ); + + void requestNewFolder( LayerItem *parent, LayerItem *after ); + void requestNewFolder( int parentID, int afterID ); + + void requestRemoveLayer( LayerItem *layer ); + void requestRemoveLayer( int id ); + + void requestRemoveLayers( QValueList<LayerItem*> layers ); + void requestRemoveLayers( QValueList<int> ids ); + + void requestLayerProperties( LayerItem *layer ); + void requestLayerProperties( int id ); + +public: //convenience + LayerItem *firstChild() const; + LayerItem *lastChild() const; + +protected slots: + virtual void constructMenu( LayerItem *layer ); + virtual void menuActivated( int id, LayerItem *layer ); + +private: + typedef KListView super; + friend class LayerItem; + friend class LayerToolTIp; + + class Private; + Private* const d; + +private slots: + void slotItemRenamed( QListViewItem *item, const QString &text, int col ); + void slotItemMoved( QPtrList<QListViewItem>&, QPtrList<QListViewItem>&, QPtrList<QListViewItem>& ); + void showContextMenu(); + void hideTip(); + void maybeTip(); + +public: //reimplemented for internal reasons + virtual void setCurrentItem( QListViewItem *i ); + +protected: + virtual void contentsMousePressEvent( QMouseEvent *e ); + virtual void contentsMouseDoubleClickEvent ( QMouseEvent *e ); + virtual void findDrop( const QPoint &pos, QListViewItem *&parent, QListViewItem *&after ); +}; + +class LayerItem: public KListViewItem +{ +public: + LayerItem( const QString &displayName, LayerList *parent, LayerItem *after = 0, int id = -1 ); + LayerItem( const QString &displayName, LayerItem *parent, LayerItem *after = 0, int id = -1 ); + virtual ~LayerItem(); + + void makeFolder(); + bool isFolder() const; + + // Returns true if this item is the given item or the tree rooted at + // this item contains the given item. + bool contains(const LayerItem *item); + + int id() const; + + QString displayName() const; + void setDisplayName( const QString &displayName ); + + bool isActive() const; + void setActive(); + + bool property( const QString &name ) const; + void setProperty( const QString &name, bool on ); + void toggleProperty( const QString &name ); + + void setPreviewImage( QImage *image ); + void previewChanged(); + + LayerItem *addLayer( const QString &displayName, LayerItem *after = 0, int id = -1 ); + + LayerItem *prevSibling() const; + +public: //convenience + LayerItem *nextSibling() const; + LayerList *listView() const; + LayerItem *firstChild() const; + LayerItem *parent() const; + void update() const; //like QWidget::update() + +protected: + virtual QRect rect() const; + + int mapXFromListView( int x ) const; + int mapYFromListView( int y ) const; + QPoint mapFromListView( const QPoint &point ) const; + QRect mapFromListView( const QRect &rect ) const; + + int mapXToListView( int x ) const; + int mapYToListView( int y ) const; + QPoint mapToListView( const QPoint &point ) const; + QRect mapToListView( const QRect &rect ) const; + + virtual QRect textRect() const; + virtual QRect iconsRect() const; + virtual QRect previewRect() const; + + virtual void drawText( QPainter *p, const QColorGroup &cg, const QRect &r ); + virtual void drawIcons( QPainter *p, const QColorGroup &cg, const QRect &r ); + virtual void drawPreview( QPainter *p, const QColorGroup &cg, const QRect &r ); + + bool multiline() const; + bool showPreview() const; + virtual QFont font() const; + QFontMetrics fontMetrics() const; + + virtual bool mousePressEvent( QMouseEvent *e ); + + virtual QString tooltip() const; + + virtual QImage *previewImage() const; + virtual QImage tooltipPreview() const; + +private: + typedef KListViewItem super; + friend class LayerList; + friend class LayerToolTip; + + class Private; + Private* const d; + + void init(); + +public: //reimplemented for internal reasons + virtual int width( const QFontMetrics &fm, const QListView *lv, int c ) const; + virtual void paintCell( QPainter *p, const QColorGroup &cg, int column, int width, int align ); + virtual void setup(); + virtual void setSelected( bool selected ); +}; + +class LayerFolder: public LayerItem +{ +public: + LayerFolder( const QString &displayName, LayerList *parent, LayerItem *after = 0, int id = -1 ) + : LayerItem( displayName, parent, after, id ) { makeFolder(); } + LayerFolder( const QString &displayName, LayerItem *parent, LayerItem *after = 0, int id = -1 ) + : LayerItem( displayName, parent, after, id ) { makeFolder(); } +}; + + +#endif diff --git a/krita/ui/squeezedcombobox.cpp b/krita/ui/squeezedcombobox.cpp new file mode 100644 index 000000000..971a73e61 --- /dev/null +++ b/krita/ui/squeezedcombobox.cpp @@ -0,0 +1,167 @@ +/* ============================================================ + * Author: Tom Albers <tomalbers@kde.nl> + * Date : 2005-01-01 + * Description : + * + * Copyright 2005 by Tom Albers + * + * 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, 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. + * + * ============================================================ */ + +/** @file squeezedcombobox.cpp */ + +// Qt includes. + +#include <qlistbox.h> +#include <qcombobox.h> +#include <qpair.h> +#include <qtimer.h> +#include <qvaluelist.h> +#include <qstyle.h> +#include <qapplication.h> +#include <qtooltip.h> + +// Local includes. + +#include "squeezedcombobox.h" + +SqueezedComboBoxTip::SqueezedComboBoxTip( QWidget * parent, SqueezedComboBox* name ) + : QToolTip( parent ) +{ + m_originalWidget = name; +} + +void SqueezedComboBoxTip::maybeTip( const QPoint &pos ) +{ + QListBox* listBox = m_originalWidget->listBox(); + if (!listBox) + return; + + QListBoxItem* selectedItem = listBox->itemAt( pos ); + if (selectedItem) + { + QRect positionToolTip = listBox->itemRect( selectedItem ); + QString toolTipText = m_originalWidget->itemHighlighted(); + if (!toolTipText.isNull()) + tip(positionToolTip, toolTipText); + } +} + +SqueezedComboBox::SqueezedComboBox( QWidget *parent, const char *name ) + : QComboBox( parent, name ) +{ + setMinimumWidth(100); + m_timer = new QTimer(this); + m_tooltip = new SqueezedComboBoxTip( listBox()->viewport(), this ); + + connect(m_timer, SIGNAL(timeout()), + SLOT(slotTimeOut())); + connect(this, SIGNAL(activated( int )), + SLOT(slotUpdateToolTip( int ))); +} + +SqueezedComboBox::~SqueezedComboBox() +{ + delete m_tooltip; + delete m_timer; +} + +bool SqueezedComboBox::contains( const QString& _text ) const +{ + if ( _text.isEmpty() ) + return false; + + const int itemCount = count(); + for (int i = 0; i < itemCount; ++i ) + { + if ( text(i) == _text ) + return true; + } + return false; +} + +QSize SqueezedComboBox::sizeHint() const +{ + constPolish(); + QFontMetrics fm = fontMetrics(); + + int maxW = count() ? 18 : 7 * fm.width(QChar('x')) + 18; + int maxH = QMAX( fm.lineSpacing(), 14 ) + 2; + + return style().sizeFromContents(QStyle::CT_ComboBox, this, + QSize(maxW, maxH)). + expandedTo(QApplication::globalStrut()); +} + +void SqueezedComboBox::insertSqueezedItem(const QString& newItem, int index) +{ + m_originalItems[index] = newItem; + insertItem( squeezeText(newItem), index ); + + // if this is the first item, set the tooltip. + if (index == 0) + slotUpdateToolTip(0); +} + +void SqueezedComboBox::resizeEvent ( QResizeEvent * ) +{ + m_timer->start(200, true); +} + +void SqueezedComboBox::slotTimeOut() +{ + QMapIterator<int,QString> it; + for (it = m_originalItems.begin() ; it != m_originalItems.end(); + ++it) + { + changeItem( squeezeText( it.data() ), it.key() ); + } +} + +QString SqueezedComboBox::squeezeText( const QString& original) +{ + // not the complete widgetSize is usable. Need to compensate for that. + int widgetSize = width()-30; + QFontMetrics fm( fontMetrics() ); + + // If we can fit the full text, return that. + if (fm.width(original) < widgetSize) + return(original); + + // We need to squeeze. + QString sqItem = original; // prevent empty return value; + widgetSize = widgetSize-fm.width("..."); + for (uint i = 0 ; i != original.length(); ++i) + { + if ( (int)fm.width(original.right(i)) > widgetSize) + { + sqItem = QString("..." + original.right(--i)); + break; + } + } + return sqItem; +} + +void SqueezedComboBox::slotUpdateToolTip( int index ) +{ + QToolTip::remove(this); + QToolTip::add(this, m_originalItems[index]); +} + +QString SqueezedComboBox::itemHighlighted() +{ + int curItem = this->listBox()->currentItem(); + return m_originalItems[curItem]; +} + +#include "squeezedcombobox.moc" diff --git a/krita/ui/squeezedcombobox.h b/krita/ui/squeezedcombobox.h new file mode 100644 index 000000000..51f9eb517 --- /dev/null +++ b/krita/ui/squeezedcombobox.h @@ -0,0 +1,136 @@ +/* ============================================================ + * Author: Tom Albers <tomalbers@kde.nl> + * Date : 2005-01-01 + * Description : + * + * Copyright 2005 by Tom Albers + * + * 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, 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. + * + * ============================================================ */ + +/** @file squeezedcombobox.h */ + +#ifndef SQUEEZEDCOMBOBOX_H +#define SQUEEZEDCOMBOBOX_H + +class QTimer; + +// Qt includes. + +#include <qcombobox.h> +#include <qtooltip.h> + +class SqueezedComboBox; + +/** @class SqueezedComboBoxTip + * This class shows a tooltip for a SqueezedComboBox + * the tooltip will contain the full text and helps + * the user find the correct entry. It is automatically + * activated when starting a SqueezedComboBox. This is + * inherited from QToolTip + * + * @author Tom Albers + */ +class SqueezedComboBoxTip : public QToolTip +{ +public: + /** + * Constructor. An example call (as done in + * SqueezedComboBox::SqueezedComboBox): + * @code + * t = new SqueezedComboBoxTip( this->listBox()->viewport(), this ); + * @endcode + * + * @param parent parent widget (viewport) + * @param name parent widget + */ + SqueezedComboBoxTip( QWidget *parent, SqueezedComboBox *name ); + +protected: + /** + * Reimplemented version from QToolTip which shows the + * tooltip when needed. + * @param pos the point where the mouse currently is + */ + void maybeTip( const QPoint& pos ); + +private: + SqueezedComboBox* m_originalWidget; +}; + +/** @class SqueezedComboBox + * + * This widget is a QComboBox, but then a little bit + * different. It only shows the right part of the items + * depending on de size of the widget. When it is not + * possible to show the complete item, it will be shortened + * and "..." will be prepended. + * + * @image html squeezedcombobox.png "This is how it looks" + * @author Tom Albers + */ +class SqueezedComboBox : public QComboBox +{ + Q_OBJECT + +public: + /** + * Constructor + * @param parent parent widget + * @param name name to give to the widget + */ + SqueezedComboBox(QWidget *parent = 0, const char *name = 0 ); + + /** + * destructor + */ + virtual ~SqueezedComboBox(); + + bool contains(const QString & text) const; + + /** + * This inserts a item to the list. See QComboBox::insertItem() + * for detaills. Please do not use QComboBox::insertItem() to this + * widget, as that will fail. + * @param newItem the original (long version) of the item which needs + * to be added to the combobox + * @param index the position in the widget. + */ + void insertSqueezedItem(const QString& newItem, int index); + + /** + * This method returns the full text (not squeezed) of the currently + * highlighted item. + * @return full text of the highlighted item + */ + QString itemHighlighted( ); + + /** + * Sets the sizeHint() of this widget. + */ + virtual QSize sizeHint() const; + +private slots: + void slotTimeOut(); + void slotUpdateToolTip( int index ); + +private: + void resizeEvent ( QResizeEvent * ); + QString squeezeText( const QString& original); + + QMap<int,QString> m_originalItems; + QTimer* m_timer; + SqueezedComboBoxTip* m_tooltip; +}; + +#endif // SQUEEZEDCOMBOBOX_H diff --git a/krita/ui/wdgapplyprofile.ui b/krita/ui/wdgapplyprofile.ui new file mode 100644 index 000000000..f486b6256 --- /dev/null +++ b/krita/ui/wdgapplyprofile.ui @@ -0,0 +1,172 @@ +<!DOCTYPE UI><UI version="3.2" stdsetdef="1"> +<class>WdgApplyProfile</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgApplyProfile</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>538</width> + <height>312</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>3</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Apply Profile</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>lblProfile</cstring> + </property> + <property name="text"> + <string>&Profiles:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbProfile</cstring> + </property> + </widget> + <widget class="SqueezedComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>None</string> + </property> + </item> + <property name="name"> + <cstring>cmbProfile</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="QLabel" row="0" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>The image data you want to paste does not have an ICM profile associated with it. If you do not select a profile, Krita will assume that the image data is encoded in the import profile defined in the Settings dialog.</string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QButtonGroup" row="2" column="0" rowspan="1" colspan="2"> + <property name="name"> + <cstring>grpRenderIntent</cstring> + </property> + <property name="title"> + <string>&Rendering Intent</string> + </property> + <property name="toolTip" stdset="0"> + <string></string> + </property> + <property name="whatsThis" stdset="0"> + <string>Rendering intent determines the bias in the color conversion.</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton" row="1" column="0"> + <property name="name"> + <cstring>radioRelativeColorimetric</cstring> + </property> + <property name="text"> + <string>Relative colorimetric</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Within and outside gamut; same as Absolute Colorimetric. White point changed to result in neutral grays.</string> + </property> + </widget> + <widget class="QRadioButton" row="2" column="0"> + <property name="name"> + <cstring>radioSaturation</cstring> + </property> + <property name="text"> + <string>Saturation</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Hue and saturation maintained with lightness sacrificed to maintain saturation. White point changed to result in neutral grays. Intended for business graphics (make it colorful charts, graphs, overheads, ...)</string> + </property> + </widget> + <widget class="QRadioButton" row="3" column="0"> + <property name="name"> + <cstring>radioButton4</cstring> + </property> + <property name="text"> + <string>Absolute colorimetric</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Within the destination device gamut; hue, lightness and saturation are maintained. Outside the gamut; hue and lightness are maintained, saturation is sacrificed. White point for source and destination; unchanged. Intended for spot colors (Pantone, TruMatch, logo colors, ...)</string> + </property> + </widget> + <widget class="QRadioButton" row="0" column="0"> + <property name="name"> + <cstring>radioPerceptual</cstring> + </property> + <property name="text"> + <string>Perceptual</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Hue hopefully maintained (but not required), lightness and saturation sacrificed to maintain the perceived color. White point changed to result in neutral grays. Intended for images.</string> + </property> + </widget> + </grid> + </widget> + </grid> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>SqueezedComboBox</class> + <header location="local">squeezedcombobox.h</header> + <sizehint> + <width>-1</width> + <height>i24</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>3</hordata> + <verdata>0</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data> + </image> +</images> +<tabstops> + <tabstop>cmbProfile</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgautobrush.ui b/krita/ui/wdgautobrush.ui new file mode 100644 index 000000000..dd6b55fcb --- /dev/null +++ b/krita/ui/wdgautobrush.ui @@ -0,0 +1,355 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgAutobrush</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgAutobrush</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>373</width> + <height>200</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="1"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox"> + <property name="name"> + <cstring>grpSize</cstring> + </property> + <property name="title"> + <string>&Size</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout21</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>spinBoxWidth</cstring> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="maxValue"> + <number>9999</number> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>spinBoxHeigth</cstring> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="maxValue"> + <number>9999</number> + </property> + <property name="value"> + <number>5</number> + </property> + </widget> + </grid> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnLinkSize</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>16</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16</width> + <height>32767</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="toggleButton"> + <bool>true</bool> + </property> + <property name="on"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>grpFade</cstring> + </property> + <property name="title"> + <string>&Fade</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout23</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabelHorizontal</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + </widget> + <widget class="QSpinBox" row="0" column="1"> + <property name="name"> + <cstring>spinBoxHorizontal</cstring> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="maxValue"> + <number>9999</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2_2_2</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + </widget> + <widget class="QSpinBox" row="1" column="1"> + <property name="name"> + <cstring>spinBoxVertical</cstring> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="maxValue"> + <number>9999</number> + </property> + <property name="value"> + <number>1</number> + </property> + </widget> + </grid> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnLinkFade</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>16</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16</width> + <height>32767</height> + </size> + </property> + <property name="backgroundMode"> + <enum>NoBackground</enum> + </property> + <property name="text"> + <string></string> + </property> + <property name="toggleButton"> + <bool>true</bool> + </property> + <property name="on"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QToolButton"> + <property name="name"> + <cstring>brushPreview</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>7</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>95</width> + <height>95</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="usesBigPixmap"> + <bool>true</bool> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Circle</string> + </property> + </item> + <item> + <property name="text"> + <string>Square</string> + </property> + </item> + <property name="name"> + <cstring>comboBoxShape</cstring> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>0</height> + </size> + </property> + </spacer> + </vbox> + </widget> + </grid> +</widget> +<images> + <image name="image0"> + <data format="PNG" length="236">89504e470d0a1a0a0000000d49484452000000190000001a0806000000427df7cd000000b3494441544889dd963112c420084581d97acdfd4f29b9005b3913135050d722bf54f0018223e6ccf06f7db4c594be4d27e63304a190f525885e20154433f646ea050d6512d516887af10075c922f5d7e4ca24da4d439059f803721c4946a1962f798c6641d4da5c05421101445c06b82a6746804d73822202cc67956289a0c89a937b77596790b638abfb59d4da5c017840664196aff97679deab62d39bfcf73cf5ef8160ef4bb4e2e7627657e4909eb694eb071e3b4da9ba4f1ddb0000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="242">89504e470d0a1a0a0000000d49484452000000190000001a0806000000427df7cd000000b9494441544889dd95410ec4200845b1e9ba78ff538a176056260c5181569bccfca590ff2a204da510ecd601008078ed8778953372cec8db20d23c0a72417aa611900999997941a795500a256d2acf7a434354bf212d4927ebc488a417518d4dd75d0dcbb5f2ed983d59f101af94eb7f20d39e3c1963136299f7e2b361f89d9e8c6ed16efc4ee3892a205ecb9adc24fdcc176ffd4b9839e9b896592eb9d623b1106464e605b821da340200086e61afb91ea2a377e89577e57f00357f504513c00b590000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgautogradient.ui b/krita/ui/wdgautogradient.ui new file mode 100644 index 000000000..ab2821c8f --- /dev/null +++ b/krita/ui/wdgautogradient.ui @@ -0,0 +1,399 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgAutogradient</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgAutogradient</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>174</width> + <height>180</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox1</cstring> + </property> + <property name="title"> + <string>Custom Gradient</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KisGradientSliderWidget"> + <property name="name"> + <cstring>gradientSlider</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>32767</width> + <height>30</height> + </size> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout11</cstring> + </property> + <property name="font"> + <font> + <family>Arial Unicode MS</family> + <pointsize>6</pointsize> + </font> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="text"> + <string>Segment Color</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelLeftColor</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="text"> + <string>Left:</string> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>leftColorButton</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelRightColor</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="text"> + <string>Right:</string> + </property> + </widget> + <widget class="KColorButton"> + <property name="name"> + <cstring>rightColorButton</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maximumSize"> + <size> + <width>30</width> + <height>30</height> + </size> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="text"> + <string></string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="text"> + <string>Opacity:</string> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>intNumInputLeftOpacity</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + </widget> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>intNumInputRightOpacity</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + <property name="suffix"> + <string>%</string> + </property> + <property name="maxValue"> + <number>100</number> + </property> + </widget> + </vbox> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout11_2</cstring> + </property> + <property name="font"> + <font> + <family>Arial Unicode MS</family> + <pointsize>6</pointsize> + </font> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Linear</string> + </property> + </item> + <item> + <property name="text"> + <string>Curved</string> + </property> + </item> + <item> + <property name="text"> + <string>Sine</string> + </property> + </item> + <item> + <property name="text"> + <string>Sphere Inc.</string> + </property> + </item> + <item> + <property name="text"> + <string>Sphere Dec.</string> + </property> + </item> + <property name="name"> + <cstring>comboBoxInterpolationType</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>RGB</string> + </property> + </item> + <item> + <property name="text"> + <string>HSV CW</string> + </property> + </item> + <item> + <property name="text"> + <string>HSV CCW</string> + </property> + </item> + <property name="name"> + <cstring>comboBoxColorInterpolationType</cstring> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="focusPolicy"> + <enum>ClickFocus</enum> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KisGradientSliderWidget</class> + <header location="local">kis_gradient_slider_widget.h</header> + <sizehint> + <width>40</width> + <height>40</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>1</hordata> + <verdata>1</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgbirdeye.ui b/krita/ui/wdgbirdeye.ui new file mode 100644 index 000000000..0333ef7aa --- /dev/null +++ b/krita/ui/wdgbirdeye.ui @@ -0,0 +1,304 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgBirdEye</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgBirdEye</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>188</width> + <height>126</height> + </rect> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="caption"> + <string>Overview</string> + </property> + <property name="layoutMargin" stdset="0"> + </property> + <property name="layoutSpacing" stdset="0"> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>1</number> + </property> + <property name="spacing"> + <number>1</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblX</cstring> + </property> + <property name="text"> + <string>X:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>txtX</cstring> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>32767</height> + </size> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>00000</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>lblY</cstring> + </property> + <property name="text"> + <string>Y:</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>txtY</cstring> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>50</width> + <height>32767</height> + </size> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <property name="text"> + <string>00000</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer6</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </vbox> + </widget> + <widget class="QFrame"> + <property name="name"> + <cstring>view</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>2</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>75</width> + <height>75</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>200</width> + <height>75</height> + </size> + </property> + <property name="mouseTracking"> + <bool>true</bool> + </property> + <property name="frameShape"> + <enum>Box</enum> + </property> + <property name="frameShadow"> + <enum>Raised</enum> + </property> + </widget> + </hbox> + </widget> + <widget class="KToolBar"> + <property name="name"> + <cstring>toolbar</cstring> + </property> + <property name="maximumSize"> + <size> + <width>32767</width> + <height>32</height> + </size> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>1</number> + </property> + <property name="spacing"> + <number>1</number> + </property> + <widget class="KIntSpinBox"> + <property name="name"> + <cstring>zoom</cstring> + </property> + <property name="suffix"> + <string></string> + </property> + <property name="maxValue"> + <number>1600</number> + </property> + <property name="minValue"> + <number>10</number> + </property> + <property name="lineStep"> + <number>10</number> + </property> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>slZoom</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>1</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="maxValue"> + <number>19</number> + </property> + <property name="pageStep"> + <number>1</number> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bn100</cstring> + </property> + <property name="text"> + <string>1:1</string> + </property> + <property name="toolTip" stdset="0"> + <string>Zoom to 100%</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KToolBar</class> + <header location="local">ktoolbar.h</header> + <sizehint> + <width>20</width> + <height>100</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="730">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000002a149444154388db595df4b536118c73f3bdbecf8036c4e41f2c6695022045e486e90b721e4ba126f1a0966627f4108512004a197fd0586588220980a9a068be63abaa884cc1f6d30a7e29cfb216dceb39d9d2e2cf3c74997e417de97972fbc9fe77d1e789e57e772b9384d369b4d3deab95c2edd497784b3404ff20f460650fff732fc0ee0f5bc241298252dc710f4174e4be4908cb9661439cefa7c0fb71eee79fbe0486096b5af3d644e4e50537a3de880b4f2c7db07a7e51819156e77fe3b1860b4bb1095d871f0c1f4239108068381f84e9cc58545c6c7c78946a3d45dafa3b4b414511411f34456d756e9eded65706090924a076bdf9e1f071fd4c0c000c15010f7b49bc93793b4de6ba5abab0bd3451300bbbbbb783e7a08ac04d858dfd0cc4013dcdedebe7f368a462449a2ff553fcd4dcdf87c3eba7bba71bbdcf8fd7e8a8a8ab20703d4d6d6d2f1a00383d180b9c84c85a58282fc027c3e1ff537ea71dc71303a36caf6f6367d2ffab203773eeaa4e1660336ab8db49226c798839c9211f402b22c53535383cd6ac35261c1eff76b82353b4fafd7a3a80a899d048220904aa588842324779278bd5e9cef9cc41371ca2e9511de0a675f8ae1a161cc2633e5e5e5980a4d0882c06678133157243f2f9f85a50526a62698fb32c78c674613acf962dfb28fd05688443c41329944de95997e3fcdc8e8088b4b8bb85d6e42c110f6463b5557aab207c77ec458febe8c3fe067657585542a85d566c5bbecc5fdc18de5b285603088925168b9db927d294451c4e9745275b50a7ba39dc44e8292e212daeeb7517dad9aa9b7534833129224d1d4d4a409de9f6e9fc61eabaf9f9d7d9a7d1e7ba20e3dd5986e8a1c47c75ecf97543ab45ff117e5e416138f7af790474bb13edf435a0195d8a19ecf46eaaf2d9339609ed7a03ff56b3aabce0dfc13238259bff00a6d890000000049454e44ae426082</data> + </image> +</images> +<includes> + <include location="local" impldecl="in declaration">kiconloader.h</include> +</includes> +<slots> + <slot>zoomChanged(int)</slot> + <slot>zoomMinus()</slot> + <slot>zoomPlus()</slot> +</slots> +<pixmapfunction>BarIcon</pixmapfunction> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>ktoolbar.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgcolorsettings.ui b/krita/ui/wdgcolorsettings.ui new file mode 100644 index 000000000..63034d504 --- /dev/null +++ b/krita/ui/wdgcolorsettings.ui @@ -0,0 +1,357 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgColorSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgColorSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>586</width> + <height>457</height> + </rect> + </property> + <property name="caption"> + <string>Color Settings</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Default color model for new images:</string> + </property> + </widget> + <widget class="KisCmbIDList"> + <property name="name"> + <cstring>cmbWorkingColorSpace</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>20</height> + </size> + </property> + </widget> + </hbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>grpDisplay</cstring> + </property> + <property name="title"> + <string>Display</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Monitor profile:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbPrintProfile</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The icm profile for your calibrated monitor.</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel1_4</cstring> + </property> + <property name="text"> + <string>&Rendering intent:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbMonitorIntent</cstring> + </property> + <property name="whatsThis" stdset="0"> + <string>In converting the image data to be shown on screen you can select different ways in which to handle colors that can not be displayed on a monitor (out of gamut). +The different rendering intent methods will affect only what is shown on screen, and exporting or printing the image will not be affected. +<li>Perceptual, shows full gamut. Recommended for photographic images.</li> +<li>Relative Colorimetric, also called Proof or Preserve Identical Color and White Point. Reproduces in-gamut colors and clips out-of-gamut colors to the nearest reproducible color.</li> +<li>Absolute Colorimetric, much like Relative Colorimetric but it sacrificing saturation and possibly lightness for out-of-gamut colors. Rarely of use for photographic images.</li><li>Saturation, Preserves saturation. Convert from the saturated primary colors in the image to saturated primary colors on screen.</li></string> + </property> + </widget> + <widget class="KComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>Perceptual</string> + </property> + </item> + <item> + <property name="text"> + <string>Relative Colorimetric</string> + </property> + </item> + <item> + <property name="text"> + <string>Saturation</string> + </property> + </item> + <item> + <property name="text"> + <string>Absolute Colorimetric</string> + </property> + </item> + <property name="name"> + <cstring>cmbMonitorIntent</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="whatsThis" stdset="0"> + <string>In converting the image data to be shown on screen you can select different ways in which to handle colors that can not be displayed on a monitor (out of gamut). +The different rendering intent methods will affect only what is shown on screen, and exporting or printing the image will not be affected. +<li>Perceptual, shows full gamut. Recommended for photographic images.</li> +<li>Relative Colorimetric, also called Proof or Preserve Identical Color and White Point. Reproduces in-gamut colors and clips out-of-gamut colors to the nearest reproducible color.</li> +<li>Absolute Colorimetric, much like Relative Colorimetric but it sacrificing saturation and possibly lightness for out-of-gamut colors. Rarely of use for photographic images.</li><li>Saturation, Preserves saturation. Convert from the saturated primary colors in the image to saturated primary colors on screen.</li></string> + </property> + </widget> + <widget class="SqueezedComboBox" row="0" column="1"> + <property name="name"> + <cstring>cmbMonitorProfile</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>groupBox2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="title"> + <string>Printing</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KisCmbIDList" row="0" column="1"> + <property name="name"> + <cstring>cmbPrintingColorSpace</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>7</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + <widget class="KComboBox" row="1" column="1"> + <property name="name"> + <cstring>cmbPrintProfile</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>lbldefaultprinterspace</cstring> + </property> + <property name="text"> + <string>Color model:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Profile:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbPrintProfile</cstring> + </property> + <property name="toolTip" stdset="0"> + <string>The icm profile for your calibrated printer</string> + </property> + </widget> + </grid> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>grpPasteBehaviour</cstring> + </property> + <property name="title"> + <string>Profile on Paste</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string><p>Select what color profile to add when pasting from external applications that do not use a color profile.</p></string> + </property> + <property name="alignment"> + <set>WordBreak|AlignVCenter</set> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioPasteWeb</cstring> + </property> + <property name="text"> + <string>Use sRGB</string> + </property> + <property name="toolTip" stdset="0"> + <string>sRGB are like images from the web are supposed to be seen.</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioPasteMonitor</cstring> + </property> + <property name="text"> + <string>Use monitor profile</string> + </property> + <property name="toolTip" stdset="0"> + <string>This is like you see it in the other application</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioPasteAsk</cstring> + </property> + <property name="text"> + <string>Ask</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>chkBlackpoint</cstring> + </property> + <property name="text"> + <string>Use Blackpoint compensation</string> + </property> + <property name="checked"> + <bool>true</bool> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KisCmbIDList</class> + <header location="local">kis_cmb_idlist.h</header> + <sizehint> + <width>1</width> + <height>24</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> + <customwidget> + <class>SqueezedComboBox</class> + <header location="local">squeezedcombobox.h</header> + <sizehint> + <width>-1</width> + <height>0</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>3</hordata> + <verdata>0</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image1</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kis_cmb_idlist.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>squeezedcombobox.h</includehint> + <includehint>kis_cmb_idlist.h</includehint> + <includehint>kcombobox.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgcustombrush.ui b/krita/ui/wdgcustombrush.ui new file mode 100644 index 000000000..ea0418b31 --- /dev/null +++ b/krita/ui/wdgcustombrush.ui @@ -0,0 +1,199 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgCustomBrush</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgCustomBrush</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>267</width> + <height>265</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Style:</string> + </property> + </widget> + <widget class="QComboBox" row="2" column="1"> + <item> + <property name="text"> + <string>Constant</string> + </property> + </item> + <item> + <property name="text"> + <string>Random</string> + </property> + </item> + <item> + <property name="text"> + <string>Incremental</string> + </property> + </item> + <item> + <property name="text"> + <string>Pressure</string> + </property> + </item> + <item> + <property name="text"> + <string>Angular</string> + </property> + </item> + <property name="name"> + <cstring>comboBox2</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="currentItem"> + <number>2</number> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Selection mode:</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Regular</string> + </property> + </item> + <item> + <property name="text"> + <string>Animated</string> + </property> + </item> + <property name="name"> + <cstring>style</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QCheckBox"> + <property name="name"> + <cstring>colorAsMask</cstring> + </property> + <property name="text"> + <string>Use color as mask</string> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>preview</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>brushButton</cstring> + </property> + <property name="text"> + <string>Use as Brush</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>addButton</cstring> + </property> + <property name="text"> + <string>Add to Predefined Brushes</string> + </property> + </widget> + </vbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgcustompalette.ui b/krita/ui/wdgcustompalette.ui new file mode 100644 index 000000000..251a51bb9 --- /dev/null +++ b/krita/ui/wdgcustompalette.ui @@ -0,0 +1,88 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgCustomPalette</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgCustomPalette</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>282</width> + <height>384</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit"> + <property name="name"> + <cstring>palettename</cstring> + </property> + <property name="text"> + <string>Unnamed</string> + </property> + </widget> + <widget class="KisPaletteView"> + <property name="name"> + <cstring>view</cstring> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>addColor</cstring> + </property> + <property name="text"> + <string>Add New Color...</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>removeColor</cstring> + </property> + <property name="enabled"> + <bool>true</bool> + </property> + <property name="text"> + <string>Remove Selected Color</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>addPalette</cstring> + </property> + <property name="text"> + <string>Add to Predefined Palettes</string> + </property> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KisPaletteView</class> + <header location="local">kis_palette_view.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kis_palette_view.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgcustompattern.ui b/krita/ui/wdgcustompattern.ui new file mode 100644 index 000000000..9db089188 --- /dev/null +++ b/krita/ui/wdgcustompattern.ui @@ -0,0 +1,156 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgCustomPattern</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgCustomPattern</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>255</width> + <height>232</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Source:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Entire Image</string> + </property> + </item> + <property name="name"> + <cstring>comboBox1</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QLabel"> + <property name="name"> + <cstring>preview</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>50</width> + <height>50</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>40</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout7</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QPushButton"> + <property name="name"> + <cstring>patternButton</cstring> + </property> + <property name="text"> + <string>Use as Pattern</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>exportButton</cstring> + </property> + <property name="enabled"> + <bool>false</bool> + </property> + <property name="text"> + <string>Export</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>addButton</cstring> + </property> + <property name="text"> + <string>Add to Predefined Patterns</string> + </property> + </widget> + </vbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgdisplaysettings.ui b/krita/ui/wdgdisplaysettings.ui new file mode 100644 index 000000000..1427a4976 --- /dev/null +++ b/krita/ui/wdgdisplaysettings.ui @@ -0,0 +1,90 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgDisplaySettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgDisplaySettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>374</width> + <height>154</height> + </rect> + </property> + <property name="caption"> + <string>Display</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>50</height> + </size> + </property> + </spacer> + <widget class="QButtonGroup" row="0" column="0"> + <property name="name"> + <cstring>buttonGroup1</cstring> + </property> + <property name="title"> + <string>OpenGL</string> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>cbUseOpenGL</cstring> + </property> + <property name="text"> + <string>Enable OpenGL</string> + </property> + </widget> + </vbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer4</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>121</width> + <height>31</height> + </size> + </property> + </spacer> + </hbox> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdggeneralsettings.ui b/krita/ui/wdggeneralsettings.ui new file mode 100644 index 000000000..35864b49f --- /dev/null +++ b/krita/ui/wdggeneralsettings.ui @@ -0,0 +1,183 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgGeneralSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgGeneralSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>335</width> + <height>209</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Cursor shape:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>m_cmbCursorShape</cstring> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Tool Icon</string> + </property> + </item> + <item> + <property name="text"> + <string>Crosshair</string> + </property> + </item> + <item> + <property name="text"> + <string>Arrow</string> + </property> + </item> + <item> + <property name="text"> + <string>Brush Outline</string> + </property> + </item> + <property name="name"> + <cstring>m_cmbCursorShape</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QButtonGroup"> + <property name="name"> + <cstring>grpDockability</cstring> + </property> + <property name="title"> + <string>Palette Behavior</string> + </property> + <property name="exclusive"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioAllowDocking</cstring> + </property> + <property name="text"> + <string>Allow &docking</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioDisallowDocking</cstring> + </property> + <property name="text"> + <string>Allow only &floating</string> + </property> + </widget> + <widget class="QRadioButton"> + <property name="name"> + <cstring>radioSmartDocking</cstring> + </property> + <property name="text"> + <string>Allow docking only on &large screens</string> + </property> + </widget> + </vbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>&Palette font size:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>numDockerFontSize</cstring> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>numDockerFontSize</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>41</height> + </size> + </property> + </spacer> + </grid> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdggridsettings.ui b/krita/ui/wdggridsettings.ui new file mode 100644 index 000000000..77515844d --- /dev/null +++ b/krita/ui/wdggridsettings.ui @@ -0,0 +1,468 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgGridSettingsBase</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgGridSettingsBase</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>422</width> + <height>233</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer14</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="0" column="1"> + <property name="name"> + <cstring>groupBox9</cstring> + </property> + <property name="title"> + <string>Colors</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="0" column="2" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer12_2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>16</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="KColorButton" row="0" column="1"> + <property name="name"> + <cstring>colorMain</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>99</red> + <green>99</green> + <blue>99</blue> + </color> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Subdivision:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2_4</cstring> + </property> + <property name="text"> + <string>Main:</string> + </property> + </widget> + <widget class="KColorButton" row="1" column="1"> + <property name="name"> + <cstring>colorSubdivision</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="color"> + <color> + <red>200</red> + <green>200</green> + <blue>200</blue> + </color> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox5</cstring> + </property> + <property name="title"> + <string>Styles</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Main:</string> + </property> + </widget> + <widget class="KComboBox" row="0" column="1"> + <item> + <property name="text"> + <string>Lines</string> + </property> + </item> + <item> + <property name="text"> + <string>Dashed Lines</string> + </property> + </item> + <item> + <property name="text"> + <string>Dots</string> + </property> + </item> + <property name="name"> + <cstring>selectMainStyle</cstring> + </property> + <property name="currentItem"> + <number>0</number> + </property> + </widget> + <widget class="KComboBox" row="1" column="1"> + <item> + <property name="text"> + <string>Lines</string> + </property> + </item> + <item> + <property name="text"> + <string>Dashed Lines</string> + </property> + </item> + <item> + <property name="text"> + <string>Dots</string> + </property> + </item> + <property name="name"> + <cstring>selectSubdivisionStyle</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel5</cstring> + </property> + <property name="text"> + <string>Subdivision:</string> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer15</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>34</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Spacing</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout8</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image0</pixmap> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2_2</cstring> + </property> + <property name="text"> + <string></string> + </property> + <property name="pixmap"> + <pixmap>image1</pixmap> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>intVSpacing</cstring> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>intHSpacing</cstring> + </property> + <property name="value"> + <number>10</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + </grid> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnLinkSpacing</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>16</width> + <height>0</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>16</width> + <height>32767</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="toggleButton"> + <bool>true</bool> + </property> + <property name="on"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget" row="1" column="0"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Subdivision:</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>intSubdivision</cstring> + </property> + <property name="value"> + <number>2</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + </widget> + </hbox> + </widget> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer12</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>41</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QGroupBox" row="1" column="1"> + <property name="name"> + <cstring>groupBox3_2</cstring> + </property> + <property name="title"> + <string>Offset</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel2_3</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>1</hsizetype> + <vsizetype>1</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>X:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2_2_2</cstring> + </property> + <property name="text"> + <string>Y:</string> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>intOffsetY</cstring> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>intOffsetX</cstring> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <spacer row="0" column="2"> + <property name="name"> + <cstring>spacer11</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> + </widget> + </grid> +</widget> +<customwidgets> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="236">89504e470d0a1a0a0000000d49484452000000190000001a0806000000427df7cd000000b3494441544889dd963112c420084581d97acdfd4f29b9005b3913135050d722bf54f0018223e6ccf06f7db4c594be4d27e63304a190f525885e20154433f646ea050d6512d516887af10075c922f5d7e4ca24da4d439059f803721c4946a1962f798c6641d4da5c05421101445c06b82a6746804d73822202cc67956289a0c89a937b77596790b638abfb59d4da5c017840664196aff97679deab62d39bfcf73cf5ef8160ef4bb4e2e7627657e4909eb694eb071e3b4da9ba4f1ddb0000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="242">89504e470d0a1a0a0000000d49484452000000190000001a0806000000427df7cd000000b9494441544889dd95410ec4200845b1e9ba78ff538a176056260c5181569bccfca590ff2a204da510ecd601008078ed8778953372cec8db20d23c0a72417aa611900999997941a795500a256d2acf7a434354bf212d4927ebc488a417518d4dd75d0dcbb5f2ed983d59f101af94eb7f20d39e3c1963136299f7e2b361f89d9e8c6ed16efc4ee3892a205ecb9adc24fdcc176ffd4b9839e9b896592eb9d623b1106464e605b821da340200086e61afb91ea2a377e89577e57f00357f504513c00b590000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>kcolorbutton.h</includehint> + <includehint>kcolorbutton.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>kcombobox.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdglayerbox.ui b/krita/ui/wdglayerbox.ui new file mode 100644 index 000000000..a384f3064 --- /dev/null +++ b/krita/ui/wdglayerbox.ui @@ -0,0 +1,299 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgLayerBox</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgLayerBox</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>352</width> + <height>542</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="KisCmbComposite"> + <property name="name"> + <cstring>cmbComposite</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>3</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="minimumSize"> + <size> + <width>0</width> + <height>10</height> + </size> + </property> + <property name="toolTip" stdset="0"> + <string>Blending mode</string> + </property> + </widget> + <widget class="KisIntSpinbox"> + <property name="name"> + <cstring>intOpacity</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + </widget> + </hbox> + </widget> + <widget class="KisLayerList"> + <property name="name"> + <cstring>listLayers</cstring> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnAdd</cstring> + </property> + <property name="minimumSize"> + <size> + <width>22</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="iconSet"> + <iconset>image0</iconset> + </property> + <property name="toolTip" stdset="0"> + <string>Create a new layer</string> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnLower</cstring> + </property> + <property name="minimumSize"> + <size> + <width>22</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="iconSet"> + <iconset>image1</iconset> + </property> + <property name="toolTip" stdset="0"> + <string>Move layer down</string> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnRaise</cstring> + </property> + <property name="minimumSize"> + <size> + <width>22</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="iconSet"> + <iconset>image2</iconset> + </property> + <property name="toolTip" stdset="0"> + <string>Move layer up</string> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnProperties</cstring> + </property> + <property name="minimumSize"> + <size> + <width>22</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string>...</string> + </property> + <property name="toolTip" stdset="0"> + <string>View or change the layer properties</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnDelete</cstring> + </property> + <property name="minimumSize"> + <size> + <width>22</width> + <height>22</height> + </size> + </property> + <property name="maximumSize"> + <size> + <width>18</width> + <height>18</height> + </size> + </property> + <property name="text"> + <string></string> + </property> + <property name="iconSet"> + <iconset>image3</iconset> + </property> + <property name="toolTip" stdset="0"> + <string>Delete the layer</string> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KisCmbComposite</class> + <header location="local">kis_cmb_composite.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image4</pixmap> + </customwidget> + <customwidget> + <class>KisLayerList</class> + <header location="local">kis_layerlist.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image4</pixmap> + </customwidget> + <customwidget> + <class>KisIntSpinbox</class> + <header location="global">kis_int_spinbox.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image4</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="405">89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff610000015c49444154388d8592c1aec22010450f94561bbfcda53f60d77e927fe0ca4d5dfb3126d59586b44271780b539eedab7924041866eebd7341c51801381c0e1160384fc7e97462bfdfab69dc0c9b18239bcd265d586b71ced1340dc6bcd3aaaa8a53103d4b071445419ee7e4799e62ebf59aaaaa4612bf02006459465114a985e3f108c076bb4d2066bef45decbdc71883738edd6ec7e572e17abd723e9fff57a094a2280ab4d6e479ceed76e37ebf638c41a95f1bbe2ad05aa7b5ef7b9c732c160b5eafd7286f164044e8ba8ee7f349d334586b59ad56946549dff7a3a7fe0320228808de7b1e8f072242599600841092b2af005a6bdab6c55a0bc072b924840080730e111979f0c7c410026ddba2b54e7330eef34f7c55e0bd9ffdce5a6b628c6459368e4f13bbae1b154d59638c2382d91606234524f52f222967d603a514defbc43cb83db04ddd1f46f2a0ae6beaba26c638621840945209ecf3fe07b32fb7352555170c0000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="274">89504e470d0a1a0a0000000d49484452000000160000001208060000005f252e2d000000d949444154388ded94210e84301045ffdfecb5b0582c24681a2c1a8e00b24d3900774063d11c0314d8594543a06cd6ace39b9974326f7e3a4d2922f8875e7fa13ee0a3debec33ccf050048625f2e49008088b87c97d69a27841f4c124551b8fc0c3b0e8ba2e877c722a29aa6b1699a5e404765590692ca6bcef78e876140d77519491b86a1d751599600a08c316d100497faedf292246901a8beef31cf33966571b1aa2a07bdebbf0593441cc72d49358e23d675c5b66da8eb1a22a2b4d6b7d0afe0235c44d4344db0d682a432c6b4e7fbbef43e7fc503bee8030549631e4f2cf51e0000000049454e44ae426082</data> + </image> + <image name="image2"> + <data format="PNG" length="275">89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff61000000da49444154388dcd92310e83300c45bfab5e872b709ca0b03022b13130b123251720e21830700060820db18623b84b5dd1a22eedd0fe29b6e2e76f27c4ccf84697afaaff02709543dbb62022c84e9c738a994dd77520a2a8aa2a2b7799196118be77e09c53004c5996e8fb1e008cd65a4931119d4790a474cef31cebba62db36344df3801c8b4f0eeaba56004c966598e719de7b78efb1ef3bacb50060e23856c7a72709ee749324099665395995384d531051340c837d05b0d61ad334bdddb8a8280a8ce3484f802008583a1d252e5ef327c0a7fafd4ffc3de006c2bf7b9f44bff3680000000049454e44ae426082</data> + </image> + <image name="image3"> + <data format="PNG" length="312">89504e470d0a1a0a0000000d49484452000000100000001008060000001ff3ff61000000ff49444154388da592318e84300c459f4773072e0105b7a1e10020eeb0ecd57205e8e9902221100851e2a9321b3261a5d5ba89127f3ddbdf1155e53ff1bc4b6459a621bcef7b0975e244755d7fa96a0b20f2a103c0694504634cdbf7fdf7d34bb64551902409499260adc55acbbaae8808aacab22cecfbce711c18635ae0072022344d43cc13077067740480aaaab42c4bf23c679a26b66d631806c671e4380ee679669a268c316f3f1e612557c581fd02eeddf7e802f0c54e749e671414058433fa77d75db8a10b20acaeaaef0eee220ab8081ebf4ba21ef86d3be37c636f4d0c2336bf0ffa008406f926c63604c1470248d354fd5dc736d3759ddc02fe1a2f646fb86fb4737d520000000049454e44ae426082</data> + </image> + <image name="image4"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdglayerproperties.ui b/krita/ui/wdglayerproperties.ui new file mode 100644 index 000000000..b4000ea54 --- /dev/null +++ b/krita/ui/wdglayerproperties.ui @@ -0,0 +1,170 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgLayerProperties</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgLayerProperties</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>362</width> + <height>210</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLineEdit" row="0" column="1"> + <property name="name"> + <cstring>editName</cstring> + </property> + </widget> + <widget class="QLabel" row="3" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>&Opacity:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>intOpacity</cstring> + </property> + </widget> + <widget class="SqueezedComboBox" row="2" column="1"> + <property name="name"> + <cstring>cmbProfile</cstring> + </property> + </widget> + <widget class="QLabel" row="4" column="0"> + <property name="name"> + <cstring>textLabel4</cstring> + </property> + <property name="text"> + <string>Composite mode:</string> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>Profile:</string> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Colorspace:</string> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>&Name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>editName</cstring> + </property> + </widget> + <widget class="KisCmbIDList" row="1" column="1"> + <property name="name"> + <cstring>cmbColorSpaces</cstring> + </property> + </widget> + <widget class="KisCmbComposite" row="4" column="1"> + <property name="name"> + <cstring>cmbComposite</cstring> + </property> + </widget> + <widget class="KisIntSpinbox" row="3" column="1"> + <property name="name"> + <cstring>intOpacity</cstring> + </property> + </widget> + </grid> +</widget> +<customwidgets> + <customwidget> + <class>KisCmbIDList</class> + <header location="local">kis_cmb_idlist.h</header> + <sizehint> + <width>1</width> + <height>24</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> + <customwidget> + <class>KisCmbComposite</class> + <header location="local">kis_cmb_composite.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image1</pixmap> + </customwidget> + <customwidget> + <class>KisIntSpinbox</class> + <header location="global">kis_int_spinbox.h</header> + <sizehint> + <width>-1</width> + <height>-1</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image1</pixmap> + </customwidget> + <customwidget> + <class>SqueezedComboBox</class> + <header location="local">squeezedcombobox.h</header> + <sizehint> + <width>-1</width> + <height>i24</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>3</hordata> + <verdata>0</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image2</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="1002">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b149444154388dad945f4c5b551cc73fe7dc4b7b4bcba0762d45c43114323599ee6192609c51d883892ce083f1718b3ebb185f8dc91e972cf39d2d2a2f1af664b6f1e0fe3863a0718969700eb0c52142da0242a1bd6d696f7bcff101585203ceb8fd9ece39f99dcff9fe7edf939f88c562ec465f5f9fe609442c161362173c3e3eae7b7a7ac8e7f36432196cdbfe4f907c3e4f2291201e8fe338cec3737357e9e8e828aded1e229d650e1f2d51754b082110124c13a4dc5ea341eb9dc284c0558a853f3ce8cb0677ef500fde7d39d2596679e326597b8e9abb85d7a770ab16ab6983ec5a05b487a70e36f0f4e10afe408d6a558310980108478dba4a1e8233990c5d474b64ed39aa3a8fe5f3317fbf81dbd70bccfeb205947632fd74f6589c1c6ea2f70d03a58ba0c1f2c9bdc1b66de3b8256a6e11cbe7e3ee1d181b590124fe2693aeee08d223c82c3a2c24b7b874bec8f26288774f7bd054504aef0dde6e99c0eb83f9fb266323cb80a27fb0958141836044605a2ee5523393371cc646fee2da37195aa35d0c0c5b4859ac03d7e91712dcaac5adab3650a3ff9d08ef7dd8404bb48869e5d958b5b87dadc4c9a1464e9f0d0326df7ebd86bd2e310cb1bf62d384d59441f2d70a070e1c60e09489929b988681bdd9cc97170bcc4c65595f71f8e0e3301337fc24a7732467831875a47f289652b0be5e4151e6d07316c1b0c0340d8ab92023e76d66a6b2840e36d2fb7a13fee632475e6edc367ea98a90fb98b7dd6310ca0328a44761582e1bab41befabcc0ec940d28bc5e93b68e064cab84e1d9beaeb48934eac1f53b01c1b000fca496aa54b61a99fcde61662a4b4b4b23d1680be9d426173e4df3602a48ea411989a4fd590f52a8fd156b05ed9d350e3defe3cfdf4b4c7ce770ea7d3fb9f520afbe1620daeee5c26735d20b9b9cfb6811a754a439e4e5c5639a4caa1e5caf586bfc0197b78702005cb9b4cae4cd3267ce8638fe964bd72b393e39d74928d242617303a756a37f284447770dcdbffc6384a05a85de1306e9a52057c7527c7131c3c42d3f475eb2303c82d4fc3276d6811db37efeb148723082d9b08f79f97c1e5729109a9a28307cc622d2d6cdf52b2b24efe548dedb00142009862cfa879ee1a71f6cec928353511472fbf4389148b0b0e0c108081412458dfe21c9f11351e67e7358595468246d1d1e5e38a6e9e851bc39d84ab502a669331dafec0d8ec7e3e8cb06e1a881d727d1ae40180a434a8c9db129a54126ad48a7358c2b4c5352c8c374bcccdab2bb37d8719cba79fab8211f9df218e0582c261e95f8bfc04f1a1e8bc5c4dfe0a190172af6a9690000000049454e44ae426082</data> + </image> + <image name="image2"> + <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data> + </image> +</images> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgnewimage.ui b/krita/ui/wdgnewimage.ui new file mode 100644 index 000000000..a85c14698 --- /dev/null +++ b/krita/ui/wdgnewimage.ui @@ -0,0 +1,435 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgNewImage</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgNewImage</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>572</width> + <height>595</height> + </rect> + </property> + <property name="caption"> + <string>New Image</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblName</cstring> + </property> + <property name="text"> + <string>&Name:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>txtName</cstring> + </property> + </widget> + <widget class="QLineEdit"> + <property name="name"> + <cstring>txtName</cstring> + </property> + <property name="text"> + <string>untitled-1</string> + </property> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>grpImage</cstring> + </property> + <property name="title"> + <string>&Image Size</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>lblHeight</cstring> + </property> + <property name="text"> + <string>&Height:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>intHeight</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>lblWidth</cstring> + </property> + <property name="text"> + <string>&Width:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>intWidth</cstring> + </property> + </widget> + <widget class="KIntNumInput" row="0" column="1"> + <property name="name"> + <cstring>intWidth</cstring> + </property> + <property name="value"> + <number>1600</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="KIntNumInput" row="1" column="1"> + <property name="name"> + <cstring>intHeight</cstring> + </property> + <property name="value"> + <number>1200</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>lblResolution</cstring> + </property> + <property name="text"> + <string>&Resolution:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>doubleResolution</cstring> + </property> + </widget> + <widget class="KDoubleSpinBox" row="0" column="3"> + <property name="name"> + <cstring>doubleResolution</cstring> + </property> + <property name="suffix"> + <string> dpi</string> + </property> + <property name="maxValue"> + <number>500</number> + </property> + <property name="minValue"> + <number>1</number> + </property> + <property name="lineStep"> + <number>10</number> + </property> + <property name="value"> + <number>100</number> + </property> + </widget> + <spacer row="0" column="4" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>131</width> + <height>61</height> + </size> + </property> + </spacer> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>grpMode</cstring> + </property> + <property name="title"> + <string>Mode</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>lblColorSpaces</cstring> + </property> + <property name="text"> + <string>Color space:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbColorSpaces</cstring> + </property> + </widget> + <widget class="KisCmbIDList" row="0" column="1"> + <property name="name"> + <cstring>cmbColorSpaces</cstring> + </property> + </widget> + <widget class="SqueezedComboBox" row="1" column="1"> + <property name="name"> + <cstring>cmbProfile</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>lblProfiles</cstring> + </property> + <property name="text"> + <string>Profile:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbProfile</cstring> + </property> + </widget> + </grid> + </widget> + <widget class="QGroupBox"> + <property name="name"> + <cstring>grpContents</cstring> + </property> + <property name="title"> + <string>Contents</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QTextEdit" row="2" column="1"> + <property name="name"> + <cstring>txtDescription</cstring> + </property> + </widget> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>lblColor</cstring> + </property> + <property name="text"> + <string>Canvas color:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>cmbColor</cstring> + </property> + </widget> + <widget class="KColorCombo" row="0" column="1"> + <property name="name"> + <cstring>cmbColor</cstring> + </property> + </widget> + <widget class="QLabel" row="2" column="0"> + <property name="name"> + <cstring>lblDescription</cstring> + </property> + <property name="text"> + <string>Description:</string> + </property> + <property name="alignment"> + <set>AlignTop</set> + </property> + <property name="buddy" stdset="0"> + <cstring>txtDescription</cstring> + </property> + </widget> + <widget class="QLabel" row="1" column="0"> + <property name="name"> + <cstring>lblOpacity</cstring> + </property> + <property name="text"> + <string>Opacity:</string> + </property> + <property name="buddy" stdset="0"> + <cstring>sliderOpacity</cstring> + </property> + </widget> + <widget class="QFrame" row="1" column="1"> + <property name="name"> + <cstring>opacityPanel</cstring> + </property> + <property name="frameShape"> + <enum>NoFrame</enum> + </property> + <property name="frameShadow"> + <enum>Plain</enum> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Transparent</string> + </property> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>sliderOpacity</cstring> + </property> + <property name="maxValue"> + <number>100</number> + </property> + <property name="pageStep"> + <number>10</number> + </property> + <property name="value"> + <number>100</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>Below</enum> + </property> + <property name="tickInterval"> + <number>20</number> + </property> + <property name="toolTip" stdset="0"> + <string>Opacity of the background color.</string> + </property> + <property name="whatsThis" stdset="0"> + <string>Opacity of the background color.</string> + </property> + </widget> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Opaque</string> + </property> + </widget> + </hbox> + </widget> + </grid> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>480</width> + <height>21</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>m_createButton</cstring> + </property> + <property name="text"> + <string>Create</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>0</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> + <customwidget> + <class>KisCmbIDList</class> + <header location="local">kis_cmb_idlist.h</header> + <sizehint> + <width>1</width> + <height>24</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>5</hordata> + <verdata>5</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image0</pixmap> + </customwidget> + <customwidget> + <class>SqueezedComboBox</class> + <header location="local">squeezedcombobox.h</header> + <sizehint> + <width>-1</width> + <height>32</height> + </sizehint> + <container>0</container> + <sizepolicy> + <hordata>3</hordata> + <verdata>0</verdata> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + <pixmap>image1</pixmap> + </customwidget> +</customwidgets> +<images> + <image name="image0"> + <data format="PNG" length="870">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b0000032d49444154388db59531681c4714863f892dde8004b320c32e3870020b74458a6b0f5458e581c016a809a8496b42208454098604d2c4904a6954a410511ae752085b858c1208dc35221244b00119f60ac12ee860062c980719708a95a248f129459cd7cceeccf0edb76fff61a706830197d5ed765ff3166a30184c4d5d829fed3c7bdd5e6ce3bda71a5738ef301802e1d6d179477152303c1842bc822797a64fbf7b4a9a43be00ada817cb0e12011c2611205ccd73755f9c087c6b19bef0d7c100f5b8267d07caf10fe8ab9210156320fc01be16aa5a11043307f30b20a21041019985f48ef2f7fa0becc68e80475fd584e831b396f210f67795c3831a4940a3228925bb27f4d652ba4b01a199b73342f3981be0ca57745042ac30c632d853b6373d44b056c8ef0922508d94d14be59b2f4aeaf58cd5751069e06f3436890114332b9487d0bf80f61e64dc5f813c3790045453f67703fd4d4f7f6b4496b5597e689044af194f5f5e841800210478bee3d1a8f41e64acbe0f69ae6852e1cf0ccf7f74f4d652defbc042226c6f55e8f89f91bb6e9c387c9d521c9558db988a3416fe3c67e32b4779ec7167f0e8939ce19ea7fc5d298a80c875f03563930855ed2081bc05e91d5014ef53363eaf288e3d6285ee520a338e76c7a251a94e41e30470d3631004a262672e3eca59cec6978ef2b889979d11f2bb904af3be92081a416e28dfe831983920b1142345d5b0ff2234a6334276d7321ad53c795c511ca654a5a251996f19b83d158ef602b45a423d52f67703abeb29ee4ce9de4fc93378f218462f6b3efdb042cf3d59666977a0aa6fe9310888d25b13342afd4dcffeaee3d147399da540ab13f8f8b39c2cb3f8710d11ba2b96f9c57fcd7180287497a03ecde86f8dd8fe1a867b9ef6bb1612a84a871f6bd35b94e217a53832589970f2dcd85d9c7d4580d57521cbdaf4bfaf288e95e268d4ec8e60e72ccb0f2dbffea454e71e8d29f57882717152509482a48d8924b0bc12e82ee51445a03a6da079cbd0eec0fc22142b06620e89a3fc8d3783870743d814d2bc8994aa6ff286472e764902e5a96f72bbd3b4c37b280e95aa9e604c84e1cf978b37c74935797d7ae2ca7fac6968fe51ff0bf86dc30783c1d49f0baa9bb819e612310000000049454e44ae426082</data> + </image> + <image name="image1"> + <data format="PNG" length="1003">89504e470d0a1a0a0000000d4948445200000016000000160806000000c4b46c3b000003b249444154388db5944d4c5c5518869f73ce9db9cc40f929cc30300e18129a50685268a28291982e1a2175212eaab1c49d3f8971e7aec6aedb54a32b435dd8685cb8c0c4b8b0feb421b7bd8186a069d23209144b18cb0c02f3732ff3c3ccbdd705a571941213f1dd9d93739ef37e6fbeef08d334d9d5d0d090c701c8344d2176c1a6697a5d5d5dd8b64d2a95c2b2ac7f05b12c8b783c8e6118d8b6fd685fdb753a39394928e2a7c55724d693a7e214104220242805520a84d8b9e4790f0b1302c7751958f1e30534be9fa41a0c60db362dbe227f64af91b6e7719c2dfc0117a71c603da591de2882a7d3d4ec27122b10acad50aeb88044d542b84de3af7ab44aa55274f4e449dbf354bc347aa096fbf37e7efa2ecbad1b36907d78b289de8120232f37726250c3f52cf0a026a0f6065b9645d929e038167aa096d91b307171059034b5f8e9e9eb44fa052b4b25eeccd9dc99cb71f6ad082fbea2e351c075bdbdc13b9109fc01b83fef63e2e232e03076b68393231a0dcd024daf502c1e66e67a89cb971ef0e5a74bb4b61e6378248094b92ab0ac024b70ca017ef8360394187b2dc6d8b89ffa500e4d4f93d9083275d5e6f9913ade3dd70ee87c7d25c95646a25415aadab152b09ed4f8c5cc130a853839eac3951b684a61e70ef3f9c739668c24eba912afbfddc6d4d506e6a6d7b8b7d082aa8eb8dab19482cdcd220e36dd3dc19df23545de0a71f952861923493456cfd3cf36123c54a0b7bf0e8064621b21f7712c040857071ca4eea0f40a99f510573ec971cb48030e811a1faded3e94be85f2fb00703d1ff26f96ab9f011a5b04d0c4f26fdb948a754c1b25668c2491483d5d5d611617d6b8f0fe32cb779b492ce65168b4c774a4701eefd8f3a02d56e6e8f13aeefe9a63fa5a89d1970e91d908f3d46003e1480d173e28b37827c9b977348ab92ce16890237d1ec907ee3e8e3d8f60d0e1f4583d009f7d9860662acff89bad1c1faad0717493f7ce7713ed8cb0995c255f2a317a26427b67198f6a70f51c0a41b902279ed1187f23cc17130b7c74de65eac77a7a8f05517e41e2deefa4930576db60fa7a8ee1535134df3e93e7b82e0817476439fd6a9070a49f6fbe4a3077739db99b15c001146dd13a46cf1cc1f83943c62e51de76b0738fc9381e8f3390f0236b252e124999e11724fd833196164bacadb87848224fe874f779b43fe9f2dca928956d505a96dbb3f9bdc18661e00534c26d1a7a40e13912a11c9454280da41048a9915c75585df500074d53d816dc9edd229528ef0db66dbbea3ffdaffa471f1f28d8344df1bf800f1a6e9aa6f813c39885bc050f269c0000000049454e44ae426082</data> + </image> +</images> +<tabstops> + <tabstop>txtName</tabstop> + <tabstop>intWidth</tabstop> + <tabstop>intHeight</tabstop> + <tabstop>doubleResolution</tabstop> + <tabstop>cmbColorSpaces</tabstop> + <tabstop>cmbProfile</tabstop> + <tabstop>cmbColor</tabstop> + <tabstop>sliderOpacity</tabstop> + <tabstop>txtDescription</tabstop> +</tabstops> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> + <includehint>kis_cmb_idlist.h</includehint> + <includehint>squeezedcombobox.h</includehint> + <includehint>kcolorcombo.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgpalettechooser.ui b/krita/ui/wdgpalettechooser.ui new file mode 100644 index 000000000..f1840dd80 --- /dev/null +++ b/krita/ui/wdgpalettechooser.ui @@ -0,0 +1,105 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisPaletteChooser</class> +<widget class="QDialog"> + <property name="name"> + <cstring>KisPaletteChooser</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>289</width> + <height>163</height> + </rect> + </property> + <property name="caption"> + <string>Choose Palette</string> + </property> + <property name="sizeGripEnabled"> + <bool>true</bool> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QListBox"> + <property name="name"> + <cstring>paletteList</cstring> + </property> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer> + <property name="name"> + <cstring>Horizontal Spacing2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>255</width> + <height>20</height> + </size> + </property> + </spacer> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonOk</cstring> + </property> + <property name="text"> + <string>&OK</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + <property name="default"> + <bool>true</bool> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>buttonCancel</cstring> + </property> + <property name="text"> + <string>&Cancel</string> + </property> + <property name="accel"> + <string></string> + </property> + <property name="autoDefault"> + <bool>true</bool> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<connections> + <connection> + <sender>buttonOk</sender> + <signal>clicked()</signal> + <receiver>KisPaletteChooser</receiver> + <slot>accept()</slot> + </connection> + <connection> + <sender>buttonCancel</sender> + <signal>clicked()</signal> + <receiver>KisPaletteChooser</receiver> + <slot>reject()</slot> + </connection> +</connections> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgperformancesettings.ui b/krita/ui/wdgperformancesettings.ui new file mode 100644 index 000000000..e5f1b9c80 --- /dev/null +++ b/krita/ui/wdgperformancesettings.ui @@ -0,0 +1,146 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgPerformanceSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgPerformanceSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>495</width> + <height>220</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Maximum number of tiles kept in memory:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>The maximum number of "tiles" that are kept in memory. For regular RGBA8 images, each tile is about 16 kB in size. Thus, for a value of 500 tiles this usually means about 8 megabytes are used for image data. If you regularly handle large images, a greater value here might be useful. +Note that this number is only a guideline for Krita, and is not guaranteed to be the actual number of tiles in memory.</string> + </property> + </widget> + <widget class="KIntNumInput"> + <property name="name"> + <cstring>m_maxTiles</cstring> + </property> + <property name="value"> + <number>500</number> + </property> + <property name="minValue"> + <number>0</number> + </property> + <property name="whatsThis" stdset="0"> + <string>The maximum number of "tiles" that are kept in memory. For regular RGBA8 images, each tile is about 16 kB in size. Thus, for a value of 500 tiles this usually means about 8 megabytes are used for image data. If you regularly handle large images, a greater value here might be useful. +Note that this number is only a guideline for Krita, and is not guaranteed to be the actual number of tiles in memory.</string> + </property> + </widget> + <spacer> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>81</width> + <height>20</height> + </size> + </property> + </spacer> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Swappiness:</string> + </property> + <property name="whatsThis" stdset="0"> + <string>This configures how much Krita will use the swap file. If you move the slider all the way to the left, Krita will not use the swap file at all. If you move it all the way to the right, Krita will make maximum use of the swap file.</string> + </property> + </widget> + <widget class="QSlider"> + <property name="name"> + <cstring>m_swappiness</cstring> + </property> + <property name="maximumSize"> + <size> + <width>600</width> + <height>32767</height> + </size> + </property> + <property name="maxValue"> + <number>6</number> + </property> + <property name="value"> + <number>3</number> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>Below</enum> + </property> + <property name="whatsThis" stdset="0"> + <string>This configures how much Krita likes to swap. Move the slider to the left, and there is no swapping at all. Move it to the right there is a lot of swapping going on.</string> + </property> + </widget> + </hbox> + </widget> + <spacer> + <property name="name"> + <cstring>spacer3</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>139</height> + </size> + </property> + </spacer> + </vbox> +</widget> +<customwidgets> +</customwidgets> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>knuminput.h</includehint> + <includehint>knuminput.h</includehint> +</includehints> +</UI> diff --git a/krita/ui/wdgpressuresettings.ui b/krita/ui/wdgpressuresettings.ui new file mode 100644 index 000000000..a081142cd --- /dev/null +++ b/krita/ui/wdgpressuresettings.ui @@ -0,0 +1,66 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgPressureSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgPressureSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>510</width> + <height>87</height> + </rect> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>89</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Softer</string> + </property> + </widget> + <widget class="QLabel" row="0" column="2"> + <property name="name"> + <cstring>textLabel2</cstring> + </property> + <property name="text"> + <string>Firmer</string> + </property> + </widget> + <widget class="QSlider" row="0" column="1"> + <property name="name"> + <cstring>slPressure</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="tickmarks"> + <enum>NoMarks</enum> + </property> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgselectionoptions.ui b/krita/ui/wdgselectionoptions.ui new file mode 100644 index 000000000..13c9394d1 --- /dev/null +++ b/krita/ui/wdgselectionoptions.ui @@ -0,0 +1,64 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgSelectionOptions</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgSelectionOptions</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>180</width> + <height>34</height> + </rect> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>0</number> + </property> + <property name="spacing"> + <number>0</number> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout1</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="spacing"> + <number>6</number> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblAction</cstring> + </property> + <property name="text"> + <string>Action:</string> + </property> + </widget> + <widget class="QComboBox"> + <item> + <property name="text"> + <string>Add</string> + </property> + </item> + <item> + <property name="text"> + <string>Subtract</string> + </property> + </item> + <property name="name"> + <cstring>cmbAction</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgshapeoptions.ui b/krita/ui/wdgshapeoptions.ui new file mode 100644 index 000000000..9c18771e5 --- /dev/null +++ b/krita/ui/wdgshapeoptions.ui @@ -0,0 +1,98 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgGeometryOptions</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgGeometryOptions</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>275</width> + <height>31</height> + </rect> + </property> + <property name="caption"> + <string>Geometry Options</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <property name="margin"> + <number>2</number> + </property> + <property name="spacing"> + <number>2</number> + </property> + <spacer row="1" column="2"> + <property name="name"> + <cstring>spacer9</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>16</height> + </size> + </property> + </spacer> + <widget class="QLabel" row="0" column="0"> + <property name="name"> + <cstring>textLabel3</cstring> + </property> + <property name="text"> + <string>Fill:</string> + </property> + </widget> + <widget class="QComboBox" row="0" column="1" rowspan="1" colspan="2"> + <item> + <property name="text"> + <string>Not Filled</string> + </property> + </item> + <item> + <property name="text"> + <string>Foreground Color</string> + </property> + </item> + <item> + <property name="text"> + <string>Background Color</string> + </property> + </item> + <item> + <property name="text"> + <string>Pattern</string> + </property> + </item> + <property name="name"> + <cstring>cmbFill</cstring> + </property> + </widget> + <spacer row="0" column="3" rowspan="2" colspan="1"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>20</height> + </size> + </property> + </spacer> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgtabletdevicesettings.ui b/krita/ui/wdgtabletdevicesettings.ui new file mode 100644 index 000000000..07f90d30d --- /dev/null +++ b/krita/ui/wdgtabletdevicesettings.ui @@ -0,0 +1,193 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgTabletDeviceSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgTabletDeviceSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>363</width> + <height>386</height> + </rect> + </property> + <property name="caption"> + <string>Configure Tablet Device</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>90</height> + </size> + </property> + </spacer> + <widget class="QGroupBox" row="0" column="0"> + <property name="name"> + <cstring>groupBox3</cstring> + </property> + <property name="title"> + <string>Axes</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2</cstring> + </property> + <property name="text"> + <string>X:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbX</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4_4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_4</cstring> + </property> + <property name="text"> + <string>Y:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbY</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4_2</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_2</cstring> + </property> + <property name="text"> + <string>Pressure:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbPressure</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4_3</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_3</cstring> + </property> + <property name="text"> + <string>X tilt:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbXTilt</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4_6</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_6</cstring> + </property> + <property name="text"> + <string>Y tilt:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbYTilt</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4_5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1_2_5</cstring> + </property> + <property name="text"> + <string>Wheel:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbWheel</cstring> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgtabletsettings.ui b/krita/ui/wdgtabletsettings.ui new file mode 100644 index 000000000..775f1e9b0 --- /dev/null +++ b/krita/ui/wdgtabletsettings.ui @@ -0,0 +1,104 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>WdgTabletSettings</class> +<widget class="QWidget"> + <property name="name"> + <cstring>WdgTabletSettings</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>510</width> + <height>268</height> + </rect> + </property> + <property name="caption"> + <string>Tablet</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QGroupBox" row="1" column="0"> + <property name="name"> + <cstring>grpTabletDevices</cstring> + </property> + <property name="title"> + <string>Tablet Devices</string> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout4</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>textLabel1</cstring> + </property> + <property name="text"> + <string>Device:</string> + </property> + </widget> + <widget class="QComboBox"> + <property name="name"> + <cstring>cbTabletDevice</cstring> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout5</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QCheckBox"> + <property name="name"> + <cstring>chkEnableTabletDevice</cstring> + </property> + <property name="text"> + <string>Enable</string> + </property> + </widget> + <widget class="QPushButton"> + <property name="name"> + <cstring>btnConfigureTabletDevice</cstring> + </property> + <property name="text"> + <string>Configure...</string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer row="2" column="0"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Expanding</enum> + </property> + <property name="sizeHint"> + <size> + <width>21</width> + <height>90</height> + </size> + </property> + </spacer> + </grid> +</widget> +<layoutdefaults spacing="6" margin="11"/> +</UI> diff --git a/krita/ui/wdgtextbrush.ui b/krita/ui/wdgtextbrush.ui new file mode 100644 index 000000000..4126dc76c --- /dev/null +++ b/krita/ui/wdgtextbrush.ui @@ -0,0 +1,158 @@ +<!DOCTYPE UI><UI version="3.3" stdsetdef="1"> +<class>KisWdgTextBrush</class> +<widget class="QWidget"> + <property name="name"> + <cstring>KisWdgTextBrush</cstring> + </property> + <property name="geometry"> + <rect> + <x>0</x> + <y>0</y> + <width>317</width> + <height>89</height> + </rect> + </property> + <property name="caption"> + <string>Text</string> + </property> + <grid> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget" row="0" column="0"> + <property name="name"> + <cstring>layout3</cstring> + </property> + <vbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout9</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>labelText</cstring> + </property> + <property name="text"> + <string>Text:</string> + </property> + </widget> + <widget class="KLineEdit"> + <property name="name"> + <cstring>lineEdit</cstring> + </property> + <property name="minimumSize"> + <size> + <width>120</width> + <height>0</height> + </size> + </property> + <property name="font"> + <font> + </font> + </property> + <property name="text"> + <string>The Quick Brown Fox Jumps Over The Lazy Dog</string> + </property> + </widget> + </hbox> + </widget> + <widget class="QLayoutWidget"> + <property name="name"> + <cstring>layout10</cstring> + </property> + <hbox> + <property name="name"> + <cstring>unnamed</cstring> + </property> + <widget class="QLabel"> + <property name="name"> + <cstring>lblFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>5</hsizetype> + <vsizetype>5</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>Font:</string> + </property> + </widget> + <widget class="QToolButton"> + <property name="name"> + <cstring>bnFont</cstring> + </property> + <property name="sizePolicy"> + <sizepolicy> + <hsizetype>0</hsizetype> + <vsizetype>0</vsizetype> + <horstretch>0</horstretch> + <verstretch>0</verstretch> + </sizepolicy> + </property> + <property name="text"> + <string>...</string> + </property> + <property name="accel"> + <string></string> + </property> + </widget> + </hbox> + </widget> + </vbox> + </widget> + <spacer row="0" column="1"> + <property name="name"> + <cstring>spacer1</cstring> + </property> + <property name="orientation"> + <enum>Horizontal</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>121</width> + <height>20</height> + </size> + </property> + </spacer> + <spacer row="1" column="0"> + <property name="name"> + <cstring>spacer2</cstring> + </property> + <property name="orientation"> + <enum>Vertical</enum> + </property> + <property name="sizeType"> + <enum>Minimum</enum> + </property> + <property name="sizeHint"> + <size> + <width>20</width> + <height>31</height> + </size> + </property> + </spacer> + </grid> +</widget> +<customwidgets> +</customwidgets> +<slots> + <slot access="private">boldButtonClicked()</slot> +</slots> +<layoutdefaults spacing="6" margin="11"/> +<includehints> + <includehint>klineedit.h</includehint> +</includehints> +</UI> |
