diff --git a/active/CMakeLists.txt b/active/CMakeLists.txt index af105045324..8fa0c6f1c04 100644 --- a/active/CMakeLists.txt +++ b/active/CMakeLists.txt @@ -1,72 +1,72 @@ cmake_minimum_required(VERSION 2.8.0) #cmake_policy CMP0017 was introduced in version 2.8.4 if(${CMAKE_VERSION} VERSION_GREATER 2.8.3) cmake_policy(SET CMP0017 NEW) endif() project(calligra-active) find_package(Qt4 4.7.0 REQUIRED) find_package(KDE4 REQUIRED) add_definitions(${QT_DEFINITIONS} ${KDE4_DEFINITIONS}) include_directories(${QT_INCLUDES} ${KDE4_INCLUDES} ${KDECLARATIVE_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}) include_directories( ${KORDF_INCLUDES} ${CMAKE_SOURCE_DIR}/words/part ${CMAKE_SOURCE_DIR}/sheets ${CMAKE_SOURCE_DIR}/libs/kopageapp ) set (calligra-active_RCCS CalligraActive.qrc) qt4_add_resources(calligra-active_RCC_SRCS ${calligra-active_RCCS}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/calligra_active_global.h.in ${CMAKE_CURRENT_BINARY_DIR}/calligra_active_global.h) set(calligra-active_SRCS src/CACanvasItem.cpp src/CAImageProvider.cpp src/CAPresentationHandler.cpp src/CASpreadsheetHandler.cpp src/CATextDocumentHandler.cpp src/CAAbstractDocumentHandler.cpp src/CADocumentController.cpp src/CADocumentInfo.cpp src/CAPADocumentModel.cpp src/CATextDocumentModel.cpp src/CAPAView.cpp src/CACanvasController.cpp src/MainWindow.cpp main.cpp ${calligra-active_RCC_SRCS} ) qt4_automoc(${calligra-active_SRCS}) add_executable(calligraactive ${calligra-active_SRCS}) target_link_libraries(calligraactive ${QT_QTDECLARATIVE_LIBRARY} ${QT_LIBRARIES} ${KDECLARATIVE_LIBRARIES} komain wordsprivate calligrasheetscommon kopageapp calligrastageprivate ) if( SHOULD_BUILD_FEATURE_RDF ) target_link_libraries(calligraactive kordf) endif() install(TARGETS calligraactive RUNTIME DESTINATION bin) install(FILES calligraactive.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) -install(DIRECTORY qml DESTINATION ${DATA_INSTALL_DIR}/calligraactive) +install(DIRECTORY qml DESTINATION share/calligraactive) diff --git a/filters/karbon/eps/PsCommentLexer.cpp b/filters/karbon/eps/PsCommentLexer.cpp index 641a2d472f4..6487df6c6de 100644 --- a/filters/karbon/eps/PsCommentLexer.cpp +++ b/filters/karbon/eps/PsCommentLexer.cpp @@ -1,344 +1,344 @@ /* This file is part of the KDE project - Copyright (C) 2002, Dirk Schönberger + Copyright (C) 2002, Dirk Schönberger 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 "PsCommentLexer.h" #include #include #include #define CATEGORY_WHITESPACE -1 #define CATEGORY_ALPHA -2 #define CATEGORY_DIGIT -3 #define CATEGORY_SPECIAL -4 #define CATEGORY_LETTERHEX -5 #define CATEGORY_INTTOOLONG -6 #define CATEGORY_ANY -127 #define MAX_INTLEN 9 #define MIN_HEXCHARS 6 #define STOP 0 int iswhitespace(char c) { return (c == ' ') || (c == '\n') || (c == '\t') || (c == '\r'); } int isSpecial(char c) { return (c == '*') || (c == '_') || (c == '?') || (c == '~') || (c == '-') || (c == '^') || (c == '`') || (c == '!') || (c == '.') || (c == '@') || (c == '&') || (c == '$') || (c == '='); } int isletterhex(char c) { return (c == 'A') || (c == 'B') || (c == 'C') || (c == 'D') || (c == 'E') || (c == 'F'); } const char*statetoa(State state) { switch (state) { case State_Comment : return "comment"; case State_CommentEncodedChar : return "encoded char (comment)"; default : return "unknown"; } } typedef struct { State oldState; char c; State newState; Action action; } Transition; static const Transition transitions[] = { { State_Comment, '\n', State_Start, Action_Output}, { State_Comment, '\r', State_Start, Action_Output}, { State_Comment, '\\', State_CommentEncodedChar, Action_InitTemp}, { State_Comment, CATEGORY_ANY, State_Comment, Action_Copy}, { State_CommentEncodedChar, '\\', State_Comment, Action_Copy}, { State_CommentEncodedChar, CATEGORY_DIGIT, State_CommentEncodedChar, Action_CopyTemp}, { State_CommentEncodedChar, CATEGORY_ANY, State_Comment, Action_DecodeUnget}, { State_Start, '%', State_Comment, Action_Ignore}, { State_Start, CATEGORY_ANY, State_Start, Action_Ignore}, { State_Start, STOP, State_Start, Action_Abort} }; PSCommentLexer::PSCommentLexer() { } PSCommentLexer::~PSCommentLexer() { } bool PSCommentLexer::parse(QIODevice& fin) { char c; m_buffer.clear(); m_curState = State_Start; parsingStarted(); while (!fin.atEnd()) { fin.getChar(&c); // qDebug ("got %c", c); State newState; Action action; nextStep(c, &newState, &action); switch (action) { case Action_Copy : m_buffer.append(c); break; case Action_CopyOutput : m_buffer.append(c); doOutput(); break; case Action_Output : doOutput(); break; case Action_OutputUnget : doOutput(); fin.ungetChar(c); break; case Action_Ignore : /* ignore */ break; case Action_Abort : qWarning("state %s / %s char %c (%d)" , statetoa(m_curState), statetoa(newState), c, c); parsingAborted(); return false; break; case Action_InitTemp : m_temp.clear(); break; case Action_CopyTemp : m_temp.append(c); break; case Action_DecodeUnget : m_buffer.append(decode()); fin.ungetChar(c); break; default : qWarning("unknown action: %d ", action); } m_curState = newState; } parsingFinished(); return true; } void PSCommentLexer::doOutput() { if (m_buffer.length() == 0) return; switch (m_curState) { case State_Comment : gotComment(m_buffer.toLatin1()); break; default: qWarning("unknown state: %d", m_curState); } m_buffer.clear(); } void PSCommentLexer::gotComment(const char *value) { qDebug("gotComment: %s ", value); } void PSCommentLexer::parsingStarted() { qDebug("parsing started"); } void PSCommentLexer::parsingFinished() { qDebug("parsing finished"); } void PSCommentLexer::parsingAborted() { qDebug("parsing aborted"); } void PSCommentLexer::nextStep(char c, State *newState, Action *newAction) { int i = 0; while (true) { Transition trans = transitions[i]; if (trans.c == STOP) { *newState = trans.newState; *newAction = trans.action; return; } bool found = false; if (trans.oldState == m_curState) { switch (trans.c) { case CATEGORY_WHITESPACE : found = isspace(c); break; case CATEGORY_ALPHA : found = isalpha(c); break; case CATEGORY_DIGIT : found = isdigit(c); break; case CATEGORY_SPECIAL : found = isSpecial(c); break; case CATEGORY_LETTERHEX : found = isletterhex(c); break; case CATEGORY_INTTOOLONG : found = m_buffer.length() > MAX_INTLEN; break; case CATEGORY_ANY : found = true; break; default : found = (trans.c == c); } if (found) { *newState = trans.newState; *newAction = trans.action; return; } } i++; } } uchar PSCommentLexer::decode() { uchar value = m_temp.toString().toShort(NULL, 8); // qDebug ("got encoded char %c",value); return value; } /* StringBuffer implementation */ const int initialSize = 20; const int addSize = 10; StringBuffer::StringBuffer() { m_buffer = (char*)calloc(initialSize, sizeof(char)); m_length = 0; m_capacity = initialSize; } StringBuffer::~StringBuffer() { free(m_buffer); } void StringBuffer::append(char c) { ensureCapacity(m_length + 1); m_buffer[m_length] = c; m_length++; } void StringBuffer::clear() { for (uint i = 0; i < m_length; i++) m_buffer[i] = '\0'; m_length = 0; } QString StringBuffer::toString() const { QString ret(m_buffer); return ret; } void StringBuffer::ensureCapacity(int p_capacity) { if (m_capacity >= p_capacity) return; int newSize = m_capacity + addSize; if (p_capacity > newSize) newSize = p_capacity; char* oldBuffer = m_buffer; char *newBuffer = (char*)calloc(newSize, sizeof(char)); strcpy(newBuffer, m_buffer); free(oldBuffer); m_buffer = newBuffer; m_capacity = newSize; } uint StringBuffer::length() const { return m_length; } double StringBuffer::toFloat() { QString data = toString(); return data.toFloat(); } int StringBuffer::toInt() { QString data = toString(); return data.toInt(); } const char *StringBuffer::toLatin1() const { return m_buffer; } QString StringBuffer::mid(uint index, uint len) const { QString data = toString(); return data.mid(index, len); } /* BoundingBoxExtractor */ BoundingBoxExtractor:: BoundingBoxExtractor() : m_llx(0), m_lly(0), m_urx(0), m_ury(0) {} BoundingBoxExtractor::~BoundingBoxExtractor() {} void BoundingBoxExtractor::gotComment(const char *value) { QString data(value); if (data.indexOf("%BoundingBox:") == -1) return; getRectangle(value, m_llx, m_lly, m_urx, m_ury); } bool BoundingBoxExtractor::getRectangle(const char* input, int &llx, int &lly, int &urx, int &ury) { if (input == NULL) return false; QString s(input); if (s.contains("(atend)")) return false; s.remove("%BoundingBox:"); QStringList values = s.split(' '); qDebug("size is %d", values.size()); // if (values.size() < 5) return false; llx = values[0].toInt(); lly = values[1].toInt(); urx = values[2].toInt(); ury = values[3].toInt(); return true; } diff --git a/filters/karbon/eps/PsCommentLexer.h b/filters/karbon/eps/PsCommentLexer.h index 7ec05b4f4f2..0e54ae09188 100644 --- a/filters/karbon/eps/PsCommentLexer.h +++ b/filters/karbon/eps/PsCommentLexer.h @@ -1,123 +1,123 @@ /* This file is part of the KDE project - Copyright (C) 2002, Dirk Schönberger + Copyright (C) 2002, Dirk Schönberger 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 PSCOMMENTLEXER_H #define PSCOMMENTLEXER_H #include #include /** - *@author Dirk Schönberger + *@author Dirk Schönberger */ typedef enum { State_Comment = 0, State_CommentEncodedChar, State_Start } State; typedef enum { Action_Copy = 1, Action_CopyOutput, Action_Output, Action_Ignore, Action_Abort, Action_OutputUnget, Action_InitTemp, Action_CopyTemp, Action_DecodeUnget, Action_ByteArraySpecial } Action; // TODO: Looks like this class is duplicated in ailexer.h class StringBuffer { public: StringBuffer(); virtual ~StringBuffer(); void append(char c); void clear(); QString toString() const; uint length() const; double toFloat(); int toInt(); const char *toLatin1() const; QString mid(uint index, uint len = 0xffffffff) const; private: char *m_buffer; uint m_length; int m_capacity; void ensureCapacity(int p_capacity); }; class PSCommentLexer { public: PSCommentLexer(); virtual ~PSCommentLexer(); virtual bool parse(QIODevice& fin); private: State m_curState; StringBuffer m_buffer; StringBuffer m_temp; void nextStep(char c, State* newState, Action* newAction); void doOutput(); uchar decode(); protected: virtual void parsingStarted(); virtual void parsingFinished(); virtual void parsingAborted(); virtual void gotComment(const char *value); }; class BoundingBoxExtractor : public PSCommentLexer { public: BoundingBoxExtractor(); virtual ~BoundingBoxExtractor(); int llx() const { return m_llx; } int lly() const { return m_lly; } int urx() const { return m_urx; } int ury() const { return m_ury; } private: int m_llx, m_lly, m_urx, m_ury; bool getRectangle(const char* input, int &llx, int &lly, int &urx, int &ury); protected: void gotComment(const char *value); }; #endif diff --git a/filters/sheets/xlsx/XlsxXmlChartReader.cpp b/filters/sheets/xlsx/XlsxXmlChartReader.cpp index 61172f1ab14..7b97929514f 100644 --- a/filters/sheets/xlsx/XlsxXmlChartReader.cpp +++ b/filters/sheets/xlsx/XlsxXmlChartReader.cpp @@ -1,3513 +1,3513 @@ /* * This file is part of Office 2007 Filters for Calligra * * Copyright (C) 2010 Sebastian Sauer * Copyright (c) 2010 Carlos Licea * Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies). * * Contact: Suresh Chande suresh.chande@nokia.com * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public License * version 2.1 as published by the Free Software Foundation. * * This library is distributed in the hope that it will be useful, but * WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA * 02110-1301 USA * */ // Own #include "XlsxXmlChartReader.h" // libodf2 #include "Charting.h" // libmso #include "XlsUtils.h" #include "NumberFormatParser.h" // The Xlsx import filter #include "XlsxChartOdfWriter.h" #define MSOOXML_CURRENT_NS "c" #define MSOOXML_CURRENT_CLASS XlsxXmlChartReader #define BIND_READ_CLASS MSOOXML_CURRENT_CLASS #include #include #include #include class SpPr { public: SpPr() {} }; class NumCache { public: int m_ptCount; QVector< QString > m_cache; QString formatCode; NumCache() : m_ptCount(0) {} }; class StrCache { public: int m_ptCount; QVector< QString > m_cache; StrCache() : m_ptCount(0) {} }; class NumRef { public: QString m_f; NumCache m_numCache; }; class NumLit { public: int m_ptCount; QVector< QString > m_cache; NumLit() : m_ptCount(0) {} }; class StrLit { public: int m_ptCount; QVector< QString > m_cache; StrLit() : m_ptCount(0) {} }; class StrRef { public: QString m_f; StrCache m_strCache; }; class Tx { public: StrRef m_strRef; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); }; QString Tx::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { chartReader->WriteIntoInternalTable(m_strRef.m_f,m_strRef.m_strCache.m_cache,KoGenStyle::NumericTextStyle); return m_strRef.m_f; } class Cat { public: NumRef m_numRef; StrRef m_strRef; NumLit m_numLit; StrLit m_strLit; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); QString writeLitToInternalTable(XlsxXmlChartReader *chartReader); }; QString Cat::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { if (m_numRef.m_numCache.m_ptCount != 0) { KoGenStyle::Type formatType = KoGenStyle::NumericNumberStyle; if (!m_numRef.m_numCache.formatCode.isEmpty() && m_numRef.m_numCache.formatCode != "General") { KoGenStyle style = NumberFormatParser::parse(m_numRef.m_numCache.formatCode); formatType = style.type(); } chartReader->WriteIntoInternalTable(m_numRef.m_f,m_numRef.m_numCache.m_cache, formatType, m_numRef.m_numCache.formatCode ); return m_numRef.m_f; } chartReader->WriteIntoInternalTable(m_strRef.m_f,m_strRef.m_strCache.m_cache,KoGenStyle::NumericTextStyle); return m_strRef.m_f; } QString Cat::writeLitToInternalTable(XlsxXmlChartReader *chartReader) { if (m_numLit.m_ptCount != 0) { return chartReader->AlocateAndWriteIntoInternalTable(m_numLit.m_cache,KoGenStyle::NumericNumberStyle); } return chartReader->AlocateAndWriteIntoInternalTable(m_strLit.m_cache,KoGenStyle::NumericTextStyle); } class Val { public: NumRef m_numRef; NumLit m_numLit; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); QString writeLitToInternalTable(XlsxXmlChartReader *chartReader); }; QString Val::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { chartReader->WriteIntoInternalTable(m_numRef.m_f,m_numRef.m_numCache.m_cache,KoGenStyle::NumericNumberStyle); return m_numRef.m_f; } QString Val::writeLitToInternalTable(XlsxXmlChartReader *chartReader) { return chartReader->AlocateAndWriteIntoInternalTable(m_numLit.m_cache,KoGenStyle::NumericNumberStyle); } class XVal { public: NumRef m_numRef; StrRef m_strRef; NumLit m_numLit; StrLit m_strLit; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); QString writeLitToInternalTable(XlsxXmlChartReader *chartReader); }; QString XVal::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { if (m_numRef.m_numCache.m_ptCount != 0) { chartReader->WriteIntoInternalTable(m_numRef.m_f,m_numRef.m_numCache.m_cache,KoGenStyle::NumericNumberStyle); return m_numRef.m_f; } chartReader->WriteIntoInternalTable(m_strRef.m_f,m_strRef.m_strCache.m_cache,KoGenStyle::NumericTextStyle); return m_strRef.m_f; } QString XVal::writeLitToInternalTable(XlsxXmlChartReader *chartReader) { if (m_numLit.m_ptCount != 0) { return chartReader->AlocateAndWriteIntoInternalTable(m_numLit.m_cache,KoGenStyle::NumericNumberStyle); } return chartReader->AlocateAndWriteIntoInternalTable(m_strLit.m_cache,KoGenStyle::NumericTextStyle); } class YVal { public: NumRef m_numRef; NumLit m_numLit; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); QString writeLitToInternalTable(XlsxXmlChartReader *chartReader); }; QString YVal::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { chartReader->WriteIntoInternalTable(m_numRef.m_f,m_numRef.m_numCache.m_cache,KoGenStyle::NumericNumberStyle); return m_numRef.m_f; } QString YVal::writeLitToInternalTable(XlsxXmlChartReader *chartReader) { return chartReader->AlocateAndWriteIntoInternalTable(m_numLit.m_cache,KoGenStyle::NumericNumberStyle); } class BubbleSize { public: NumRef m_numRef; NumLit m_numLit; QString writeRefToInternalTable(XlsxXmlChartReader *chartReader); QString writeLitToInternalTable(XlsxXmlChartReader *chartReader); }; QString BubbleSize::writeRefToInternalTable(XlsxXmlChartReader *chartReader) { chartReader->WriteIntoInternalTable(m_numRef.m_f,m_numRef.m_numCache.m_cache,KoGenStyle::NumericNumberStyle); return m_numRef.m_f; } QString BubbleSize::writeLitToInternalTable(XlsxXmlChartReader *chartReader) { return chartReader->AlocateAndWriteIntoInternalTable(m_numLit.m_cache,KoGenStyle::NumericNumberStyle); } class Ser { }; class ValSeries : public Ser { public: int m_idx; int m_order; Tx m_tx; Cat m_cat; Val m_val; ValSeries() : m_idx(0), m_order(0) {} }; class BubbleSeries : public Ser { public: int m_idx; int m_order; Tx m_tx; XVal m_xVal; YVal m_yVal; BubbleSize m_bubbleSize; BubbleSeries() : m_idx(0), m_order(0) {} }; class ScatterSeries : public Ser { public: int m_idx; int m_order; Tx m_tx; XVal m_xVal; YVal m_yVal; SpPr m_spPr; ScatterSeries() : m_idx(0), m_order(0) {} }; class LineSeries :public ValSeries { public: LineSeries() {} }; class PieSeries :public ValSeries { public: int m_explosion; PieSeries() : m_explosion(0) {} }; class BarSeries :public ValSeries { public: BarSeries() {} }; class AreaSeries :public ValSeries { public: AreaSeries() {} }; class RadarSeries :public ValSeries { public: RadarSeries() {} }; class SurfaceSeries :public ValSeries { public: SurfaceSeries() {} }; class XlsxXmlChartReader::Private { public: Private(); QList m_seriesData; QVariant::Type m_currentType; int *m_currentIdx; int *m_currentOrder; int *m_currentExplosion; Tx *m_currentTx; Cat *m_currentCat; Val *m_currentVal; StrRef *m_currentStrRef; QString *m_currentF; StrCache *m_currentStrCache; int *m_currentPtCount; QVector< QString > *m_currentPtCache; NumRef *m_currentNumRef; NumLit *m_currentNumLit; NumCache *m_currentNumCache; XVal *m_currentXVal; YVal *m_currentYVal; BubbleSize *m_currentBubbleSize; int m_numReadSeries; }; XlsxXmlChartReader::Private::Private ( ) : m_numReadSeries( 0 ) { //sebsauer; hmmmm... does that really make sense? qDeleteAll(m_seriesData); m_seriesData.clear(); } // calculates the column width in pixels int columnWidth(unsigned long col, unsigned long dx = 0, qreal defaultColumnWidth = 8.43) { QFont font("Arial", 10); QFontMetricsF fm(font); const qreal characterWidth = fm.width("h"); defaultColumnWidth *= characterWidth; return (defaultColumnWidth * col) + (dx / 1024.0 * defaultColumnWidth); } // calculates the row height in pixels int rowHeight(unsigned long row, unsigned long dy = 0, qreal defaultRowHeight = 12.75) { return defaultRowHeight * row + dy; } // Returns A for 1, B for 2, C for 3, etc. QString columnName(uint column) { QString s; column = column - 1; unsigned digits = 1; unsigned offset = 0; for (unsigned limit = 26; column >= limit + offset; limit *= 26, ++digits) offset += limit; for (unsigned col = column - offset; digits; --digits, col /= 26) s.prepend(QChar('A' + (col % 26))); return s; } XlsxXmlChartReaderContext::XlsxXmlChartReaderContext(KoStore* _storeout, XlsxChartOdfWriter* _chartWriter) : MSOOXML::MsooXmlReaderContext() , m_storeout(_storeout) , m_chart(_chartWriter->chart()) , m_chartWriter(_chartWriter) { } XlsxXmlChartReaderContext::~XlsxXmlChartReaderContext() { delete m_chart; delete m_chartWriter; } XlsxXmlChartReader::XlsxXmlChartReader(KoOdfWriters *writers) : MSOOXML::MsooXmlCommonReader(writers) , m_context(0) , m_currentSeries(0) , m_currentShapeProperties(0) , m_readTxContext( None ) , m_areaContext( ChartArea ) , m_serMarkerDefined(false) , m_autoTitleDeleted(true) , d ( new Private( ) ) { } XlsxXmlChartReader::~XlsxXmlChartReader() { delete d; } //! chart (Chart) /*! ECMA-376, 21.2.2.29, p.3768. Parent elements: - chartSpace (§21.2.2.29) Child elements: - [Done]autoTitleDeleted (Auto Title Is Deleted) §21.2.2.7 - backWall (Back Wall) §21.2.2.11 - dispBlanksAs (Display Blanks As) §21.2.2.42 - extLst (Chart Extensibility) §21.2.2.64 - floor (Floor) §21.2.2.69 - [Done]legend (Legend) §21.2.2.93 - pivotFmts (Pivot Formats) §21.2.2.143 - [Done]plotArea (Plot Area) §21.2.2.145 - plotVisOnly (Plot Visible Only) §21.2.2.146 - showDLblsOverMax (Show Data Labels over Maximum) §21.2.2.180 - sideWall (Side Wall) §21.2.2.191 - [Done]title (Title) §21.2.2.210 - view3D (View In 3D) §21.2.2.228 */ KoFilter::ConversionStatus XlsxXmlChartReader::read(MSOOXML::MsooXmlReaderContext* context) { m_context = dynamic_cast(context); Q_ASSERT(m_context); readNext(); if (!isStartDocument()) { return KoFilter::WrongFormat; } readNext(); if (!expectEl("c:chartSpace")) { return KoFilter::WrongFormat; } while (!atEnd()) { QXmlStreamReader::TokenType tokenType = readNext(); if(tokenType == QXmlStreamReader::Invalid || tokenType == QXmlStreamReader::EndDocument) break; if (isStartElement()) { m_areaContext = ChartArea; TRY_READ_IF(plotArea) ELSE_TRY_READ_IF(title) ELSE_TRY_READ_IF(legend) ELSE_TRY_READ_IF(spPr) ELSE_TRY_READ_IF(txPr) if (qualifiedName() == QLatin1String(QUALIFIED_NAME(autoTitleDeleted))) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) m_autoTitleDeleted = MSOOXML::Utils::convertBooleanAttr(val, true); } if (qualifiedName() == QLatin1String(QUALIFIED_NAME(style))) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) m_context->m_chart->m_style = val.toInt(); } } } if (!m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty()) m_context->m_chart->m_title = "Chart Title"; // static is fine here cause we only need to take care that that number is unique in the // exported ODS file and do not take if the number is continuous or whatever. static int chartNumber = 0; m_context->m_chartWriter->m_href = QString("Chart%1").arg(++chartNumber); KoChart::Chart* c = m_context->m_chart; if (!c->m_cellRangeAddress.isNull() ) { m_context->m_chartWriter->m_cellRangeAddress.clear(); if (!c->m_sheetName.isEmpty()) m_context->m_chartWriter->m_cellRangeAddress += c->m_sheetName + '.'; m_context->m_chartWriter->m_cellRangeAddress += columnName(c->m_cellRangeAddress.left()) + QString::number(c->m_cellRangeAddress.top()) + ":" + columnName(c->m_cellRangeAddress.right()) + QString::number(c->m_cellRangeAddress.bottom()); } if (m_currentSeries) { m_context->m_chartWriter->m_notifyOnUpdateOfRanges = m_currentSeries->m_valuesCellRangeAddress; //m_cellRangeAddress } // the index will by written by the XlsxXmlWorksheetReader //m_context->m_chartWriter->saveIndex(body); // write the embedded object file m_context->m_chartWriter->saveContent(m_context->m_storeout, manifest); m_context = 0; return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL txPr KoFilter::ConversionStatus XlsxXmlChartReader::read_txPr() { READ_PROLOGUE while( !atEnd() ) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if ( isStartElement() ) if ( qualifiedName() == "a:p" ) read_p(); } READ_EPILOGUE return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL p KoFilter::ConversionStatus XlsxXmlChartReader::read_p() { //READ_PROLOGUE while( !atEnd() ) { readNext(); if ( isEndElement() && qualifiedName() == QLatin1String( "a:p") ) break; if ( isStartElement() ) if ( qualifiedName() == "a:pPr" ) read_pPr(); //TRY_READ_IF_NS(a,pPr); } //READ_EPILOGUE return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL pPr KoFilter::ConversionStatus XlsxXmlChartReader::read_pPr() { //READ_PROLOGUE while( !atEnd() ) { readNext(); if ( isEndElement() && qualifiedName() == QLatin1String( "a:pPr") ) break; if ( isStartElement() ) if ( qualifiedName() == "a:defRPr" ) read_defRPr(); } //READ_EPILOGUE return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL defRPr KoFilter::ConversionStatus XlsxXmlChartReader::read_defRPr() { //READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(sz); bool ok = false; const qreal size = sz.toDouble( &ok ); if ( ok ) { m_context->m_chart->m_textSize = size / 100.0; } while( !atEnd() ) { if ( isEndElement() && qualifiedName() == QLatin1String( "a:defRPr") ) break; readNext(); //BREAK_IF_END_OF(CURRENT_EL) } //READ_EPILOGUE return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL valAx KoFilter::ConversionStatus XlsxXmlChartReader::read_valAx() { READ_PROLOGUE // The logic here is that if the x-axis defines a category then it should be already // set above using the read_catAx else this read_valAx could be either a x-axis or // a y-axis. In that case we just look if there was already a x-axis defined in // which case we know if must be the y-axis or, if not, then it's the a-axis. // This sounds hacky (and it certainly is) but that's how OO.org does it too. bool xAxisAlreadyDefined = !m_context->m_chart->m_verticalCellRangeAddress.isEmpty(); if (!xAxisAlreadyDefined) { foreach(KoChart::Axis* axis, m_context->m_chart->m_axes) { if (axis->m_type == KoChart::Axis::HorizontalValueAxis) { xAxisAlreadyDefined = true; break; } } } KoChart::Axis* axis = new KoChart::Axis( xAxisAlreadyDefined ? KoChart::Axis::VerticalValueAxis : KoChart::Axis::HorizontalValueAxis ); m_context->m_chart->m_axes.push_back( axis ); while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(axPos) ) ) { // const QXmlStreamAttributes attrs(attributes()); // TRY_READ_ATTR_WITHOUT_NS(val) // if ( val == QLatin1String( "b" ) ){ // axis->m_type = KoChart::Axis::HorizontalValueAxis; // } // else if ( val == QLatin1String( "l" ) ){ // } // } } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(majorGridlines) ) ) { axis->m_majorGridlines = KoChart::Axis::Gridline( KoChart::LineFormat( KoChart::LineFormat::Solid ) ); } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(numFmt) ) ) { const QXmlStreamAttributes attrs(attributes()); axis->m_numberFormat = attrs.value("formatCode").toString(); } ELSE_TRY_READ_IF(scaling) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL catAx KoFilter::ConversionStatus XlsxXmlChartReader::read_catAx() { READ_PROLOGUE // category-axis or date-axis are always x-axis. They are only defined for the case the // x-axis itself defines a category. If not then the x-axis will be defined via read_valAx. KoChart::Axis* axis = new KoChart::Axis( KoChart::Axis::HorizontalValueAxis ); m_context->m_chart->m_axes.push_back( axis ); while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(axPos) ) ) { // const QXmlStreamAttributes attrs(attributes()); // TRY_READ_ATTR_WITHOUT_NS(val) // if ( val == QLatin1String( "b" ) ){ // } // else if ( val == QLatin1String( "l" ) ){ // } } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(majorGridlines) ) ) { axis->m_majorGridlines = KoChart::Axis::Gridline( KoChart::LineFormat( KoChart::LineFormat::Solid ) ); } ELSE_TRY_READ_IF(scaling) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL scaling KoFilter::ConversionStatus XlsxXmlChartReader::read_scaling() { READ_PROLOGUE Q_ASSERT(!m_context->m_chart->m_axes.isEmpty()); KoChart::Axis* axis = m_context->m_chart->m_axes.last(); while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { const QXmlStreamAttributes attrs(attributes()); if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(orientation) ) ) { TRY_READ_ATTR_WITHOUT_NS(val) axis->m_reversed = ( val == QLatin1String( "maxMin" ) ); } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(logBase) ) ) { TRY_READ_ATTR_WITHOUT_NS(val) axis->m_logarithmic = ( val.toDouble() >= 2. ); } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(max) ) ) { TRY_READ_ATTR_WITHOUT_NS(val) axis->m_maximum = val.toDouble(); axis->m_autoMaximum = false; } else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(min) ) ) { TRY_READ_ATTR_WITHOUT_NS(val) axis->m_minimum = val.toDouble(); axis->m_autoMinimum = false; } } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL plotArea //! plotArea (Plot Area) /*! ECMA-376, 21.2.2.145, p.3828. Parent elements: - chart (§21.2.2.27) Child elements: - [Done]area3DChart (3D Area Charts) §21.2.2.4 - [Done]areaChart (Area Charts) §21.2.2.5 - [Done]bar3DChart (3D Bar Charts) §21.2.2.15 - [Done]barChart (Bar Charts) §21.2.2.16 - [Done]bubbleChart (Bubble Charts) §21.2.2.20 - [Done]catAx (Category Axis Data) §21.2.2.25 - dateAx (Date Axis) §21.2.2.39 - [Done]doughnutChart (Doughnut Charts) §21.2.2.50 - dTable (Data Table) §21.2.2.54 - extLst (Chart Extensibility) §21.2.2.64 - layout (Layout) §21.2.2.88 - [Done]line3DChart (3D Line Charts) §21.2.2.96 - [Done]lineChart (Line Charts) §21.2.2.97 - [Done]ofPieChart (Pie of Pie or Bar of Pie Charts) §21.2.2.126 - [Done]pie3DChart (3D Pie Charts) §21.2.2.140 - [Done]pieChart (Pie Charts) §21.2.2.141 - [Done]radarChart (Radar Charts) §21.2.2.153 - [Done]scatterChart (Scatter Charts) §21.2.2.161 - serAx (Series Axis) §21.2.2.175 - [Done]spPr (Shape Properties) §21.2.2.197 - [Done]stockChart (Stock Charts) §21.2.2.198 - [Done]surface3DChart (3D Surface Charts) §21.2.2.203 - [Done]surfaceChart (Surface Charts) §21.2.2.204 - [Done]valAx (Value Axis) §21.2.2.226 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_plotArea() { m_areaContext = PlotArea; if (!m_context->m_chart->m_plotArea) { m_context->m_chart->m_plotArea = new KoChart::PlotArea(); } READ_PROLOGUE while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(spPr) ELSE_TRY_READ_IF(valAx) // x-axis or y-axis ELSE_TRY_READ_IF(catAx) // x-axis //ELSE_TRY_READ_IF(serAx) // z-axis ELSE_TRY_READ_IF(pieChart) ELSE_TRY_READ_IF(pie3DChart) ELSE_TRY_READ_IF(ofPieChart) ELSE_TRY_READ_IF(doughnutChart) ELSE_TRY_READ_IF(areaChart) ELSE_TRY_READ_IF(area3DChart) ELSE_TRY_READ_IF(barChart) ELSE_TRY_READ_IF(bar3DChart) ELSE_TRY_READ_IF(lineChart) ELSE_TRY_READ_IF(line3DChart) ELSE_TRY_READ_IF(scatterChart) ELSE_TRY_READ_IF(radarChart) ELSE_TRY_READ_IF(surfaceChart) ELSE_TRY_READ_IF(surface3DChart) ELSE_TRY_READ_IF(bubbleChart) ELSE_TRY_READ_IF(stockChart) SKIP_UNKNOWN } } READ_EPILOGUE m_areaContext = ChartArea; } #undef CURRENT_EL #define CURRENT_EL title /*! Read the horizontal value. */ KoFilter::ConversionStatus XlsxXmlChartReader::read_title() { m_readTxContext = Title; READ_PROLOGUE while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if(QUALIFIED_NAME_IS(tx)) { TRY_READ(chartText_Tx) } } } m_readTxContext = None; READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL val //! val (Values) /*! ECMA-376, 21.2.2.224, p.3867. Parent elements: - ser §21.2.2.168 - ser §21.2.2.170 - ser §21.2.2.174 - ser §21.2.2.171 - ser §21.2.2.172 - ser §21.2.2.169 - ser §21.2.2.167 - ser §21.2.2.173 Child elements: - numLit (Number Literal) §21.2.2.122 - [Done] numRef (Number Reference) §21.2.2.123 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_val() { READ_PROLOGUE d->m_currentNumRef = &d->m_currentVal->m_numRef; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(numRef) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL xVal //! xVal (X Values) /*! ECMA-376, 21.2.2.234, p.3872. Parent elements: - ser §21.2.2.174 - ser §21.2.2.167 Child elements: - multiLvlStrRef (Multi Level String Reference) §21.2.2.115 - numLit (Number Literal) §21.2.2.122 - [Done]numRef (Number Reference) §21.2.2.123 - strLit (String Literal) §21.2.2.200 - [Done]strRef (String Reference) §21.2.2.201 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_xVal() { READ_PROLOGUE d->m_currentNumRef = &d->m_currentXVal->m_numRef; d->m_currentStrRef = &d->m_currentXVal->m_strRef; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(numRef) ELSE_TRY_READ_IF(strRef) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL yVal //! yVal (Y Values) /*! ECMA-376, 21.2.2.237, p.3873. Parent elements: - ser §21.2.2.174 - ser §21.2.2.167 Child elements: - numLit (Number Literal) §21.2.2.122 - numRef (Number Reference) §21.2.2.123 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_yVal() { READ_PROLOGUE d->m_currentNumRef = &d->m_currentYVal->m_numRef; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(numRef) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL cat //! cat (Category Axis Data) /*! ECMA-376, 21.2.2.24, p.3766. Parent elements: - ser §21.2.2.168 - ser §21.2.2.170 - ser §21.2.2.174 - ser §21.2.2.171 - ser §21.2.2.172 - ser §21.2.2.169 - ser §21.2.2.167 - ser §21.2.2.173 Child elements: - multiLvlStrRef (Multi Level String Reference) §21.2.2.115 - numLit (Number Literal) §21.2.2.122 - [Done]numRef (Number Reference) §21.2.2.123 - strLit (String Literal) §21.2.2.200 - strRef (String Reference) §21.2.2.201 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_cat() { READ_PROLOGUE d->m_currentStrRef = &d->m_currentCat->m_strRef; d->m_currentNumRef = &d->m_currentCat->m_numRef; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(strRef) ELSE_TRY_READ_IF(multiLvlStrRef) ELSE_TRY_READ_IF(numRef) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL tx //! tx (Chart Text) /*! ECMA-376, 21.2.2.215, p.3863. Parent elements: - dispUnitsLbl (§21.2.2.46) - dLbl (§21.2.2.47) - title (§21.2.2.210) - trendlineLbl (§21.2.2.212) Child elements: - rich (Rich Text) §21.2.2.156 - strRef (String Reference) §21.2.2.201 */ /*! This element specifies text to use on a chart, including rich text formatting. */ KoFilter::ConversionStatus XlsxXmlChartReader::read_chartText_Tx() { READ_PROLOGUE2(chartText_Tx) enum { Start, InStrRef, InRichText } state; state = Start; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) switch(state) { case Start: if (qualifiedName() == QLatin1String(QUALIFIED_NAME(strRef))) state = isStartElement() ? InStrRef : Start; else if (qualifiedName() == QLatin1String(QUALIFIED_NAME(rich))) state = isStartElement() ? InRichText : Start; break; case InStrRef: // plaintext within a series // if (isStartElement() && !m_currentSeriesData->m_datasetValue.contains(KoChart::Value::SeriesLegendOrTrendlineName)) { // if (qualifiedName() == QLatin1String(QUALIFIED_NAME(f))) { // KoChart::Value* v = new KoChart::Value(KoChart::Value::SeriesLegendOrTrendlineName, KoChart::Value::CellRange, readElementText()); // m_currentSeriesData->m_datasetValue[v->m_dataId] = v; // } else if (qualifiedName() == QLatin1String(QUALIFIED_NAME(v))) { // KoChart::Value* v = new KoChart::Value(KoChart::Value::SeriesLegendOrTrendlineName, KoChart::Value::TextOrValue, readElementText()); // m_currentSeriesData->m_datasetValue[v->m_dataId] = v; // } // } break; case InRichText: // richtext means the title text // we extract the text from the richtext cause we cannot handle the richtext formattings anyway QString result; enum { Rich, Paragraph, TextRun } s; s = Rich; while (!atEnd()) { readNext(); switch(s) { case Rich: if (isStartElement() && qualifiedName() == QLatin1String("a:p")) s = Paragraph; break; case Paragraph: if (qualifiedName() == QLatin1String("a:r")) // text run s = isStartElement() ? TextRun : Rich; break; case TextRun: if (qualifiedName() == QLatin1String("a:t")) { if(isStartElement()) { if(!result.isEmpty()) result += ' '; //concat multiple strings into one result const QString text = readElementText(); result += text; m_context->m_chart->m_title = text; } else s = Paragraph; } break; } BREAK_IF_END_OF(rich) } if(!result.isEmpty()) m_context->m_chart->m_texts << new KoChart::Text(result); state = Start; break; } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL tx //! tx (Series Text) /*! ECMA-376, 21.2.2.215, p.3863. Parent elements: - ser §21.2.2.168 - ser §21.2.2.170 - ser §21.2.2.174 - ser §21.2.2.171 - ser §21.2.2.172 - ser §21.2.2.169 - ser §21.2.2.167 - ser §21.2.2.173 Child elements: - [Done]strRef (String Reference) §21.2.2.201 - v (Text Value) §21.2.2.223 */ /*! This element specifies text to use on a chart, including rich text formatting. */ KoFilter::ConversionStatus XlsxXmlChartReader::read_seriesText_Tx() { READ_PROLOGUE2(seriesText_Tx) d->m_currentStrRef = &d->m_currentTx->m_strRef; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(strRef) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL numCache //! numCache (Number Cache) /*! ECMA-376, 21.2.2.120, p.3813. Parent elements: - numRef (§21.2.2.123) Child elements: - extLst (Chart Extensibility) §21.2.2.64 - formatCode (Format Code) §21.2.2.71 - [Done]pt (Numeric Point) §21.2.2.150 - [Done]ptCount (Point Count) §21.2.2.152 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_numCache() { READ_PROLOGUE d->m_currentPtCount = &d->m_currentNumCache->m_ptCount; d->m_currentPtCache = &d->m_currentNumCache->m_cache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(ptCount) ELSE_TRY_READ_IF(pt) ELSE_TRY_READ_IF(formatCode) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL formatCode //! formatCode (Format Code) /*! ECMA-376, 21.2.2.71, p.3802. Parent elements: - - numCache (§21.2.2.120) + - numCache (§21.2.2.120) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_formatCode() { READ_PROLOGUE const QString val = readElementText(); d->m_currentNumCache->formatCode = val; // while (!atEnd()) { // readNext(); // BREAK_IF_END_OF(CURRENT_EL) // // } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL legend KoFilter::ConversionStatus XlsxXmlChartReader::read_legend() { READ_PROLOGUE if (!m_context->m_chart->m_legend) { m_context->m_chart->m_legend = new KoChart::Legend(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) //TODO } READ_EPILOGUE } void XlsxXmlChartReader::read_showDataLabel() { if ( m_currentSeries ) { const QXmlStreamAttributes attrs(attributes()); if ( qualifiedName() == "c:showVal" ) { m_currentSeries->m_showDataLabelValues = MSOOXML::Utils::convertBooleanAttr(attrs.value("val").toString(), true); } else if ( qualifiedName() == "c:showPercent" ) { m_currentSeries->m_showDataLabelPercent = MSOOXML::Utils::convertBooleanAttr(attrs.value("val").toString(), true); } else if ( qualifiedName() == "c:showCatName" ) { m_currentSeries->m_showDataLabelCategory = MSOOXML::Utils::convertBooleanAttr(attrs.value("val").toString(), true); } else if ( qualifiedName() == "c:showSerName" ) { m_currentSeries->m_showDataLabelSeries = MSOOXML::Utils::convertBooleanAttr(attrs.value("val").toString(), true); } } } #undef CURRENT_EL #define CURRENT_EL dLbl //! dLbl (Data Label) /*! ECMA-376, 21.2.2.47, p.3780. Parent elements: - dLbls (§21.2.2.49) - pivotFmt (§21.2.2.142) Child elements: - delete (Delete) §21.2.2.40 - dLblPos (Data Label Position) §21.2.2.48 - extLst (Chart Extensibility) §21.2.2.64 - idx (Index) §21.2.2.84 - layout (Layout) §21.2.2.88 - numFmt (Number Format) §21.2.2.121 - separator (Separator) §21.2.2.166 - showBubbleSize (Show Bubble Size) §21.2.2.178 - showCatName (Show Category Name) §21.2.2.179 - showLegendKey (Show Legend Key) §21.2.2.184 - showPercent (Show Percent) §21.2.2.187 - showSerName (Show Series Name) §21.2.2.188 - [Done]showVal (Show Value) §21.2.2.189 - spPr (Shape Properties) §21.2.2.197 - tx (Chart Text) §21.2.2.214 - txPr (Text Properties) §21.2.2.216 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_dLbl() { READ_PROLOGUE while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { read_showDataLabel(); } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL dLbls //! dLbls (Data Labels) /*! ECMA-376, 21.2.2.49, p.3781. Parent elements: - area3DChart (§21.2.2.4) - areaChart (§21.2.2.5) - bar3DChart (§21.2.2.15) - barChart (§21.2.2.16) - bubbleChart (§21.2.2.20) - doughnutChart (§21.2.2.50) - line3DChart (§21.2.2.96) - lineChart (§21.2.2.97) - ofPieChart (§21.2.2.126) - pie3DChart (§21.2.2.140) - pieChart (§21.2.2.141) - radarChart (§21.2.2.153) - scatterChart (§21.2.2.161) - ser (§21.2.2.168) - ser (§21.2.2.170) - ser (§21.2.2.174) - ser (§21.2.2.171) - ser (§21.2.2.172) - ser (§21.2.2.169) - ser (§21.2.2.167) - stockChart (§21.2.2.198) Child elements: - delete (Delete) §21.2.2.40 - [Done]dLbl (Data Label) §21.2.2.47 - dLblPos (Data Label Position) §21.2.2.48 - extLst (Chart Extensibility) §21.2.2.64 - leaderLines (Leader Lines) §21.2.2.92 - numFmt (Number Format) §21.2.2.121 - separator (Separator) §21.2.2.166 - showBubbleSize (Show Bubble Size) §21.2.2.178 - showCatName (Show Category Name) §21.2.2.179 - showLeaderLines (Show Leader Lines) §21.2.2.183 - showLegendKey (Show Legend Key) §21.2.2.184 - showPercent (Show Percent) §21.2.2.187 - showSerName (Show Series Name) §21.2.2.188 - [Done]showVal (Show Value) §21.2.2.189 - spPr (Shape Properties) §21.2.2.197 - txPr (Text Properties) §21.2.2.216 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_dLbls() { READ_PROLOGUE while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(dLbl) else if ( qualifiedName() == QLatin1String( QUALIFIED_NAME(numFmt) ) ) { const QXmlStreamAttributes attrs(attributes()); m_currentSeries->m_numberFormat = attrs.value("formatCode").toString(); } read_showDataLabel(); } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL spPr // Visual shape properties that can be applied to a shape. /*! * spPr Shape Properties * ECMA-376, 5.7.2.98, p.4108. * Parent Elements: * - backWall( §5.7.2.11 ) * - bandFmt( §5.7.2.13 ) * - catAx( §5.7.2.25 ) * - chartspace( §5.7.2.29 ) * - dataAx( §5.7.2.39 ) * - dispUnitsLbl( §5.7.2.46 ) * - dLbl( §5.7.2.47 ) * - dLbls( §5.7.2.49 ) * - downBars( §5.7.2.51) * - dPt( §5.7.2.52 ) * ... * * Child elements: * - blipFill( Picture Fill ) §5.1.10.14 * - customGeom( Custom Geometry ) §5.1.11.8 * - effectDag( Effect Container ) §5.1.10.25 * - effectLst( Effect Container ) §5.1.10.26 * - gradFill ( Gradient Fill ) §5.1.10.33 * - gradFill ( Group Fill ) §5.1.10.35 * - ln ( Outline ) §5.1.2.1.24 * - noFill( No Fill ) §5.1.10.44 * - pattFill( Pattern Fill ) §5.1.10.47 * - prstGeom( Preset geometry ) §5.1.11.18 * - scene3d ( 3D Scene Properties ) §5.1.4.1.26 * - solidFill( Solid Fill ) §5.1.10.54 * - sp3d ( Apply 3D shape properties ) §5.1.7.12 * - xrfm( 2D Transform for Individual Objects ) § 5.1.9.6 * * attributes: * - bwMode ( Black and White Mode ) §5.1.12.10 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_spPr() { enum State { Start, NoFill, InFill }; State state = Start; READ_PROLOGUE int level = 0; bool readingGradient = false; bool readingGradientStop = false; KoChart::Gradient* gradient = NULL; KoChart::Gradient::GradientStop currentStop; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if ( !m_currentShapeProperties ) continue; if(isStartElement()) ++level; else if(isEndElement()) --level; if (qualifiedName() == "a:solidFill" || qualifiedName() == "a:pattFill" || qualifiedName() == "a:gradFill") { if (level == 1) state = isStartElement() ? InFill : Start; } else if (qualifiedName() == "a:noFill") { m_currentShapeProperties->lineFill.setType( KoChart::Fill::None ); if (level == 1) state = isStartElement() ? NoFill : Start; } else if ((state == NoFill || state == InFill) && qualifiedName() == "a:srgbClr") { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if(!val.isEmpty() && !m_context->m_chart->m_areaFormat) { if(!val.startsWith('#')) val.prepend('#'); if ( readingGradientStop ) { currentStop.knownColorValue = QColor( val ); } else { KoChart::AreaFormat *areaFormat = new KoChart::AreaFormat(QColor(val), QColor(), state == InFill); if ( m_areaContext == ChartArea ) m_context->m_chart->m_areaFormat = areaFormat; else m_context->m_chart->m_plotArea->m_areaFormat = areaFormat; } } state = Start; // job done } else if ( qualifiedName() == "a:srgbClr" ) { if ( isStartElement() ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if(!val.isEmpty() && !m_context->m_chart->m_areaFormat) { if(!val.startsWith('#')) val.prepend('#'); if ( readingGradientStop ) { currentStop.knownColorValue = QColor( val ); } else { KoChart::AreaFormat *areaFormat = new KoChart::AreaFormat(QColor(val), QColor(), state == InFill); if ( m_areaContext == ChartArea ) { m_context->m_chart->m_areaFormat = areaFormat; } else { m_context->m_chart->m_plotArea->m_areaFormat = areaFormat; } } } } } else if ( qualifiedName() == "a:alpha" ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if ( !val.isEmpty() ) { if ( readingGradientStop ) { currentStop.knownColorValue.setAlphaF( val.toDouble() / 100000.0 ); } else { if ( m_areaContext == ChartArea ) { if ( m_context->m_chart->m_areaFormat ) m_context->m_chart->m_areaFormat->m_foreground.setAlphaF( val.toDouble() / 100000.0 ); } else { if ( m_context->m_chart->m_plotArea->m_areaFormat ) m_context->m_chart->m_plotArea->m_areaFormat->m_foreground.setAlphaF( val.toDouble() / 100000.0 ); } } } } else if ( qualifiedName() == "a:gsLst" ) { if ( isStartElement() ) { readingGradient = true; gradient = new KoChart::Gradient; } else if ( isEndElement() ) { readingGradient = false; switch ( m_areaContext ) { case( PlotArea ): m_context->m_chart->m_plotAreaFillGradient = gradient; break; case( ChartArea ): m_context->m_chart->m_fillGradient = gradient; break; } gradient = NULL; } } else if ( qualifiedName() == "a:gs" && readingGradient ) { if ( isStartElement() ) { readingGradientStop = true; const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(pos) if ( !pos.isEmpty() ) currentStop.position = pos.toDouble() / 1000.0; } else if ( isEndElement() ) { // append the current gradient stop gradient->gradientStops.append( currentStop ); readingGradientStop = false; currentStop.reset(); } } else if ( qualifiedName() == "a:schemeClr" && readingGradientStop ) { if ( isStartElement() ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if ( !val.isEmpty() ) currentStop.referenceColor = val; } else if ( isEndElement() ) { } } else if ( qualifiedName() == "a:tint" && readingGradientStop ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if ( !val.isEmpty() ) currentStop.tintVal = val.toDouble() / 1000.0; } else if ( qualifiedName() == "a:satMod" && readingGradientStop ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if ( !val.isEmpty() ) currentStop.satVal = val.toDouble() / 1000.0; } else if ( qualifiedName() == "a:lin" && readingGradient ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(ang) if ( !ang.isEmpty() ) gradient->angle = ang.toDouble() / 60000.0; } else if ( qualifiedName() == "a:noFill" ) { m_currentShapeProperties->lineFill.setType( KoChart::Fill::None ); } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL pieChart //! pieChart (Pie Charts) /*! ECMA-376, 21.2.2.141, p.3826. Parent elements: - plotArea §21.2.2.145 Child elements: - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - [Done]firstSliceAng (First Slice Angle) §21.2.2.68 - [Done] ser (Pie Chart Series) §21.2.2.172 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_pieChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::PieImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(pieChart_Ser) } ELSE_TRY_READ_IF(firstSliceAng) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL pie3DChart //! pie3DChart (3D Pie Charts) /*! ECMA-376, 21.2.2.140, p.3826. Parent elements: - plotArea §21.2.2.145 Child elements: - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - [Done] ser (Pie Chart Series) §21.2.2.172 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_pie3DChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::PieImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(pieChart_Ser) } } } // // if there is only one c:ser, then c:tx can be chart title // if ((m_context->m_chart->m_title == "Chart Title") && (d->m_seriesData.size() == 1)) { // PieSeries * tempPieSeriesData = (PieSeries *)d->m_seriesData[0]; // if (tempPieSeriesData->m_tx.m_strRef.m_strCache.m_cache.size() == 1) { // m_context->m_chart->m_title = tempPieSeriesData->m_tx.m_strRef.m_strCache.m_cache[0]; // } // } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL ofPieChart //! ofPieChart (Pie of Pie or Bar of Pie Charts) /*! ECMA-376, §21.2.2.126, p.4057. Parent elements: - plotArea §21.2.2.145 Child elements: - - custSplit (Custom Split) §5.7.2.35 - - dLbls (Data Labels) §5.7.2.49 - - extLst (Chart Extensibility) §5.7.2.64 - - gapWidth (Gap Width) §5.7.2.75 - - ofPieType (Pie of Pie or Bar of Pie Type) §5.7.2.128 - - secondPieSize (Second Pie Size) §5.7.2.165 - - ser (Pie Chart Series) §5.7.2.170 - - serLines (Series Lines) §5.7.2.177 - - splitPos (Split Position) §5.7.2.196 - - splitType (Split Type) §5.7.2.197 - - varyColors (Vary Colors by Point) §5.7.2.228 + - custSplit (Custom Split) §5.7.2.35 + - dLbls (Data Labels) §5.7.2.49 + - extLst (Chart Extensibility) §5.7.2.64 + - gapWidth (Gap Width) §5.7.2.75 + - ofPieType (Pie of Pie or Bar of Pie Type) §5.7.2.128 + - secondPieSize (Second Pie Size) §5.7.2.165 + - ser (Pie Chart Series) §5.7.2.170 + - serLines (Series Lines) §5.7.2.177 + - splitPos (Split Position) §5.7.2.196 + - splitType (Split Type) §5.7.2.197 + - varyColors (Vary Colors by Point) §5.7.2.228 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_ofPieChart() { // KDChart used in the charting-plugin doesn't support pie-of-pie or bar-of-pie // charts nor does ODF. So, we do the same OO.org is doing and just translate // it to pie-chart what is better then nothing. if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::PieImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(pieChart_Ser) } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL doughnutChart //! doughnutChart (Doughnut Charts) /*! ECMA-376, 21.2.2.50, p.3782. Parent elements: - plotArea §21.2.2.145 Child elements: - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - firstSliceAng (First Slice Angle) §21.2.2.68 - [Done]holeSize (Hole Size) §21.2.2.82 - [Done]ser (Pie Chart Series) §21.2.2.172 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_doughnutChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::RingImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(pieChart_Ser) } ELSE_TRY_READ_IF(holeSize) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL areaChart //! areaChart (Area Charts) /*! ECMA-376, 21.2.2.5, p.3757. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - dropLines (Drop Lines) §21.2.2.53 - extLst (Chart Extensibility) §21.2.2.64 - [done] grouping (Grouping) §21.2.2.76 - [Done] ser (Area Chart Series) §21.2.2.168 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_areaChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::AreaImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(areaChart_Ser) } ELSE_TRY_READ_IF(grouping) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL area3DChart //! area3DChart (3D Area Charts) /*! ECMA-376, 21.2.2.4, p.3757. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - dropLines (Drop Lines) §21.2.2.53 - extLst (Chart Extensibility) §21.2.2.64 - gapDepth (Gap Depth) §21.2.2.74 - [done] grouping (Grouping) §21.2.2.76 - [Done] ser (Area Chart Series) §21.2.2.168 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_area3DChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::AreaImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(areaChart_Ser) } ELSE_TRY_READ_IF(grouping) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL barChart //! barChart (Bar Charts) /*! ECMA-376, 21.2.2.16, p.3863. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - [Done]barDir (Bar Direction) §21.2.2.17 - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - gapWidth (Gap Width) §21.2.2.75 - [Done]grouping (Bar Grouping) §21.2.2.77 - overlap (Overlap) §21.2.2.131 - [Done]ser (Bar Chart Series) §21.2.2.170 - serLines (Series Lines) §21.2.2.176 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_barChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::BarImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(barChart_Ser) } ELSE_TRY_READ_IF(barDir) ELSE_TRY_READ_IF(grouping) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL bar3DChart //! bar3DChart (3D Bar Charts) /*! ECMA-376, 21.2.2.15, p.3862. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - [done]barDir (Bar Direction) §21.2.2.17 - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - gapDepth (Gap Depth) §21.2.2.74 - gapWidth (Gap Width) §21.2.2.75 - [Done]grouping (Bar Grouping) §21.2.2.77 - [Done]ser (Bar Chart Series) §21.2.2.170 - shape (Shape) §21.2.2.177 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bar3DChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::BarImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(barChart_Ser) } ELSE_TRY_READ_IF(barDir) ELSE_TRY_READ_IF(grouping) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL lineChart //! lineChart (Line Charts) /*! ECMA-376, 21.2.2.97, p.3804. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - dropLines (Drop Lines) §21.2.2.53 - extLst (Chart Extensibility) §21.2.2.64 - [Done]grouping (Grouping) §21.2.2.76 - hiLowLines (High Low Lines) §21.2.2.80 - marker (Show Marker) §21.2.2.105 - [Done]ser (Line Chart Series) §21.2.2.171 - smooth (Smoothing) §21.2.2.194 - upDownBars (Up/Down Bars) §21.2.2.218 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_lineChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::LineImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(lineChart_Ser) } ELSE_TRY_READ_IF(grouping) ELSE_TRY_READ_IF(marker) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL line3DChart //! line3DChart (3D Line Charts) /*! ECMA-376, 21.2.2.96, p.3803. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - dropLines (Drop Lines) §21.2.2.53 - extLst (Chart Extensibility) §21.2.2.64 - gapDepth (Gap Depth) §21.2.2.74 - [Done]grouping (Grouping) §21.2.2.76 - [Done]ser (Line Chart Series) §21.2.2.171 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_line3DChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::LineImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(lineChart_Ser) } ELSE_TRY_READ_IF(grouping) } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL scatterChart //! scatterChart (Scatter Charts) /*! ECMA-376, 21.2.2.161, p.3836. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - scatterStyle (Scatter Style) §21.2.2.162 - [Done]ser (Scatter Chart Series) §21.2.2.167 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_scatterChart() { KoChart::ScatterImpl* impl = dynamic_cast(m_context->m_chart->m_impl); if (!impl) { m_context->m_chart->m_impl = impl = new KoChart::ScatterImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(scatterChart_Ser) } else if (QUALIFIED_NAME_IS(scatterStyle)) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val); if ( val == "none" ) impl->style = KoChart::ScatterImpl::None; else if ( val == "line" ) impl->style = KoChart::ScatterImpl::Line; else if ( val == "lineMarker" ) impl->style = KoChart::ScatterImpl::LineMarker; else if ( val == "marker" ) impl->style = KoChart::ScatterImpl::Marker; else if ( val == "smooth" ) impl->style = KoChart::ScatterImpl::Smooth; else if ( val == "smoothMarker" ) impl->style = KoChart::ScatterImpl::SmoothMarker; } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL radarChart //! radarChart (Radar Charts) /*! ECMA-376, 21.2.2.153, p.3832. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - radarStyle (Radar Style) §21.2.2.154 - [Done]ser (Radar Chart Series) §21.2.2.169 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_radarChart() { KoChart::RadarImpl* impl = dynamic_cast(m_context->m_chart->m_impl); if (!impl) { m_context->m_chart->m_impl = impl = new KoChart::RadarImpl(false); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(radarStyle)) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if (val == "filled") impl->m_filled = true; } else if (QUALIFIED_NAME_IS(ser)) { TRY_READ(radarChart_Ser) } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL surfaceChart //! surface3DChart (3D Surface Charts) /*! ECMA-376, 21.2.2.203, p.3858. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - bandFmts (Band Formats) §21.2.2.14 - extLst (Chart Extensibility) §21.2.2.64 - [Done]ser (Surface Chart Series) §21.2.2.173 - wireframe (Wireframe) §21.2.2.230 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_surfaceChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::SurfaceImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(surfaceChart_Ser) } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL surface3DChart //! surfaceChart (Surface Charts) /*! ECMA-376, 21.2.2.204, p.3858. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - bandFmts (Band Formats) §21.2.2.14 - extLst (Chart Extensibility) §21.2.2.64 - ser (Surface Chart Series) §21.2.2.173 - wireframe (Wireframe) §21.2.2.230 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_surface3DChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::SurfaceImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(surfaceChart_Ser) } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL bubbleChart //! bubbleChart (Bubble Charts) /*! ECMA-376, 21.2.2.20, p.3765. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - [Done]bubble3D (3D Bubble) §21.2.2.19 - [Done]bubbleScale (Bubble Scale) §21.2.2.21 - dLbls (Data Labels) §21.2.2.49 - extLst (Chart Extensibility) §21.2.2.64 - [Done]ser (Bubble Chart Series) §21.2.2.174 - showNegBubbles (Show Negative Bubbles) §21.2.2.185 - sizeRepresents (Size Represents) §21.2.2.193 - varyColors (Vary Colors by Point) §21.2.2.227 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bubbleChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::BubbleImpl(); m_context->m_chart->m_is3d = true; } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(bubbleChart_Ser) } ELSE_TRY_READ_IF(bubbleScale) ELSE_TRY_READ_IF(bubble3D) } } // check if there are some c:strLit or c:numLit data and if yes then write them into internalTable // for (int i=0; im_seriesData.size(); i++ ){ // QString range = ((BubbleSeries *)d->m_seriesData[i])->m_bubbleSize.writeLitToInternalTable(this); // if (!range.isEmpty()) { // m_context->m_chart->m_series[i]->m_domainValuesCellRangeAddress.push_back(range); // } // } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL stockChart //! stockChart (Stock Charts) /*! ECMA-376, 21.2.2.199, p.3856. Parent elements: - plotArea §21.2.2.145 Child elements: - axId (Axis ID) §21.2.2.9 - dLbls (Data Labels) §21.2.2.49 - dropLines (Drop Lines) §21.2.2.53 - extLst (Chart Extensibility) §21.2.2.64 - hiLowLines (High Low Lines) §21.2.2.80 - [done]ser (Line Chart Series) §21.2.2.171 - upDownBars (Up/Down Bars) §21.2.2.218 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_stockChart() { if(!m_context->m_chart->m_impl) { m_context->m_chart->m_impl = new KoChart::StockImpl(); } while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(ser)) { TRY_READ(lineChart_Ser) } } } qDeleteAll(d->m_seriesData); d->m_seriesData.clear(); return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Pie Chart Series) /*! ECMA-376, 21.2.2.172, p.3842. Parent elements: - doughnutChart §21.2.2.50 - ofPieChart §21.2.2.126 - pie3DChart §21.2.2.140 - pieChart §21.2.2.141 Child elements: - cat (Category Axis Data) §21.2.2.24 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - explosion (Explosion) §21.2.2.61 - extLst (Chart Extensibility) §21.2.2.64 - [Done]idx (Index) §21.2.2.84 - [Done] order (Order) §21.2.2.128 - spPr (Shape Properties) §21.2.2.197 - tx (Series Text) §21.2.2.215 - val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_pieChart_Ser() { READ_PROLOGUE2(pieChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; PieSeries * tempPieSeriesData = new PieSeries(); d->m_seriesData << tempPieSeriesData; d->m_currentIdx = &tempPieSeriesData->m_idx; d->m_currentOrder = &tempPieSeriesData->m_order; d->m_currentTx = &tempPieSeriesData->m_tx; d->m_currentCat = &tempPieSeriesData->m_cat; d->m_currentVal = &tempPieSeriesData->m_val; d->m_currentExplosion = &tempPieSeriesData->m_explosion; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) ELSE_TRY_READ_IF(explosion) ELSE_TRY_READ_IF(dLbls) } } // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempPieSeriesData->m_val.m_numRef.m_numCache.m_ptCount; if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempPieSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempPieSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; m_currentSeries->m_labelCell = tempPieSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempPieSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempPieSeriesData->m_cat.writeRefToInternalTable(this); // set explosion if (tempPieSeriesData->m_explosion != 0) { if(KoChart::PieImpl* pie = dynamic_cast(m_context->m_chart->m_impl)) { Q_UNUSED(pie); m_currentSeries->m_datasetFormat << new KoChart::PieFormat(tempPieSeriesData->m_explosion); } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Bubble Chart Series) /*! ECMA-376, 21.2.2.174, p.3843. Parent elements: - ser (Bubble Chart Series) Child elements: - [Done]bubble3D (3D Bubble) §21.2.2.19 - [Done]bubbleSize (Bubble Size) §21.2.2.22 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - errBars (Error Bars) §21.2.2.55 - extLst (Chart Extensibility) §21.2.2.64 - [Done]idx (Index) §21.2.2.84 - invertIfNegative (Invert if Negative) §21.2.2.86 - [Done]order (Order) §21.2.2.128 - spPr (Shape Properties) §21.2.2.197 - trendline (Trendlines) §21.2.2.211 - [Done]tx (Series Text) §21.2.2.215 - [Done]xVal (X Values) §21.2.2.234 - [Done]yVal (Y Values) §21.2.2.237 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bubbleChart_Ser() { READ_PROLOGUE2(bubbleChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; BubbleSeries * tempBubbleSeriesData = new BubbleSeries(); d->m_seriesData << tempBubbleSeriesData; d->m_currentIdx = &tempBubbleSeriesData->m_idx; d->m_currentOrder = &tempBubbleSeriesData->m_order; d->m_currentTx = &tempBubbleSeriesData->m_tx; d->m_currentXVal = &tempBubbleSeriesData->m_xVal; d->m_currentYVal = &tempBubbleSeriesData->m_yVal; d->m_currentBubbleSize = &tempBubbleSeriesData->m_bubbleSize; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(xVal) ELSE_TRY_READ_IF(yVal) ELSE_TRY_READ_IF(bubbleSize) ELSE_TRY_READ_IF(dLbls) ELSE_TRY_READ_IF(bubble3D) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempBubbleSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempBubbleSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_labelCell = tempBubbleSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_countYValues = tempBubbleSeriesData->m_yVal.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_domainValuesCellRangeAddress << tempBubbleSeriesData->m_yVal.writeRefToInternalTable(this); if ( tempBubbleSeriesData->m_bubbleSize.m_numRef.m_f.isEmpty() ) m_currentSeries->m_valuesCellRangeAddress = tempBubbleSeriesData->m_bubbleSize.writeLitToInternalTable(this); else m_currentSeries->m_valuesCellRangeAddress = tempBubbleSeriesData->m_bubbleSize.writeRefToInternalTable(this); // m_currentSeries->m_domainValuesCellRangeAddress.push_back(tempBubbleSeriesData->m_xVal.writeRefToInternalTable(this)); // // QString bubbleSizeRange = tempBubbleSeriesData->m_bubbleSize.writeRefToInternalTable(this); // if (!bubbleSizeRange.isEmpty()) { // m_currentSeries->m_domainValuesCellRangeAddress.push_back(tempBubbleSeriesData->m_bubbleSize.writeRefToInternalTable(this)); // } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Scatter Chart Series) /*! ECMA-376, 21.2.2.167, p.3838. Parent elements: - scatterChart (§21.2.2.161) Child elements: - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - errBars (Error Bars) §21.2.2.55 - extLst (Chart Extensibility) §21.2.2.64 - [done] idx (Index) §21.2.2.84 - marker (Marker) §21.2.2.106 - [Done] order (Order) §21.2.2.128 - smooth (Smoothing) §21.2.2.194 - spPr (Shape Properties) §21.2.2.197 - trendline (Trendlines) §21.2.2.211 - [Done] tx (Series Text) §21.2.2.215 - [Done] xVal (X Values) §21.2.2.234 - [Done] yVal (Y Values) §21.2.2.237 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_scatterChart_Ser() { READ_PROLOGUE2(scatterChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; ScatterSeries * tempScatterSeriesData = new ScatterSeries(); d->m_seriesData << tempScatterSeriesData; d->m_currentIdx = &tempScatterSeriesData->m_idx; d->m_currentOrder = &tempScatterSeriesData->m_order; d->m_currentTx = &tempScatterSeriesData->m_tx; d->m_currentXVal = &tempScatterSeriesData->m_xVal; d->m_currentYVal = &tempScatterSeriesData->m_yVal; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if (QUALIFIED_NAME_IS(spPr) ) { m_currentSeries->spPr = new KoChart::ShapeProperties; m_currentShapeProperties = m_currentSeries->spPr; } ELSE_TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(xVal) ELSE_TRY_READ_IF(yVal) ELSE_TRY_READ_IF(dLbls) ELSE_TRY_READ_IF(spPr) // ELSE_TRY_READ_IF(spPr) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempScatterSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempScatterSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_labelCell = tempScatterSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_countXValues = tempScatterSeriesData->m_xVal.m_numLit.m_ptCount; if (m_currentSeries->m_countXValues == 0 ) { m_currentSeries->m_countXValues = tempScatterSeriesData->m_xVal.m_strRef.m_strCache.m_ptCount; m_currentSeries->m_domainValuesCellRangeAddress << tempScatterSeriesData->m_xVal.writeRefToInternalTable(this); } else { m_currentSeries->m_domainValuesCellRangeAddress << tempScatterSeriesData->m_xVal.writeLitToInternalTable(this); } m_currentSeries->m_countYValues = tempScatterSeriesData->m_yVal.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_valuesCellRangeAddress = tempScatterSeriesData->m_yVal.writeRefToInternalTable(this); //m_currentSeries->m_domainValuesCellRangeAddress.push_back(tempScatterSeriesData->m_xVal.writeRefToInternalTable(this)); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Bar Chart Series) /*! ECMA-376, 21.2.2.167, p.3840. Parent elements: - bar3DChart (§21.2.2.15) - barChart (§21.2.2.16) Child elements: - [Done]cat (Category Axis Data) §21.2.2.24 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - errBars (Error Bars) §21.2.2.55 - extLst (Chart Extensibility) §21.2.2.64 - idx (Index) §21.2.2.84 - invertIfNegative (Invert if Negative) §21.2.2.86 - order (Order) §21.2.2.128 - pictureOptions (Picture Options) §21.2.2.138 - shape (Shape) §21.2.2.177 - spPr (Shape Properties) §21.2.2.197 - trendline (Trendlines) §21.2.2.211 - [Done]tx (Series Text) §21.2.2.215 - [Done]val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_barChart_Ser() { READ_PROLOGUE2(barChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; BarSeries * tempBarSeriesData = new BarSeries(); d->m_seriesData << tempBarSeriesData; d->m_currentIdx = &tempBarSeriesData->m_idx; d->m_currentOrder = &tempBarSeriesData->m_order; d->m_currentTx = &tempBarSeriesData->m_tx; d->m_currentCat = &tempBarSeriesData->m_cat; d->m_currentVal = &tempBarSeriesData->m_val; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) else if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) ELSE_TRY_READ_IF(dLbls) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempBarSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempBarSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempBarSeriesData->m_val.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_labelCell = tempBarSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempBarSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempBarSeriesData->m_cat.writeRefToInternalTable(this); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Area Chart Series) /*! ECMA-376, 21.2.2.168, p.3839. Parent elements: - area3DChart (§21.2.2.4) - areaChart (§21.2.2.5) Child elements: - cat (Category Axis Data) §21.2.2.24 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - errBars (Error Bars) §21.2.2.55 - extLst (Chart Extensibility) §21.2.2.64 - idx (Index) §21.2.2.84 - order (Order) §21.2.2.128 - pictureOptions (Picture Options) §21.2.2.138 - spPr (Shape Properties) §21.2.2.197 - trendline (Trendlines) §21.2.2.211 - tx (Series Text) §21.2.2.215 - val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_areaChart_Ser() { READ_PROLOGUE2(areaChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; AreaSeries * tempAreaSeriesData = new AreaSeries(); d->m_seriesData << tempAreaSeriesData; d->m_currentIdx = &tempAreaSeriesData->m_idx; d->m_currentOrder = &tempAreaSeriesData->m_order; d->m_currentTx = &tempAreaSeriesData->m_tx; d->m_currentCat = &tempAreaSeriesData->m_cat; d->m_currentVal = &tempAreaSeriesData->m_val; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) else if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) ELSE_TRY_READ_IF(dLbls) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempAreaSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempAreaSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempAreaSeriesData->m_val.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_labelCell = tempAreaSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempAreaSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempAreaSeriesData->m_cat.writeRefToInternalTable(this); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Radar Chart Series) /*! ECMA-376, 21.2.2.169, p.3840. Parent elements: - radarChart (§21.2.2.153) Child elements: - [Done]cat (Category Axis Data) §21.2.2.24 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - extLst (Chart Extensibility) §21.2.2.64 - [Done]idx (Index) §21.2.2.84 - marker (Marker) §21.2.2.106 - [Done]order (Order) §21.2.2.128 - spPr (Shape Properties) §21.2.2.197 - [Done]tx (Series Text) §21.2.2.215 - [Done]val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_radarChart_Ser() { READ_PROLOGUE2(radarChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; RadarSeries * tempRadarSeriesData = new RadarSeries(); d->m_seriesData << tempRadarSeriesData; d->m_currentIdx = &tempRadarSeriesData->m_idx; d->m_currentOrder = &tempRadarSeriesData->m_order; d->m_currentTx = &tempRadarSeriesData->m_tx; d->m_currentCat = &tempRadarSeriesData->m_cat; d->m_currentVal = &tempRadarSeriesData->m_val; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) else if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) ELSE_TRY_READ_IF(dLbls) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempRadarSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempRadarSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempRadarSeriesData->m_val.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_labelCell = tempRadarSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempRadarSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempRadarSeriesData->m_cat.writeRefToInternalTable(this); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Line Chart Series) /*! ECMA-376, 21.2.2.168, p.3839. Parent elements: - line3DChart (§21.2.2.96) - lineChart (§21.2.2.97) - stockChart (§21.2.2.198) Child elements: - [Done]cat (Category Axis Data) §21.2.2.24 - [Done]dLbls (Data Labels) §21.2.2.49 - dPt (Data Point) §21.2.2.52 - errBars (Error Bars) §21.2.2.55 - extLst (Chart Extensibility) §21.2.2.64 - [Done]idx (Index) §21.2.2.84 - marker (Marker) §21.2.2.106 - [Done]order (Order) §21.2.2.128 - smooth (Smoothing) §21.2.2.194 - spPr (Shape Properties) §21.2.2.197 - trendline (Trendlines) §21.2.2.211 - [Done]tx (Series Text) §21.2.2.215 - [Done]val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_lineChart_Ser() { READ_PROLOGUE2(lineChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; LineSeries * tempLineSeriesData = new LineSeries(); d->m_seriesData << tempLineSeriesData; d->m_currentIdx = &tempLineSeriesData->m_idx; d->m_currentOrder = &tempLineSeriesData->m_order; d->m_currentTx = &tempLineSeriesData->m_tx; d->m_currentCat = &tempLineSeriesData->m_cat; d->m_currentVal = &tempLineSeriesData->m_val; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) else if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } else if (QUALIFIED_NAME_IS(marker)) { TRY_READ(serMarker) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) ELSE_TRY_READ_IF(dLbls) } } if ( !m_autoTitleDeleted && m_context->m_chart->m_title.isEmpty() && m_context->m_chart->m_series.count() == 1 && !tempLineSeriesData->m_tx.m_strRef.m_strCache.m_cache.isEmpty() ) m_context->m_chart->m_title = tempLineSeriesData->m_tx.m_strRef.m_strCache.m_cache[ 0 ]; // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempLineSeriesData->m_val.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_labelCell = tempLineSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempLineSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempLineSeriesData->m_cat.writeRefToInternalTable(this); READ_EPILOGUE } KoChart::MarkerType markerType(const QString &_val) { const QString val = _val.toLower(); if ( val == "star" ) return KoChart::StarMarker; if ( val == "dash" ) return KoChart::DashMarker; if ( val == "dot" ) return KoChart::DotMarker; if ( val == "plus" ) return KoChart::PlusMarker; if ( val == "circle" ) return KoChart::CircleMarker; if ( val == "x" ) return KoChart::SymbolXMarker; if ( val == "triangle" ) return KoChart::TriangleMarker; if ( val == "squre" ) return KoChart::SquareMarker; if ( val == "diamond" ) return KoChart::DiamondMarker; return KoChart::NoMarker; } #undef CURRENT_EL #define CURRENT_EL marker KoFilter::ConversionStatus XlsxXmlChartReader::read_marker() { READ_PROLOGUE bool gotSymbol = m_serMarkerDefined; const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if ( !gotSymbol && qualifiedName() == "c:symbol" ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val); m_context->m_chart->m_markerType = markerType(val); gotSymbol = true; } } } if (!gotSymbol) if (MSOOXML::Utils::convertBooleanAttr(val, true)) m_context->m_chart->m_markerType = KoChart::AutoMarker; READ_EPILOGUE return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL marker KoFilter::ConversionStatus XlsxXmlChartReader::read_serMarker() { READ_PROLOGUE2( serMarker ) m_serMarkerDefined = true; bool gotSymbol = false; const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { if ( qualifiedName() == "c:symbol" ) { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val); m_currentSeries->m_markerType = markerType(val); gotSymbol = true; } } } if (!gotSymbol) if (MSOOXML::Utils::convertBooleanAttr(val, true)) m_currentSeries->m_markerType = KoChart::AutoMarker; READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ser //! ser (Surface Chart Series) /*! ECMA-376, 21.2.2.169, p.3840. Parent elements: - surface3DChart (§21.2.2.203) - surfaceChart (§21.2.2.204) Child elements: - [Done]cat (Category Axis Data) §21.2.2.24 - extLst (Chart Extensibility) §21.2.2.64 - [Done]idx (Index) §21.2.2.84 - marker (Marker) §21.2.2.106 - [Done]order (Order) §21.2.2.128 - spPr (Shape Properties) §21.2.2.197 - [Done]tx (Series Text) §21.2.2.215 - [Done]val (Values) §21.2.2.224 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_surfaceChart_Ser() { READ_PROLOGUE2(surfaceChart_Ser) m_currentSeries = new KoChart::Series(); m_context->m_chart->m_series << m_currentSeries; SurfaceSeries * tempSurfaceSeriesData = new SurfaceSeries(); d->m_seriesData << tempSurfaceSeriesData; d->m_currentIdx = &tempSurfaceSeriesData->m_idx; d->m_currentOrder = &tempSurfaceSeriesData->m_order; d->m_currentTx = &tempSurfaceSeriesData->m_tx; d->m_currentCat = &tempSurfaceSeriesData->m_cat; d->m_currentVal = &tempSurfaceSeriesData->m_val; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(order) ELSE_TRY_READ_IF(idx) else if (QUALIFIED_NAME_IS(tx)) { TRY_READ(seriesText_Tx) } ELSE_TRY_READ_IF(cat) ELSE_TRY_READ_IF(val) } } // set data ranges and write data to internal table m_currentSeries->m_countYValues = tempSurfaceSeriesData->m_val.m_numRef.m_numCache.m_ptCount; m_currentSeries->m_labelCell = tempSurfaceSeriesData->m_tx.writeRefToInternalTable(this); m_currentSeries->m_valuesCellRangeAddress = tempSurfaceSeriesData->m_val.writeRefToInternalTable(this); m_context->m_chart->m_verticalCellRangeAddress = tempSurfaceSeriesData->m_cat.writeRefToInternalTable(this); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL barDir //! barDir (Bar Direction) /*! ECMA-376, 21.2.2.17, p.3763. Parent elements: - bar3DChart (§21.2.2.15) - barChart (§21.2.2.16) Attributes: - [Done] val (Bar Direction Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_barDir() { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) m_context->m_chart->m_transpose = (val == "bar"); // "bar" or "col" while (!atEnd()) { BREAK_IF_END_OF(CURRENT_EL) readNext(); } return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL grouping //! grouping (Bar Grouping) /*! ECMA-376, 21.2.2.77, p.3794. Parent elements: - bar3DChart (§21.2.2.15) - barChart (§21.2.2.16) Attributes: - [Done] val (Bar Grouping Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_grouping() { const QXmlStreamAttributes attrs(attributes()); TRY_READ_ATTR_WITHOUT_NS(val) if(val == "stacked") { m_context->m_chart->m_stacked = true; } else if(val == "percentStacked") { m_context->m_chart->m_stacked = true; m_context->m_chart->m_f100 = true; } else if(val == "clustered") { //TODO } // else if(val == "standard") is not needed cause that's the default anyway while (!atEnd()) { BREAK_IF_END_OF(CURRENT_EL) readNext(); } return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL firstSliceAng //! firstSliceAng (First Slice Angle) /*! ECMA-376, 21.2.2.68, p.3790. Parent elements: - doughnutChart (§21.2.2.50) - pieChart (§21.2.2.141) Child elements: - val (First Slice Angle Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_firstSliceAng() { if(KoChart::PieImpl* pie = dynamic_cast(m_context->m_chart->m_impl)) { const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); pie->m_anStart = val.toInt(); // default value is zero } while (!atEnd()) { BREAK_IF_END_OF(CURRENT_EL) readNext(); } return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL holeSize //! holeSize (Hole Size) /*! ECMA-376, 21.2.2.82, p.3797. Parent elements: - doughnutChart (§21.2.2.50) Child elements: - val (Hole Size Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_holeSize() { if(KoChart::RingImpl* ring = dynamic_cast(m_context->m_chart->m_impl)) { const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); ring->m_pcDonut = val.toInt(); // default value is zero } while (!atEnd()) { BREAK_IF_END_OF(CURRENT_EL) readNext(); } return KoFilter::OK; } #undef CURRENT_EL #define CURRENT_EL bubbleSize //! bubbleSize (Bubble Size) /*! ECMA-376, 21.2.2.22, p.3876. Parent elements: - ser §21.2.2.174 Child elements: - [done] numLit (Number Literal) §21.2.2.122 - [done] numRef (Number Reference) §21.2.2.123 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bubbleSize() { READ_PROLOGUE d->m_currentNumRef = &d->m_currentBubbleSize->m_numRef; d->m_currentNumLit = &d->m_currentBubbleSize->m_numLit; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(numRef) ELSE_TRY_READ_IF(numLit) ELSE_WRONG_FORMAT } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL bubbleScale //! bubbleScale (Bubble Scale) /*! ECMA-376, 21.2.2.21, p.3765. Parent elements: - bubbleChart (§21.2.2.20) Attributes: - [Done] val (Bubble Scale Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bubbleScale() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); if(KoChart::BubbleImpl* bubble = dynamic_cast(m_context->m_chart->m_impl)) { bool ok; const int i = val.toInt(&ok); if(ok) bubble->m_sizeRatio = i; } readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL bubble3D //! bubble3D (3D Bubble) /*! ECMA-376, 21.2.2.21, p.3765. Parent elements: - bubbleChart (§21.2.2.20) - dPt (§21.2.2.52) - ser (§21.2.2.174) Attributes: - [Done] val (Boolean Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_bubble3D() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); m_context->m_chart->m_is3d = val.toInt(); readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL numLit //! numLit (Number Literal) /*! ECMA-376, 21.2.2.122, p.3815. Parent elements: - bubbleSize (§21.2.2.22) - cat (§21.2.2.24) - minus (§21.2.2.113) - plus (§21.2.2.147) - val (§21.2.2.224) - xVal(§21.2.2.234) - yVal (§21.2.2.237) Child elements: - extLst (Chart Extensibility) §21.2.2.64 - formatCode (Format Code) §21.2.2.71 - [Done]pt (Numeric Point) §21.2.2.150 - [Done]ptCount (Point Count) §21.2.2.152 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_numLit() { READ_PROLOGUE d->m_currentPtCount = &d->m_currentNumLit->m_ptCount; d->m_currentPtCache = &d->m_currentNumLit->m_cache; while ( !atEnd() ) { readNext(); BREAK_IF_END_OF( CURRENT_EL ) if ( isStartElement() ) { TRY_READ_IF(ptCount) ELSE_TRY_READ_IF(pt) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL pt //! pt (String Point) /*! ECMA-376, 21.2.2.151, p.3831. Parent elements: - lvl (§21.2.2.99) - strCache (§21.2.2.199) - strLit (§21.2.2.200) Child elements: - [Done]v (Text Value) Attributes: - idx (Index) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_pt() { READ_PROLOGUE while ( !atEnd() ) { readNext(); BREAK_IF_END_OF( CURRENT_EL ) if ( isStartElement() ) { if ( qualifiedName() == QLatin1String( QUALIFIED_NAME( v ) ) ) { d->m_currentPtCache->append(readElementText()); } } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL order //! order (Order) /*! ECMA-376, 21.2.2.128, p.3817. Parent elements: - ser §21.2.2.168 - ser §21.2.2.170 - ser §21.2.2.174 - ser §21.2.2.171 - ser §21.2.2.172 - ser §21.2.2.169 - ser §21.2.2.167 - ser §21.2.2.173 Attributes: - [Done] val (Integer Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_order() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); *d->m_currentOrder = val.toInt(); readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL idx //! idx (Index) /*! ECMA-376, 21.2.2.84, p.3798. Parent elements: - bandFmt (§21.2.2.13) - dLbl (§21.2.2.47) - dPt (§21.2.2.52) - legendEntry (§21.2.2.94) - pivotFmt (§21.2.2.142) - ser §21.2.2.168 - ser §21.2.2.170 - ser §21.2.2.174 - ser §21.2.2.171 - ser §21.2.2.172 - ser §21.2.2.169 - ser §21.2.2.167 - ser §21.2.2.173 Attributes: - [Done] val (Integer Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_idx() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); *d->m_currentIdx = val.toInt(); readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL explosion //! explosion (Explosion) /*! ECMA-376, 21.2.2.61, p.3787. Parent elements: - dPt (§21.2.2.52) - ser (§21.2.2.172) Attributes: - [Done] val (Integer Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_explosion() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); *d->m_currentExplosion = val.toInt(); readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL strRef //! strRef (String Reference) /*! ECMA-376, 21.2.2.201, p.3857. Parent elements: - cat (§21.2.2.24) - tx (§21.2.2.215) - tx (§21.2.2.214) - xVal (§21.2.2.234) Child elements: - extLst (Chart Extensibility) §21.2.2.64 - [Done] f (Formula) §21.2.2.65 - [Done] strCache (String Cache) §21.2.2.199 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_strRef() { READ_PROLOGUE d->m_currentF = &d->m_currentStrRef->m_f; d->m_currentStrCache = &d->m_currentStrRef->m_strCache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(f) ELSE_TRY_READ_IF(strCache) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL multiLvlStrRef //! multiLvlStrRef (Multi Level String Reference) /*! ECMA-376, 5.7.2.116, p.4060 Parent Elements: - - cat (§5.7.2.24); xVal (§5.7.2.235) + - cat (§5.7.2.24); xVal (§5.7.2.235) Child Elements: - - extLst (Chart Extensibility) §5.7.2.64 - - f (Formula) §5.7.2.65 - - multiLvlStrCache (Multi Level String Cache) §5.7.2.115 + - extLst (Chart Extensibility) §5.7.2.64 + - f (Formula) §5.7.2.65 + - multiLvlStrCache (Multi Level String Cache) §5.7.2.115 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_multiLvlStrRef() { READ_PROLOGUE d->m_currentF = &d->m_currentStrRef->m_f; d->m_currentStrCache = &d->m_currentStrRef->m_strCache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(f) ELSE_TRY_READ_IF(multiLvlStrCache) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL multiLvlStrCache KoFilter::ConversionStatus XlsxXmlChartReader::read_multiLvlStrCache() { READ_PROLOGUE while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(lvl) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL lvl KoFilter::ConversionStatus XlsxXmlChartReader::read_lvl() { READ_PROLOGUE d->m_currentPtCount = &d->m_currentStrCache->m_ptCount; d->m_currentPtCache = &d->m_currentStrCache->m_cache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(ptCount) ELSE_TRY_READ_IF(pt) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL numRef //! numRef (String Reference) /*! ECMA-376, 21.2.2.123, p.3815. Parent elements: - bubbleSize (§21.2.2.22) - cat (§21.2.2.24) - minus (§21.2.2.113) - plus (§21.2.2.147) - val (§21.2.2.224) - xVal (§21.2.2.234) - yVal (§21.2.2.237) Child elements: - extLst (Chart Extensibility) §21.2.2.64 - [Done]f (Formula) §21.2.2.65 - [Done]numCache (Number Cache) §21.2.2.120 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_numRef() { READ_PROLOGUE d->m_currentF = &d->m_currentNumRef->m_f; d->m_currentNumCache = &d->m_currentNumRef->m_numCache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(f) ELSE_TRY_READ_IF(numCache) } } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL f //! f (Formula) /*! ECMA-376, 21.2.2.65, p.3789. Parent elements: - multiLvlStrRef (§21.2.2.115) - numRef (§21.2.2.123) - strRef (§21.2.2.201) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_f() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); *d->m_currentF = readElementText(); while (!atEnd()) { BREAK_IF_END_OF(CURRENT_EL) readNext(); } if (d->m_currentF->size() != 0) { QPair result = splitCellRange( *d->m_currentF ); m_context->m_chart->addRange( result.second ); } READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL ptCount //! ptCount (Point Count) /*! ECMA-376, 21.2.2.152, p.3832. Parent elements: - multiLvlStrCache (§21.2.2.114) - numCache (§21.2.2.120) - numLit (§21.2.2.122) - strCache (§21.2.2.199) - strLit (§21.2.2.200) Attributes: - [Done] val (Integer Value) */ KoFilter::ConversionStatus XlsxXmlChartReader::read_ptCount() { READ_PROLOGUE const QXmlStreamAttributes attrs(attributes()); QString val(attrs.value("val").toString()); *d->m_currentPtCount = val.toInt(); readNext(); READ_EPILOGUE } #undef CURRENT_EL #define CURRENT_EL strCache //! strCache (String Cache) /*! ECMA-376, 21.2.2.199, p.3856. Parent elements: - strRef (§21.2.2.201) Child elements: - extLst (Chart Extensibility) §21.2.2.64 - [Done]pt (String Point) §21.2.2.151 - [Done]ptCount (Point Count) §21.2.2.152 */ KoFilter::ConversionStatus XlsxXmlChartReader::read_strCache() { READ_PROLOGUE d->m_currentPtCount = &d->m_currentStrCache->m_ptCount; d->m_currentPtCache = &d->m_currentStrCache->m_cache; while (!atEnd()) { readNext(); BREAK_IF_END_OF(CURRENT_EL) if (isStartElement()) { TRY_READ_IF(ptCount) ELSE_TRY_READ_IF(pt) } } READ_EPILOGUE } int charToInt( const QString& string ) { if (string.isEmpty()) { return -1; } int ret = 0; int multiplier = 1; for(int i=string.size()-1; i>-1; i--,multiplier = multiplier*26) { const char val = string[i].toLatin1(); if ( val >= 65 && val <= 90 ) { ret = ret + (val - 64)*multiplier; } else { ret = -1; break; } } return ret; } QString XlsxXmlChartReader::AlocateAndWriteIntoInternalTable(QVector< QString > &buffer, KoGenStyle::Type formatType) { if (buffer.size() == 0) return QString(); //create range where to place the data QString range("local"); KoChart::InternalTable *internalTable = &m_context->m_chart->m_internalTable; range += "!$" + columnName(internalTable->maxColumn()+1) +"$" + "1" + ":$" + columnName(internalTable->maxColumn()+1) + "$" + QString::number(buffer.size()); WriteIntoInternalTable(range, buffer, formatType); return range; } QString convertToFormat( KoGenStyle::Type formatType ) { switch (formatType) { case KoGenStyle::NumericDateStyle: return "date"; case KoGenStyle::NumericTimeStyle: return "time"; case KoGenStyle::NumericPercentageStyle: return "percentage"; case KoGenStyle::NumericCurrencyStyle: return "currency"; case KoGenStyle::NumericTextStyle: return "string"; case KoGenStyle::NumericBooleanStyle: return "boolean"; case KoGenStyle::NumericNumberStyle: case KoGenStyle::NumericFractionStyle: case KoGenStyle::NumericScientificStyle: return "float"; default: kWarning() << "Unhandled format-type=" << formatType; break; } return "string"; } QString convertToFormat( KoGenStyle::Type formatType, const QString& formatString, const QString& value ) { switch (formatType) { case KoGenStyle::NumericDateStyle: { QString f = formatString; f.replace( QRegExp( "[m{1}]" ), "M" ); QDateTime dt( QDate( 1899, 12, 30 ) ); return dt.addDays( value.toInt() ).toString( f ); } case KoGenStyle::NumericTimeStyle: { QTime t(0,0,0,0); t = t.addSecs( value.toInt() ); return t.toString( Qt::ISODate ); } case KoGenStyle::NumericPercentageStyle: { return value + '%'; } /*TODO case KoGenStyle::NumericCurrencyStyle: case KoGenStyle::NumericBooleanStyle: case KoGenStyle::NumericFractionStyle: case KoGenStyle::NumericScientificStyle: */ case KoGenStyle::NumericNumberStyle: case KoGenStyle::NumericTextStyle: return value; default: kWarning() << "Unhandled format-type=" << formatType; break; } return value; } void XlsxXmlChartReader::WriteIntoInternalTable(QString &range, QVector< QString > &buffer, KoGenStyle::Type formatType, const QString& formatString) { if(range.isEmpty()) { return; } const QString sheet = range.section( '!', 0, 0 ); const QString cellRange = range.section( '!', 1, -1 ); const QStringList& res = cellRange.split( QRegExp( "[$:]" ), QString::SkipEmptyParts ); if (res.count() <= 1) { return; } int startColumn = charToInt( res[ 0 ] ); int startRow = res[ 1 ].toInt(); int endColumn = 0; int endRow = 0; if (res.size() >= 4) { endColumn = charToInt( res[ 2 ] ); endRow = res[ 3 ].toInt(); } else { endColumn = startColumn ; endRow = startRow; } // kDebug()<<"range " << range; // kDebug()<<"sheet " << sheet; // kDebug()<<"cellRange " << cellRange; // kDebug()<<"startColumn " << startColumn; // kDebug()<<"startRow " << startRow; // kDebug()<<"endColumn " << endColumn; // kDebug()<<"endRow " << endRow; // // kDebug()<<"buffer.size() " << buffer.size(); KoChart::InternalTable *internalTable = &m_context->m_chart->m_internalTable; if (startColumn < endColumn) { if ((endColumn - startColumn +1) == buffer.size()) { int bufferIndex = 0; for(int i = startColumn; i <=endColumn; i++,bufferIndex++) { KoChart::Cell *cell = internalTable->cell(i,startRow,true); cell->m_valueType = convertToFormat( formatType ); cell->m_value = convertToFormat( formatType, formatString, buffer[bufferIndex] ); // kDebug()<<"m_value " << format; // kDebug()<<"buffer[bufferIndex] " << buffer[bufferIndex]; // kDebug()<<"cell row" << startRow; // kDebug()<<"cell column " << i; } } } else if (startRow < endRow){ if ((endRow - startRow +1) == buffer.size()) { int bufferIndex = 0; for(int i = startRow; i <=endRow; i++,bufferIndex++) { KoChart::Cell *cell = internalTable->cell(startColumn,i,true); cell->m_valueType = convertToFormat( formatType ); cell->m_value = convertToFormat( formatType, formatString, buffer[bufferIndex] ); // kDebug()<<"m_value " << format; // kDebug()<<"buffer[bufferIndex] " << buffer[bufferIndex]; // kDebug()<<"cell row" << i; // kDebug()<<"cell column " << startColumn; } } } else { if (buffer.size() != 0) { KoChart::Cell *cell = internalTable->cell(startColumn,startRow,true); cell->m_valueType = convertToFormat( formatType ); cell->m_value = convertToFormat( formatType, formatString, buffer[ 0 ] ); // kDebug()<<"m_value " << format; // kDebug()<<"buffer[bufferIndex] " << buffer[0]; // kDebug()<<"cell row" << startRow; // kDebug()<<"cell column " << startColumn; } } } diff --git a/krita/data/profiles/CMakeLists.txt b/krita/data/profiles/CMakeLists.txt index 4a7b5c937db..a2a997b30aa 100644 --- a/krita/data/profiles/CMakeLists.txt +++ b/krita/data/profiles/CMakeLists.txt @@ -1,8 +1,8 @@ ########### install files ############### add_subdirectory(elles-icc-profiles) install(FILES README scRGB.icm cmyk.icm krita25_lcms-builtin-sRGB_g100-truegamma.icc - DESTINATION ${DATA_INSTALL_DIR}/color/icc/krita) + DESTINATION ${CMAKE_INSTALL_PREFIX}/share/color/icc/krita) diff --git a/krita/data/profiles/elles-icc-profiles/CMakeLists.txt b/krita/data/profiles/elles-icc-profiles/CMakeLists.txt index cc9ac45bae3..f252e164e50 100644 --- a/krita/data/profiles/elles-icc-profiles/CMakeLists.txt +++ b/krita/data/profiles/elles-icc-profiles/CMakeLists.txt @@ -1,50 +1,50 @@ ########### install files ############### install(FILES AllColorsRGB-elle-V2-g10.icc AllColorsRGB-elle-V2-srgbtrc.icc AllColorsRGB-elle-V4-g10.icc AllColorsRGB-elle-V4-srgbtrc.icc CIERGB-elle-V2-g10.icc CIERGB-elle-V2-g22.icc CIERGB-elle-V2-srgbtrc.icc CIERGB-elle-V4-g10.icc CIERGB-elle-V4-g22.icc CIERGB-elle-V4-srgbtrc.icc ClayRGB-elle-V2-g10.icc ClayRGB-elle-V2-g22.icc ClayRGB-elle-V2-srgbtrc.icc ClayRGB-elle-V4-g10.icc ClayRGB-elle-V4-g22.icc ClayRGB-elle-V4-srgbtrc.icc CMakeLists.txt Gray-D50-elle-V2-g10.icc Gray-D50-elle-V2-g18.icc Gray-D50-elle-V2-g22.icc Gray-D50-elle-V2-srgbtrc.icc Gray-D50-elle-V4-g10.icc Gray-D50-elle-V4-g18.icc Gray-D50-elle-V4-g22.icc Gray-D50-elle-V4-srgbtrc.icc IdentityRGB-elle-V2-g10.icc IdentityRGB-elle-V2-srgbtrc.icc IdentityRGB-elle-V4-g10.icc IdentityRGB-elle-V4-srgbtrc.icc Lab-D50-Identity-elle-V2.icc Lab-D50-Identity-elle-V4.icc LargeRGB-elle-V2-g10.icc LargeRGB-elle-V2-g18.icc LargeRGB-elle-V2-srgbtrc.icc LargeRGB-elle-V4-g10.icc LargeRGB-elle-V4-g18.icc LargeRGB-elle-V4-srgbtrc.icc sRGB-elle-V2-g10.icc sRGB-elle-V2-srgbtrc.icc sRGB-elle-V4-g10.icc sRGB-elle-V4-srgbtrc.icc WideRGB-elle-V2-g10.icc WideRGB-elle-V2-g22.icc WideRGB-elle-V2-srgbtrc.icc WideRGB-elle-V4-g10.icc WideRGB-elle-V4-g22.icc WideRGB-elle-V4-srgbtrc.icc -DESTINATION ${DATA_INSTALL_DIR}/color/icc/krita) +DESTINATION ${CMAKE_INSTALL_PREFIX}/share/color/icc/krita) diff --git a/krita/image/CMakeLists.txt b/krita/image/CMakeLists.txt index 6cc171d9221..13b099fb054 100644 --- a/krita/image/CMakeLists.txt +++ b/krita/image/CMakeLists.txt @@ -1,390 +1,391 @@ add_subdirectory( tests ) ########### next target ############### add_definitions(${KDE4_ENABLE_EXCEPTIONS}) # Chose a tiles backend # 1 - image/tiles # 3 - image/tiles3 set(USE_TILESYSTEM 3) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-tiles.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/../config-tiles.h) ### WRONG PLACE??? if(USE_TILESYSTEM EQUAL 3) set(libkritatile_SRCS ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_tile.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_tile_data.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_tile_data_store.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_tile_data_pooler.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_tiled_data_manager.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_memento_manager.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_hline_iterator.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_vline_iterator.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/kis_random_accessor.cc ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_abstract_compression.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_lzf_compression.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_abstract_tile_compressor.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_legacy_tile_compressor.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_tile_compressor_2.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_chunk_allocator.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_memory_window.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_swapped_data_store.cpp ${CMAKE_SOURCE_DIR}/krita/image/tiles3/swap/kis_tile_data_swapper.cpp ) add_subdirectory( tiles3 ) endif() option(HAVE_MEMORY_LEAK_TRACKER "Enable memory leak tracker (always disabled in release build)" OFF) option(HAVE_BACKTRACE_SUPPORT "Enable recording of backtrace in memory leak tracker" OFF) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config-memory-leak-tracker.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-memory-leak-tracker.h) ### WRONG PLACE??? include_directories( ${CMAKE_SOURCE_DIR}/krita/image/metadata 3rdparty ) if(FFTW3_FOUND) include_directories(${FFTW3_INCLUDE_DIR}) endif() if(HAVE_VC) include_directories(${Vc_INCLUDE_DIR}) ko_compile_for_all_implementations(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) else() set(__per_arch_circle_mask_generator_objs kis_brush_mask_applicator_factories.cpp) endif() set(kritaimage_LIB_SRCS ${libkritatile_SRCS} kis_debug.cpp kis_distance_information.cpp kis_painter.cc kis_progress_updater.cpp brushengine/kis_paint_information.cc brushengine/kis_paintop.cc brushengine/kis_paintop_factory.cpp brushengine/kis_paintop_preset.cpp brushengine/kis_paintop_registry.cc brushengine/kis_paintop_settings.cpp brushengine/kis_locked_properties.cc brushengine/kis_locked_properties_proxy.cpp brushengine/kis_locked_properties_server.cpp commands/kis_deselect_global_selection_command.cpp commands/kis_image_change_layers_command.cpp commands/kis_image_command.cpp commands/kis_image_set_projection_color_space_command.cpp commands/kis_image_layer_add_command.cpp commands/kis_image_layer_move_command.cpp commands/kis_image_layer_remove_command.cpp commands/kis_image_layer_remove_command_impl.cpp commands/kis_image_node_lower_command.cpp commands/kis_image_node_raise_command.cpp commands/kis_image_node_to_bottom_command.cpp commands/kis_image_node_to_top_command.cpp commands/kis_image_lock_command.cpp commands/kis_layer_command.cpp commands/kis_layer_props_command.cpp commands/kis_node_command.cpp commands/kis_node_compositeop_command.cpp commands/kis_node_opacity_command.cpp commands/kis_node_property_list_command.cpp commands/kis_reselect_global_selection_command.cpp commands/kis_set_global_selection_command.cpp commands_new/kis_saved_commands.cpp commands_new/kis_processing_command.cpp commands_new/kis_image_resize_command.cpp commands_new/kis_image_set_resolution_command.cpp commands_new/kis_node_move_command2.cpp commands_new/kis_set_layer_style_command.cpp commands_new/kis_selection_move_command2.cpp commands_new/kis_update_command.cpp + commands_new/kis_activate_selection_mask_command.cpp processing/kis_do_nothing_processing_visitor.cpp processing/kis_simple_processing_visitor.cpp processing/kis_crop_processing_visitor.cpp processing/kis_crop_selections_processing_visitor.cpp processing/kis_transform_processing_visitor.cpp processing/kis_mirror_processing_visitor.cpp filter/kis_filter.cc filter/kis_filter_configuration.cc filter/kis_color_transformation_configuration.cc filter/kis_filter_registry.cc filter/kis_color_transformation_filter.cc generator/kis_generator.cpp generator/kis_generator_layer.cpp generator/kis_generator_registry.cpp floodfill/kis_fill_interval_map.cpp floodfill/kis_scanline_fill.cpp kis_adjustment_layer.cc kis_selection_based_layer.cpp kis_node_filter_interface.cpp kis_base_accessor.cpp kis_base_node.cpp kis_base_processor.cpp kis_basic_math_toolbox.cpp kis_bookmarked_configuration_manager.cc kis_clone_info.cpp kis_clone_layer.cpp kis_colorspace_convert_visitor.cpp kis_config_widget.cpp kis_convolution_kernel.cc kis_convolution_painter.cc kis_gaussian_kernel.cpp kis_cubic_curve.cpp kis_default_bounds.cpp kis_default_bounds_base.cpp kis_effect_mask.cc kis_fast_math.cpp kis_fill_painter.cc kis_filter_mask.cpp kis_filter_strategy.cc kis_transform_mask.cpp kis_transform_mask_params_interface.cpp kis_recalculate_transform_mask_job.cpp kis_recalculate_generator_layer_job.cpp kis_transform_mask_params_factory_registry.cpp kis_safe_transform.cpp kis_gradient_painter.cc kis_gradient_shape_strategy.cpp kis_cached_gradient_shape_strategy.cpp kis_polygonal_gradient_shape_strategy.cpp kis_iterator_ng.cpp kis_async_merger.cpp kis_merge_walker.cc kis_updater_context.cpp kis_update_job_item.cpp kis_stroke_strategy_undo_command_based.cpp kis_simple_stroke_strategy.cpp kis_stroke_job_strategy.cpp kis_stroke_strategy.cpp kis_stroke.cpp kis_strokes_queue.cpp kis_simple_update_queue.cpp kis_update_scheduler.cpp kis_queues_progress_updater.cpp kis_composite_progress_proxy.cpp kis_update_time_monitor.cpp kis_group_layer.cc kis_count_visitor.cpp kis_histogram.cc kis_image_interfaces.cpp kis_node_graph_listener.cpp kis_image.cc kis_image_signal_router.cpp kis_image_config.cpp kis_crop_saved_extra_data.cpp kis_signal_compressor.cpp kis_signal_compressor_with_param.cpp kis_thread_safe_signal_compressor.cpp kis_acyclic_signal_connector.cpp kis_layer.cc kis_indirect_painting_support.cpp kis_abstract_projection_plane.cpp kis_layer_projection_plane.cpp kis_mask_projection_plane.cpp kis_projection_leaf.cpp kis_mask.cc kis_base_mask_generator.cpp kis_rect_mask_generator.cpp kis_circle_mask_generator.cpp kis_gauss_circle_mask_generator.cpp kis_gauss_rect_mask_generator.cpp ${__per_arch_circle_mask_generator_objs} kis_curve_circle_mask_generator.cpp kis_curve_rect_mask_generator.cpp kis_math_toolbox.cpp kis_memory_leak_tracker.cpp kis_memory_statistics_server.cpp kis_name_server.cpp kis_node.cpp kis_node_facade.cpp kis_node_progress_proxy.cpp kis_busy_progress_indicator.cpp kis_node_visitor.cpp kis_paint_device.cc kis_fixed_paint_device.cpp kis_paint_layer.cc kis_perspective_grid.cpp kis_perspective_math.cpp kis_pixel_selection.cpp kis_processing_information.cpp kis_properties_configuration.cc kis_random_accessor_ng.cpp kis_random_generator.cc kis_random_sub_accessor.cpp kis_wrapped_random_accessor.cpp kis_selection.cc kis_selection_mask.cpp kis_update_outline_job.cpp kis_update_selection_job.cpp kis_serializable_configuration.cc kis_shared.cc kis_transaction_data.cpp kis_transform_worker.cc kis_perspectivetransform_worker.cpp bsplines/kis_bspline_1d.cpp bsplines/kis_bspline_2d.cpp bsplines/kis_nu_bspline_2d.cpp kis_warptransform_worker.cc kis_cage_transform_worker.cpp kis_liquify_transform_worker.cpp kis_green_coordinates_math.cpp kis_algebra_2d.cpp kis_dom_utils.cpp kis_transparency_mask.cc kis_undo_store.cpp kis_undo_stores.cpp kis_undo_adapter.cpp kis_surrogate_undo_adapter.cpp kis_legacy_undo_adapter.cpp kis_post_execution_undo_adapter.cpp kis_processing_visitor.cpp kis_processing_applicator.cpp krita_utils.cpp kis_outline_generator.cpp kis_layer_composition.cpp kis_selection_filters.cpp metadata/kis_meta_data_entry.cc metadata/kis_meta_data_filter.cc metadata/kis_meta_data_filter_p.cc metadata/kis_meta_data_filter_registry.cc metadata/kis_meta_data_filter_registry_model.cc metadata/kis_meta_data_io_backend.cc metadata/kis_meta_data_merge_strategy.cc metadata/kis_meta_data_merge_strategy_p.cc metadata/kis_meta_data_merge_strategy_registry.cc metadata/kis_meta_data_parser.cc metadata/kis_meta_data_schema.cc metadata/kis_meta_data_schema_registry.cc metadata/kis_meta_data_store.cc metadata/kis_meta_data_type_info.cc metadata/kis_meta_data_validator.cc metadata/kis_meta_data_value.cc recorder/kis_action_recorder.cc recorder/kis_macro.cc recorder/kis_macro_player.cc recorder/kis_node_query_path.cc recorder/kis_play_info.cc recorder/kis_recorded_action.cc recorder/kis_recorded_action_factory_registry.cc recorder/kis_recorded_action_load_context.cpp recorder/kis_recorded_action_save_context.cpp recorder/kis_recorded_filter_action.cpp recorder/kis_recorded_fill_paint_action.cpp recorder/kis_recorded_node_action.cc recorder/kis_recorded_paint_action.cpp recorder/kis_recorded_path_paint_action.cpp recorder/kis_recorded_shape_paint_action.cpp kis_psd_layer_style.cpp layerstyles/kis_layer_style_filter.cpp layerstyles/kis_layer_style_filter_environment.cpp layerstyles/kis_layer_style_filter_projection_plane.cpp layerstyles/kis_layer_style_projection_plane.cpp layerstyles/kis_ls_drop_shadow_filter.cpp layerstyles/kis_ls_satin_filter.cpp layerstyles/kis_ls_stroke_filter.cpp layerstyles/kis_ls_bevel_emboss_filter.cpp layerstyles/kis_ls_overlay_filter.cpp layerstyles/kis_ls_utils.cpp layerstyles/gimp_bump_map.cpp ) set(einspline_SRCS 3rdparty/einspline/bspline_create.cpp 3rdparty/einspline/bspline_data.cpp 3rdparty/einspline/multi_bspline_create.cpp 3rdparty/einspline/nubasis.cpp 3rdparty/einspline/nubspline_create.cpp 3rdparty/einspline/nugrid.cpp ) kde4_add_library(kritaimage SHARED ${kritaimage_LIB_SRCS} ${einspline_SRCS}) target_link_libraries(kritaimage ${KDE4_KDEUI_LIBS} kritaglobal kritapsd koodf pigmentcms kundo2 kowidgetutils) target_link_libraries(kritaimage LINK_INTERFACE_LIBRARIES kritaglobal kritapsd koodf pigmentcms kundo2 kowidgetutils) target_link_libraries(kritaimage ${Boost_SYSTEM_LIBRARY}) message("DEBUG_BOOST_LIBRARIES = " ${Boost_LIBRARIES}) message("DEBUG_BOOST_SYSTEM_FOUND = " ${Boost_SYSTEM_FOUND}) message("DEBUG_BOOST_SYSTEM_LIBRARY = " ${Boost_SYSTEM_LIBRARY}) if(OPENEXR_FOUND) target_link_libraries(kritaimage ${OPENEXR_LIBRARIES}) endif() if(FFTW3_FOUND) target_link_libraries(kritaimage ${FFTW3_LIBRARIES}) endif() if(HAVE_VC) target_link_libraries(kritaimage ${Vc_LIBRARIES}) endif() if (NOT GSL_FOUND) message (WARNING "KRITA WARNING! No GNU Scientific Library was found! Krita's Shaped Gradients might be non-normalized! Please install GSL library.") else () target_link_libraries(kritaimage ${GSL_LIBRARIES} ${GSL_CBLAS_LIBRARIES}) endif () set_target_properties(kritaimage PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaimage ${INSTALL_TARGETS_DEFAULT_ARGS}) ########### install schemas ############# install( FILES metadata/schemas/dc.schema metadata/schemas/exif.schema metadata/schemas/tiff.schema metadata/schemas/mkn.schema metadata/schemas/xmp.schema metadata/schemas/xmpmm.schema metadata/schemas/xmprights.schema DESTINATION ${DATA_INSTALL_DIR}/krita/metadata/schemas) ########### install files ############### install( FILES kis_base_node.h kis_base_processor.h kis_config_widget.h kis_convolution_kernel.h kis_convolution_painter.h kis_convolution_worker.h kis_cubic_curve.h kis_debug.h kis_default_bounds.h kis_distance_information.h filter/kis_filter.h filter/kis_filter_registry.h kis_filter_strategy.h kis_global.h kis_image.h kis_mask.h kis_node.h kis_node_facade.h kis_node_graph_listener.h kis_painter.h kis_paint_device.h kis_properties_configuration.h kis_processing_information.h kis_transform_worker.h kis_perspectivetransform_worker.h kis_warptransform_worker.h kis_serializable_configuration.h kis_selection.h kis_shared.h kis_shared_ptr.h kis_transaction.h kis_types.h - krita_export.h + kritaimage_export.h filter/kis_filter_configuration.h generator/kis_generator.h generator/kis_generator_registry.h brushengine/kis_locked_properties.h brushengine/kis_locked_properties_proxy.h brushengine/kis_locked_properties_server.h DESTINATION ${INCLUDE_INSTALL_DIR}/krita) diff --git a/krita/image/brushengine/kis_paint_information.h b/krita/image/brushengine/kis_paint_information.h index 3501ed349bf..2544c75dcb3 100644 --- a/krita/image/brushengine/kis_paint_information.h +++ b/krita/image/brushengine/kis_paint_information.h @@ -1,252 +1,252 @@ /* * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_PAINT_INFORMATION_ #define _KIS_PAINT_INFORMATION_ #include #include #include "kis_global.h" #include "kis_vec.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_distance_information.h" class QDomDocument; class QDomElement; class KisDistanceInformation; /** * KisPaintInformation contains information about the input event that * causes the brush action to happen to the brush engine's paint * methods. * * XXX: we directly pass the KoPointerEvent x and y tilt to * KisPaintInformation, and their range is -60 to +60! * * @param pos: the position of the paint event in subpixel accuracy * @param pressure: the pressure of the stylus * @param xTilt: the angle between the device (a pen, for example) and * the perpendicular in the direction of the x axis. Positive values * are towards the bottom of the tablet. The angle is within the range * 0 to 1 * @param yTilt: the angle between the device (a pen, for example) and * the perpendicular in the direction of the y axis. Positive values * are towards the bottom of the tablet. The angle is within the range * 0 to . * @param movement: current position minus the last position of the call to paintAt * @param rotation * @param tangentialPressure * @param perspective **/ class KRITAIMAGE_EXPORT KisPaintInformation { public: /** * Note, that this class is relied on the compiler optimization * of the return value. So if it doesn't work for some reason, * please implement a proper copy c-tor */ class KRITAIMAGE_EXPORT DistanceInformationRegistrar { public: DistanceInformationRegistrar(KisPaintInformation *_p, KisDistanceInformation *distanceInfo); ~DistanceInformationRegistrar(); private: KisPaintInformation *p; }; public: /** * Create a new KisPaintInformation object. */ KisPaintInformation(const QPointF & pos, qreal pressure, qreal xTilt, qreal yTilt, qreal rotation, qreal tangentialPressure, qreal perspective, qreal time, qreal speed); KisPaintInformation(const QPointF & pos, qreal pressure, qreal xTilt, qreal yTilt, qreal rotation); KisPaintInformation(const QPointF & pos = QPointF(), qreal pressure = PRESSURE_DEFAULT); KisPaintInformation(const KisPaintInformation& rhs); void operator=(const KisPaintInformation& rhs); ~KisPaintInformation(); template void paintAt(PaintOp &op, KisDistanceInformation *distanceInfo) { KisSpacingInformation spacingInfo; { DistanceInformationRegistrar r = registerDistanceInformation(distanceInfo); spacingInfo = op.paintAt(*this); } distanceInfo->registerPaintedDab(*this, spacingInfo); } const QPointF& pos() const; void setPos(const QPointF& p); /// The pressure of the value (from 0.0 to 1.0) qreal pressure() const; /// Set the pressure void setPressure(qreal p); /// The tilt of the pen on the horizontal axis (from 0.0 to 1.0) qreal xTilt() const; /// The tilt of the pen on the vertical axis (from 0.0 to 1.0) qreal yTilt() const; /// XXX !!! :-| Please add dox! void overrideDrawingAngle(qreal angle); /// XXX !!! :-| Please add dox! qreal drawingAngleSafe(const KisDistanceInformation &distance) const; /// XXX !!! :-| Please add dox! DistanceInformationRegistrar registerDistanceInformation(KisDistanceInformation *distance); /** * Current brush direction computed from the cursor movement * * WARNING: this method is available *only* inside paintAt() call, * that is when the distance information is registered. */ qreal drawingAngle() const; /** * Current brush direction vector computed from the cursor movement * * WARNING: this method is available *only* inside paintAt() call, * that is when the distance information is registered. */ QPointF drawingDirectionVector() const; /** * Current brush speed computed from the cursor movement * * WARNING: this method is available *only* inside paintAt() call, * that is when the distance information is registered. */ qreal drawingSpeed() const; /** * Current distance from the previous dab * * WARNING: this method is available *only* inside paintAt() call, * that is when the distance information is registered. */ qreal drawingDistance() const; /// rotation as given by the tablet event qreal rotation() const; /// tangential pressure (i.e., rate for an airbrush device) qreal tangentialPressure() const; /// reciprocal of distance on the perspective grid qreal perspective() const; /// Number of ms since the beginning of the stroke qreal currentTime() const; /** * The paint information may be generated not only during real * stroke when the actual painting is happening, but also when the * cursor is hovering the canvas. In this mode some of the sensors * work a bit differently. The most outstanding example is Fuzzy * sensor, which returns unit value in this mode, otherwise it is * too irritating for a user. * * This value is true only for paint information objects created with * createHoveringModeInfo() constructor. * * \see createHoveringModeInfo() */ bool isHoveringMode() const; /** * Create a fake info object with isHoveringMode() property set to * true. * * \see isHoveringMode() */ static KisPaintInformation createHoveringModeInfo(const QPointF &pos, qreal pressure = PRESSURE_DEFAULT, qreal xTilt = 0.0, qreal yTilt = 0.0, qreal rotation = 0.0, qreal tangentialPressure = 0.0, qreal perspective = 1.0, qreal speed = 0.0, int canvasrotation = 0, bool canvasMirroredH = false); /** *Returns the canvas rotation if that has been given to the kispaintinformation. */ int canvasRotation() const; /** *set the canvas rotation. */ void setCanvasRotation(int rotation); /* *Whether the canvas is mirrored for the paint-operation. */ bool canvasMirroredH() const; /* *Set whether the canvas is mirrored for the paint-operation. */ void setCanvasHorizontalMirrorState(bool mir); void toXML(QDomDocument&, QDomElement&) const; static KisPaintInformation fromXML(const QDomElement&); /// (1-t) * p1 + t * p2 static KisPaintInformation mixOnlyPosition(qreal t, const KisPaintInformation& mixedPi, const KisPaintInformation& basePi); static KisPaintInformation mix(const QPointF& p, qreal t, const KisPaintInformation& p1, const KisPaintInformation& p2); static KisPaintInformation mix(qreal t, const KisPaintInformation& pi1, const KisPaintInformation& pi2); static qreal tiltDirection(const KisPaintInformation& info, bool normalize = true); static qreal tiltElevation(const KisPaintInformation& info, qreal maxTiltX = 60.0, qreal maxTiltY = 60.0, bool normalize = true); private: struct Private; Private* const d; }; KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisPaintInformation& info); #endif diff --git a/krita/image/brushengine/kis_paintop.h b/krita/image/brushengine/kis_paintop.h index c7a9ce801aa..a17755e3947 100644 --- a/krita/image/brushengine/kis_paintop.h +++ b/krita/image/brushengine/kis_paintop.h @@ -1,144 +1,144 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2004 Clarence Dang * Copyright (c) 2004 Adrian Page * Copyright (c) 2004,2010 Cyrille Berger * * 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_H_ #define KIS_PAINTOP_H_ #include "kis_distance_information.h" #include "kis_shared.h" #include "kis_types.h" #include "kis_paintop_settings.h" -#include +#include class QPointF; class KoColorSpace; class KisPainter; class KisPaintInformation; /** * KisPaintOp are use by tools to draw on a paint device. A paintop takes settings * and input information, like pressure, tilt or motion and uses that to draw pixels */ class KRITAIMAGE_EXPORT KisPaintOp : public KisShared { struct Private; public: KisPaintOp(KisPainter * painter); virtual ~KisPaintOp(); /** * Paint at the subpixel point pos using the specified paint * information.. * * The distance between two calls of the paintAt is always * specified by spacing, which is automatically saved into the * current distance information object */ void paintAt(const KisPaintInformation& info, KisDistanceInformation *currentDistance); /** * Draw a line between pos1 and pos2 using the currently set brush and color. * If savedDist is less than zero, the brush is painted at pos1 before being * painted along the line using the spacing setting. * * @return the drag distance, that is the remains of the distance * between p1 and p2 not covered because the currenlty set brush * has a spacing greater than that distance. */ virtual void paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance); /** * Draw a Bezier curve between pos1 and pos2 using control points 1 and 2. * If savedDist is less than zero, the brush is painted at pos1 before being * painted along the curve using the spacing setting. * @return the drag distance, that is the remains of the distance between p1 and p2 not covered * because the currenlty set brush has a spacing greater than that distance. */ virtual void paintBezierCurve(const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance); /** * Whether this paintop can paint. Can be false in case that some setting isn't read correctly. * @return if paintop is ready for painting, default is true */ virtual bool canPaint() const { return true; } /** * Split the coordinate into whole + fraction, where fraction is always >= 0. */ static void splitCoordinate(qreal coordinate, qint32 *whole, qreal *fraction); /** * returns the scale and rotation dynamically computed for the single dab * rotation is in radians * This is used e.g. for dynamic brush outline */ qreal currentScale() const; qreal currentRotation() const; protected: friend class KisPaintInformation; /** * The implementation of painting of a dab */ virtual KisSpacingInformation paintAt(const KisPaintInformation& info) = 0; void setCurrentScale(qreal scale); /** * Set rotation in radians */ void setCurrentRotation(qreal rotation); KisFixedPaintDeviceSP cachedDab(); KisFixedPaintDeviceSP cachedDab(const KoColorSpace *cs); /** * Return the painter this paintop is owned by */ KisPainter* painter() const; /** * Return the paintdevice the painter this paintop is owned by */ KisPaintDeviceSP source() const; private: friend class KisPressureRotationOption; void setFanCornersInfo(bool fanCornersEnabled, qreal fanCornersStep); private: Private* const d; }; #endif // KIS_PAINTOP_H_ diff --git a/krita/image/brushengine/kis_paintop_config_widget.h b/krita/image/brushengine/kis_paintop_config_widget.h index 4af2c2853cf..e59a5bdc690 100644 --- a/krita/image/brushengine/kis_paintop_config_widget.h +++ b/krita/image/brushengine/kis_paintop_config_widget.h @@ -1,93 +1,93 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PAINTOP_CONFIG_WIDGET_H_ #define KIS_PAINTOP_CONFIG_WIDGET_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_config_widget.h" #include "kis_image.h" #include /** * Base class for widgets that are used to edit and display paintop settings. */ class KRITAIMAGE_EXPORT KisPaintOpConfigWidget : public KisConfigWidget { public: KisPaintOpConfigWidget(QWidget * parent = 0, Qt::WFlags f = 0) : KisConfigWidget(parent, f, 10) { } virtual ~KisPaintOpConfigWidget() { } /** * Write the settings in this widget to the given properties * configuration, which is cleared first. */ virtual void writeConfiguration(KisPropertiesConfiguration *config) const = 0; virtual void setImage(KisImageWSP image) { m_image = image; } virtual void setNode(KisNodeWSP node) { m_node = node; } /** * @see KisPaintOpSettings::changePaintOpSize(qreal x, qreal y) */ virtual void changePaintOpSize(qreal x, qreal y) { Q_UNUSED(x); Q_UNUSED(y); } /** * @see KisPaintOpSettings::paintOpSize() */ virtual QSizeF paintOpSize() const { return QSizeF(1.0, 1.0); }; /** * This is true for all of the paintop widget except for the Custom brush tab in the Brush tip dialog */ virtual bool presetIsValid() { return true; } /** * Some paintops are more complicated and require full canvas with layers, projections and KisImage etc. * Example is duplicate paintop. In this case simple canvas like scratchbox does not work. * Every paintop supports the scratchbox by default, override and return false if paintop does not. */ virtual bool supportScratchBox() { return true; } protected: KisImageWSP m_image; KisNodeWSP m_node; }; #endif diff --git a/krita/image/brushengine/kis_paintop_factory.h b/krita/image/brushengine/kis_paintop_factory.h index 831b8d42d1f..a44dd707cb8 100644 --- a/krita/image/brushengine/kis_paintop_factory.h +++ b/krita/image/brushengine/kis_paintop_factory.h @@ -1,115 +1,115 @@ /* * Copyright (c) 2008 Boudewijn Rempt * Copyright (c) 2010 Lukáš Tvrdý * 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_FACTORY_H_ #define KIS_PAINTOP_FACTORY_H_ #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include #include #include #include class KisPainter; class KisPaintOp; class QWidget; class KisPaintOpConfigWidget; /** * The paintop factory is responsible for creating paintops of the specified class. * If there is an optionWidget, the derived paintop itself must support settings, * and it's up to the factory to do that. */ class KRITAIMAGE_EXPORT KisPaintOpFactory : public QObject { Q_OBJECT public: enum PaintopVisibility { AUTO, ALWAYS, NEVER }; /** * @param whiteListedCompositeOps list of compositeops that don't work with this paintop */ KisPaintOpFactory(const QStringList & whiteListedCompositeOps = QStringList()); virtual ~KisPaintOpFactory() {} static QString categoryStable(); #ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND virtual void preinitializePaintOpIfNeeded(const KisPaintOpSettingsSP settings); #endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */ /** * Create a KisPaintOp with the given settings and painter. * @param settings the settings associated with the input device * @param painter the painter used to draw */ virtual KisPaintOp * createOp(const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image) = 0; virtual QString id() const = 0; virtual QString name() const = 0; virtual QString category() const = 0; /** * List of usually hidden compositeops that are useful for this paintop. */ QStringList whiteListedCompositeOps() const; /** * The filename of the pixmap we can use to represent this paintop in the ui. */ virtual QString pixmap(); /** * Create and return an settings object for this paintop. */ virtual KisPaintOpSettingsSP settings() = 0; /** * create a widget that can display paintop settings */ virtual KisPaintOpConfigWidget* createConfigWidget(QWidget* parent) = 0; /** * Set the priority of this paintop, as it is shown in the UI; lower number means * it will be show more to the front of the list. * @param newPriority the priority */ void setPriority(int newPriority); int priority() const; /** * This method will be called by the registry after all paintops are loaded * Overwrite to let the factory do something. */ virtual void processAfterLoading() {} private: QStringList m_whiteListedCompositeOps; int m_priority; PaintopVisibility m_visibility; }; #endif diff --git a/krita/image/brushengine/kis_paintop_preset.cpp b/krita/image/brushengine/kis_paintop_preset.cpp index 736699de04c..41b48279def 100644 --- a/krita/image/brushengine/kis_paintop_preset.cpp +++ b/krita/image/brushengine/kis_paintop_preset.cpp @@ -1,361 +1,345 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * Copyright (C) Sven Langkamp , (C) 2009 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_paintop_preset.h" #include #include #include #include #include #include #include -#include #include #include "kis_types.h" #include "kis_paintop_settings.h" #include "kis_paintop_registry.h" #include "kis_painter.h" #include "kis_paint_information.h" #include "kis_paint_device.h" #include "kis_image.h" #include struct KisPaintOpPreset::Private { Private() : settings(0), dirtyPreset(false) { } KisPaintOpSettingsSP settings; bool dirtyPreset; }; KisPaintOpPreset::KisPaintOpPreset() : KoResource(QString()) , m_d(new Private) { } KisPaintOpPreset::KisPaintOpPreset(const QString & fileName) : KoResource(fileName) , m_d(new Private) { } KisPaintOpPreset::~KisPaintOpPreset() { delete m_d; } KisPaintOpPresetSP KisPaintOpPreset::clone() const { KisPaintOpPresetSP preset = new KisPaintOpPreset(); if (settings()) { preset->setSettings(settings()->clone()); } preset->setPresetDirty(isPresetDirty()); // only valid if we could clone the settings preset->setValid(settings()); preset->setPaintOp(paintOp()); preset->setName(name()); preset->setImage(image()); preset->settings()->setPreset(KisPaintOpPresetWSP(preset)); Q_ASSERT(preset->valid()); return preset; } void KisPaintOpPreset::setPresetDirty(bool value) { m_d->dirtyPreset = value; } bool KisPaintOpPreset::isPresetDirty() const { return m_d->dirtyPreset; } void KisPaintOpPreset::setPaintOp(const KoID & paintOp) { Q_ASSERT(m_d->settings); m_d->settings->setProperty("paintop", paintOp.id()); } KoID KisPaintOpPreset::paintOp() const { Q_ASSERT(m_d->settings); return KoID(m_d->settings->getString("paintop"), name()); } void KisPaintOpPreset::setSettings(KisPaintOpSettingsSP settings) { Q_ASSERT(settings); Q_ASSERT(!settings->getString("paintop", "").isEmpty()); DirtyStateSaver dirtyStateSaver(this); if (settings) { m_d->settings = settings->clone(); m_d->settings->setPreset(KisPaintOpPresetWSP(this)); } else { m_d->settings = 0; m_d->settings->setPreset(0); } setValid(m_d->settings); } KisPaintOpSettingsSP KisPaintOpPreset::settings() const { Q_ASSERT(m_d->settings); Q_ASSERT(!m_d->settings->getString("paintop", "").isEmpty()); return m_d->settings; } bool KisPaintOpPreset::load() { dbgImage << "Load preset " << filename(); setValid(false); if (filename().isEmpty()) { return false; } QIODevice *dev = 0; QByteArray ba; if (filename().startsWith("bundle://")) { qDebug() << "bundle"; QString bn = filename().mid(9); QString fn = bn.mid(bn.indexOf(":") + 1); bn = bn.left(bn.indexOf(":")); QScopedPointer resourceStore(KoStore::createStore(bn, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { qWarning() << "Could not open store on bundle" << bn; return false; } if (resourceStore->isOpen()) resourceStore->close(); if (!resourceStore->open(fn)) { qWarning() << "Could not open preset" << fn << "in bundle" << bn; return false; } ba = resourceStore->device()->readAll(); dev = new QBuffer(&ba); resourceStore->close(); } else { dev = new QFile(filename()); if (dev->size() == 0) { delete dev; return false; } if (!dev->open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); delete dev; return false; } } bool res = loadFromDevice(dev); delete dev; setValid(res); setPresetDirty(false); return res; } bool KisPaintOpPreset::loadFromDevice(QIODevice *dev) { QImageReader reader(dev, "PNG"); QString version = reader.text("version"); QString preset = reader.text("preset"); dbgImage << version; if (version != "2.2") { return false; } QImage img; if (!reader.read(&img)) { dbgImage << "Fail to decode PNG"; return false; } //Workaround for broken presets //Presets was saved with nested cdata section preset.replace(""); preset.replace("]]>", ""); QDomDocument doc; if (!doc.setContent(preset)) { return false; } fromXML(doc.documentElement()); if (!m_d->settings) { return false; } setValid(true); setImage(img); return true; } bool KisPaintOpPreset::save() { if (filename().isEmpty()) return false; QString paintopid = m_d->settings->getString("paintop", ""); if (paintopid.isEmpty()) return false; QFile f(filename()); f.open(QFile::WriteOnly); return saveToDevice(&f); } void KisPaintOpPreset::toXML(QDomDocument& doc, QDomElement& elt) const { QString paintopid = m_d->settings->getString("paintop", ""); elt.setAttribute("paintopid", paintopid); elt.setAttribute("name", name()); // sanitize the settings bool hasTexture = m_d->settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { foreach(const QString & key, m_d->settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { m_d->settings->removeProperty(key); } } } m_d->settings->toXML(doc, elt); } void KisPaintOpPreset::fromXML(const QDomElement& presetElt) { setName(presetElt.attribute("name")); QString paintopid = presetElt.attribute("paintopid"); if (paintopid.isEmpty()) { dbgImage << "No paintopid attribute"; setValid(false); return; } if (KisPaintOpRegistry::instance()->get(paintopid) == 0) { dbgImage << "No paintop " << paintopid; setValid(false); return; } KoID id(paintopid, ""); KisPaintOpSettingsSP settings = KisPaintOpRegistry::instance()->settings(id); if (!settings) { setValid(false); qWarning() << "Could not load settings for preset" << paintopid; return; } settings->fromXML(presetElt); // sanitize the settings bool hasTexture = settings->getBool("Texture/Pattern/Enabled"); if (!hasTexture) { foreach(const QString & key, settings->getProperties().keys()) { if (key.startsWith("Texture") && key != "Texture/Pattern/Enabled") { settings->removeProperty(key); } } } setSettings(settings); } -QByteArray KisPaintOpPreset::generateMD5() const -{ - QByteArray ba; - QBuffer buf(&ba); - buf.open(QBuffer::WriteOnly); - saveToDevice(&buf); - buf.close(); - - if (!ba.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - return md5.result(); - } - - return ba; -} - bool KisPaintOpPreset::saveToDevice(QIODevice *dev) const { QImageWriter writer(dev, "PNG"); QDomDocument doc; QDomElement root = doc.createElement("Preset"); toXML(doc, root); doc.appendChild(root); writer.setText("version", "2.2"); writer.setText("preset", doc.toString()); QImage img; if (image().isNull()) { img = QImage(1, 1, QImage::Format_RGB32); } else { img = image(); } m_d->dirtyPreset = false; + KoResource::saveToDevice(dev); + return writer.write(img); } diff --git a/krita/image/brushengine/kis_paintop_preset.h b/krita/image/brushengine/kis_paintop_preset.h index 52caacc2238..a87c4fc5569 100644 --- a/krita/image/brushengine/kis_paintop_preset.h +++ b/krita/image/brushengine/kis_paintop_preset.h @@ -1,118 +1,114 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PAINTOP_PRESET_H #define KIS_PAINTOP_PRESET_H #include "KoResource.h" #include "KoID.h" #include "kis_types.h" #include "kis_shared.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * A KisPaintOpPreset contains a particular set of settings * associated with a paintop, like brush, paintopsettings. * A new property in this class is to make it dirty. That means the * user can now temporarily save any tweaks in the Preset throughout * the session. The Dirty Preset setting/unsetting is handled by KisPaintOpPresetSettings */ class KRITAIMAGE_EXPORT KisPaintOpPreset : public KoResource, public KisShared { public: KisPaintOpPreset(); KisPaintOpPreset(const QString& filename); ~KisPaintOpPreset(); KisPaintOpPresetSP clone() const; /// set the id of the paintop plugin void setPaintOp(const KoID & paintOp); /// return the id of the paintop plugin KoID paintOp() const; /// replace the current settings object with the specified settings void setSettings(KisPaintOpSettingsSP settings); void setOriginalSettings(KisPaintOpSettingsSP originalSettings); /// return the settings that define this paintop preset KisPaintOpSettingsSP settings() const; KisPaintOpSettingsSP originalSettings() const; bool load(); bool loadFromDevice(QIODevice *dev); bool save(); bool saveToDevice(QIODevice* dev) const; void toXML(QDomDocument& doc, QDomElement& elt) const; void fromXML(const QDomElement& elt); bool removable() const { return true; } QString defaultFileExtension() const { return ".kpp"; } void setPresetDirty(bool value); bool isPresetDirty() const; /** * Never use manual save/restore calls to * isPresetDirty()/setPresetDirty()! They will lead to * hard-to-tack-down bugs when the dirty state will not be * restored on jumps like 'return', 'break' or exception. */ class DirtyStateSaver { public: DirtyStateSaver(KisPaintOpPreset *preset) : m_preset(preset), m_isDirty(preset->isPresetDirty()) { } ~DirtyStateSaver() { m_preset->setPresetDirty(m_isDirty); } private: KisPaintOpPreset *m_preset; bool m_isDirty; }; -protected: - - virtual QByteArray generateMD5() const; - private: struct Private; Private * const m_d; }; Q_DECLARE_METATYPE(KisPaintOpPresetSP) #endif diff --git a/krita/image/brushengine/kis_paintop_registry.h b/krita/image/brushengine/kis_paintop_registry.h index 9c24922a8b2..dae973daafe 100644 --- a/krita/image/brushengine/kis_paintop_registry.h +++ b/krita/image/brushengine/kis_paintop_registry.h @@ -1,104 +1,104 @@ /* * Copyright (c) 2004 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_PAINTOP_REGISTRY_H_ #define KIS_PAINTOP_REGISTRY_H_ #include #include "KoGenericRegistry.h" #include "kis_paintop.h" #include "kis_paintop_factory.h" #include "kis_types.h" #include "kis_paintop_settings.h" #include "kis_paintop_preset.h" #include -#include +#include class KisPaintOp; class KisPainter; /** * Manages the loading and creating of all paintop plugins. */ class KRITAIMAGE_EXPORT KisPaintOpRegistry : public QObject, public KoGenericRegistry { Q_OBJECT public: virtual ~KisPaintOpRegistry(); #ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND void preinitializePaintOpIfNeeded(const KisPaintOpPresetSP preset); #endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */ /** * Create and return a paintop based on the given preset. A preset defines * a paintop, a settings object and possible a brush tip. */ KisPaintOp* paintOp(const KisPaintOpPresetSP preset, KisPainter * painter, KisNodeSP node, KisImageSP image) const; /** * Create and return an (abstracted) configuration widget * for using the specified paintop with the specified input device, * with the specified parent as widget parent. Returns 0 if there * are no settings available for the given device. */ KisPaintOpSettingsSP settings(const KoID& id) const; /** * @return a default preset for the given paintop. */ KisPaintOpPresetSP defaultPreset(const KoID& id) const; // Get the name of the icon to show in the toolchest QString pixmap(const KoID & id) const; /** * This function return a list of all the keys in KoID format by using the name() method * on the objects stored in the registry. */ QList listKeys() const; public: static KisPaintOpRegistry* instance(); private: KisPaintOpRegistry(); KisPaintOpRegistry(const KisPaintOpRegistry&); KisPaintOpRegistry operator=(const KisPaintOpRegistry&); // So the settings can get a paintop to render their sample image friend class KisPaintOpSettings; /** * Return a newly created paintop. You are responsible for deleting */ KisPaintOp * paintOp(const QString& id, const KisPaintOpSettingsSP settings, KisPainter * painter, KisNodeSP node, KisImageSP image) const; }; #endif // KIS_PAINTOP_REGISTRY_H_ diff --git a/krita/image/brushengine/kis_paintop_settings.h b/krita/image/brushengine/kis_paintop_settings.h index cbc95fbe745..4a3ecfe90b6 100644 --- a/krita/image/brushengine/kis_paintop_settings.h +++ b/krita/image/brushengine/kis_paintop_settings.h @@ -1,254 +1,254 @@ /* * Copyright (c) 2007 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_PAINTOP_SETTINGS_H_ #define KIS_PAINTOP_SETTINGS_H_ #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include #include #include "kis_shared.h" #include "kis_properties_configuration.h" #include "kis_paint_information.h" class KisPaintOpConfigWidget; /** * This class is used to cache the settings for a paintop * between two creations. There is one KisPaintOpSettings per input device (mouse, tablet, * etc...). * * The settings may be stored in a preset or a recorded brush stroke. Note that if your * paintop's settings subclass has data that is not stored as a property, that data is not * saved and restored. * * The object also contains a pointer to its parent KisPaintOpPreset object.This is to control the DirtyPreset * property of KisPaintOpPreset. Whenever the settings are changed/modified from the original -- the preset is * set to dirty. */ class KRITAIMAGE_EXPORT KisPaintOpSettings : public KisPropertiesConfiguration, public KisShared { public: KisPaintOpSettings(); virtual ~KisPaintOpSettings(); /** * */ virtual void setOptionsWidget(KisPaintOpConfigWidget* widget); /** * This function is called by a tool when the mouse is pressed. It's useful if * the paintop needs mouse interaction for instance in the case of the clone op. * If the tool is supposed to ignore the event, the paint op should return false * and if the tool is supposed to use the event, return true. */ virtual bool mousePressEvent(const KisPaintInformation &pos, Qt::KeyboardModifiers modifiers); /** * This function is called to set random offsets to the brush whenever the mouse is clicked. It is * specific to when the pattern option is set. * */ virtual void setRandomOffset(); /** * Clone the current settings object. Override this if your settings instance doesn't * store everything as properties. */ virtual KisPaintOpSettingsSP clone() const; /** * @return the node the paintop is working on. */ KisNodeSP node() const; /** * Call this function when the paint op is selected or the tool is activated */ virtual void activate(); /** * XXX: Remove this after 2.0, when the paint operation (incremental/non incremental) will * be completely handled in the paintop, not in the tool. This is a filthy hack to move * the option to the right place, at least. * @return true if we paint incrementally, false if we paint like Photoshop. By default, paintops * do not support non-incremental. */ virtual bool paintIncremental() { return true; } /** * @return the composite op it to which the indirect painting device * should be initialized to. This is used by clone op to reset * the composite op to COMPOSITE_COPY */ virtual QString indirectPaintingCompositeOp() const; /** * Whether this paintop wants to deposit paint even when not moving, i.e. the * tool needs to activate its timer. */ virtual bool isAirbrushing() const { return false; } /** * If this paintop deposit the paint even when not moving, the tool needs to know the rate of it in miliseconds */ virtual int rate() const { return 100; } /** * This enum defines the current mode for painting an outline. */ enum OutlineMode { CursorIsOutline = 1, ///< When this mode is set, an outline is painted around the cursor CursorIsCircleOutline, CursorNoOutline, CursorTiltOutline, CursorColorOutline }; /** * Returns the brush outline in pixel coordinates. Tool is responsible for conversion into view coordinates. * Outline mode has to be passed to the paintop which builds the outline as some paintops have to paint outline * always like clone paintop indicating the duplicate position */ virtual QPainterPath brushOutline(const KisPaintInformation &info, OutlineMode mode) const; /** * Useful for simple elliptical brush outline. */ QPainterPath ellipseOutline(qreal width, qreal height, qreal scale, qreal rotation) const; /** * The behaviour might be different per paintop. Most of the time * the brush diameter is increased by x pixels, y ignored * * @param x is add to the diameter or radius (according the paintop) * It might be also negative, to decrease the value of the brush diameter/radius. * x is in pixels * @param y is unused, it supposed to be used to change some different attribute * of the brush like softness or density */ virtual void changePaintOpSize(qreal x, qreal y); /** * @return The width and the height of the brush mask/dab in pixels */ virtual QSizeF paintOpSize() const; /** * Set paintop opacity directly in the properties */ void setPaintOpOpacity(qreal value); /** * Set paintop flow directly in the properties */ void setPaintOpFlow(qreal value); /** * Set paintop composite mode directly in the properties */ void setPaintOpCompositeOp(const QString &value); /** * @return opacity saved in the properties */ qreal paintOpOpacity() const; /** * @return flow saved in the properties */ qreal paintOpFlow() const; /** * @return composite mode saved in the properties */ QString paintOpCompositeOp() const; void setPreset(KisPaintOpPresetWSP preset); KisPaintOpPresetWSP preset() const; /** * @return filename of the 3D brush model, empty if no brush is set */ virtual QString modelName() const; /** * Set filename of 3D brush model. By default no brush is set */ void setModelName(const QString & modelName); /// Check if the settings are valid, setting might be invalid through missing brushes etc /// Overwrite if the settings of a paintop can be invalid /// @return state of the settings, default implementation is true virtual bool isValid() const; /// Check if the settings are loadable, that might the case if we can fallback to something /// Overwrite if the settings can do some kind of fallback /// @return loadable state of the settings, by default implementation return the same as isValid() virtual bool isLoadable(); /** * These methods are populating properties with runtime * information about canvas rotation/mirroring. This information * is set directly by KisToolFreehand. Later the data is accessed * by the pressure options to make a final decision. */ void setCanvasRotation(qreal angle); void setCanvasMirroring(bool xAxisMirrored, bool yAxisMirrored); /** * Overrides the method in KisPropertiesCofiguration to allow * onPropertyChanged() callback */ void setProperty(const QString & name, const QVariant & value); protected: /** * @return the option widget of the paintop (can be 0 is no option widgets is set) */ KisPaintOpConfigWidget* optionsWidget() const; /** * The callback is called every time when a property changes */ virtual void onPropertyChanged(); private: struct Private; const QScopedPointer d; }; #endif diff --git a/krita/image/bsplines/kis_bspline_1d.h b/krita/image/bsplines/kis_bspline_1d.h index 9b8d424b5d2..61c4799677a 100644 --- a/krita/image/bsplines/kis_bspline_1d.h +++ b/krita/image/bsplines/kis_bspline_1d.h @@ -1,83 +1,83 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_BSPLINE_1D_H #define __KIS_BSPLINE_1D_H -#include +#include #include #include #include "kis_bspline.h" namespace KisBSplines { class KRITAIMAGE_EXPORT KisBSpline1D { public: KisBSpline1D(float gridStart, float gridEnd, int numSamples, BorderCondition bc); ~KisBSpline1D(); template inline void initializeSpline() { FunctionOp op; float step = (m_gridEnd - m_gridStart) / (m_numSamples - 1); QVector values(m_numSamples); for (int i = 0; i < m_numSamples; i++) { float x = m_gridStart + i * step; float y = op(x); values[i] = y; } initializeSplineImpl(values); } float value(float x) const; inline float gridStart() const { return m_gridStart; } inline float gridEnd() const { return m_gridEnd; } private: void initializeSplineImpl(const QVector &values); private: struct Private; const QScopedPointer m_d; /** * We need to store them separately, because they should * be accessible from the templated part */ float m_gridStart; float m_gridEnd; int m_numSamples; }; } #endif /* __KIS_BSPLINE_1D_H */ diff --git a/krita/image/bsplines/kis_bspline_2d.h b/krita/image/bsplines/kis_bspline_2d.h index 56c778cfa43..8965a2ad939 100644 --- a/krita/image/bsplines/kis_bspline_2d.h +++ b/krita/image/bsplines/kis_bspline_2d.h @@ -1,124 +1,124 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_BSPLINE_2D_H #define __KIS_BSPLINE_2D_H -#include +#include #include #include #include #include #include "kis_bspline.h" namespace KisBSplines { template struct ConvertSplineOp { ConvertSplineOp(const Spline &spline) : m_spline(spline) {} float operator() (float x, float y) const { return m_spline.value(x, y); } const Spline &m_spline; }; class KRITAIMAGE_EXPORT KisBSpline2D { public: KisBSpline2D(float xStart, float xEnd, int numSamplesX, BorderCondition bcX, float yStart, float yEnd, int numSamplesY, BorderCondition bcY); ~KisBSpline2D(); template static inline KisBSpline2D* createResampledSpline(const Spline &other, int xSamples, int ySamples) { QPointF tl = other.topLeft(); QPointF br = other.bottomRight(); KisBSpline2D *newSpline = new KisBSpline2D(tl.x(), br.x(), xSamples, other.borderConditionX(), tl.y(), br.y(), ySamples, other.borderConditionY()); ConvertSplineOp op(other); newSpline->initializeSpline(op); return newSpline; } template inline void initializeSpline(const FunctionOp &op) { float xStep = (m_xEnd - m_xStart) / (m_numSamplesX - 1); float yStep = (m_yEnd - m_yStart) / (m_numSamplesY - 1); QVector values(m_numSamplesX * m_numSamplesY); for (int x = 0; x < m_numSamplesX; x++) { float fx = m_xStart + xStep * x; for (int y = 0; y < m_numSamplesY; y++) { float fy = m_yStart + yStep * y; float v = op(fx, fy); values[x * m_numSamplesY + y] = v; } } initializeSplineImpl(values); } float value(float x, float y) const; inline QPointF topLeft() const { return QPointF(m_xStart, m_yStart); } inline QPointF bottomRight() const { return QPointF(m_xEnd, m_yEnd); } BorderCondition borderConditionX() const; BorderCondition borderConditionY() const; private: void initializeSplineImpl(const QVector &values); private: struct Private; const QScopedPointer m_d; /** * We need to store them separately, because they should * be accessible from the templated part */ float m_xStart; float m_xEnd; int m_numSamplesX; float m_yStart; float m_yEnd; int m_numSamplesY; }; } #endif /* __KIS_BSPLINE_2D_H */ diff --git a/krita/image/bsplines/kis_nu_bspline_2d.h b/krita/image/bsplines/kis_nu_bspline_2d.h index 71c5cd50d64..eac80771cb4 100644 --- a/krita/image/bsplines/kis_nu_bspline_2d.h +++ b/krita/image/bsplines/kis_nu_bspline_2d.h @@ -1,88 +1,88 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_NU_BSPLINE_2D_H #define __KIS_NU_BSPLINE_2D_H -#include +#include #include #include #include #include #include "kis_bspline.h" namespace KisBSplines { class KRITAIMAGE_EXPORT KisNUBSpline2D { public: KisNUBSpline2D(const QVector &xSamples, BorderCondition bcX, const QVector &ySamples, BorderCondition bcY); ~KisNUBSpline2D(); template inline void initializeSpline(const FunctionOp &op) { const int xSize = m_xSamples.size(); const int ySize = m_ySamples.size(); QVector values(xSize * ySize); for (int x = 0; x < xSize; x++) { double fx = m_xSamples[x]; for (int y = 0; y < ySize; y++) { double fy = m_ySamples[y]; float v = op(fx, fy); values[x * ySize + y] = v; } } initializeSplineImpl(values); } float value(float x, float y) const; QPointF topLeft() const; QPointF bottomRight() const; BorderCondition borderConditionX() const; BorderCondition borderConditionY() const; private: void initializeSplineImpl(const QVector &values); private: struct Private; const QScopedPointer m_d; /** * We need to store them separately, because they should * be accessible from the templated part */ const QVector m_xSamples; const QVector m_ySamples; }; } #endif /* __KIS_NU_BSPLINE_2D_H */ diff --git a/krita/image/commands/kis_change_filter_command.h b/krita/image/commands/kis_change_filter_command.h index aadd164931c..ed06a946313 100644 --- a/krita/image/commands/kis_change_filter_command.h +++ b/krita/image/commands/kis_change_filter_command.h @@ -1,99 +1,98 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CHANGE_FILTER_COMMAND_H #define KIS_CHANGE_FILTER_COMMAND_H -#include #include #include #include "kis_types.h" #include #include "filter/kis_filter_configuration.h" #include "kis_node.h" #include "kis_node_filter_interface.h" #include "filter/kis_filter_registry.h" #include "filter/kis_filter.h" #include "generator/kis_generator_registry.h" #include "generator/kis_generator.h" class KisNode; class KisChangeFilterCmd : public KUndo2Command { public: KisChangeFilterCmd(KisNodeSP node, const QString &filterNameBefore, const QString &xmlBefore, const QString &filterNameAfter, const QString &xmlAfter, bool useGeneratorRegistry) : KUndo2Command(kundo2_i18n("Change Filter")) { m_node = node; m_filterInterface = dynamic_cast(node.data()); Q_ASSERT(m_filterInterface); m_useGeneratorRegistry = useGeneratorRegistry; m_xmlBefore = xmlBefore; m_xmlAfter = xmlAfter; m_filterNameBefore = filterNameBefore; m_filterNameAfter = filterNameAfter; } public: virtual void redo() { m_filterInterface->setFilter(createConfiguration(m_filterNameAfter, m_xmlAfter)); m_node->setDirty(); } virtual void undo() { m_filterInterface->setFilter(createConfiguration(m_filterNameBefore, m_xmlBefore)); m_node->setDirty(); } private: KisFilterConfiguration* createConfiguration(const QString &name, const QString &data) { KisFilterConfiguration *config; if (m_useGeneratorRegistry) { KisGeneratorSP generator = KisGeneratorRegistry::instance()->value(name); config = generator->defaultConfiguration(0); } else { KisFilterSP filter = KisFilterRegistry::instance()->value(name); config = filter->defaultConfiguration(0); } config->fromXML(data); return config; } private: KisNodeSP m_node; KisNodeFilterInterface *m_filterInterface; bool m_useGeneratorRegistry; QString m_xmlBefore; QString m_xmlAfter; QString m_filterNameBefore; QString m_filterNameAfter; }; #endif diff --git a/krita/image/commands/kis_deselect_global_selection_command.h b/krita/image/commands/kis_deselect_global_selection_command.h index 644beb7d308..dcb5fa3aec6 100644 --- a/krita/image/commands/kis_deselect_global_selection_command.h +++ b/krita/image/commands/kis_deselect_global_selection_command.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DESELECT_GLOBAL_SELECTION_COMMAND_H_ #define KIS_DESELECT_GLOBAL_SELECTION_COMMAND_H_ -#include +#include #include #include "kis_types.h" /// The command for deselection the global selection of KisImage class KRITAIMAGE_EXPORT KisDeselectGlobalSelectionCommand : public KUndo2Command { public: /** * Constructor * @param image the image * @param parent the parent command */ KisDeselectGlobalSelectionCommand(KisImageWSP image, KUndo2Command * parent = 0); virtual ~KisDeselectGlobalSelectionCommand(); virtual void redo(); virtual void undo(); private: KisImageWSP m_image; KisSelectionSP m_oldSelection; }; #endif diff --git a/krita/image/commands/kis_image_change_layers_command.h b/krita/image/commands/kis_image_change_layers_command.h index 6d7240e90eb..03d83495b74 100644 --- a/krita/image/commands/kis_image_change_layers_command.h +++ b/krita/image/commands/kis_image_change_layers_command.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_CHANGE_LAYERS_COMMAND_H_ #define KIS_IMAGE_CHANGE_LAYERS_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" class KisImageChangeLayersCommand : public KisImageCommand { public: KisImageChangeLayersCommand(KisImageWSP image, KisNodeSP oldRootLayer, KisNodeSP newRootLayer); virtual void redo(); virtual void undo(); private: KisNodeSP m_oldRootLayer; KisNodeSP m_newRootLayer; }; #endif diff --git a/krita/image/commands/kis_image_command.h b/krita/image/commands/kis_image_command.h index f6b990bddbc..e627996d0fa 100644 --- a/krita/image/commands/kis_image_command.h +++ b/krita/image/commands/kis_image_command.h @@ -1,71 +1,71 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_COMMAND_H_ #define KIS_IMAGE_COMMAND_H_ -#include +#include #include #include #include #include "kis_types.h" #include "kis_paint_device.h" /// the base command for commands altering a KisImage class KRITAIMAGE_EXPORT KisImageCommand : public KUndo2Command { public: /** * Constructor * @param name The name that will be shown in the ui * @param image The image the command will be working on. */ KisImageCommand(const KUndo2MagicString& name, KisImageWSP image, KUndo2Command *parent = 0); virtual ~KisImageCommand(); protected: /** * Used for performing the smallest update * after a node has been removed from stack. * First tries to setDirty() node's siblings. * If it doesn't help, performs full refresh. */ class UpdateTarget { public: UpdateTarget(KisImageWSP image, KisNodeSP removedNode, const QRect &updateRect); void update(); private: KisImageWSP m_image; QRect m_updateRect; int m_removedNodeIndex; KisNodeSP m_removedNodeParent; }; protected: KisImageWSP m_image; }; #endif // KIS_IMAGE_COMMAND_H_ diff --git a/krita/image/commands/kis_image_layer_add_command.h b/krita/image/commands/kis_image_layer_add_command.h index f93215a4a29..a683caecffe 100644 --- a/krita/image/commands/kis_image_layer_add_command.h +++ b/krita/image/commands/kis_image_layer_add_command.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_LAYER_ADD_COMMAND_H_ #define KIS_IMAGE_LAYER_ADD_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" /// The command for adding a layer class KRITAIMAGE_EXPORT KisImageLayerAddCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param layer the layer to add */ KisImageLayerAddCommand(KisImageWSP image, KisNodeSP layer, KisNodeSP parent, KisNodeSP aboveThis, bool doRedoUpdates = true, bool doUndoUpdates = true); KisImageLayerAddCommand(KisImageWSP image, KisNodeSP layer, KisNodeSP parent, quint32 index, bool doRedoUpdates = true, bool doUndoUpdates = true); virtual void redo(); virtual void undo(); private: KisNodeSP m_layer; KisNodeSP m_parent; KisNodeSP m_aboveThis; quint32 m_index; bool m_doRedoUpdates; bool m_doUndoUpdates; }; #endif diff --git a/krita/image/commands/kis_image_layer_move_command.h b/krita/image/commands/kis_image_layer_move_command.h index ae3a0068870..e72c388fd13 100644 --- a/krita/image/commands/kis_image_layer_move_command.h +++ b/krita/image/commands/kis_image_layer_move_command.h @@ -1,61 +1,61 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_LAYER_MOVE_COMMAND_H_ #define KIS_IMAGE_LAYER_MOVE_COMMAND_H_ -#include +#include #include #include #include "kis_types.h" #include "kis_image_command.h" /// The command for layer moves inside the layer stack class KRITAIMAGE_EXPORT KisImageLayerMoveCommand : public KisImageCommand { public: /** * Command for layer moves inside the layer stack * * @param image the image * @param layer the moved layer * @param newParent the next parent of the layer * @param newAbove the layer that will be below the layer after the move */ KisImageLayerMoveCommand(KisImageWSP image, KisNodeSP node, KisNodeSP newParent, KisNodeSP newAbove); KisImageLayerMoveCommand(KisImageWSP image, KisNodeSP node, KisNodeSP newParent, quint32 index); virtual void redo(); virtual void undo(); private: KisNodeSP m_layer; KisNodeSP m_prevParent; KisNodeSP m_prevAbove; KisNodeSP m_newParent; KisNodeSP m_newAbove; quint32 m_index; bool m_useIndex; }; #endif diff --git a/krita/image/commands/kis_image_layer_remove_command.h b/krita/image/commands/kis_image_layer_remove_command.h index 31df225406f..f668031875e 100644 --- a/krita/image/commands/kis_image_layer_remove_command.h +++ b/krita/image/commands/kis_image_layer_remove_command.h @@ -1,43 +1,43 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_IMAGE_LAYER_REMOVE_COMMAND_H #define __KIS_IMAGE_LAYER_REMOVE_COMMAND_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_image_command.h" class KRITAIMAGE_EXPORT KisImageLayerRemoveCommand : public KisImageCommand { public: KisImageLayerRemoveCommand(KisImageWSP image, KisNodeSP node); ~KisImageLayerRemoveCommand(); void redo(); void undo(); private: void addSubtree(KisImageWSP image, KisNodeSP node); private: KisNodeSP m_node; }; #endif /* __KIS_IMAGE_LAYER_REMOVE_COMMAND_H */ diff --git a/krita/image/commands/kis_image_layer_remove_command_impl.h b/krita/image/commands/kis_image_layer_remove_command_impl.h index a63fc974856..991471d47df 100644 --- a/krita/image/commands/kis_image_layer_remove_command_impl.h +++ b/krita/image/commands/kis_image_layer_remove_command_impl.h @@ -1,51 +1,51 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_LAYER_REMOVE_COMMAND_IMPL_H_ #define KIS_IMAGE_LAYER_REMOVE_COMMAND_IMPL_H_ #include -#include +#include #include "kis_types.h" #include "kis_image_command.h" /// The command for removing a single node. It should be used inside /// KisImageLayerRemoveCommand only class KRITAIMAGE_EXPORT KisImageLayerRemoveCommandImpl : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param node the node to remove */ KisImageLayerRemoveCommandImpl(KisImageWSP image, KisNodeSP node, KUndo2Command *parent = 0); ~KisImageLayerRemoveCommandImpl(); virtual void redo(); virtual void undo(); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/commands/kis_image_lock_command.h b/krita/image/commands/kis_image_lock_command.h index c477e1db2b0..62559aec9eb 100644 --- a/krita/image/commands/kis_image_lock_command.h +++ b/krita/image/commands/kis_image_lock_command.h @@ -1,50 +1,48 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_LOCK_COMMAND_H_ #define KIS_IMAGE_LOCK_COMMAND_H_ -#include - #include "kis_types.h" #include "kis_image_command.h" /** * The command for image locking inside macro commands. * * It will ensurce that the image is properly locked during the execution * of macro commands. Place it at the start and end of the macro command. */ class KisImageLockCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param lockImage Locking state of the image, while redo. */ KisImageLockCommand(KisImageWSP image, bool lockImage); virtual void redo(); virtual void undo(); }; #endif diff --git a/krita/image/commands/kis_image_node_lower_command.h b/krita/image/commands/kis_image_node_lower_command.h index 2567518e285..6cb1a64497d 100644 --- a/krita/image/commands/kis_image_node_lower_command.h +++ b/krita/image/commands/kis_image_node_lower_command.h @@ -1,46 +1,46 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_IMAGE_NODE_LOWER_COMMAND_H_ #define KIS_IMAGE_NODE_LOWER_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" /// The command for adding a layer class KRITAIMAGE_EXPORT KisImageNodeLowerCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param layer the layer to add */ KisImageNodeLowerCommand(KisImageWSP image, KisNodeSP node); virtual void redo(); virtual void undo(); private: KisNodeSP m_node; }; #endif diff --git a/krita/image/commands/kis_image_node_raise_command.h b/krita/image/commands/kis_image_node_raise_command.h index 934b0d475f1..8de7b69f464 100644 --- a/krita/image/commands/kis_image_node_raise_command.h +++ b/krita/image/commands/kis_image_node_raise_command.h @@ -1,46 +1,46 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_IMAGE_NODE_RAISE_COMMAND_H_ #define KIS_IMAGE_NODE_RAISE_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" /// The command for adding a layer class KRITAIMAGE_EXPORT KisImageNodeRaiseCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param layer the layer to add */ KisImageNodeRaiseCommand(KisImageWSP image, KisNodeSP node); virtual void redo(); virtual void undo(); private: KisNodeSP m_node; }; #endif diff --git a/krita/image/commands/kis_image_node_to_bottom_command.h b/krita/image/commands/kis_image_node_to_bottom_command.h index c381ef21495..8248ef386bf 100644 --- a/krita/image/commands/kis_image_node_to_bottom_command.h +++ b/krita/image/commands/kis_image_node_to_bottom_command.h @@ -1,49 +1,49 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_IMAGE_NODE_TO_BOTTOM_COMMAND_H_ #define KIS_IMAGE_NODE_TO_BOTTOM_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" #include "kis_paint_device.h" /// The command for adding a layer class KRITAIMAGE_EXPORT KisImageNodeToBottomCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param layer the layer to add */ KisImageNodeToBottomCommand(KisImageWSP image, KisNodeSP node); virtual void redo(); virtual void undo(); private: KisNodeSP m_node; KisNodeSP m_prevParent; KisNodeSP m_prevAbove; }; #endif diff --git a/krita/image/commands/kis_image_node_to_top_command.h b/krita/image/commands/kis_image_node_to_top_command.h index 17420a563df..b296e91fa55 100644 --- a/krita/image/commands/kis_image_node_to_top_command.h +++ b/krita/image/commands/kis_image_node_to_top_command.h @@ -1,49 +1,49 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_IMAGE_NODE_TO_TOP_COMMAND_H_ #define KIS_IMAGE_NODE_TO_TOP_COMMAND_H_ -#include +#include #include "kis_types.h" #include "kis_image_command.h" #include "kis_paint_device.h" /// The command for adding a layer class KRITAIMAGE_EXPORT KisImageNodeToTopCommand : public KisImageCommand { public: /** * Constructor * @param image The image the command will be working on. * @param layer the layer to add */ KisImageNodeToTopCommand(KisImageWSP image, KisNodeSP node); virtual void redo(); virtual void undo(); private: KisNodeSP m_node; KisNodeSP m_prevParent; KisNodeSP m_prevAbove; }; #endif diff --git a/krita/image/commands/kis_image_set_projection_color_space_command.h b/krita/image/commands/kis_image_set_projection_color_space_command.h index 617b92d6d9b..40c26b7a07a 100644 --- a/krita/image/commands/kis_image_set_projection_color_space_command.h +++ b/krita/image/commands/kis_image_set_projection_color_space_command.h @@ -1,42 +1,41 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_SET_PROJECTION_COLOR_SPACE_COMMAND_H_ #define KIS_IMAGE_SET_PROJECTION_COLOR_SPACE_COMMAND_H_ -#include #include "kis_image_command.h" class KoColorSpace; class KisImageSetProjectionColorSpaceCommand : public KisImageCommand { public: KisImageSetProjectionColorSpaceCommand(KisImageWSP image, const KoColorSpace * afterColorSpace); virtual void redo(); virtual void undo(); private: const KoColorSpace * m_beforeColorSpace; const KoColorSpace * m_afterColorSpace; }; #endif /* KIS_IMAGE_SET_PROJECTION_COLOR_SPACE_COMMAND_H_ */ diff --git a/krita/image/commands/kis_layer_command.h b/krita/image/commands/kis_layer_command.h index 6185a8852f0..067a21a5c4e 100644 --- a/krita/image/commands/kis_layer_command.h +++ b/krita/image/commands/kis_layer_command.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * * 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_LAYER_COMMAND_H_ #define KIS_LAYER_COMMAND_H_ #include -#include +#include #include "kis_types.h" class KisLayer; /// the base command for commands altering a layer class KRITAIMAGE_EXPORT KisLayerCommand : public KUndo2Command { public: /** * Constructor * @param name The name that will be shown in the ui * @param layer The layer the command will be working on. */ KisLayerCommand(const KUndo2MagicString& name, KisLayerSP layer); virtual ~KisLayerCommand(); protected: KisLayerSP m_layer; }; #endif diff --git a/krita/image/commands/kis_layer_props_command.h b/krita/image/commands/kis_layer_props_command.h index cc625a7b29b..d729f34ada5 100644 --- a/krita/image/commands/kis_layer_props_command.h +++ b/krita/image/commands/kis_layer_props_command.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LAYER_PROPS_COMMAND_H #define KIS_LAYER_PROPS_COMMAND_H -#include +#include #include #include #include #include "kis_types.h" #include "kis_layer_command.h" #include "kis_paint_device.h" /// The command for layer property changes class KRITAIMAGE_EXPORT KisLayerPropsCommand : public KisLayerCommand { public: /** * Command for layer property changes * * This command stores the current layer properties and set the new properties * * @param image the image * @param layer the layer whose propertys will be changed * @param opacity the new layer opacity * @param compositeOp the new layer composite op * @param name the new layer name * @param undoChannelFlags specifies if the channel flags should be undoable, normally they are not but they can be if e.g the channels change */ KisLayerPropsCommand(KisLayerSP layer, qint32 oldOpacity, qint32 newOpactiy, const QString& oldCompositeOp, const QString& newCompositeOp, const QString& oldName, const QString& newName, const QBitArray oldChannelFlags, const QBitArray newChannelFlags, bool undoChannelFlags = false); virtual ~KisLayerPropsCommand(); virtual void redo(); virtual void undo(); private: QString m_oldName; QString m_newName; qint32 m_oldOpacity; qint32 m_newOpacity; QString m_oldCompositeOp; QString m_newCompositeOp; QBitArray m_oldChannelFlags; QBitArray m_newChannelFlags; bool m_undoChannelFlags; }; #endif diff --git a/krita/image/commands/kis_node_command.h b/krita/image/commands/kis_node_command.h index 12a57745cc7..e19164891f0 100644 --- a/krita/image/commands/kis_node_command.h +++ b/krita/image/commands/kis_node_command.h @@ -1,45 +1,45 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * * 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_NODE_COMMAND_H_ #define KIS_NODE_COMMAND_H_ -#include +#include #include #include "kis_types.h" class KisNode; /// the base command for commands altering a node class KRITAIMAGE_EXPORT KisNodeCommand : public KUndo2Command { public: /** * Constructor * @param name The name that will be shown in the ui * @param node The node the command will be working on. */ KisNodeCommand(const KUndo2MagicString& name, KisNodeSP node); virtual ~KisNodeCommand(); protected: KisNodeSP m_node; }; #endif /* KIS_NODE_COMMAND_H_*/ diff --git a/krita/image/commands/kis_paintdevice_convert_type_command.h b/krita/image/commands/kis_paintdevice_convert_type_command.h index e1b238e3c4a..416a0eca625 100644 --- a/krita/image/commands/kis_paintdevice_convert_type_command.h +++ b/krita/image/commands/kis_paintdevice_convert_type_command.h @@ -1,107 +1,105 @@ /* * Copyright (c) 2009 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_PAINTDEVICE_CONVERT_TYPE_COMMAND_H #define KIS_PAINTDEVICE_CONVERT_TYPE_COMMAND_H -#include - #include #include #include #include #include #include #include "kis_types.h" #include "kis_paint_device.h" class KisPaintDeviceConvertTypeCommand : public KUndo2Command { public: KisPaintDeviceConvertTypeCommand(KisPaintDeviceSP paintDevice, KisDataManagerSP beforeData, const KoColorSpace * beforeColorSpace, KisDataManagerSP afterData, const KoColorSpace * afterColorSpace) { m_firstRedo = true; Q_ASSERT(paintDevice); Q_ASSERT(beforeData); Q_ASSERT(afterData); Q_ASSERT(beforeData != afterData); m_paintDevice = paintDevice; m_beforeData = beforeData; m_beforeColorSpaceModelId = beforeColorSpace->colorModelId().id(); m_beforeColorSpaceDepthId = beforeColorSpace->colorDepthId().id(); if (beforeColorSpace->profile()) { m_beforeProfileName = beforeColorSpace->profile()->name(); } m_afterData = afterData; m_afterColorSpaceModelId = afterColorSpace->colorModelId().id(); m_afterColorSpaceDepthId = afterColorSpace->colorDepthId().id(); if (afterColorSpace->profile()) { m_afterProfileName = afterColorSpace->profile()->name(); } } virtual ~KisPaintDeviceConvertTypeCommand() { } public: virtual void redo() { //KUndo2QStack calls redo(), so the first call needs to be blocked if (m_firstRedo) { m_firstRedo = false; return; } dbgImage << m_paintDevice << m_beforeColorSpaceModelId << m_beforeColorSpaceDepthId << "to" << m_afterColorSpaceModelId << m_afterColorSpaceDepthId; const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(m_afterColorSpaceModelId, m_afterColorSpaceDepthId, m_afterProfileName); m_paintDevice->setDataManager(m_afterData, cs); m_paintDevice->setDirty(); } virtual void undo() { dbgImage << m_paintDevice << m_afterColorSpaceModelId << m_afterColorSpaceDepthId << "to" << m_beforeColorSpaceModelId << m_beforeColorSpaceDepthId ; const KoColorSpace* cs = KoColorSpaceRegistry::instance()->colorSpace(m_beforeColorSpaceModelId, m_beforeColorSpaceDepthId, m_beforeProfileName); m_paintDevice->setDataManager(m_beforeData, cs); m_paintDevice->setDirty(); } private: bool m_firstRedo; // there is a mismatch between the Qt undo system and what we need for krita... KisPaintDeviceSP m_paintDevice; KisDataManagerSP m_beforeData; QString m_beforeColorSpaceModelId; QString m_beforeColorSpaceDepthId; QString m_beforeProfileName; KisDataManagerSP m_afterData; QString m_afterColorSpaceModelId; QString m_afterColorSpaceDepthId; QString m_afterProfileName; }; #endif diff --git a/krita/image/commands/kis_reselect_global_selection_command.h b/krita/image/commands/kis_reselect_global_selection_command.h index a1a2856be84..f823b609f9d 100644 --- a/krita/image/commands/kis_reselect_global_selection_command.h +++ b/krita/image/commands/kis_reselect_global_selection_command.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_RESELECT_GLOBAL_SELECTION_COMMAND_H #define KIS_RESELECT_GLOBAL_SELECTION_COMMAND_H -#include +#include #include #include "kis_types.h" /// The command for deselection the global selection of KisImage class KRITAIMAGE_EXPORT KisReselectGlobalSelectionCommand : public KUndo2Command { public: /** * Constructor * @param image the image * @param parent the parent command */ KisReselectGlobalSelectionCommand(KisImageWSP image, KUndo2Command * parent = 0); virtual ~KisReselectGlobalSelectionCommand(); virtual void redo(); virtual void undo(); private: KisImageWSP m_image; bool m_canReselect; }; #endif diff --git a/krita/image/commands/kis_set_global_selection_command.h b/krita/image/commands/kis_set_global_selection_command.h index 7eb563c06de..2615157401b 100644 --- a/krita/image/commands/kis_set_global_selection_command.h +++ b/krita/image/commands/kis_set_global_selection_command.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SET_GLOBAL_SELECTION_COMMAND_H #define KIS_SET_GLOBAL_SELECTION_COMMAND_H -#include +#include #include #include "kis_types.h" /** * This command sets the global selection of the image. No saving * of the previous selection for "Reselect" action happens */ class KRITAIMAGE_EXPORT KisSetGlobalSelectionCommand : public KUndo2Command { public: /** * Constructor * @param image the image to set the global selection on * @param selection the selection that will be set a global selection, * null selection will remove the selection */ KisSetGlobalSelectionCommand(KisImageWSP image, KisSelectionSP selection); virtual void redo(); virtual void undo(); private: KisImageWSP m_image; KisSelectionSP m_newSelection; KisSelectionSP m_oldSelection; }; /** * Sets initial selection for the image. Nothing is selected, * but the defaultBounds are set properly */ class KRITAIMAGE_EXPORT KisSetEmptyGlobalSelectionCommand : public KisSetGlobalSelectionCommand { public: KisSetEmptyGlobalSelectionCommand(KisImageWSP image); }; #endif //KIS_SET_GLOBAL_SELECTION_COMMAND_H diff --git a/krita/image/commands_new/kis_activate_selection_mask_command.cpp b/krita/image/commands_new/kis_activate_selection_mask_command.cpp new file mode 100644 index 00000000000..12eeaa13ade --- /dev/null +++ b/krita/image/commands_new/kis_activate_selection_mask_command.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Dmitry Kazakov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_activate_selection_mask_command.h" + +#include "kis_layer.h" +#include "kis_selection_mask.h" + + +KisActivateSelectionMaskCommand::KisActivateSelectionMaskCommand(KisSelectionMaskSP selectionMask, bool value) + : m_selectionMask(selectionMask), + m_value(value) +{ + if (m_previousActiveMask != m_selectionMask) { + KisLayerSP parent = dynamic_cast(selectionMask->parent().data()); + if (parent) { + m_previousActiveMask = parent->selectionMask(); + } + } + + m_previousValue = selectionMask->active(); +} + +void KisActivateSelectionMaskCommand::redo() +{ + m_selectionMask->setActive(m_value); +} + +void KisActivateSelectionMaskCommand::undo() +{ + m_selectionMask->setActive(m_previousValue); + + if (m_value && m_previousActiveMask) { + m_previousActiveMask->setActive(true); + } +} + + diff --git a/krita/ui/flake/kis_take_all_shapes_command.h b/krita/image/commands_new/kis_activate_selection_mask_command.h similarity index 60% copy from krita/ui/flake/kis_take_all_shapes_command.h copy to krita/image/commands_new/kis_activate_selection_mask_command.h index e281fec5877..3aa07501d7f 100644 --- a/krita/ui/flake/kis_take_all_shapes_command.h +++ b/krita/image/commands_new/kis_activate_selection_mask_command.h @@ -1,48 +1,42 @@ /* - * Copyright (c) 2013 Dmitry Kazakov + * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -#ifndef __KIS_TAKE_ALL_SHAPES_COMMAND_H -#define __KIS_TAKE_ALL_SHAPES_COMMAND_H - -#include +#ifndef __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H +#define __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H +#include #include "kundo2command.h" - -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" -class KoShape; -class KisShapeSelection; - - -class KisTakeAllShapesCommand : public KUndo2Command +class KRITAIMAGE_EXPORT KisActivateSelectionMaskCommand : public KUndo2Command { public: - KisTakeAllShapesCommand(KisShapeSelection *shapeSelection, bool takeSilently); - ~KisTakeAllShapesCommand(); + KisActivateSelectionMaskCommand(KisSelectionMaskSP selectionMask, bool value); - void redo(); void undo(); + void redo(); private: - KisShapeSelection *m_shapeSelection; - QList m_shapes; - bool m_takeSilently; + KisSelectionMaskSP m_selectionMask; + KisSelectionMaskSP m_previousActiveMask; + bool m_value; + bool m_previousValue; }; -#endif /* __KIS_TAKE_ALL_SHAPES_COMMAND_H */ +#endif /* __KIS_ACTIVATE_SELECTION_MASK_COMMAND_H */ diff --git a/krita/image/commands_new/kis_image_resize_command.h b/krita/image/commands_new/kis_image_resize_command.h index 8cefc8bfcde..992594a380b 100644 --- a/krita/image/commands_new/kis_image_resize_command.h +++ b/krita/image/commands_new/kis_image_resize_command.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_RESIZE_COMMAND_H_ #define KIS_IMAGE_RESIZE_COMMAND_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include #include class KRITAIMAGE_EXPORT KisImageResizeCommand : public KUndo2Command { public: KisImageResizeCommand(KisImageWSP image, const QSize& newRect); void redo(); void undo(); private: QSize m_sizeBefore; QSize m_sizeAfter; KisImageWSP m_image; }; #endif diff --git a/krita/image/commands_new/kis_image_set_resolution_command.h b/krita/image/commands_new/kis_image_set_resolution_command.h index 621243ae2e6..41cdea9d8cd 100644 --- a/krita/image/commands_new/kis_image_set_resolution_command.h +++ b/krita/image/commands_new/kis_image_set_resolution_command.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_SET_RESOLUTION_COMMAND_H #define KIS_IMAGE_SET_RESOLUTION_COMMAND_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include class KRITAIMAGE_EXPORT KisImageSetResolutionCommand : public KUndo2Command { public: KisImageSetResolutionCommand(KisImageWSP image, qreal newXRes, qreal newYRes, KUndo2Command *parent = 0); void undo(); void redo(); private: KisImageWSP m_image; qreal m_newXRes; qreal m_newYRes; qreal m_oldXRes; qreal m_oldYRes; }; /** * A special workaround command for updating the shapes. It resets * shapes always (for both undo() and redo() actions) after all the * child commands are finished. Usually, it should have the only child * KisImageSetResolutionCommand. * * Usecase: When you change the resolution of the image, the * projection of the vector layer is still rendered in old * resolution. So you should reset it and render again. */ class KRITAIMAGE_EXPORT KisResetShapesCommand : public KUndo2Command { public: KisResetShapesCommand(KisNodeSP rootNode); void undo(); void redo(); private: void resetNode(KisNodeSP node); private: KisNodeSP m_rootNode; }; #endif // KIS_IMAGE_SET_RESOLUTION_COMMAND_H diff --git a/krita/image/commands_new/kis_move_command_common.h b/krita/image/commands_new/kis_move_command_common.h index d365b3acfe4..33f9f3090a6 100644 --- a/krita/image/commands_new/kis_move_command_common.h +++ b/krita/image/commands_new/kis_move_command_common.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2007 Boudewijn Rempt * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_MOVE_COMMAND_COMMON_H #define KIS_MOVE_COMMAND_COMMON_H #include #include #include "kundo2command.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" /** * KisMoveCommandCommon is a general template for a command that moves * entities capable of setX() and setY() actions. Generally in Krita * you should now move the device itself, only the node containing * that device. But the case of the selections is a bit special, so we * move them separately. */ template class KRITAIMAGE_EXPORT KisMoveCommandCommon : public KUndo2Command { public: KisMoveCommandCommon(ObjectSP object, const QPoint& oldPos, const QPoint& newPos, KUndo2Command *parent = 0) : KUndo2Command(kundo2_i18n("Move"), parent), m_oldPos(oldPos), m_newPos(newPos), m_object(object) { } void redo() { moveTo(m_newPos); } void undo() { moveTo(m_oldPos); } private: void moveTo(const QPoint& pos) { /** * FIXME: Hack alert: * Our iterators don't have guarantees on thread-safety * when the offset varies. When it is fixed, remove the locking. * see: KisIterator::stressTest(), KisToolMove::mousePressEvent() */ m_object->setX(pos.x()); m_object->setY(pos.y()); } private: QPoint m_oldPos; QPoint m_newPos; protected: ObjectSP m_object; }; #endif diff --git a/krita/image/commands_new/kis_saved_commands.h b/krita/image/commands_new/kis_saved_commands.h index c2229b5d7c9..dfb5c80a34f 100644 --- a/krita/image/commands_new/kis_saved_commands.h +++ b/krita/image/commands_new/kis_saved_commands.h @@ -1,94 +1,93 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SAVED_COMMANDS_H #define __KIS_SAVED_COMMANDS_H #include #include "kis_types.h" -#include "krita_export.h" #include "kis_stroke_job_strategy.h" class KisStrokesFacade; class KisSavedCommandBase : public KUndo2Command { public: KisSavedCommandBase(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade); virtual ~KisSavedCommandBase(); void undo(); void redo(); protected: virtual void addCommands(KisStrokeId id, bool undo) = 0; KisStrokesFacade* strokesFacade(); private: void runStroke(bool undo); private: KisStrokesFacade *m_strokesFacade; bool m_skipOneRedo; }; class KisSavedCommand : public KisSavedCommandBase { public: KisSavedCommand(KUndo2CommandSP command, KisStrokesFacade *strokesFacade); virtual int timedId(); void setTimedID(int timedID); virtual bool timedMergeWith(KUndo2Command *other); virtual QVector mergeCommandsVector(); virtual void setTime(); virtual QTime time(); virtual void setEndTime(); virtual QTime endTime(); virtual bool isMerged(); protected: void addCommands(KisStrokeId id, bool undo); private: KUndo2CommandSP m_command; }; class KisSavedMacroCommand : public KisSavedCommandBase { public: KisSavedMacroCommand(const KUndo2MagicString &name, KisStrokesFacade *strokesFacade); ~KisSavedMacroCommand(); void addCommand(KUndo2CommandSP command, KisStrokeJobData::Sequentiality sequentiality, KisStrokeJobData::Exclusivity exclusivity); void performCancel(KisStrokeId id, bool strokeUndo); protected: void addCommands(KisStrokeId id, bool undo); private: struct Private; Private * const m_d; }; #endif /* __KIS_SAVED_COMMANDS_H */ diff --git a/krita/image/commands_new/kis_set_layer_style_command.h b/krita/image/commands_new/kis_set_layer_style_command.h index a68d2b4d473..0b0659538a0 100644 --- a/krita/image/commands_new/kis_set_layer_style_command.h +++ b/krita/image/commands_new/kis_set_layer_style_command.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2007 Boudewijn Rempt * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SET_LAYER_STYLE_COMMAND_H #define KIS_SET_LAYER_STYLE_COMMAND_H #include #include "kundo2command.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" class KRITAIMAGE_EXPORT KisSetLayerStyleCommand : public KUndo2Command { public: KisSetLayerStyleCommand(KisLayerSP layer, KisPSDLayerStyleSP oldStyle, KisPSDLayerStyleSP newStyle, KUndo2Command *parent = 0); void undo(); void redo(); static void updateLayerStyle(KisLayerSP layer, KisPSDLayerStyleSP style); private: KisLayerSP m_layer; KisPSDLayerStyleSP m_oldStyle; KisPSDLayerStyleSP m_newStyle; }; #endif diff --git a/krita/image/commands_new/kis_update_command.h b/krita/image/commands_new/kis_update_command.h index f7d9f5c74c8..87adc4bf334 100644 --- a/krita/image/commands_new/kis_update_command.h +++ b/krita/image/commands_new/kis_update_command.h @@ -1,51 +1,51 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_UPDATE_COMMAND_H #define __KIS_UPDATE_COMMAND_H #include "kundo2command.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" class KisUpdatesFacade; class KRITAIMAGE_EXPORT KisUpdateCommand : public KUndo2Command { public: KisUpdateCommand(KisNodeSP node, QRect dirtyRect, KisUpdatesFacade *updatesFacade, bool needsFullRefresh = false); ~KisUpdateCommand(); void undo(); void redo(); private: void update(); private: KisNodeSP m_node; QRect m_dirtyRect; KisUpdatesFacade *m_updatesFacade; bool m_needsFullRefresh; }; #endif /* __KIS_UPDATE_COMMAND_H */ diff --git a/krita/image/filter/kis_color_transformation_configuration.h b/krita/image/filter/kis_color_transformation_configuration.h index 5910bbf2f52..3208c056a5c 100644 --- a/krita/image/filter/kis_color_transformation_configuration.h +++ b/krita/image/filter/kis_color_transformation_configuration.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2015 Thorsten Zachmann * * 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_TRANSFORMATION_CONFIGURATION_H_ #define _KIS_COLOR_TRANSFORMATION_CONFIGURATION_H_ #include "filter/kis_filter_configuration.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KoColorSpace; class KisColorTransformationFilter; class KRITAIMAGE_EXPORT KisColorTransformationConfiguration : public KisFilterConfiguration { public: KisColorTransformationConfiguration(const QString & name, qint32 version); virtual ~KisColorTransformationConfiguration(); KoColorTransformation *colorTransformation(const KoColorSpace *cs, const KisColorTransformationFilter * filter) const; private: struct Private; Private* const d; }; #endif /* _KIS_COLOR_TRANSFORMATION_CONFIGURATION_H_ */ diff --git a/krita/image/filter/kis_color_transformation_filter.h b/krita/image/filter/kis_color_transformation_filter.h index 7fa24561695..9e9b5f595ea 100644 --- a/krita/image/filter/kis_color_transformation_filter.h +++ b/krita/image/filter/kis_color_transformation_filter.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_COLOR_TRANSFORMATION_FILTER_H_ #define _KIS_COLOR_TRANSFORMATION_FILTER_H_ #include "kis_filter.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * This is a base class for filters that implement a filter for * \ref KoColorTransformation based filters. */ class KRITAIMAGE_EXPORT KisColorTransformationFilter : public KisFilter { public: KisColorTransformationFilter(const KoID& id, const KoID & category, const QString & entry); virtual ~KisColorTransformationFilter(); virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const; /** * Create the color transformation that will be applied on the device. */ virtual KoColorTransformation* createTransformation(const KoColorSpace* cs, const KisFilterConfiguration* config) const = 0; virtual KisFilterConfiguration* factoryConfiguration(const KisPaintDeviceSP) const; }; #endif diff --git a/krita/image/filter/kis_filter.h b/krita/image/filter/kis_filter.h index c32d103f970..772a23a1db1 100644 --- a/krita/image/filter/kis_filter.h +++ b/krita/image/filter/kis_filter.h @@ -1,130 +1,130 @@ /* * Copyright (c) 2004,2006-2007 Cyrille Berger * * 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_H_ #define _KIS_FILTER_H_ #include #include #include #include "KoID.h" #include "KoColorSpace.h" #include "kis_types.h" #include "kis_base_processor.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * Basic interface of a Krita filter. */ class KRITAIMAGE_EXPORT KisFilter : public KisBaseProcessor { public: static KoID categoryAdjust(); static KoID categoryArtistic(); static KoID categoryBlur(); static KoID categoryColors(); static KoID categoryEdgeDetection(); static KoID categoryEmboss(); static KoID categoryEnhance(); static KoID categoryMap(); static KoID categoryNonPhotorealistic(); static KoID categoryOther(); public: /** * Construct a Krita filter */ KisFilter(const KoID& id, const KoID & category, const QString & entry); virtual ~KisFilter(); public: /** * Override this function with the implementation of your filter. * * This is a low level function that expects all the conditions * for the @param device be met. Use usual process() methods * instead. * * @param device the paint device to filter * @param applyRect the rectangle where the filter is applied * @param config the parameters of the filter * @param progressUpdater to pass on the progress the filter is making */ virtual void processImpl(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater = 0 ) const = 0; /** * Filter \p src device and write the result into \p dst device. * If \p dst is an alpha color space device, it will get special * treatment. * * @param src the source paint device * @param dst the destination paint device * @param selection the selection * @param applyRect the rectangle where the filter is applied * @param config the parameters of the filter * @param progressUpdater to pass on the progress the filter is making */ void process(const KisPaintDeviceSP src, KisPaintDeviceSP dst, KisSelectionSP selection, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater = 0 ) const; /** * A convenience method for a two-device process() function */ void process(KisPaintDeviceSP device, const QRect& applyRect, const KisFilterConfiguration* config, KoUpdater* progressUpdater = 0 ) const; /** * Some filters need pixels outside the current processing rect to compute the new * value (for instance, convolution filters) */ virtual QRect neededRect(const QRect & rect, const KisFilterConfiguration* = 0) const; /** * Similar to \ref neededRect: some filters will alter a lot of pixels that are * near to each other at the same time. So when you changed a single rectangle * in a device, the actual rectangle that will feel the influence of this change * might be bigger. Use this function to determine that rect. */ virtual QRect changedRect(const QRect & rect, const KisFilterConfiguration* = 0) const; protected: QString configEntryGroup() const; }; #endif diff --git a/krita/image/filter/kis_filter_configuration.h b/krita/image/filter/kis_filter_configuration.h index 81777c0a68e..b94b905c997 100644 --- a/krita/image/filter/kis_filter_configuration.h +++ b/krita/image/filter/kis_filter_configuration.h @@ -1,138 +1,138 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_FILTER_CONFIGURATION_H_ #define _KIS_FILTER_CONFIGURATION_H_ #include #include "kis_properties_configuration.h" #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * KisFilterConfiguration does inherit neither KisShared or QSharedData * so sometimes there might be problem with broken QSharedPointer counters. * This macro activates debugging routines for such stuff. * * In the future, please either port the entire KisNodeFilterInterface * into KisSafeFilterConfigurationSP or derive filter configuration * interface from QSharedData to handle these cases. */ #define SANITY_CHECK_FILTER_CONFIGURATION_OWNER /** * A KisFilterConfiguration is the serializable representation of * the filter parameters. Filters can subclass this class to implement * direct accessors to properties, but properties not in the map will * not be serialized. * * XXX: Use KoProperties here! */ class KRITAIMAGE_EXPORT KisFilterConfiguration : public KisPropertiesConfiguration { public: /** * Create a new filter config. */ KisFilterConfiguration(const QString & name, qint32 version); protected: /** * Deep copy the filter configFile */ KisFilterConfiguration(const KisFilterConfiguration & rhs); public: virtual ~KisFilterConfiguration(); public: /** * This function is use to convert from legacy XML as used in .kra file. */ virtual void fromLegacyXML(const QDomElement&); using KisPropertiesConfiguration::fromXML; using KisPropertiesConfiguration::toXML; virtual void fromXML(const QDomElement&); virtual void toXML(QDomDocument&, QDomElement&) const; /** * Get the unique, language independent name of the filter. */ const QString & name() const; /** * Get the version of the filter that has created this config */ qint32 version() const; /** * Check if that configuration is compatible with this paint device. * The default implementation always return true. */ virtual bool isCompatible(const KisPaintDeviceSP) const; /** * @return an array with each colorspace channel a true/false bit * that indicates whether the channel should be filtered or left * alone. It is up to the filter to decide whether channels that * are to be left alone are copied to the dest file or not. */ QBitArray channelFlags() const; /** * Set the channel flags. An empty array is allowed; that means * that all channels are to be filtered. Filters can optimize on * that. The array must be in the order of the pixel layout. */ void setChannelFlags(QBitArray channelFlags); /** * These functions exist solely to allow plugins to reimplement them as * needed, while allowing consumers to implement support for them without * linking directly to the plugin. In particular, the filter management * in Sketch requires this. */ virtual void setCurve(const KisCubicCurve &curve); virtual const KisCubicCurve& curve() const; virtual void setCurves(QList &curves); virtual const QList& curves() const; #ifdef SANITY_CHECK_FILTER_CONFIGURATION_OWNER private: friend class KisNodeFilterInterface; int sanityRefUsageCounter(); int sanityDerefUsageCounter(); #endif /* SANITY_CHECK_FILTER_CONFIGURATION_OWNER */ protected: void setVersion(qint32 version); private: struct Private; Private* const d; }; Q_DECLARE_METATYPE(KisFilterConfiguration*) #endif // _KIS_FILTER_CONFIGURATION_H_ diff --git a/krita/image/filter/kis_filter_registry.h b/krita/image/filter/kis_filter_registry.h index bd30dcbe336..ba594be091d 100644 --- a/krita/image/filter/kis_filter_registry.h +++ b/krita/image/filter/kis_filter_registry.h @@ -1,59 +1,59 @@ /* * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004 Cyrille Berger * * 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_REGISTRY_H_ #define KIS_FILTER_REGISTRY_H_ #include #include "kis_types.h" #include "KoGenericRegistry.h" -#include +#include class QString; class KisFilterConfiguration; class KRITAIMAGE_EXPORT KisFilterRegistry : public QObject, public KoGenericRegistry { Q_OBJECT public: virtual ~KisFilterRegistry(); static KisFilterRegistry* instance(); void add(KisFilterSP item); void add(const QString &id, KisFilterSP item); KisFilterConfiguration* cloneConfiguration(KisFilterConfiguration*); Q_SIGNALS: void filterAdded(QString id); private: KisFilterRegistry(QObject *parent); KisFilterRegistry(const KisFilterRegistry&); KisFilterRegistry operator=(const KisFilterRegistry&); }; #endif // KIS_FILTERSPACE_REGISTRY_H_ diff --git a/krita/image/floodfill/kis_fill_interval_map.h b/krita/image/floodfill/kis_fill_interval_map.h index af40b215a9b..84fe9558988 100644 --- a/krita/image/floodfill/kis_fill_interval_map.h +++ b/krita/image/floodfill/kis_fill_interval_map.h @@ -1,51 +1,51 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_FILL_INTERVAL_MAP_H #define __KIS_FILL_INTERVAL_MAP_H #include #include #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_fill_interval.h" class KRITAIMAGE_EXPORT KisFillIntervalMap { public: public: KisFillIntervalMap(); ~KisFillIntervalMap(); void insertInterval(const KisFillInterval &interval); void cropInterval(KisFillInterval *interval); QStack fetchAllIntervals(int rowCorrection = 0) const; void clear(); private: friend class KisFillIntervalMapTest; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_FILL_INTERVAL_MAP_H */ diff --git a/krita/image/floodfill/kis_scanline_fill.h b/krita/image/floodfill/kis_scanline_fill.h index 13895f0893c..e505bd3fbce 100644 --- a/krita/image/floodfill/kis_scanline_fill.h +++ b/krita/image/floodfill/kis_scanline_fill.h @@ -1,65 +1,65 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SCANLINE_FILL_H #define __KIS_SCANLINE_FILL_H #include -#include +#include #include #include class KisFillInterval; class KisFillIntervalMap; class KRITAIMAGE_EXPORT KisScanlineFill { public: KisScanlineFill(KisPaintDeviceSP device, const QPoint &startPoint, const QRect &boundingRect); ~KisScanlineFill(); void fillColor(const KoColor &fillColor); void fillSelection(KisPixelSelectionSP pixelSelection); void setThreshold(int threshold); private: friend class KisScanlineFillTest; Q_DISABLE_COPY(KisScanlineFill) template void processLine(KisFillInterval interval, const int rowIncrement, T &pixelPolicy); template void extendedPass(KisFillInterval *currentInterval, int srcRow, bool extendRight, T &pixelPolicy); template void runImpl(T &pixelPolicy); private: void testingProcessLine(const KisFillInterval &processInterval); QVector testingGetForwardIntervals() const; KisFillIntervalMap* testingGetBackwardIntervals() const; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_SCANLINE_FILL_H */ diff --git a/krita/image/generator/kis_generator.h b/krita/image/generator/kis_generator.h index 97addbbab54..f0da49fede3 100644 --- a/krita/image/generator/kis_generator.h +++ b/krita/image/generator/kis_generator.h @@ -1,98 +1,98 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_GENERATOR_H_ #define _KIS_GENERATOR_H_ #include #include #include "KoID.h" #include "KoColorSpace.h" #include "kis_types.h" #include "kis_base_processor.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KisProcessingInformation; /** * Basic interface of a Krita generator: a generator is a program * that can fill a paint device with a color. A generator can have a * preferred colorspace. * * Generators can have initial parameter settings that determine the * way a particular generator works, but also state that allows the generator * to continue from one invocation of generate to another (handy for, e.g., * painting) */ class KRITAIMAGE_EXPORT KisGenerator : public KisBaseProcessor { friend class KisGeneratorConfigurationFactory; public: KisGenerator(const KoID& id, const KoID & category, const QString & entry); virtual ~KisGenerator(); public: /** * Override this function with the implementation of your generator. * * @param dst the destination paint device * @param size the size of the area that is to be filled * @param config the parameters of the filter */ virtual void generate(KisProcessingInformation dst, const QSize& size, const KisFilterConfiguration* config, KoUpdater* progressUpdater ) const = 0; /** * Provided for convenience when no progress reporting is needed. */ virtual void generate(KisProcessingInformation dst, const QSize& size, const KisFilterConfiguration* config ) const; /** * A generator may be specialized for working in a certain colorspace. * If so, this function returns in instance of that colorspace, else * it return 0. */ virtual const KoColorSpace * colorSpace(); /** * @param _imageArea the rectangle of the image * @return the rectangle that is affected by this generator, if the generator * is supposed to affect all pixels, then the function should return * @p _imageArea */ virtual QRect generatedRect(QRect _imageArea, const KisFilterConfiguration* = 0) const; protected: /// @return the name of config group in KConfig QString configEntryGroup() const; }; #endif diff --git a/krita/image/generator/kis_generator_layer.cpp b/krita/image/generator/kis_generator_layer.cpp index b76008eca0b..1a076742a46 100644 --- a/krita/image/generator/kis_generator_layer.cpp +++ b/krita/image/generator/kis_generator_layer.cpp @@ -1,166 +1,165 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_generator_layer.h" #include #include "kis_debug.h" #include #include "kis_selection.h" #include "filter/kis_filter_configuration.h" #include "kis_processing_information.h" #include "generator/kis_generator_registry.h" #include "generator/kis_generator.h" #include "kis_node_visitor.h" #include "kis_processing_visitor.h" #include "kis_signal_compressor.h" #include "kis_recalculate_generator_layer_job.h" #define UPDATE_DELAY 100 /*ms */ struct KisGeneratorLayer::Private { Private() : updateSignalCompressor(UPDATE_DELAY, KisSignalCompressor::FIRST_INACTIVE) { } KisSignalCompressor updateSignalCompressor; }; KisGeneratorLayer::KisGeneratorLayer(KisImageWSP image, const QString &name, KisFilterConfiguration *kfc, KisSelectionSP selection) : KisSelectionBasedLayer(image, name, selection, kfc, true), m_d(new Private) { connect(&m_d->updateSignalCompressor, SIGNAL(timeout()), SLOT(slotDelayedStaticUpdate())); update(); } KisGeneratorLayer::KisGeneratorLayer(const KisGeneratorLayer& rhs) : KisSelectionBasedLayer(rhs), m_d(new Private) { connect(&m_d->updateSignalCompressor, SIGNAL(timeout()), SLOT(slotDelayedStaticUpdate())); } KisGeneratorLayer::~KisGeneratorLayer() { } void KisGeneratorLayer::setFilter(KisFilterConfiguration *filterConfig) { KisSelectionBasedLayer::setFilter(filterConfig); update(); } void KisGeneratorLayer::slotDelayedStaticUpdate() { /** * The mask might have been deleted from the layers stack in the * meanwhile. Just ignore the updates in the case. */ KisLayerSP parentLayer = dynamic_cast(parent().data()); if (!parentLayer) return; KisImageSP image = parentLayer->image(); if (image) { image->addSpontaneousJob(new KisRecalculateGeneratorLayerJob(this)); } } void KisGeneratorLayer::update() { KisSafeFilterConfigurationSP filterConfig = filter(); if (!filterConfig) { warnImage << "BUG: No Filter configuration in KisGeneratorLayer"; return; } KisGeneratorSP f = KisGeneratorRegistry::instance()->value(filterConfig->name()); if (!f) return; QRect processRect = exactBounds(); resetCache(f->colorSpace()); KisPaintDeviceSP originalDevice = original(); KisProcessingInformation dstCfg(originalDevice, processRect.topLeft(), 0); - filterConfig->setChannelFlags(channelFlags()); f->generate(dstCfg, processRect.size(), filterConfig.data()); // hack alert! // this avoids cyclic loop with KisRecalculateGeneratorLayerJob::run() KisSelectionBasedLayer::setDirty(extent()); } bool KisGeneratorLayer::accept(KisNodeVisitor & v) { return v.visit(this); } void KisGeneratorLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) { return visitor.visit(this, undoAdapter); } QIcon KisGeneratorLayer::icon() const { return themedIcon("krita_tool_color_fill"); } KisDocumentSectionModel::PropertyList KisGeneratorLayer::sectionModelProperties() const { KisSafeFilterConfigurationSP filterConfig = filter(); KisDocumentSectionModel::PropertyList l = KisLayer::sectionModelProperties(); l << KisDocumentSectionModel::Property(i18n("Generator"), KisGeneratorRegistry::instance()->value(filterConfig->name())->name()); return l; } void KisGeneratorLayer::setX(qint32 x) { KisSelectionBasedLayer::setX(x); m_d->updateSignalCompressor.start(); } void KisGeneratorLayer::setY(qint32 y) { KisSelectionBasedLayer::setY(y); m_d->updateSignalCompressor.start(); } void KisGeneratorLayer::setDirty(const QRect & rect) { KisSelectionBasedLayer::setDirty(rect); m_d->updateSignalCompressor.start(); } #include "kis_generator_layer.moc" diff --git a/krita/image/generator/kis_generator_layer.h b/krita/image/generator/kis_generator_layer.h index 06d40395f97..4ec53fee91f 100644 --- a/krita/image/generator/kis_generator_layer.h +++ b/krita/image/generator/kis_generator_layer.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GENERATOR_LAYER_H_ #define KIS_GENERATOR_LAYER_H_ #include "kis_selection_based_layer.h" -#include +#include #include class KisFilterConfiguration; /** * A generator layer is a special kind of layer that can be prefilled * with some pixel pattern generated by a KisGenerator plugin. * A KisGenerator is similar to a filter, but doesn't take * input pixel data and creates new pixel data. * * It is not possible to destructively paint on a generator layer. * * XXX: what about threadedness? */ class KRITAIMAGE_EXPORT KisGeneratorLayer : public KisSelectionBasedLayer { Q_OBJECT public: /** * Create a new Generator layer with the given configuration * and selection. Note that the selection will be _copied_ * (using COW, though). */ KisGeneratorLayer(KisImageWSP image, const QString &name, KisFilterConfiguration * kfc, KisSelectionSP selection); KisGeneratorLayer(const KisGeneratorLayer& rhs); virtual ~KisGeneratorLayer(); KisNodeSP clone() const { return KisNodeSP(new KisGeneratorLayer(*this)); } void setFilter(KisFilterConfiguration *filterConfig); bool accept(KisNodeVisitor &); void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); QIcon icon() const; KisDocumentSectionModel::PropertyList sectionModelProperties() const; /** * re-run the generator. This happens over the bounds * of the associated selection. */ void update(); using KisSelectionBasedLayer::setDirty; void setDirty(const QRect & rect); void setX(qint32 x); void setY(qint32 y); private Q_SLOTS: void slotDelayedStaticUpdate(); public: // KisIndirectPaintingSupport KisLayer* layer() { return this; } private: struct Private; const QScopedPointer m_d; }; #endif diff --git a/krita/image/generator/kis_generator_registry.h b/krita/image/generator/kis_generator_registry.h index 6bbd8cc15d1..d3fdf1b78d8 100644 --- a/krita/image/generator/kis_generator_registry.h +++ b/krita/image/generator/kis_generator_registry.h @@ -1,59 +1,59 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GENERATOR_REGISTRY_H_ #define KIS_GENERATOR_REGISTRY_H_ #include #include "kis_types.h" #include "KoGenericRegistry.h" -#include +#include class QString; class KisFilterConfiguration; /** * XXX_DOCS */ class KRITAIMAGE_EXPORT KisGeneratorRegistry : public QObject, public KoGenericRegistry { Q_OBJECT public: virtual ~KisGeneratorRegistry(); static KisGeneratorRegistry* instance(); void add(KisGeneratorSP item); void add(const QString &id, KisGeneratorSP item); KisFilterConfiguration* cloneConfiguration(KisFilterConfiguration* kfc); Q_SIGNALS: void generatorAdded(QString id); private: KisGeneratorRegistry(QObject *parent); KisGeneratorRegistry(const KisGeneratorRegistry&); KisGeneratorRegistry operator=(const KisGeneratorRegistry&); }; #endif // KIS_GENERATOR_REGISTRY_H_ diff --git a/krita/image/kis_acyclic_signal_connector.h b/krita/image/kis_acyclic_signal_connector.h index 7f4fc1bd3cb..7ee341b7efd 100644 --- a/krita/image/kis_acyclic_signal_connector.h +++ b/krita/image/kis_acyclic_signal_connector.h @@ -1,106 +1,106 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ACYCLIC_SIGNAL_CONNECTOR_H #define __KIS_ACYCLIC_SIGNAL_CONNECTOR_H #include -#include "krita_export.h" +#include "kritaimage_export.h" /** * A special class for connecting UI elements to manager classes. * It allows to avoid direct calling blockSignals() for the sender UI * element all the time. This is the most important when the measured * value can be changed not only by the user through the UI, but also * by the manager according to some internal rules. * * Example: * * Suppose we have the following connections: * * 1) QDoubleSpinBox::valueChanged(double) -> Manager::slotSetValue(double) * 2) Manager::valueChanged(double) -> QDoubleSpinBox::setValue(double) * * Now if the manager decides to change/correct the value, the spinbox * will go into an infinite loop. * * See an example in KisToolCropConfigWidget. */ class KRITAIMAGE_EXPORT KisAcyclicSignalConnector : public QObject { Q_OBJECT public: KisAcyclicSignalConnector(QObject *parent); void connectForwardDouble(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectBackwardDouble(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectForwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectBackwardInt(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectForwardBool(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectBackwardBool(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectForwardVoid(QObject *sender, const char *signal, QObject *receiver, const char *method); void connectBackwardVoid(QObject *sender, const char *signal, QObject *receiver, const char *method); private Q_SLOTS: void forwardSlotDouble(double value); void backwardSlotDouble(double value); void forwardSlotInt(int value); void backwardSlotInt(int value); void forwardSlotBool(bool value); void backwardSlotBool(bool value); void forwardSlotVoid(); void backwardSlotVoid(); Q_SIGNALS: void forwardSignalDouble(double value); void backwardSignalDouble(double value); void forwardSignalInt(int value); void backwardSignalInt(int value); void forwardSignalBool(bool value); void backwardSignalBool(bool value); void forwardSignalVoid(); void backwardSignalVoid(); private: int m_signalsBlocked; }; #endif /* __KIS_ACYCLIC_SIGNAL_CONNECTOR_H */ diff --git a/krita/image/kis_adjustment_layer.h b/krita/image/kis_adjustment_layer.h index 83584d1e93b..6c1a034acf2 100644 --- a/krita/image/kis_adjustment_layer.h +++ b/krita/image/kis_adjustment_layer.h @@ -1,123 +1,123 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ /** * @file * This file is part of the Krita calligra application. It handles * a contains a KisFilter OR a KisLayer, and this class is created * to influence the rendering of layers below this one. Can also * function as a fixating layer. * * @author Boudewijn Rempt * @author comments by hscott * @since 1.5 */ #ifndef KIS_ADJUSTMENT_LAYER_H_ #define KIS_ADJUSTMENT_LAYER_H_ #include -#include +#include #include "kis_selection_based_layer.h" class KisFilterConfiguration; /** * @class KisAdjustmentLayer Contains a KisFilter and a KisSelection. * If the selection is present, it is a mask used by the adjustment layer * to know where to apply the filter, thus the combination is used * to influence the rendering of the layers under this layer * in the layerstack. AdjustmentLayers also function as a kind * of "fixating layers". */ class KRITAIMAGE_EXPORT KisAdjustmentLayer : public KisSelectionBasedLayer { Q_OBJECT public: /** * creates a new adjustment layer with the given * configuration and selection. Note that the selection * will be _copied_ (with COW, though). * @param image the image to set this AdjustmentLayer to * @param name name of the adjustment layer * @param kfc the configuration for the adjustment layer filter * @param selection is a mask used by the adjustment layer to * know where to apply the filter. */ KisAdjustmentLayer(KisImageWSP image, const QString &name, KisFilterConfiguration * kfc, KisSelectionSP selection); KisAdjustmentLayer(const KisAdjustmentLayer& rhs); virtual ~KisAdjustmentLayer(); bool accept(KisNodeVisitor &); void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); /** * clones this AdjustmentLayer into a KisNodeSP type. * @return the KisNodeSP returned */ KisNodeSP clone() const { return KisNodeSP(new KisAdjustmentLayer(*this)); } /** * gets the adjustmentLayer's tool filter * @return QIcon returns the KIcon tool filter */ QIcon icon() const; /** * gets the AdjustmentLayer properties describing whether * or not the node is locked, visible, and the filter * name is it is a filter. Overrides sectionModelProperties * in KisLayer, and KisLayer overrides * sectionModelProperties in KisBaseNode. * @return KisDocumentSectionModel::PropertyList returns a list * of the properties */ KisDocumentSectionModel::PropertyList sectionModelProperties() const; public: /** * \see KisNodeFilterInterface::setFilter() */ void setFilter(KisFilterConfiguration *filterConfig); void setChannelFlags(const QBitArray & channelFlags); protected: // override from KisLayer QRect incomingChangeRect(const QRect &rect) const; // override from KisNode QRect needRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; public Q_SLOTS: /** * gets this AdjustmentLayer. Overrides function in * KisIndirectPaintingSupport * @return this AdjustmentLayer */ KisLayer* layer() { return this; } }; #endif // KIS_ADJUSTMENT_LAYER_H_ diff --git a/krita/image/kis_algebra_2d.h b/krita/image/kis_algebra_2d.h index b5f0121aedf..c5383530aa1 100644 --- a/krita/image/kis_algebra_2d.h +++ b/krita/image/kis_algebra_2d.h @@ -1,260 +1,260 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ALGEBRA_2D_H #define __KIS_ALGEBRA_2D_H #include #include #include #include #include #include -#include +#include class QPainterPath; namespace KisAlgebra2D { template struct PointTypeTraits { }; template <> struct PointTypeTraits { typedef int value_type; typedef qreal calculation_type; }; template <> struct PointTypeTraits { typedef qreal value_type; typedef qreal calculation_type; }; template typename PointTypeTraits::value_type dotProduct(const T &a, const T &b) { return a.x() * b.x() + a.y() * b.y(); } template typename PointTypeTraits::value_type crossProduct(const T &a, const T &b) { return a.x() * b.y() - a.y() * b.x(); } template qreal norm(const T &a) { return std::sqrt(pow2(a.x()) + pow2(a.y())); } template Point normalize(const Point &a) { const qreal length = norm(a); return (1.0 / length) * a; } /** * Usual sign() function with positive zero */ template T signPZ(T x) { return x >= T(0) ? T(1) : T(-1); } /** * Usual sign() function with zero returning zero */ template T signZZ(T x) { return x == T(0) ? T(0) : x > T(0) ? T(1) : T(-1); } /** * Copies the sign of \p y into \p x and returns the result */ template inline T copysign(T x, T y) { T strippedX = qAbs(x); return y >= T(0) ? strippedX : -strippedX; } template T leftUnitNormal(const T &a) { T result = a.x() != 0 ? T(-a.y() / a.x(), 1) : T(-1, 0); qreal length = norm(result); result *= (crossProduct(a, result) >= 0 ? 1 : -1) / length; return -result; } template T rightUnitNormal(const T &a) { return -leftUnitNormal(a); } template T inwardUnitNormal(const T &a, int polygonDirection) { return polygonDirection * leftUnitNormal(a); } /** * \return 1 if the polygon is counterclockwise * -1 if the polygon is clockwise * * Note: the sign is flipped because our 0y axis * is reversed */ template int polygonDirection(const QVector &polygon) { typename PointTypeTraits::value_type doubleSum = 0; const int numPoints = polygon.size(); for (int i = 1; i <= numPoints; i++) { int prev = i - 1; int next = i == numPoints ? 0 : i; doubleSum += (polygon[next].x() - polygon[prev].x()) * (polygon[next].y() + polygon[prev].y()); } return doubleSum >= 0 ? 1 : -1; } template bool isInRange(T x, T a, T b) { T length = qAbs(a - b); return qAbs(x - a) <= length && qAbs(x - b) <= length; } void KRITAIMAGE_EXPORT adjustIfOnPolygonBoundary(const QPolygonF &poly, int polygonDirection, QPointF *pt); /** * Let \p pt, \p base1 are two vectors. \p base1 is uniformly scaled * and then rotated into \p base2 using transformation matrix S * * R. The function applies the same transformation to \pt and returns * the result. **/ QPointF KRITAIMAGE_EXPORT transformAsBase(const QPointF &pt, const QPointF &base1, const QPointF &base2); qreal KRITAIMAGE_EXPORT angleBetweenVectors(const QPointF &v1, const QPointF &v2); namespace Private { inline void resetEmptyRectangle(const QPoint &pt, QRect *rc) { *rc = QRect(pt, QSize(1, 1)); } inline void resetEmptyRectangle(const QPointF &pt, QRectF *rc) { static const qreal eps = 1e-10; *rc = QRectF(pt, QSizeF(eps, eps)); } } template inline void accumulateBounds(const Point &pt, Rect *bounds) { if (bounds->isEmpty()) { Private::resetEmptyRectangle(pt, bounds); } if (pt.x() > bounds->right()) { bounds->setRight(pt.x()); } if (pt.x() < bounds->left()) { bounds->setLeft(pt.x()); } if (pt.y() > bounds->bottom()) { bounds->setBottom(pt.y()); } if (pt.y() < bounds->top()) { bounds->setTop(pt.y()); } } template inline Point clampPoint(Point pt, const Rect &bounds) { if (pt.x() > bounds.right()) { pt.rx() = bounds.right(); } if (pt.x() < bounds.left()) { pt.rx() = bounds.left(); } if (pt.y() > bounds.bottom()) { pt.ry() = bounds.bottom(); } if (pt.y() < bounds.top()) { pt.ry() = bounds.top(); } return pt; } QPainterPath KRITAIMAGE_EXPORT smallArrow(); /** * Multiply width and height of \p rect by \p coeff keeping the * center of the rectangle pinned */ QRect KRITAIMAGE_EXPORT blowRect(const QRect &rect, qreal coeff); QPoint KRITAIMAGE_EXPORT ensureInRect(QPoint pt, const QRect &bounds); QPointF KRITAIMAGE_EXPORT ensureInRect(QPointF pt, const QRectF &bounds); QRect KRITAIMAGE_EXPORT ensureRectNotSmaller(QRect rc, const QSize &size); /** * Attempt to intersect a line to the area of the a rectangle. * * If the line intersects the rectange, it will be modified to represent the intersecting line segment and true is returned. * If the line does not intersect the area, it remains unmodified and false will be returned. * * @param segment * @param area * @return true if successful */ bool KRITAIMAGE_EXPORT intersectLineRect(QLineF &line, const QRect rect); template inline Point abs(const Point &pt) { return Point(qAbs(pt.x()), qAbs(pt.y())); } } #endif /* __KIS_ALGEBRA_2D_H */ diff --git a/krita/image/kis_async_merger.h b/krita/image/kis_async_merger.h index 418d0d393a2..cca09ade993 100644 --- a/krita/image/kis_async_merger.h +++ b/krita/image/kis_async_merger.h @@ -1,70 +1,70 @@ /* Copyright (c) Dmitry Kazakov , 2009 * * 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_ASYNC_MERGER_H #define __KIS_ASYNC_MERGER_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_paint_device.h" class QRect; class KisBaseRectsWalker; class KRITAIMAGE_EXPORT KisAsyncMerger { public: void startMerge(KisBaseRectsWalker &walker, bool notifyClones = true); private: inline void resetProjection(); inline void setupProjection(KisProjectionLeafSP currentLeaf, const QRect& rect, bool useTempProjection); inline void writeProjection(KisProjectionLeafSP topmostLeaf, bool useTempProjection, QRect rect); inline bool compositeWithProjection(KisProjectionLeafSP leaf, const QRect &rect); inline void doNotifyClones(KisBaseRectsWalker &walker); private: /** * The place where intermediate results of layer's merge * are going. It may be equal to m_finalProjection. In * this case the projection will be written directly to * the original of the parent layer */ KisPaintDeviceSP m_currentProjection; /** * The final destination of every projection of all * the layers. It is equal to the original of a parental * node. * NOTE: This pointer is cached here to avoid * race conditions */ KisPaintDeviceSP m_finalProjection; /** * Creation of the paint device is quite expensive, so we'll just * save the pointer to our temporary device here and will get it when * needed. This variable must not be used anywhere out of * setupProjection() */ KisPaintDeviceSP m_cachedPaintDevice; }; #endif /* __KIS_ASYNC_MERGER_H */ diff --git a/krita/image/kis_base_accessor.h b/krita/image/kis_base_accessor.h index f8fe1da98de..2cc89bb8573 100644 --- a/krita/image/kis_base_accessor.h +++ b/krita/image/kis_base_accessor.h @@ -1,59 +1,59 @@ /* This file is part of the KDE project * Copyright (c) 2010 Cyrille Berger * * 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 _KISBASEACCESSOR_H_ #define _KISBASEACCESSOR_H_ -#include +#include #include class KRITAIMAGE_EXPORT KisBaseConstAccessor : public KisShared { Q_DISABLE_COPY(KisBaseConstAccessor) public: KisBaseConstAccessor() {} virtual ~KisBaseConstAccessor(); /** * @return a pointer to the pixel data as it was at the moment of the last memento creation. */ virtual const quint8 * oldRawData() const = 0; /** * @return a pointer to the most actual pixel data, * this points to te same data as rawData() method of * a writable accessor */ virtual const quint8 * rawDataConst() const = 0; virtual qint32 x() const = 0; virtual qint32 y() const = 0; }; class KRITAIMAGE_EXPORT KisBaseAccessor { Q_DISABLE_COPY(KisBaseAccessor) public: KisBaseAccessor() {} virtual ~KisBaseAccessor(); /** * @return a pointer to the pixel data. Do NOT interpret the data - leave that to a colorspace */ virtual quint8 * rawData() = 0; }; #endif diff --git a/krita/image/kis_base_mask_generator.h b/krita/image/kis_base_mask_generator.h index 14aa61ab571..495883e3b81 100644 --- a/krita/image/kis_base_mask_generator.h +++ b/krita/image/kis_base_mask_generator.h @@ -1,138 +1,138 @@ /* * Copyright (c) 2008-2009 Cyrille Berger * Copyright (c) 2010 Lukáš Tvrdý * * 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_MASK_GENERATOR_H_ #define _KIS_MASK_GENERATOR_H_ #include "kis_brush_mask_applicator_base.h" // vc.h must come first #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class QDomElement; class QDomDocument; const KoID DefaultId("default", ki18n("Default")); ///< generate Krita default mask generator const KoID SoftId("soft", ki18n("Soft")); ///< generate brush mask from former softbrush paintop, where softness is based on curve const KoID GaussId("gauss", ki18n("Gaussian")); ///< generate brush mask with a Gaussian-blurred edge static const int OVERSAMPLING = 4; /** * This is the base class for mask shapes * You should subclass it if you want to create a new * shape. */ class KRITAIMAGE_EXPORT KisMaskGenerator { public: enum Type { CIRCLE, RECTANGLE }; public: /** * This function creates an auto brush shape with the following value : * @param w width * @param h height * @param fh horizontal fade (fh \< w / 2 ) * @param fv vertical fade (fv \< h / 2 ) */ KisMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges, Type type, const KoID& id = DefaultId); virtual ~KisMaskGenerator(); private: void init(); public: /** * @return the alpha value at the position (x,y) */ virtual quint8 valueAt(qreal x, qreal y) const = 0; virtual bool shouldSupersample() const; virtual bool shouldVectorize() const; virtual KisBrushMaskApplicatorBase* applicator(); virtual void toXML(QDomDocument& , QDomElement&) const; /** * Unserialise a \ref KisMaskGenerator */ static KisMaskGenerator* fromXML(const QDomElement&); qreal width() const; qreal height() const; qreal diameter() const; qreal ratio() const; qreal horizontalFade() const; qreal verticalFade() const; int spikes() const; Type type() const; inline QString id() const { return m_id.id(); } inline QString name() const { return m_id.name(); } static QList maskGeneratorIds(); qreal softness() const; virtual void setSoftness(qreal softness); QString curveString() const; void setCurveString(const QString& curveString); bool antialiasEdges() const; virtual void setScale(qreal scaleX, qreal scaleY); protected: qreal effectiveSrcWidth() const; qreal effectiveSrcHeight() const; protected: struct Private { qreal diameter, ratio; qreal softness; qreal fh, fv; int spikes; qreal cachedSpikesAngle; qreal cs, ss; bool empty; Type type; QString curveString; bool antialiasEdges; qreal scaleX; qreal scaleY; KisBrushMaskApplicatorBase *defaultMaskProcessor; }; Private* const d; private: const KoID& m_id; }; #endif diff --git a/krita/image/kis_base_node.h b/krita/image/kis_base_node.h index a6e4fab5462..c495de13e5b 100644 --- a/krita/image/kis_base_node.h +++ b/krita/image/kis_base_node.h @@ -1,441 +1,441 @@ /* * Copyright (c) 2007 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_BASE_NODE_H #define _KIS_BASE_NODE_H #include #include #include #include #include "KisDocumentSectionModel.h" #include "kis_shared.h" #include "kis_paint_device.h" #include "kis_processing_visitor.h" // included, not forward declared for msvc class KoProperties; class KoColorSpace; class KoCompositeOp; class KisNodeVisitor; class KisUndoAdapter; -#include "krita_export.h" +#include "kritaimage_export.h" /** * A KisBaseNode is the base class for all components of an image: * nodes, layers masks, selections. A node has a number of properties, * can be represented as a thumbnail and knows what to do when it gets * a certain paint device to process. A KisBaseNode does not know * anything about its peers. You should not directly inherit from a * KisBaseNode; inherit from KisNode instead. */ class KRITAIMAGE_EXPORT KisBaseNode : public QObject, public KisShared { Q_OBJECT public: /** * Create a new, empty base node. The node is unnamed, unlocked * visible and unlinked. */ KisBaseNode(); /** * Create a copy of this node. */ KisBaseNode(const KisBaseNode & rhs); /** * Delete this node */ virtual ~KisBaseNode(); /** * Return the paintdevice you can use to change pixels on. For a * paint layer these will be paint pixels, for an adjustment layer or a mask * the selection paint device. * * @return the paint device to paint on. Can be 0 if the actual * node type does not support painting. */ virtual KisPaintDeviceSP paintDevice() const; /** * @return the rendered representation of a node * before the effect masks have had their go at it. Can be 0. */ virtual KisPaintDeviceSP original() const; /** * @return the fully rendered representation of this layer: its * rendered original and its effect masks. Can be 0. */ virtual KisPaintDeviceSP projection() const; virtual const KoColorSpace *colorSpace() const = 0; /** * Return the opacity of this layer, scaled to a range between 0 * and 255. * XXX: Allow true float opacity */ quint8 opacity() const; //0-255 /** * Set the opacity for this layer. The range is between 0 and 255. * The layer will be marked dirty. * * XXX: Allow true float opacity */ void setOpacity(quint8 val); //0-255 /** * return the 8-bit opacity of this layer scaled to the range * 0-100 * * XXX: Allow true float opacity */ quint8 percentOpacity() const; //0-100 /** * Set the opacity of this layer with a number between 0 and 100; * the number will be scaled to between 0 and 255. * XXX: Allow true float opacity */ void setPercentOpacity(quint8 val); //0-100 /** * Return the composite op associated with this layer. */ virtual const KoCompositeOp *compositeOp() const = 0; const QString& compositeOpId() const; /** * Set a new composite op for this layer. The layer will be marked * dirty. */ void setCompositeOp(const QString& compositeOpId); /** * @return unique id, which is now used by clone layers. */ QUuid uuid() const; /** * Set the uuid of node. This should only be used when loading * existing node and in constructor. */ void setUuid(const QUuid& id); /** * return the name of this node. This is the same as the * QObject::objectName. */ QString name() const { return objectName(); } /** * set the QObject::objectName. This is also the user-visible name * of the layer. The reason for this is that we want to see the * layer name also when debugging. */ void setName(const QString& name) { setObjectName(name); baseNodeChangedCallback(); } /** * @return the icon used to represent the node type, for instance * in the layerbox and in the menu. */ virtual QIcon icon() const { return QIcon(); }; /** * Return a the properties of this base node (locked, visible etc, * with the right icons for their representation and their state. * * Subclasses can extend this list with new properties, like * opacity for layers or visualized for masks. * * The order of properties is, unfortunately, for now, important, * so take care which properties superclasses of your class * define. * * KisBaseNode defines visible = 0, locked = 1 * KisLayer defines opacity = 2, compositeOp = 3 * KisMask defines active = 2 (KisMask does not inherit kislayer) */ virtual KisDocumentSectionModel::PropertyList sectionModelProperties() const; /** * Change the section model properties. */ virtual void setSectionModelProperties(const KisDocumentSectionModel::PropertyList &properties); /** * Return all the properties of this layer as a KoProperties-based * serializable key-value list. */ KoProperties & nodeProperties() const; /** * Merge the specified properties with the properties of this * layer. Whereever these properties overlap, the value of the * node properties is changed. No properties on the node are * deleted. If there are new properties in this list, they will be * added on the node. */ void mergeNodeProperties(const KoProperties & properties); /** * Compare the given properties list with the properties of this * node. * * @return false only if the same property exists in both lists * but with a different value. Properties that are not in both * lists are disregarded. */ bool check(const KoProperties & properties) const; /** * Accept the KisNodeVisitor (for the Visitor design pattern), * should call the correct function on the KisNodeVisitor for this * node type, so you need to override it for all leaf classes in * the node inheritance hierarchy. * * return false if the visitor could not successfully act on this * node instance. */ virtual bool accept(KisNodeVisitor &) { return false; } /** * Accept the KisNodeVisitor (for the Visitor design pattern), * should call the correct function on the KisProcessingVisitor * for this node type, so you need to override it for all leaf * classes in the node inheritance hierarchy. * * The processing visitor differs from node visitor in the way * that it accepts undo adapter, that allows the processing to * be multithreaded */ virtual void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) { Q_UNUSED(visitor); Q_UNUSED(undoAdapter); } /** * @return a thumbnail in requested size. The thumbnail is a rgba * QImage and may have transparent parts. Returns a fully * transparent QImage of the requested size if the current node * type cannot generate a thumbnail. If the requested size is too * big, return a null QImage. */ virtual QImage createThumbnail(qint32 w, qint32 h); /** * Ask this node to re-read the pertinent settings from the krita * configuration. */ virtual void updateSettings() { } /** * @return true if this node is visible (i.e, active (except for * selection masks where visible and active properties are * different)) in the graph */ virtual bool visible(bool recursive = false) const; /** * Set the visible status of this node. Visible nodes are active * in the graph (except for selections masks which can be active * while hidden), that is to say, they are taken into account * when merging. Invisible nodes play no role in the final image *, but will be modified when modifying all layers, for instance * when cropping. * * Toggling the visibility of a node will not automatically lead * to recomposition. * * @param visible the new visibility state * @param isLoading if true, the property is set during loading. */ virtual void setVisible(bool visibile, bool loading = false); /** * Return the locked status of this node. Locked nodes cannot be * edited. */ bool userLocked() const; /** * Set the locked status of this node. Locked nodes cannot be * edited. */ void setUserLocked(bool l); /** * Return the locked status of this node. System Locked nodes indicates * that an algorithm is processing them and that an other * algorithm need to wait before accessing it. */ bool systemLocked() const; /** * Set the locked status of this node. System Locked nodes indicates * that an algorithm is processing them and that an other * algorithm need to wait before accessing it. * * A KisNode will update the layer model when the lock is released. * * @param l lock state * @param update set false if the tools shouldn't be locked */ virtual void setSystemLocked(bool l, bool update = true); /** * @return true if the node can be edited: * * if checkVisibility is true, then the node is only editable if it is visible and not locked. * if checkVisibility is false, then the node is editable if it's not locked. */ bool isEditable(bool checkVisibility = true) const; /** * @return true if the node is editable and has a paintDevice() * which which can be used for accessing pixels. It is an * equivalent to (isEditable() && paintDevice()) */ bool hasEditablePaintDevice() const; /** * @return the x-offset of this layer in the image plane. */ virtual qint32 x() const { return 0; } /** * Set the x offset of this layer in the image place. * Re-implement this where it makes sense, by default it does * nothing. It should not move child nodes. */ virtual void setX(qint32) { } /** * @return the y-offset of this layer in the image plane. */ virtual qint32 y() const { return 0; } /** * Set the y offset of this layer in the image place. * Re-implement this where it makes sense, by default it does * nothing. It should not move child nodes. */ virtual void setY(qint32) { } /** * Returns an approximation of where the bounds on actual data are * in this node. */ virtual QRect extent() const { return QRect(); } /** * Returns the exact bounds of where the actual data resides in * this node. */ virtual QRect exactBounds() const { return QRect(); } /** * Sets the state of the node to the value of @param collapsed */ void setCollapsed(bool collapsed); /** * returns the collapsed state of this node */ bool collapsed() const; protected: /** * FIXME: This method is a workaround for getting parent node * on a level of KisBaseNode. In fact, KisBaseNode should inherit * KisNode (in terms of current Krita) to be able to traverse * the node stack */ virtual KisBaseNodeSP parentCallback() const { return 0; } virtual void notifyParentVisibilityChanged(bool value) { Q_UNUSED(value); } /** * This callback is called when some meta state of the base node * that can be interesting to the UI has changed. E.g. visibility, * lockness, opacity, compositeOp and etc. This signal is * forwarded by the KisNode and KisNodeGraphListener to the model * in KisLayerBox, so it can update its controls when information * changes. */ virtual void baseNodeChangedCallback() { } Q_SIGNALS: /** * This signal is emitted when the visibility of the layer is changed with \ref setVisible. */ void visibilityChanged(bool); /** * This signal is emitted when the node is locked or unlocked with \ref setUserLocked. */ void userLockingChanged(bool); /** * This signal is emitted when the node is locked or unlocked with \ref setSystemLocked. */ void systemLockingChanged(bool); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/kis_base_processor.h b/krita/image/kis_base_processor.h index 81f387bfddb..922a8358474 100644 --- a/krita/image/kis_base_processor.h +++ b/krita/image/kis_base_processor.h @@ -1,167 +1,167 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_BASE_PROCESSOR_H_ #define _KIS_BASE_PROCESSOR_H_ #include #include #include #include #include "KoID.h" #include "KoColorSpace.h" #include "kis_types.h" #include "kis_shared.h" #include "kis_image.h" -#include "krita_export.h" +#include "kritaimage_export.h" class QWidget; class KisBookmarkedConfigurationManager; class KisFilterConfiguration; class KisConfigWidget; /** * Base class for classes that process areas of pixels. * Processors can either read in pixels and write out pixels * or just write out pixels, using a certain set of configuation * pixels. * * in-out processing is typically filtering: @see KisFilter. * out-only processing is typiccaly generating: @see KisGenerator. * * Information about the area that needs to be processed is contained * @see KisProcessingInformation and @see KisConstProcessingInformation. */ class KRITAIMAGE_EXPORT KisBaseProcessor : public KisShared { friend class KisBaseProcessorConfigurationFactory; public: KisBaseProcessor(const KoID& id, const KoID & category, const QString & entry); virtual ~KisBaseProcessor(); /** * Return the configuration set as the default by the user or the default * configuration from the filter writer as returned by factoryConfiguration. * * This configuration is used by default for the configuration widget and * given to the process function if there is no configuration widget. * * @return the default configuration of this widget */ KisFilterConfiguration * defaultConfiguration(const KisPaintDeviceSP) const; /** * @return the bookmark manager for this processor */ KisBookmarkedConfigurationManager* bookmarkManager(); /** * @return the bookmark manager for this processor */ const KisBookmarkedConfigurationManager* bookmarkManager() const; /// @return Unique identification for this processor QString id() const; /// @return User-visible identification for this processor QString name() const; /// @return the submenu in the filters menu does processor want to go? KoID menuCategory() const; /// @return the i18n'ed string this filter wants to show itself in the menu QString menuEntry() const; /** * Return the default keyboard shortcut for activation of this filter * * @return the shortcut */ KShortcut shortcut() const; /** * Create the configuration widget for this processor. * * @param parent the Qt owner widget of this widget * @param dev the paintdevice this filter will act on */ virtual KisConfigWidget * createConfigurationWidget(QWidget * parent, const KisPaintDeviceSP dev) const; // "Support" functions public: /** * If true, this filter can be used in painting tools as a paint operation */ bool supportsPainting() const; /// This filter can be used in adjustment layers bool supportsAdjustmentLayers() const; /** * This filter supports cutting up the work area and filtering * each chunk in a separate thread. Filters that need access to the * whole area for correct computations should return false. */ bool supportsThreading() const; /// If true, the filter wants to show a configuration widget bool showConfigurationWidget(); /** * Determine the colorspace independence of this filter. * @see ColorSpaceIndependence * * @return the degree of independence */ ColorSpaceIndependence colorSpaceIndependence() const; /// @return the default configuration as defined by whoever wrote the plugin virtual KisFilterConfiguration* factoryConfiguration(const KisPaintDeviceSP) const; protected: void setSupportsPainting(bool v); void setSupportsAdjustmentLayers(bool v); void setSupportsThreading(bool v); void setColorSpaceIndependence(ColorSpaceIndependence v); void setShowConfigurationWidget(bool v); /** * Set the default shortcut for activation of this filter. */ void setShortcut(const KShortcut & shortcut); protected: void init(const QString& configEntryGroup); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_basic_math_toolbox.h b/krita/image/kis_basic_math_toolbox.h index 41b7729cc0f..98aaf25aefa 100644 --- a/krita/image/kis_basic_math_toolbox.h +++ b/krita/image/kis_basic_math_toolbox.h @@ -1,44 +1,44 @@ /* * This file is part of the KDE project * * Copyright (c) 2005 Cyrille Berger * * 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_BASIC_MATH_TOOLBOX_H #define KIS_BASIC_MATH_TOOLBOX_H #include "kis_math_toolbox.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * This class implement KisMathToolbox for most colorspaces, only colorspaces with "angular" * channels need to reimplement the functions */ class KRITAIMAGE_EXPORT KisBasicMathToolbox : public KisMathToolbox { public: KisBasicMathToolbox(); ~KisBasicMathToolbox(); public: virtual KisWavelet* fastWaveletTransformation(KisPaintDeviceSP src, const QRect&, KisWavelet* buff = 0); virtual void fastWaveletUntransformation(KisPaintDeviceSP dst, const QRect&, KisWavelet* wav, KisWavelet* buff = 0); private: void wavetrans(KisWavelet* wav, KisWavelet* buff, uint halfsize); void waveuntrans(KisWavelet* wav, KisWavelet* buff, uint halfsize); }; #endif diff --git a/krita/image/kis_bookmarked_configuration_manager.h b/krita/image/kis_bookmarked_configuration_manager.h index 6d5d8cb6b3f..304a105d474 100644 --- a/krita/image/kis_bookmarked_configuration_manager.h +++ b/krita/image/kis_bookmarked_configuration_manager.h @@ -1,86 +1,86 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_BOOKMARKED_CONFIGURATION_MANAGER_H_ #define _KIS_BOOKMARKED_CONFIGURATION_MANAGER_H_ #include class KisSerializableConfiguration; class KisSerializableConfigurationFactory; class QString; class KLocalizedString; -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisBookmarkedConfigurationManager { public: static const char ConfigDefault[]; static const char ConfigLastUsed[]; public: /** * @param configEntryGroup name of the configuration entry with the * bookmarked configurations. */ KisBookmarkedConfigurationManager(const QString & configEntryGroup, KisSerializableConfigurationFactory*); ~KisBookmarkedConfigurationManager(); /** * Load the configuration. */ KisSerializableConfiguration* load(const QString & configname) const; /** * Save the configuration. */ void save(const QString & configname, const KisSerializableConfiguration*); /** * @return true if the configuration configname exists */ bool exists(const QString & configname) const; /** * @return the list of the names of configurations. */ QList configurations() const; /** * @return the default configuration */ KisSerializableConfiguration* defaultConfiguration() const; /** * Remove a bookmarked configuration */ void remove(const QString & name); /** * Generate an unique name, for instance when the user is creating a new * entry. * @param base the base of the new name, including a "%1" for incrementing * the number, for instance : "New Configuration %1", then this function * will return the string where %1 will be replaced by the lowest number * and be inexistant in the lists of configuration */ QString uniqueName(const KLocalizedString & base); private: QString configEntryGroup() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_cached_gradient_shape_strategy.h b/krita/image/kis_cached_gradient_shape_strategy.h index 216a04dcff2..7045917d131 100644 --- a/krita/image/kis_cached_gradient_shape_strategy.h +++ b/krita/image/kis_cached_gradient_shape_strategy.h @@ -1,43 +1,43 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CACHED_GRADIENT_SHAPE_STRATEGY_H #define __KIS_CACHED_GRADIENT_SHAPE_STRATEGY_H #include "kis_gradient_shape_strategy.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include class QRect; class KRITAIMAGE_EXPORT KisCachedGradientShapeStrategy : public KisGradientShapeStrategy { public: KisCachedGradientShapeStrategy(const QRect &rc, qreal xStep, qreal yStep, KisGradientShapeStrategy *baseStrategy); ~KisCachedGradientShapeStrategy(); double valueAt(double x, double y) const; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_CACHED_GRADIENT_SHAPE_STRATEGY_H */ diff --git a/krita/image/kis_cage_transform_worker.h b/krita/image/kis_cage_transform_worker.h index fdf31a95ed3..00bb233628d 100644 --- a/krita/image/kis_cage_transform_worker.h +++ b/krita/image/kis_cage_transform_worker.h @@ -1,55 +1,55 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CAGE_TRANSFORM_WORKER_H #define __KIS_CAGE_TRANSFORM_WORKER_H #include -#include +#include #include class QImage; class KRITAIMAGE_EXPORT KisCageTransformWorker { public: KisCageTransformWorker(KisPaintDeviceSP dev, const QVector &origCage, KoUpdater *progress, int pixelPrecision = 8); KisCageTransformWorker(const QImage &srcImage, const QPointF &srcImageOffset, const QVector &origCage, KoUpdater *progress, int pixelPrecision = 8); ~KisCageTransformWorker(); void prepareTransform(); void setTransformedCage(const QVector &transformedCage); void run(); QImage runOnQImage(QPointF *newOffset); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_CAGE_TRANSFORM_WORKER_H */ diff --git a/krita/image/kis_circle_mask_generator.h b/krita/image/kis_circle_mask_generator.h index 6469e504f56..1141801d64f 100644 --- a/krita/image/kis_circle_mask_generator.h +++ b/krita/image/kis_circle_mask_generator.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2008-2009 Cyrille Berger * * 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_CIRCLE_MASK_GENERATOR_H_ #define _KIS_CIRCLE_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_mask_generator.h" /** * Create, serialize and deserialize an elliptical 8-bit mask. */ class KRITAIMAGE_EXPORT KisCircleMaskGenerator : public KisMaskGenerator { public: struct FastRowProcessor; public: KisCircleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges); virtual ~KisCircleMaskGenerator(); virtual quint8 valueAt(qreal x, qreal y) const; virtual bool shouldSupersample() const; virtual bool shouldVectorize() const; KisBrushMaskApplicatorBase* applicator(); virtual void setSoftness(qreal softness); virtual void setScale(qreal scaleX, qreal scaleY); private: qreal norme(qreal a, qreal b) const { return a*a + b * b; } private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_clone_layer.h b/krita/image/kis_clone_layer.h index 0e6f0353204..8ea67321e40 100644 --- a/krita/image/kis_clone_layer.h +++ b/krita/image/kis_clone_layer.h @@ -1,134 +1,134 @@ /* * Copyright (c) 2007 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_CLONE_LAYER_H_ #define KIS_CLONE_LAYER_H_ #include #include "kis_types.h" #include "kis_layer.h" #include "kis_indirect_painting_support.h" -#include +#include #include "kis_clone_info.h" class KisNodeVisitor; enum CopyLayerType { COPY_PROJECTION, COPY_ORIGINAL }; /** * A copy layer adds the contents of another layer in another place in * the layer stack. It is possible to add more effect masks to the * copy. You can either copy the original data or the projection data * produced by the original layer + original effect masks. There is no * physical copy of the data; if the original changes, the copy * changes too. The copy layer can be positioned differently from the * original layer. **/ class KRITAIMAGE_EXPORT KisCloneLayer : public KisLayer { Q_OBJECT public: KisCloneLayer(KisLayerSP from, KisImageWSP image, const QString &name, quint8 opacity); KisCloneLayer(const KisCloneLayer& rhs); virtual ~KisCloneLayer(); KisNodeSP clone() const { return KisNodeSP(new KisCloneLayer(*this)); } /** * When the source layer of the clone is removed from the stack * we should substitute the clone with a usual paint layer, * because the source might become unreachable quite soon. This * method builds a paint layer representation of this clone. */ KisLayerSP reincarnateAsPaintLayer() const; bool allowAsChild(KisNodeSP) const; KisPaintDeviceSP original() const; KisPaintDeviceSP paintDevice() const; bool needProjection() const; QIcon icon() const; KisDocumentSectionModel::PropertyList sectionModelProperties() const; qint32 x() const; qint32 y() const; void setX(qint32); void setY(qint32); /// Returns an approximation of where the bounds on actual data are in this layer QRect extent() const; /// Returns the exact bounds of where the actual data resides in this layer QRect exactBounds() const; bool accept(KisNodeVisitor &); void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); /** * Used when loading: loading is done in two passes, and the copy * from layer is set when all layers have been created, not during * loading. */ void setCopyFromInfo(KisCloneInfo info); KisCloneInfo copyFromInfo() const; void setCopyFrom(KisLayerSP layer); KisLayerSP copyFrom() const; void setCopyType(CopyLayerType type); CopyLayerType copyType() const; /** * This function is called by the original to notify * us that it is dirty */ void setDirtyOriginal(const QRect &rect); QRect needRectOnSourceForMasks(const QRect &rc) const; protected: // override from KisNode QRect accessRect(const QRect &rect, PositionToFilthy pos) const; // override from KisLayer void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect& rect) const; void notifyParentVisibilityChanged(bool value); QRect outgoingChangeRect(const QRect &rect) const; private: struct Private; Private * const m_d; }; #endif // KIS_CLONE_LAYER_H_ diff --git a/krita/image/kis_colorspace_convert_visitor.h b/krita/image/kis_colorspace_convert_visitor.h index 0bf6d39e3aa..c249218e8ff 100644 --- a/krita/image/kis_colorspace_convert_visitor.h +++ b/krita/image/kis_colorspace_convert_visitor.h @@ -1,85 +1,85 @@ /* * Copyright (c) 2005 C. Boemann * * 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_COLORSPACE_CONVERT_VISITOR_H_ #define KIS_COLORSPACE_CONVERT_VISITOR_H_ #include #include -#include +#include #include "kis_global.h" #include "kis_types.h" #include "kis_node_visitor.h" /** * This will convert all layers to the destination color space. */ class KRITAIMAGE_EXPORT KisColorSpaceConvertVisitor : public KisNodeVisitor { public: KisColorSpaceConvertVisitor(KisImageWSP image, const KoColorSpace *srcColorSpace, const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); virtual ~KisColorSpaceConvertVisitor(); public: bool visit(KisPaintLayer *layer); bool visit(KisGroupLayer *layer); bool visit(KisAdjustmentLayer* layer); bool visit(KisGeneratorLayer * layer); bool visit(KisExternalLayer *); bool visit(KisNode*) { return true; } bool visit(KisCloneLayer*) { return true; } bool visit(KisFilterMask*) { return true; } bool visit(KisTransformMask*) { return true; } bool visit(KisTransparencyMask*) { return true; } bool visit(KisSelectionMask*) { return true; } private: bool convertPaintDevice(KisLayer* layer); KisImageWSP m_image; const KoColorSpace *m_srcColorSpace; const KoColorSpace *m_dstColorSpace; KoColorConversionTransformation::Intent m_renderingIntent; KoColorConversionTransformation::ConversionFlags m_conversionFlags; QBitArray m_emptyChannelFlags; }; #endif // KIS_COLORSPACE_CONVERT_VISITOR_H_ diff --git a/krita/image/kis_composite_progress_proxy.h b/krita/image/kis_composite_progress_proxy.h index 834c416a6f6..d27a4c7e0d1 100644 --- a/krita/image/kis_composite_progress_proxy.h +++ b/krita/image/kis_composite_progress_proxy.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_COMPOSITE_PROGRESS_PROXY_H #define __KIS_COMPOSITE_PROGRESS_PROXY_H #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisCompositeProgressProxy : public KoProgressProxy { public: void addProxy(KoProgressProxy *proxy); void removeProxy(KoProgressProxy *proxy); int maximum() const; void setValue(int value); void setRange(int minimum, int maximum); void setFormat(const QString &format); private: QList m_proxies; }; #endif /* __KIS_COMPOSITE_PROGRESS_PROXY_H */ diff --git a/krita/image/kis_config_widget.h b/krita/image/kis_config_widget.h index be8aa7917b6..99fbe01ba88 100644 --- a/krita/image/kis_config_widget.h +++ b/krita/image/kis_config_widget.h @@ -1,94 +1,94 @@ /* * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2004-2006 Cyrille Berger * * 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_WIDGET_H_ #define _KIS_CONFIG_WIDGET_H_ #include -#include +#include #include class KisViewManager; class KisPropertiesConfiguration; /** * Empty base class. Configurable resources like filters, paintops etc. * can build their own configuration widgets that inherit this class. * The configuration widget should emit sigConfigurationItemChanged * when it wants a preview updated; there is a timer that * waits a little time to see if there are more changes coming * and then emits sigConfigurationUpdated. */ class KRITAIMAGE_EXPORT KisConfigWidget : public QWidget { Q_OBJECT protected: KisConfigWidget(QWidget * parent = 0, Qt::WFlags f = 0, int delay = 500); public: virtual ~KisConfigWidget(); /** * @param config the configuration for this configuration widget. */ virtual void setConfiguration(const KisPropertiesConfiguration * config) = 0; /** * @return the configuration */ virtual KisPropertiesConfiguration* configuration() const = 0; /** * Sets the view object that can be used by the configuration * widget for richer functionality */ virtual void setView(KisViewManager *view); Q_SIGNALS: /** * emitted whenever it makes sense to update the preview */ void sigConfigurationUpdated(); /** * Subclasses should emit this signal whenever the preview should be * be recalculated. This kicks of a timer, so it's perfectly fine * to connect this to the changed signals of the widgets in your configuration * widget. */ void sigConfigurationItemChanged(); void sigSaveLockedConfig(KisPropertiesConfiguration* p); void sigDropLockedConfig(KisPropertiesConfiguration* p); private Q_SLOTS: void slotConfigChanged(); void kickTimer(); private: QTimer m_timer; int m_delay; }; #endif diff --git a/krita/image/kis_convolution_kernel.h b/krita/image/kis_convolution_kernel.h index 63568f07568..7df71dd384a 100644 --- a/krita/image/kis_convolution_kernel.h +++ b/krita/image/kis_convolution_kernel.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2005,2008 Cyrille Berger * * 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_CONVOLUTION_KERNEL_H_ #define _KIS_CONVOLUTION_KERNEL_H_ #include #include #include "kis_shared.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" using namespace Eigen; class KisMaskGenerator; class QImage; class KRITAIMAGE_EXPORT KisConvolutionKernel : public KisShared { public: KisConvolutionKernel(quint32 width, quint32 height, qreal offset, qreal factor); virtual ~KisConvolutionKernel(); quint32 width() const; quint32 height() const; /** * Change the size of a kernel, it won't reallocate, and therefore it must keep the same kernel size ( oldwidth * oldheight = newwidth*newheight) */ void setSize(quint32 width, quint32 height); qreal offset() const; qreal factor() const; void setFactor(qreal); Matrix& data(); const Matrix * data() const; static KisConvolutionKernelSP fromQImage(const QImage& image); static KisConvolutionKernelSP fromMaskGenerator(KisMaskGenerator *, qreal angle = 0.0); static KisConvolutionKernelSP fromMatrix(Matrix matrix, qreal offset, qreal factor); private: struct Private; Private* const d; }; class QDebug; QDebug operator<<(QDebug debug, const KisConvolutionKernel &c); #endif diff --git a/krita/image/kis_convolution_painter.h b/krita/image/kis_convolution_painter.h index 32832a8fe10..0cf302ba9db 100644 --- a/krita/image/kis_convolution_painter.h +++ b/krita/image/kis_convolution_painter.h @@ -1,93 +1,93 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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_CONVOLUTION_PAINTER_H_ #define KIS_CONVOLUTION_PAINTER_H_ #include "kis_shared.h" #include "kis_shared_ptr.h" #include "kis_types.h" #include "kis_painter.h" #include "kis_image.h" -#include "krita_export.h" +#include "kritaimage_export.h" template class KisConvolutionWorker; enum KisConvolutionBorderOp { BORDER_IGNORE = 0, // read the pixels outside of the application rect BORDER_REPEAT = 1 // Use the border for the missing pixels }; /** * @brief The KisConvolutionPainter class applies a convolution kernel to a paint device. * * * Note: https://bugs.kde.org/show_bug.cgi?id=220310 shows that there's something here * that we need to fix... */ class KRITAIMAGE_EXPORT KisConvolutionPainter : public KisPainter { public: KisConvolutionPainter(); KisConvolutionPainter(KisPaintDeviceSP device); KisConvolutionPainter(KisPaintDeviceSP device, KisSelectionSP selection); /** * Convolve all channels in src using the specified kernel; there is only one kernel for all * channels possible. By default the border pixels are not convolved, that is, convolving * starts with at (x + kernel.width/2, y + kernel.height/2) and stops at w - (kernel.width/2) * and h - (kernel.height/2) * * The border op decides what to do with pixels too close to the edge of the rect as defined above. * * The channels flag determines which set out of color channels, alpha channels. * channels we convolve. * * Note that we do not (currently) support different kernels for * different channels _or_ channel types. * * If you want to convolve a subset of the channels in a pixel, * set those channels with KisPainter::setChannelFlags(); */ void applyMatrix(const KisConvolutionKernelSP kernel, const KisPaintDeviceSP src, QPoint srcPos, QPoint dstPos, QSize areaSize, KisConvolutionBorderOp borderOp = BORDER_REPEAT); protected: friend class KisConvolutionPainterTest; enum TestingEnginePreference { NONE, SPATIAL, FFTW }; KisConvolutionPainter(KisPaintDeviceSP device, TestingEnginePreference enginePreference); private: template KisConvolutionWorker* createWorker(const KisConvolutionKernelSP kernel, KisPainter *painter, KoUpdater *progress); private: TestingEnginePreference m_enginePreference; }; #endif //KIS_CONVOLUTION_PAINTER_H_ diff --git a/krita/image/kis_count_visitor.h b/krita/image/kis_count_visitor.h index 210d33662c8..3d86eba65a5 100644 --- a/krita/image/kis_count_visitor.h +++ b/krita/image/kis_count_visitor.h @@ -1,120 +1,120 @@ /* * Copyright (c) 2007 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_COUNT_VISITOR #define KIS_COUNT_VISITOR -#include "krita_export.h" +#include "kritaimage_export.h" #include #include "kis_node_visitor.h" #include "kis_node.h" #include "kis_paint_layer.h" #include "kis_paint_device.h" #include "kis_group_layer.h" #include "kis_adjustment_layer.h" #include "kis_external_layer_iface.h" #include "kis_clone_layer.h" #include "kis_filter_mask.h" #include "kis_transform_mask.h" #include "kis_transparency_mask.h" #include "kis_selection_mask.h" #include "generator/kis_generator_layer.h" /** * The count visitor traverses the node stack for nodes that conform * to certain properties. You can set the types of nodes to count and * add a list of properties to check. The children of nodes that are * not counted will be checked and counted if they conform to the * requirements. */ class KRITAIMAGE_EXPORT KisCountVisitor : public KisNodeVisitor { public: using KisNodeVisitor::visit; KisCountVisitor(const QStringList & nodeTypes, const KoProperties & properties) : m_nodeTypes(nodeTypes) , m_properties(properties) , m_count(0) { } quint32 count() { return m_count; } bool visit(KisNode* node) { return check(node); } bool visit(KisPaintLayer *layer) { return check(layer); } bool visit(KisGroupLayer *layer) { return check(layer); } bool visit(KisAdjustmentLayer *layer) { return check(layer); } bool visit(KisExternalLayer *layer) { return check(layer); } bool visit(KisCloneLayer *layer) { return check(layer); } bool visit(KisFilterMask *mask) { return check(mask); } bool visit(KisTransformMask *mask) { return check(mask); } bool visit(KisTransparencyMask *mask) { return check(mask); } bool visit(KisGeneratorLayer * layer) { return check(layer); } bool visit(KisSelectionMask* mask) { return check(mask); } private: bool inList(KisNode* node); bool check(KisNode * node); const QStringList m_nodeTypes; const KoProperties m_properties; quint32 m_count; }; #endif diff --git a/krita/image/kis_crop_saved_extra_data.h b/krita/image/kis_crop_saved_extra_data.h index 54cbd575916..9e2f3f79740 100644 --- a/krita/image/kis_crop_saved_extra_data.h +++ b/krita/image/kis_crop_saved_extra_data.h @@ -1,61 +1,61 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CROP_SAVED_EXTRA_DATA_H #define __KIS_CROP_SAVED_EXTRA_DATA_H #include #include "kundo2commandextradata.h" #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisCropSavedExtraData : public KUndo2CommandExtraData { public: enum Type { CROP_IMAGE, RESIZE_IMAGE, CROP_LAYER }; public: KisCropSavedExtraData(Type type, QRect cropRect, KisNodeSP cropNode = 0); ~KisCropSavedExtraData(); inline Type type() const { return m_type; } inline QRect cropRect() const { return m_cropRect; } inline KisNodeSP cropNode() const { return m_cropNode; } private: Type m_type; QRect m_cropRect; KisNodeSP m_cropNode; }; #endif /* __KIS_CROP_SAVED_EXTRA_DATA_H */ diff --git a/krita/image/kis_cubic_curve.h b/krita/image/kis_cubic_curve.h index 77351dc1baf..2a6cf414d3f 100644 --- a/krita/image/kis_cubic_curve.h +++ b/krita/image/kis_cubic_curve.h @@ -1,81 +1,81 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_CUBIC_CURVE_H_ #define _KIS_CUBIC_CURVE_H_ #include #include #include -#include +#include class QPointF; const QString DEFAULT_CURVE_STRING = "0,0;1,1;"; /** * Hold the data for a cubic curve. */ class KRITAIMAGE_EXPORT KisCubicCurve { public: KisCubicCurve(); KisCubicCurve(const QList& points); KisCubicCurve(const QVector& points); KisCubicCurve(const KisCubicCurve& curve); ~KisCubicCurve(); KisCubicCurve& operator=(const KisCubicCurve& curve); bool operator==(const KisCubicCurve& curve) const; public: qreal value(qreal x) const; QList points() const; void setPoints(const QList& points); void setPoint(int idx, const QPointF& point); /** * Add a point to the curve, the list of point is always sorted. * @return the index of the inserted point */ int addPoint(const QPointF& point); void removePoint(int idx); bool isNull() const; /** * This allows us to carry around a display name for the curve internally. It is used * currently in Sketch for perchannel, but would potentially be useful anywhere * curves are used in the UI */ void setName(const QString& name); const QString& name() const; public: const QVector uint8Transfer(int size = 256) const; const QVector uint16Transfer(int size = 256) const; const QVector floatTransfer(int size = 256) const; public: QString toString() const; void fromString(const QString&); private: struct Data; struct Private; Private* const d; }; Q_DECLARE_METATYPE(KisCubicCurve) #endif diff --git a/krita/image/kis_curve_circle_mask_generator.h b/krita/image/kis_curve_circle_mask_generator.h index 0decf74884a..cf58aa59816 100644 --- a/krita/image/kis_curve_circle_mask_generator.h +++ b/krita/image/kis_curve_circle_mask_generator.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_CURVE_CIRCLE_MASK_GENERATOR_H_ #define _KIS_CURVE_CIRCLE_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_mask_generator.h" #include #include class KisCubicCurve; class QDomElement; class QDomDocument; class QPointF; /** * This mask generator use softness/hardness defined by user curve * It used to be soft brush paintop. */ class KRITAIMAGE_EXPORT KisCurveCircleMaskGenerator : public KisMaskGenerator { public: KisCurveCircleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes,const KisCubicCurve& curve, bool antialiasEdges); virtual ~KisCurveCircleMaskGenerator(); virtual quint8 valueAt(qreal x, qreal y) const; void setScale(qreal scaleX, qreal scaleY); bool shouldSupersample() const; virtual void toXML(QDomDocument& , QDomElement&) const; virtual void setSoftness(qreal softness); static void transformCurveForSoftness(qreal softness,const QList &points, int curveResolution, QVector &result); private: qreal norme(qreal a, qreal b) const { return a*a + b*b; } private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_curve_rect_mask_generator.h b/krita/image/kis_curve_rect_mask_generator.h index 503c35b27ab..9d9c9e2a91e 100644 --- a/krita/image/kis_curve_rect_mask_generator.h +++ b/krita/image/kis_curve_rect_mask_generator.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_CURVE_RECT_MASK_GENERATOR_H_ #define _KIS_CURVE_RECT_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" class KisCubicCurve; class QDomElement; class QDomDocument; #include "kis_mask_generator.h" /** * Curve based softness for this rectangular mask generator */ class KRITAIMAGE_EXPORT KisCurveRectangleMaskGenerator : public KisMaskGenerator { public: KisCurveRectangleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, const KisCubicCurve& curve, bool antialiasEdges); virtual ~KisCurveRectangleMaskGenerator(); virtual quint8 valueAt(qreal x, qreal y) const; void setScale(qreal scaleX, qreal scaleY); virtual void toXML(QDomDocument& , QDomElement&) const; virtual void setSoftness(qreal softness); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_debug.h b/krita/image/kis_debug.h index 08d11c1091b..e4041f47d60 100644 --- a/krita/image/kis_debug.h +++ b/krita/image/kis_debug.h @@ -1,150 +1,150 @@ /* * Copyright (c) 2005 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_DEBUG_AREAS_H_ #define KIS_DEBUG_AREAS_H_ #include #define dbgResources kDebug(30009) #define dbgKrita kDebug(41000) // For temporary debug lines, where you'd have used kDebug() before. #define dbgImage kDebug(41001) #define dbgRegistry kDebug(41002) #define dbgTools kDebug(41003) #define dbgTiles kDebug(41004) #define dbgFilters kDebug(41005) #define dbgPlugins kDebug(41006) #define dbgUI kDebug(41007) #define dbgFile kDebug(41008) #define dbgMath kDebug(41009) #define dbgRender kDebug(41010) #define dbgScript kDebug(41011) #define warnKrita kWarning(41000) // For temporary debug lines, where you'd have used kWarning() before. #define warnImage kWarning(41001) #define warnRegistry kWarning(41002) #define warnTools kWarning(41003) #define warnTiles kWarning(41004) #define warnFilters kWarning(41005) #define warnPlugins kWarning(41006) #define warnUI kWarning(41007) #define warnFile kWarning(41008) #define warnMath kWarning(41009) #define warnRender kWarning(41010) #define warnScript kWarning(41011) #define errKrita kError(41000) // For temporary debug lines, where you'd have used kError() before. #define errImage kError(41001) #define errRegistry kError(41002) #define errTools kError(41003) #define errTiles kError(41004) #define errFilters kError(41005) #define errPlugins kError(41006) #define errUI kError(41007) #define errFile kError(41008) #define errMath kError(41009) #define errRender kError(41010) #define errScript kError(41011) #define fatalKrita kFatal(41000) // For temporary debug lines, where you'd have used kFatal() before. #define fatalImage kFatal(41001) #define fatalRegistry kFatal(41002) #define fatalTools kFatal(41003) #define fatalTiles kFatal(41004) #define fatalFilters kFatal(41005) #define fatalPlugins kFatal(41006) #define fatalUI kFatal(41007) #define fatalFile kFatal(41008) #define fatalMath kFatal(41009) #define fatalRender kFatal(41010) #define fatalScript kFatal(41011) #endif /** * Use this macro to display in the output stream the name of a variable followed by its value. */ #define ppVar( var ) #var << "=" << var #ifdef __GNUC__ #define ENTER_FUNCTION() qDebug() << "Entering" << __func__ #define LEAVE_FUNCTION() qDebug() << "Leaving " << __func__ #else #define ENTER_FUNCTION() qDebug() << "Entering" << "" #define LEAVE_FUNCTION() qDebug() << "Leaving " << "" #endif # ifndef QT_NO_DEBUG # undef Q_ASSERT # define Q_ASSERT(cond) if(!(cond)) { kError() << kBacktrace(); qt_assert(#cond,__FILE__,__LINE__); } qt_noop() # endif -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" class QRect; class QString; void KRITAIMAGE_EXPORT kis_debug_save_device_incremental(KisPaintDeviceSP device, int i, const QRect &rc, const QString &suffix, const QString &prefix); /** * Saves the paint device incrementally. Put this macro into a * function that is called several times and you'll have as many * separate dump files as the number of times the function was * called. That is very convenient for debugging canvas updates: * adding this macro will let you track the whole history of updates. * * The files are saved with pattern: _.png */ #define KIS_DUMP_DEVICE_1(device, rc, suffix) \ do { \ static int i = -1; i++; \ kis_debug_save_device_incremental((device), i, (rc), (suffix), QString()); \ } while(0) /** * Saves the paint device incrementally. Put this macro into a * function that is called several times and you'll have as many * separate dump files as the number of times the function was * called. That is very convenient for debugging canvas updates: * adding this macro will let you track the whole history of updates. * * The \p prefix parameter makes it easy to sort out dumps from * different functions. * * The files are saved with pattern: __.png */ #define KIS_DUMP_DEVICE_2(device, rc, suffix, prefix) \ do { \ static int i = -1; i++; \ kis_debug_save_device_incremental((device), i, (rc), (suffix), (prefix)); \ } while(0) #ifdef __GNUC__ KRITAIMAGE_EXPORT const char* __methodName(const char *prettyFunction); #define __METHOD_NAME__ __methodName(__PRETTY_FUNCTION__) #else #define __METHOD_NAME__ ":" #endif #define PREPEND_METHOD(msg) QString("%1: %2").arg(__METHOD_NAME__).arg(msg) #include "kis_assert.h" diff --git a/krita/image/kis_default_bounds.cpp b/krita/image/kis_default_bounds.cpp index 6df3e98e53a..f00ac18bb41 100644 --- a/krita/image/kis_default_bounds.cpp +++ b/krita/image/kis_default_bounds.cpp @@ -1,107 +1,111 @@ /* * Copyright (c) 2010 Boudewijn Rempt * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_global.h" #include "kis_default_bounds.h" #include "kis_paint_device.h" const QRect KisDefaultBounds::infiniteRect = QRect(qint32_MIN/2, qint32_MIN/2, qint32_MAX, qint32_MAX); /******************************************************************/ /* KisDefaultBounds */ /******************************************************************/ struct KisDefaultBounds::Private { KisImageWSP image; }; KisDefaultBounds::KisDefaultBounds(KisImageWSP image) : m_d(new Private()) { m_d->image = image; } KisDefaultBounds::~KisDefaultBounds() { delete m_d; } +void KisDefaultBounds::setImage(KisImageWSP image) +{ + m_d->image = image; +} + QRect KisDefaultBounds::bounds() const { /** * By default return infinite rect to cover everything */ return m_d->image ? m_d->image->bounds() : infiniteRect; } bool KisDefaultBounds::wrapAroundMode() const { return m_d->image ? m_d->image->wrapAroundModeActive() : false; } /******************************************************************/ /* KisSelectionDefaultBounds */ /******************************************************************/ struct KisSelectionDefaultBounds::Private { KisPaintDeviceSP parentDevice; }; KisSelectionDefaultBounds::KisSelectionDefaultBounds(KisPaintDeviceSP parentDevice, KisImageWSP image) : KisDefaultBounds(image), m_d(new Private()) { m_d->parentDevice = parentDevice; } KisSelectionDefaultBounds::~KisSelectionDefaultBounds() { delete m_d; } QRect KisSelectionDefaultBounds::bounds() const { QRect additionalRect = m_d->parentDevice ? m_d->parentDevice->extent() : QRect(); return additionalRect | KisDefaultBounds::bounds(); } - /******************************************************************/ /* KisSelectionEmptyBounds */ /******************************************************************/ KisSelectionEmptyBounds::KisSelectionEmptyBounds(KisImageWSP image) : KisDefaultBounds(image) { } KisSelectionEmptyBounds::~KisSelectionEmptyBounds() { } QRect KisSelectionEmptyBounds::bounds() const { return QRect(0, 0, 0, 0); } diff --git a/krita/image/kis_default_bounds.h b/krita/image/kis_default_bounds.h index 94c11625a49..ce5c8b802ab 100644 --- a/krita/image/kis_default_bounds.h +++ b/krita/image/kis_default_bounds.h @@ -1,77 +1,79 @@ /* * Copyright (c) 2010 Boudewijn Rempt * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DEFAULT_BOUNDS_H #define KIS_DEFAULT_BOUNDS_H #include #include "kis_types.h" #include "kis_image.h" #include "kis_default_bounds_base.h" class KisDefaultBounds; class KisSelectionDefaultBounds; class KisSelectionEmptyBounds; typedef KisSharedPtr KisDefaultBoundsSP; typedef KisSharedPtr KisSelectionDefaultBoundsSP; typedef KisSharedPtr KisSelectionEmptyBoundsSP; class KRITAIMAGE_EXPORT KisDefaultBounds : public KisDefaultBoundsBase { public: KisDefaultBounds(KisImageWSP image = 0); virtual ~KisDefaultBounds(); + void setImage(KisImageWSP image); + QRect bounds() const; bool wrapAroundMode() const; protected: friend class KisPaintDeviceTest; static const QRect infiniteRect; private: Q_DISABLE_COPY(KisDefaultBounds) struct Private; Private * const m_d; }; class KRITAIMAGE_EXPORT KisSelectionDefaultBounds : public KisDefaultBounds { public: KisSelectionDefaultBounds(KisPaintDeviceSP parentPaintDevice = 0, KisImageWSP image = 0); ~KisSelectionDefaultBounds(); QRect bounds() const; private: Q_DISABLE_COPY(KisSelectionDefaultBounds) struct Private; Private * const m_d; }; class KRITAIMAGE_EXPORT KisSelectionEmptyBounds : public KisDefaultBounds { public: KisSelectionEmptyBounds(KisImageWSP image); virtual ~KisSelectionEmptyBounds(); QRect bounds() const; }; #endif // KIS_DEFAULT_BOUNDS_H diff --git a/krita/image/kis_distance_information.h b/krita/image/kis_distance_information.h index 847ef0b87a8..0ab01df03d0 100644 --- a/krita/image/kis_distance_information.h +++ b/krita/image/kis_distance_information.h @@ -1,118 +1,118 @@ /* * Copyright (c) 2010 Cyrille Berger * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_DISTANCE_INFORMATION_H_ #define _KIS_DISTANCE_INFORMATION_H_ #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class KisPaintInformation; /** * This structure contains information about the desired spacing * requested by the paintAt call */ class KisSpacingInformation { public: explicit KisSpacingInformation() : m_spacing(0.0, 0.0) , m_isIsotropic(true) , m_rotation(0.0) { } explicit KisSpacingInformation(qreal isotropicSpacing) : m_spacing(isotropicSpacing, isotropicSpacing) , m_isIsotropic(true) , m_rotation(0.0) { } explicit KisSpacingInformation(const QPointF &anisotropicSpacing, qreal rotation) : m_spacing(anisotropicSpacing) , m_isIsotropic(anisotropicSpacing.x() == anisotropicSpacing.y()) , m_rotation(rotation) { } inline QPointF spacing() const { return m_spacing; } inline bool isIsotropic() const { return m_isIsotropic; } inline qreal scalarApprox() const { return m_isIsotropic ? m_spacing.x() : QVector2D(m_spacing).length(); } inline qreal rotation() const { return m_rotation; } private: QPointF m_spacing; bool m_isIsotropic; qreal m_rotation; }; /** * This structure is used as return value of paintLine to contain * information that is needed to be passed for the next call. */ class KRITAIMAGE_EXPORT KisDistanceInformation { public: KisDistanceInformation(); KisDistanceInformation(const QPointF &lastPosition, qreal lastTime); KisDistanceInformation(const KisDistanceInformation &rhs); KisDistanceInformation& operator=(const KisDistanceInformation &rhs); ~KisDistanceInformation(); const KisSpacingInformation& currentSpacing() const; bool hasLastDabInformation() const; QPointF lastPosition() const; qreal lastTime() const; qreal lastDrawingAngle() const; bool hasLastPaintInformation() const; const KisPaintInformation& lastPaintInformation() const; void registerPaintedDab(const KisPaintInformation &info, const KisSpacingInformation &spacing); qreal getNextPointPosition(const QPointF &start, const QPointF &end); private: qreal getNextPointPositionIsotropic(const QPointF &start, const QPointF &end); qreal getNextPointPositionAnisotropic(const QPointF &start, const QPointF &end); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/kis_dom_utils.h b/krita/image/kis_dom_utils.h index 2d29be47bd5..4059224a463 100644 --- a/krita/image/kis_dom_utils.h +++ b/krita/image/kis_dom_utils.h @@ -1,235 +1,235 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DOM_UTILS_H #define __KIS_DOM_UTILS_H #include #include #include #include #include #include "klocale.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_debug.h" namespace KisDomUtils { namespace Private { inline QString numberToString(const QString &value) { return value; } template inline QString numberToString(T value) { return QString::number(value); } inline int stringToInt(const QString &str) { bool ok = false; int value = 0; QLocale c(QLocale::German); value = str.toInt(&ok); if (!ok) { value = c.toInt(str, &ok); } if (!ok) { qWarning() << "WARNING: KisDomUtils::stringToInt failed:" << ppVar(str); value = 0; } return value; } inline double stringToDouble(const QString &str) { bool ok = false; double value = 0; QLocale c(QLocale::German); /** * A special workaround to handle ','/'.' decimal point * in different locales. Added for backward compatibility, * because we used to save qreals directly using * * e.setAttribute("w", (qreal)value), * * which did local-aware conversion. */ value = str.toDouble(&ok); if (!ok) { value = c.toDouble(str, &ok); } if (!ok) { qWarning() << "WARNING: KisDomUtils::stringToDouble failed:" << ppVar(str); value = 0; } return value; } } /** * Save a value of type QRect into an XML tree. A child for \p parent * is created and assigned a tag \p tag. The corresponding value can * be fetched from the XML using loadValue() later. * * \see loadValue() */ void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const QRect &rc); void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const QSize &size); void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const QPointF &pt); void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const QVector3D &pt); void KRITAIMAGE_EXPORT saveValue(QDomElement *parent, const QString &tag, const QTransform &t); /** * Save a value of a scalar type into an XML tree. A child for \p parent * is created and assigned a tag \p tag. The corresponding value can * be fetched from the XML using loadValue() later. * * \see loadValue() */ template void saveValue(QDomElement *parent, const QString &tag, T value) { QDomDocument doc = parent->ownerDocument(); QDomElement e = doc.createElement(tag); parent->appendChild(e); e.setAttribute("type", "value"); e.setAttribute("value", Private::numberToString(value)); } /** * Save a vector of values into an XML tree. A child for \p parent is * created and assigned a tag \p tag. The values in the array should * have a type supported by saveValue() overrides. The corresponding * vector can be fetched from the XML using loadValue() later. * * \see loadValue() */ template void saveValue(QDomElement *parent, const QString &tag, const QVector &array) { QDomDocument doc = parent->ownerDocument(); QDomElement e = doc.createElement(tag); parent->appendChild(e); e.setAttribute("type", "array"); int i = 0; foreach (const T &v, array) { saveValue(&e, QString("item_%1").arg(i++), v); } } /** * Find an element with tag \p tag which is a child of \p parent. The element should * be the only element with the provided tag in this parent. * * \return true is the element with \p tag is found and it is unique */ bool KRITAIMAGE_EXPORT findOnlyElement(const QDomElement &parent, const QString &tag, QDomElement *el, QStringList *errorMessages = 0); /** * Load an object from an XML element, which is a child of \p parent and has * a tag \p tag. * * \return true if the object is successfully loaded and is unique * * \see saveValue() */ bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, float *v); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, double *v); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, QSize *size); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, QRect *rc); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, QPointF *pt); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, QVector3D *pt); bool KRITAIMAGE_EXPORT loadValue(const QDomElement &e, QTransform *t); namespace Private { bool KRITAIMAGE_EXPORT checkType(const QDomElement &e, const QString &expectedType); } /** * Load a scalar value from an XML element, which is a child of \p parent * and has a tag \p tag. * * \return true if the object is successfully loaded and is unique * * \see saveValue() */ template bool loadValue(const QDomElement &e, T *value) { if (!Private::checkType(e, "value")) return false; QVariant v(e.attribute("value", "no-value")); *value = v.value(); return true; } /** * Load an array from an XML element, which is a child of \p parent * and has a tag \p tag. * * \return true if the object is successfully loaded and is unique * * \see saveValue() */ template bool loadValue(const QDomElement &e, QVector *array) { if (!Private::checkType(e, "array")) return false; QDomElement child = e.firstChildElement(); while (!child.isNull()) { T value; if (!loadValue(child, &value)) return false; *array << value; child = child.nextSiblingElement(); } return true; } template bool loadValue(const QDomElement &parent, const QString &tag, T *value) { QDomElement e; if (!findOnlyElement(parent, tag, &e)) return false; return loadValue(e, value); } KRITAIMAGE_EXPORT QDomElement findElementByAttibute(QDomNode parent, const QString &tag, const QString &attribute, const QString &key); } #endif /* __KIS_DOM_UTILS_H */ diff --git a/krita/image/kis_fast_math.h b/krita/image/kis_fast_math.h index 2da7f3a447c..041488e0c18 100644 --- a/krita/image/kis_fast_math.h +++ b/krita/image/kis_fast_math.h @@ -1,36 +1,36 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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. * * adopted from here http://www.snippetcenter.org/en/a-fast-atan2-function-s1868.aspx */ #ifndef _KIS_IMAGE_FAST_ #define _KIS_IMAGE_FAST_ -#include "krita_export.h" +#include "kritaimage_export.h" /** * This namespace countains fast but inaccurate version of mathematical function. */ namespace KisFastMath { /// atan2 replacement KRITAIMAGE_EXPORT qreal atan2(qreal y, qreal x); } #endif diff --git a/krita/image/kis_fill_painter.h b/krita/image/kis_fill_painter.h index 117f49ee06a..57eb35263ad 100644 --- a/krita/image/kis_fill_painter.h +++ b/krita/image/kis_fill_painter.h @@ -1,285 +1,285 @@ /* * Copyright (c) 2004 Adrian Page * Copyright (c) 2004 Bart Coppens * * 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_FILL_PAINTER_H_ #define KIS_FILL_PAINTER_H_ #include #include "KoColor.h" #include "KoColorSpaceRegistry.h" #include "kis_painter.h" #include "kis_types.h" #include "kis_selection.h" -#include +#include class KoPattern; class KisFilterConfiguration; // XXX: Filling should set dirty rect. /** * This painter can be used to fill paint devices in different ways. This can also be used * for flood filling related operations. */ class KRITAIMAGE_EXPORT KisFillPainter : public KisPainter { public: /** * Construct an empty painter. Use the begin(KisPaintDeviceSP) method to attach * to a paint device */ KisFillPainter(); /** * Start painting on the specified paint device */ KisFillPainter(KisPaintDeviceSP device); KisFillPainter(KisPaintDeviceSP device, KisSelectionSP selection); private: void initFillPainter(); public: /** * Fill a rectangle with black transparent pixels (0, 0, 0, 0 for RGBA). */ void eraseRect(qint32 x1, qint32 y1, qint32 w, qint32 h); /** * Overloaded version of the above function. */ void eraseRect(const QRect& rc); /** * Fill current selection of KisPainter with a specified \p color. * * The filling rect is limited by \p rc to allow multithreaded * filling/processing. */ void fillSelection(const QRect &rc, const KoColor &color); /** * Fill a rectangle with a certain color. */ void fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor& c); /** * Overloaded version of the above function. */ void fillRect(const QRect& rc, const KoColor& c); /** * Fill a rectangle with a certain color and opacity. */ void fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor& c, quint8 opacity); /** * Overloaded version of the above function. */ void fillRect(const QRect& rc, const KoColor& c, quint8 opacity); /** * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the * entire rectangle. */ void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KoPattern * pattern); /** * Fill a rectangle with a certain pattern. The pattern is repeated if it does not fit the * entire rectangle. */ void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisPaintDeviceSP device, const QRect& deviceRect); /** * Overloaded version of the above function. */ void fillRect(const QRect& rc, const KoPattern * pattern); /** * Fill the specified area with the output of the generator plugin that is configured * in the generator parameter */ void fillRect(qint32 x1, qint32 y1, qint32 w, qint32 h, const KisFilterConfiguration * generator); /** * Fills the enclosed area around the point with the set color. If * there is a selection, the whole selection is filled. Note that * you must have set the width and height on the painter if you * don't have a selection. * * @param startX the X position where the floodfill starts * @param startY the Y position where the floodfill starts * @param sourceDevice the sourceDevice that determines the area that * is floodfilled if sampleMerged is on */ void fillColor(int startX, int startY, KisPaintDeviceSP sourceDevice); /** * Fills the enclosed area around the point with the set pattern. * If there is a selection, the whole selection is filled. Note * that you must have set the width and height on the painter if * you don't have a selection. * * @param startX the X position where the floodfill starts * @param startY the Y position where the floodfill starts * @param sourceDevice the sourceDevice that determines the area that * is floodfilled if sampleMerged is on */ void fillPattern(int startX, int startY, KisPaintDeviceSP sourceDevice); /** * Returns a selection mask for the floodfill starting at the specified position. * * @param startX the X position where the floodfill starts * @param startY the Y position where the floodfill starts * @param sourceDevice the sourceDevice that determines the area that * is floodfilled if sampleMerged is on */ KisSelectionSP createFloodSelection(int startX, int startY, KisPaintDeviceSP sourceDevice); /** * Set the threshold for floodfill. The range is 0-255: 0 means the fill will only * fill parts that are the exact same color, 255 means anything will be filled */ void setFillThreshold(int threshold); /** Returns the fill threshold, see setFillThreshold for details */ int fillThreshold() const { return m_threshold; } bool useCompositioning() const { return m_useCompositioning; } void setUseCompositioning(bool useCompositioning) { m_useCompositioning = useCompositioning; } /** Sets the width of the paint device */ void setWidth(int w) { m_width = w; } /** Sets the height of the paint device */ void setHeight(int h) { m_height = h; } /** If true, floodfill doesn't fill outside the selected area of a layer */ bool careForSelection() const { return m_careForSelection; } /** Set caring for selection. See careForSelection for details */ void setCareForSelection(bool set) { m_careForSelection = set; } /** Sets the auto growth/shrinking radius */ void setSizemod(int sizemod) { m_sizemod = sizemod; } /** Sets how much to auto-grow or shrink (if @param sizemod is negative) the selection flood before painting, this affects every fill operation except fillRect */ int sizemod() { return m_sizemod; } /** Sets feathering radius */ void setFeather(int feather) { m_feather = feather; } /** defines the feathering radius for selection flood operations, this affects every fill operation except fillRect */ uint feather() { return m_feather; } private: // for floodfill void genericFillStart(int startX, int startY, KisPaintDeviceSP sourceDevice); void genericFillEnd(KisPaintDeviceSP filled); KisSelectionSP m_fillSelection; int m_feather; int m_sizemod; int m_threshold; int m_width, m_height; QRect m_rect; bool m_careForSelection; bool m_useCompositioning; }; inline void KisFillPainter::fillRect(qint32 x, qint32 y, qint32 w, qint32 h, const KoColor& c) { fillRect(x, y, w, h, c, OPACITY_OPAQUE_U8); } inline void KisFillPainter::fillRect(const QRect& rc, const KoColor& c) { fillRect(rc.x(), rc.y(), rc.width(), rc.height(), c, OPACITY_OPAQUE_U8); } inline void KisFillPainter::eraseRect(qint32 x1, qint32 y1, qint32 w, qint32 h) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KoColor c(Qt::black, cs); fillRect(x1, y1, w, h, c, OPACITY_TRANSPARENT_U8); } inline void KisFillPainter::eraseRect(const QRect& rc) { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); KoColor c(Qt::black, cs); fillRect(rc.x(), rc.y(), rc.width(), rc.height(), c, OPACITY_TRANSPARENT_U8); } inline void KisFillPainter::fillRect(const QRect& rc, const KoColor& c, quint8 opacity) { fillRect(rc.x(), rc.y(), rc.width(), rc.height(), c, opacity); } inline void KisFillPainter::fillRect(const QRect& rc, const KoPattern* pattern) { fillRect(rc.x(), rc.y(), rc.width(), rc.height(), pattern); } inline void KisFillPainter::setFillThreshold(int threshold) { m_threshold = threshold; } #endif //KIS_FILL_PAINTER_H_ diff --git a/krita/image/kis_filter_strategy.h b/krita/image/kis_filter_strategy.h index ab2b678ced6..18fc47be418 100644 --- a/krita/image/kis_filter_strategy.h +++ b/krita/image/kis_filter_strategy.h @@ -1,207 +1,207 @@ /* * Copyright (c) 2004 Michael Thaler * Copyright (c) 2005 C. Boemann * Copyright (c) 2013 Juan Palacios * * 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_STRATEGY_H_ #define KIS_FILTER_STRATEGY_H_ #include #include "kis_types.h" #include "KoGenericRegistry.h" #include "KoID.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisFilterStrategy { public: KisFilterStrategy(KoID id) : m_id(id) {} virtual ~KisFilterStrategy() {} QString id() { return m_id.id(); } QString name() { return m_id.name(); } virtual qreal valueAt(qreal /*t*/) const { return 0; } virtual qint32 intValueAt(qint32 t) const { return qint32(255*valueAt(t / 256.0)); } qreal support() { return supportVal; } qint32 intSupport() { return intSupportVal; } virtual bool boxSpecial() { return false; } virtual QString description() { return QString(""); } protected: qreal supportVal; qint32 intSupportVal; KoID m_id; }; class KRITAIMAGE_EXPORT KisHermiteFilterStrategy : public KisFilterStrategy { public: KisHermiteFilterStrategy() : KisFilterStrategy(KoID("Hermite", i18n("Hermite"))) { supportVal = 1.0; intSupportVal = 256; } virtual ~KisHermiteFilterStrategy() {} virtual qint32 intValueAt(qint32 t) const; virtual qreal valueAt(qreal t) const; }; class KRITAIMAGE_EXPORT KisBicubicFilterStrategy : public KisFilterStrategy { public: KisBicubicFilterStrategy() : KisFilterStrategy(KoID("Bicubic", i18n("Bicubic"))) { supportVal = 2.0; intSupportVal = 512; } virtual ~KisBicubicFilterStrategy() {} virtual QString description() { return i18n("Adds pixels using the color of surrounding pixels. Produces smoother tonal gradations than Bilinear."); } virtual qint32 intValueAt(qint32 t) const; }; class KRITAIMAGE_EXPORT KisBoxFilterStrategy : public KisFilterStrategy { public: KisBoxFilterStrategy() : KisFilterStrategy(KoID("Box", i18n("Box"))) { supportVal = 0.5; intSupportVal = 128; } virtual ~KisBoxFilterStrategy() {} virtual QString description() { return i18n("Replicate pixels in the image. Preserves all the original detail, but can produce jagged effects."); } virtual qint32 intValueAt(qint32 t) const; virtual qreal valueAt(qreal t) const; virtual bool boxSpecial() { return true; } }; class KRITAIMAGE_EXPORT KisBilinearFilterStrategy : public KisFilterStrategy { public: KisBilinearFilterStrategy() : KisFilterStrategy(KoID("Bilinear", i18n("Bilinear"))) { supportVal = 1.0; intSupportVal = 256; } virtual ~KisBilinearFilterStrategy() {} virtual QString description() { return i18n("Adds pixels averaging the color values of surrounding pixels. Produces medium quality results when the image is scaled from half to two times the original size."); } virtual qint32 intValueAt(qint32 t) const; virtual qreal valueAt(qreal t) const; }; class KRITAIMAGE_EXPORT KisBellFilterStrategy : public KisFilterStrategy { public: KisBellFilterStrategy() : KisFilterStrategy(KoID("Bell", i18n("Bell"))) { supportVal = 1.5; intSupportVal = 128 + 256; } virtual ~KisBellFilterStrategy() {} virtual qreal valueAt(qreal t) const; }; class KRITAIMAGE_EXPORT KisBSplineFilterStrategy : public KisFilterStrategy { public: KisBSplineFilterStrategy() : KisFilterStrategy(KoID("BSpline", i18n("BSpline"))) { supportVal = 2.0; intSupportVal = 512; } virtual ~KisBSplineFilterStrategy() {} virtual qreal valueAt(qreal t) const; }; class KRITAIMAGE_EXPORT KisLanczos3FilterStrategy : public KisFilterStrategy { public: KisLanczos3FilterStrategy() : KisFilterStrategy(KoID("Lanczos3", i18n("Lanczos3"))) { supportVal = 3.0; intSupportVal = 768; } virtual ~KisLanczos3FilterStrategy() {} virtual QString description() { return i18n("Offers similar results than Bicubic, but maybe a little bit sharper. Can produce light and dark halos along strong edges."); } virtual qreal valueAt(qreal t) const; private: qreal sinc(qreal x) const; }; class KRITAIMAGE_EXPORT KisMitchellFilterStrategy : public KisFilterStrategy { public: KisMitchellFilterStrategy() : KisFilterStrategy(KoID("Mitchell", i18n("Mitchell"))) { supportVal = 2.0; intSupportVal = 256; } virtual ~KisMitchellFilterStrategy() {} virtual qreal valueAt(qreal t) const; }; class KRITAIMAGE_EXPORT KisFilterStrategyRegistry : public KoGenericRegistry { public: static KisFilterStrategyRegistry* instance(); /** * This function return a list of all the keys in KoID format by using the name() method * on the objects stored in the registry. */ QList listKeys() const; /** * This function return a string formated in HTML that contains the descriptions of all objects * (with a non empty description) stored in the registry. */ QString formatedDescriptions() const; private: KisFilterStrategyRegistry(); ~KisFilterStrategyRegistry(); KisFilterStrategyRegistry(const KisFilterStrategyRegistry&); KisFilterStrategyRegistry operator=(const KisFilterStrategyRegistry&); }; #endif // KIS_FILTER_STRATEGY_H_ diff --git a/krita/image/kis_fixed_paint_device.h b/krita/image/kis_fixed_paint_device.h index b56e43d7c1e..5fdbf07734a 100644 --- a/krita/image/kis_fixed_paint_device.h +++ b/krita/image/kis_fixed_paint_device.h @@ -1,183 +1,183 @@ /* * Copyright (c) 2009 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_FIXED_PAINT_DEVICE_H #define KIS_FIXED_PAINT_DEVICE_H -#include +#include #include #include "kis_global.h" #include "kis_shared.h" #include #include #include #include /** * A fixed paint device is a simple paint device that consists of an array * of bytes and a rectangle. It cannot grow, it cannot shrink, all you can * do is fill the paint device with the right bytes and use it as an argument * to KisPainter or use the bytes as an argument to KoColorSpace functions. */ class KRITAIMAGE_EXPORT KisFixedPaintDevice : public KisShared { public: KisFixedPaintDevice(const KoColorSpace* colorSpace); virtual ~KisFixedPaintDevice(); /** * Deep copy the fixed paint device, including the data. */ KisFixedPaintDevice(const KisFixedPaintDevice& rhs); /** * Deep copy the fixed paint device, including the data. */ KisFixedPaintDevice& operator=(const KisFixedPaintDevice& rhs); /** * setRect sets the rect of the fixed paint device to rect. * This will _not_ create the associated data area. * * @rect the bounds in pixels. The x,y of the rect represent the origin * of the fixed paint device. */ void setRect(const QRect& rc); /** * @return the rect that the data represents */ QRect bounds() const; /** * @return the amount of allocated pixels (you can fake the size with setRect/bounds) * It is useful to know the accumulated memory size in pixels (not in bytes) for optimizations to avoid re-allocation. */ int allocatedPixels() const; /** * @return the pixelSize associated with this fixed paint device. */ quint32 pixelSize() const; const KoColorSpace* colorSpace() const { return m_colorSpace; } /** * initializes the paint device. * * @param defaultValue the default byte with which all pixels will be filled. * @return false if the allocation failed. */ bool initialize(quint8 defaultValue = 0); /** * @return a pointer to the beginning of the data associated with this fixed paint device. */ quint8* data(); quint8* data() const; /** * Read the bytes representing the rectangle described by x, y, w, h into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * The reading is done only if the rectangular area x,y,w,h is inside the bounds of the device * and the device is not empty */ void readBytes(quint8 * dstData, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Converts the paint device to a different colorspace */ void convertTo(const KoColorSpace * dstColorSpace = 0, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags); /** * Fill this paint device with the data from image * * @param srcProfileName name of the RGB profile to interpret the image as. 0 is interpreted as sRGB */ virtual void convertFromQImage(const QImage& image, const QString &srcProfileName); /** * Create an RGBA QImage from a rectangle in the paint device. * * @param x Left coordinate of the rectangle * @param y Top coordinate of the rectangle * @param w Width of the rectangle in pixels * @param h Height of the rectangle in pixels * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). */ virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; /** * Create an RGBA QImage from a rectangle in the paint device. The * rectangle is defined by the parent image's bounds. * * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). */ virtual QImage convertToQImage(const KoColorProfile *dstProfile, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; /** * Clear the given rectangle to transparent black. * * XXX: this will not (yet) expand the paint device to contain the specified rect * but if the paintdevice has not been initialized, it will be. */ void clear(const QRect & rc); /** * Fill the given rectangle with the given pixel. This does not take the * selection into account. * * XXX: this will not (yet) expand the paint device to contain the specified rect * but if the paintdevice has not been initialized, it will be. */ void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel); /** * Mirrors the device. */ void mirror(bool horizontal, bool vertical); private: const KoColorSpace* m_colorSpace; QRect m_bounds; QVector m_data; }; #endif diff --git a/krita/image/kis_gauss_circle_mask_generator.h b/krita/image/kis_gauss_circle_mask_generator.h index 8779af71391..17867f08cae 100644 --- a/krita/image/kis_gauss_circle_mask_generator.h +++ b/krita/image/kis_gauss_circle_mask_generator.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2011 Geoffry Song * * 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_GAUSS_MASK_GENERATOR_H_ #define _KIS_GAUSS_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_mask_generator.h" /** * This mask generator uses a Gaussian-blurred circle */ class KRITAIMAGE_EXPORT KisGaussCircleMaskGenerator : public KisMaskGenerator { public: KisGaussCircleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges); virtual ~KisGaussCircleMaskGenerator(); virtual quint8 valueAt(qreal x, qreal y) const; void setScale(qreal scaleX, qreal scaleY); private: qreal norme(qreal a, qreal b) const { return a*a + b*b; } private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_gauss_rect_mask_generator.h b/krita/image/kis_gauss_rect_mask_generator.h index cb40e08f914..fd61f03412a 100644 --- a/krita/image/kis_gauss_rect_mask_generator.h +++ b/krita/image/kis_gauss_rect_mask_generator.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2011 Geoffry Song * * 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_GAUSS_RECT_MASK_GENERATOR_H_ #define _KIS_GAUSS_RECT_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_mask_generator.h" /** * This mask generator uses a Gaussian-blurred rectangle */ class KRITAIMAGE_EXPORT KisGaussRectangleMaskGenerator : public KisMaskGenerator { public: KisGaussRectangleMaskGenerator(qreal diameter, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges); virtual ~KisGaussRectangleMaskGenerator(); virtual quint8 valueAt(qreal x, qreal y) const; void setScale(qreal scaleX, qreal scaleY); private: qreal norme(qreal a, qreal b) const { return a*a + b*b; } private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_gaussian_kernel.h b/krita/image/kis_gaussian_kernel.h index daafea7fcb8..ae59286333e 100644 --- a/krita/image/kis_gaussian_kernel.h +++ b/krita/image/kis_gaussian_kernel.h @@ -1,55 +1,55 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_GAUSSIAN_KERNEL_H #define __KIS_GAUSSIAN_KERNEL_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include using namespace Eigen; class QRect; class KRITAIMAGE_EXPORT KisGaussianKernel { public: static Matrix createHorizontalMatrix(qreal radius); static Matrix createVerticalMatrix(qreal radius); static KisConvolutionKernelSP createHorizontalKernel(qreal radius); static KisConvolutionKernelSP createVerticalKernel(qreal radius); static qreal sigmaFromRadius(qreal radius); static int kernelSizeFromRadius(qreal radius); static void applyGaussian(KisPaintDeviceSP device, const QRect& rect, qreal xRadius, qreal yRadius, const QBitArray &channelFlags, KoUpdater *updater); }; #endif /* __KIS_GAUSSIAN_KERNEL_H */ diff --git a/krita/image/kis_gradient_painter.h b/krita/image/kis_gradient_painter.h index e3cfb9d77ae..32f964f5a09 100644 --- a/krita/image/kis_gradient_painter.h +++ b/krita/image/kis_gradient_painter.h @@ -1,91 +1,91 @@ /* * Copyright (c) 2004 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_GRADIENT_PAINTER_H_ #define KIS_GRADIENT_PAINTER_H_ #include #include #include "kis_global.h" #include "kis_types.h" #include "kis_painter.h" -#include +#include /** * XXX: Docs! */ class KRITAIMAGE_EXPORT KisGradientPainter : public KisPainter { public: KisGradientPainter(); KisGradientPainter(KisPaintDeviceSP device); KisGradientPainter(KisPaintDeviceSP device, KisSelectionSP selection); ~KisGradientPainter(); enum enumGradientShape { GradientShapeLinear, GradientShapeBiLinear, GradientShapeRadial, GradientShapeSquare, GradientShapeConical, GradientShapeConicalSymetric, GradientShapePolygonal }; enum enumGradientRepeat { GradientRepeatNone, GradientRepeatForwards, GradientRepeatAlternate }; void setGradientShape(enumGradientShape shape); void precalculateShape(); /** * Paint a gradient in the rect between startx, starty, width and height. */ bool paintGradient(const QPointF& gradientVectorStart, const QPointF& gradientVectorEnd, enumGradientRepeat repeat, double antiAliasThreshold, bool reverseGradient, qint32 startx, qint32 starty, qint32 width, qint32 height); // convenience overload bool paintGradient(const QPointF& gradientVectorStart, const QPointF& gradientVectorEnd, enumGradientRepeat repeat, double antiAliasThreshold, bool reverseGradient, const QRect &applyRect); private: struct Private; const QScopedPointer m_d; }; #endif //KIS_GRADIENT_PAINTER_H_ diff --git a/krita/image/kis_green_coordinates_math.h b/krita/image/kis_green_coordinates_math.h index 53eb7530cfd..2a20d74d4fb 100644 --- a/krita/image/kis_green_coordinates_math.h +++ b/krita/image/kis_green_coordinates_math.h @@ -1,59 +1,59 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_GREEN_COORDINATES_MATH_H #define __KIS_GREEN_COORDINATES_MATH_H #include #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisGreenCoordinatesMath { public: KisGreenCoordinatesMath(); ~KisGreenCoordinatesMath(); /** * Prepare the transformation framework by computing internal * coordinates of the points in cage. * * Please note that the points in \p points will later be accessed * with indexes only. */ void precalculateGreenCoordinates(const QVector &originalCage, const QVector &points); /** * Precalculate coefficients of the destination cage. Should be * called once for every cage change */ void generateTransformedCageNormals(const QVector &transformedCage); /** * Transform one point according to its index */ QPointF transformedPoint(int pointIndex, const QVector &transformedCage); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_GREEN_COORDINATES_MATH_H */ diff --git a/krita/image/kis_group_layer.cc b/krita/image/kis_group_layer.cc index 90aa2cf300b..acefd805940 100644 --- a/krita/image/kis_group_layer.cc +++ b/krita/image/kis_group_layer.cc @@ -1,383 +1,385 @@ /* * Copyright (c) 2005 C. Boemann * Copyright (c) 2007 Boudewijn Rempt * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_group_layer.h" #include #include #include #include #include "kis_types.h" #include "kis_node_visitor.h" #include "kis_processing_visitor.h" #include "kis_debug.h" #include "kis_image.h" #include "kis_paint_device.h" #include "kis_default_bounds.h" #include "kis_clone_layer.h" #include "kis_selection_mask.h" #include "kis_psd_layer_style.h" struct KisGroupLayer::Private { public: Private() : paintDevice(0) , x(0) , y(0) , passThroughMode(false) { } KisPaintDeviceSP paintDevice; qint32 x; qint32 y; bool passThroughMode; }; KisGroupLayer::KisGroupLayer(KisImageWSP image, const QString &name, quint8 opacity) : KisLayer(image, name, opacity), m_d(new Private()) { resetCache(); } KisGroupLayer::KisGroupLayer(const KisGroupLayer &rhs) : KisLayer(rhs), m_d(new Private()) { m_d->paintDevice = new KisPaintDevice(*rhs.m_d->paintDevice.data()); m_d->x = rhs.m_d->x; m_d->y = rhs.m_d->y; m_d->paintDevice->setDefaultPixel(const_cast(&rhs)->m_d->paintDevice->defaultPixel()); } KisGroupLayer::~KisGroupLayer() { delete m_d; } bool KisGroupLayer::checkCloneLayer(KisCloneLayerSP clone) const { KisNodeSP source = clone->copyFrom(); if (source) { if(!allowAsChild(source)) return false; if (source->inherits("KisGroupLayer")) { KisNodeSP newParent = const_cast(this); while (newParent) { if (newParent == source) { return false; } newParent = newParent->parent(); } } } return true; } bool KisGroupLayer::checkNodeRecursively(KisNodeSP node) const { KisCloneLayerSP cloneLayer = dynamic_cast(node.data()); if(cloneLayer) { return checkCloneLayer(cloneLayer); } else if (node->inherits("KisGroupLayer")) { KisNodeSP child = node->firstChild(); while (child) { if (!checkNodeRecursively(child)) { return false; } child = child->nextSibling(); } } return true; } bool KisGroupLayer::allowAsChild(KisNodeSP node) const { return checkNodeRecursively(node) && (parent() || (node->inherits("KisSelectionMask") && !selectionMask()) || !node->inherits("KisMask")); } const KoColorSpace * KisGroupLayer::colorSpace() const { return m_d->paintDevice->colorSpace(); } QIcon KisGroupLayer::icon() const { return themedIcon("folder"); } void KisGroupLayer::setImage(KisImageWSP image) { m_d->paintDevice->setDefaultBounds(new KisDefaultBounds(image)); KisLayer::setImage(image); } KisLayerSP KisGroupLayer::createMergedLayer(KisLayerSP prevLayer) { KisGroupLayer *prevGroup = dynamic_cast(prevLayer.data()); if (prevGroup && canMergeAndKeepBlendOptions(prevLayer)) { KisSharedPtr merged(new KisGroupLayer(*prevGroup)); KisNodeSP child, cloned; for (child = firstChild(); child; child = child->nextSibling()) { cloned = child->clone(); image()->addNode(cloned, merged); } image()->refreshGraphAsync(merged); return merged; } else return KisLayer::createMergedLayer(prevLayer); } void KisGroupLayer::resetCache(const KoColorSpace *colorSpace) { if (!colorSpace) colorSpace = image()->colorSpace(); Q_ASSERT(colorSpace); if (!m_d->paintDevice) { m_d->paintDevice = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image())); m_d->paintDevice->setX(m_d->x); m_d->paintDevice->setY(m_d->y); } else if(!(*m_d->paintDevice->colorSpace() == *colorSpace)) { KisPaintDeviceSP dev = new KisPaintDevice(this, colorSpace, new KisDefaultBounds(image())); dev->setX(m_d->x); dev->setY(m_d->y); quint8* defaultPixel = new quint8[colorSpace->pixelSize()]; m_d->paintDevice->colorSpace()-> convertPixelsTo(m_d->paintDevice->defaultPixel(), defaultPixel, colorSpace, 1, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); dev->setDefaultPixel(defaultPixel); delete[] defaultPixel; m_d->paintDevice = dev; } else { m_d->paintDevice->clear(); } } KisLayer* KisGroupLayer::onlyMeaningfulChild() const { KisNode *child = firstChild().data(); KisLayer *onlyLayer = 0; while (child) { KisLayer *layer = dynamic_cast(child); if (layer) { if (onlyLayer) return 0; onlyLayer = layer; } child = child->nextSibling().data(); } return onlyLayer; } KisPaintDeviceSP KisGroupLayer::tryObligeChild() const { const KisLayer *child = onlyMeaningfulChild(); if (child && child->channelFlags().isEmpty() && child->projection() && child->visible() && (child->compositeOpId() == COMPOSITE_OVER || child->compositeOpId() == COMPOSITE_ALPHA_DARKEN || child->compositeOpId() == COMPOSITE_COPY) && child->opacity() == OPACITY_OPAQUE_U8 && *child->projection()->colorSpace() == *colorSpace() && !child->layerStyle()) { quint8 defaultOpacity = m_d->paintDevice->colorSpace()->opacityU8( m_d->paintDevice->defaultPixel()); if(defaultOpacity == OPACITY_TRANSPARENT_U8) { return child->projection(); } } return 0; } KisPaintDeviceSP KisGroupLayer::original() const { /** * We are too lazy! Let's our children work for us. * Try to use children's paintDevice if it's the only * one in stack and meets some conditions */ KisPaintDeviceSP realOriginal = tryObligeChild(); if (!realOriginal) { if (!childCount() && !m_d->paintDevice->extent().isEmpty()) { m_d->paintDevice->clear(); } realOriginal = m_d->paintDevice; } return realOriginal; } void KisGroupLayer::setDefaultProjectionColor(KoColor color) { color.convertTo(m_d->paintDevice->colorSpace()); m_d->paintDevice->setDefaultPixel(color.data()); } KoColor KisGroupLayer::defaultProjectionColor() const { KoColor color(m_d->paintDevice->defaultPixel(), m_d->paintDevice->colorSpace()); return color; } bool KisGroupLayer::passThroughMode() const { return m_d->passThroughMode; } void KisGroupLayer::setPassThroughMode(bool value) { m_d->passThroughMode = value; } KisDocumentSectionModel::PropertyList KisGroupLayer::sectionModelProperties() const { KisDocumentSectionModel::PropertyList l = KisLayer::sectionModelProperties(); // XXX: get right icons l << KisDocumentSectionModel::Property(i18n("Pass Through"), koIcon("passthrough-enabled"), koIcon("passthrough-disabled"), passThroughMode()); return l; } void KisGroupLayer::setSectionModelProperties(const KisDocumentSectionModel::PropertyList &properties) { foreach (const KisDocumentSectionModel::Property &property, properties) { if (property.name == i18n("Pass Through")) { setPassThroughMode(property.state.toBool()); } } KisLayer::setSectionModelProperties(properties); } bool KisGroupLayer::accept(KisNodeVisitor &v) { return v.visit(this); } void KisGroupLayer::accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter) { return visitor.visit(this, undoAdapter); } qint32 KisGroupLayer::x() const { return m_d->x; } qint32 KisGroupLayer::y() const { return m_d->y; } void KisGroupLayer::setX(qint32 x) { qint32 delta = x - m_d->x; m_d->x = x; if(m_d->paintDevice) { m_d->paintDevice->setX(m_d->paintDevice->x() + delta); Q_ASSERT(m_d->paintDevice->x() == m_d->x); } } void KisGroupLayer::setY(qint32 y) { qint32 delta = y - m_d->y; m_d->y = y; if(m_d->paintDevice) { m_d->paintDevice->setY(m_d->paintDevice->y() + delta); Q_ASSERT(m_d->paintDevice->y() == m_d->y); } } struct ExtentPolicy { inline QRect operator() (const KisNode *node) { return node->extent(); } }; struct ExactBoundsPolicy { inline QRect operator() (const KisNode *node) { return node->exactBounds(); } }; template QRect collectRects(const KisNode *node, MetricPolicy policy) { QRect accumulator; const KisNode *child = node->firstChild(); while (child) { - accumulator |= policy(child); + if (!qobject_cast(child)) { + accumulator |= policy(child); + } child = child->nextSibling(); } return accumulator; } QRect KisGroupLayer::extent() const { return m_d->passThroughMode ? collectRects(this, ExtentPolicy()) : KisLayer::extent(); } QRect KisGroupLayer::exactBounds() const { return m_d->passThroughMode ? collectRects(this, ExactBoundsPolicy()) : KisLayer::exactBounds(); } #include "kis_group_layer.moc" diff --git a/krita/image/kis_image.cc b/krita/image/kis_image.cc index 6f368b8d20a..4cc707d5668 100644 --- a/krita/image/kis_image.cc +++ b/krita/image/kis_image.cc @@ -1,1816 +1,1936 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_image.h" #include // WORDS_BIGENDIAN #include #include #include #include #include #include #include #include #include #include "KoColorSpaceRegistry.h" #include "KoColor.h" #include "KoColorConversionTransformation.h" #include "KoColorProfile.h" #include #include "recorder/kis_action_recorder.h" #include "kis_adjustment_layer.h" #include "kis_annotation.h" #include "kis_change_profile_visitor.h" #include "kis_colorspace_convert_visitor.h" #include "kis_count_visitor.h" #include "kis_filter_strategy.h" #include "kis_group_layer.h" #include "commands/kis_image_commands.h" #include "kis_layer.h" #include "kis_meta_data_merge_strategy_registry.h" #include "kis_name_server.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_painter.h" #include "kis_perspective_grid.h" #include "kis_selection.h" #include "kis_transaction.h" #include "kis_types.h" #include "kis_meta_data_merge_strategy.h" #include "kis_memory_statistics_server.h" #include "kis_image_config.h" #include "kis_update_scheduler.h" #include "kis_image_signal_router.h" #include "kis_stroke_strategy.h" #include "kis_image_barrier_locker.h" #include "kis_undo_stores.h" #include "kis_legacy_undo_adapter.h" #include "kis_post_execution_undo_adapter.h" #include "kis_transform_worker.h" #include "kis_processing_applicator.h" #include "processing/kis_crop_processing_visitor.h" #include "processing/kis_crop_selections_processing_visitor.h" #include "processing/kis_transform_processing_visitor.h" #include "commands_new/kis_image_resize_command.h" #include "commands_new/kis_image_set_resolution_command.h" +#include "commands_new/kis_activate_selection_mask_command.h" #include "kis_composite_progress_proxy.h" #include "kis_layer_composition.h" #include "kis_wrapped_rect.h" #include "kis_crop_saved_extra_data.h" #include "kis_layer_projection_plane.h" #include "kis_update_time_monitor.h" +#include +#include + // #define SANITY_CHECKS #ifdef SANITY_CHECKS #define SANITY_CHECK_LOCKED(name) \ if (!locked()) warnKrita() << "Locking policy failed:" << name \ << "has been called without the image" \ "being locked"; #else #define SANITY_CHECK_LOCKED(name) #endif class KisImage::KisImagePrivate { public: + KisImagePrivate(KisImage *_q) : q(_q) {} + + KisImage *q; + quint32 lockCount; KisPerspectiveGrid* perspectiveGrid; qint32 width; qint32 height; double xres; double yres; const KoColorSpace * colorSpace; KisSelectionSP deselectedGlobalSelection; KisGroupLayerSP rootLayer; // The layers are contained in here QList dirtyLayers; // for thumbnails QList compositions; KisNodeSP isolatedRootNode; bool wrapAroundModePermitted; KisNameServer *nserver; KisUndoStore *undoStore; KisUndoAdapter *legacyUndoAdapter; KisPostExecutionUndoAdapter *postExecutionUndoAdapter; KisActionRecorder *recorder; vKisAnnotationSP annotations; QAtomicInt disableUIUpdateSignals; QAtomicInt disableDirtyRequests; KisImageSignalRouter *signalRouter; KisUpdateScheduler *scheduler; KisCompositeProgressProxy *compositeProgressProxy; bool startProjection; bool tryCancelCurrentStrokeAsync(); + + void notifyProjectionUpdatedInPatches(const QRect &rc); }; KisImage::KisImage(KisUndoStore *undoStore, qint32 width, qint32 height, const KoColorSpace * colorSpace, const QString& name, bool startProjection) : QObject(0) , KisShared() - , m_d(new KisImagePrivate()) + , m_d(new KisImagePrivate(this)) { setObjectName(name); dbgImage << "creating" << name; m_d->startProjection = startProjection; if (colorSpace == 0) { colorSpace = KoColorSpaceRegistry::instance()->rgb8(); } m_d->lockCount = 0; m_d->perspectiveGrid = 0; m_d->scheduler = 0; m_d->wrapAroundModePermitted = false; m_d->signalRouter = new KisImageSignalRouter(this); if (!undoStore) { undoStore = new KisDumbUndoStore(); } m_d->undoStore = undoStore; m_d->legacyUndoAdapter = new KisLegacyUndoAdapter(m_d->undoStore, this); m_d->postExecutionUndoAdapter = new KisPostExecutionUndoAdapter(m_d->undoStore, this); m_d->nserver = new KisNameServer(1); m_d->colorSpace = colorSpace; setRootLayer(new KisGroupLayer(this, "root", OPACITY_OPAQUE_U8)); m_d->xres = 1.0; m_d->yres = 1.0; m_d->width = width; m_d->height = height; m_d->recorder = new KisActionRecorder(this); m_d->compositeProgressProxy = new KisCompositeProgressProxy(); if (m_d->startProjection) { m_d->scheduler = new KisUpdateScheduler(this); m_d->scheduler->setProgressProxy(m_d->compositeProgressProxy); } connect(this, SIGNAL(sigImageModified()), KisMemoryStatisticsServer::instance(), SLOT(notifyImageChanged())); } KisImage::~KisImage() { dbgImage << "deleting kisimage" << objectName(); /** * Request the tools to end currently running strokes */ waitForDone(); /** * First delete the nodes, while strokes * and undo are still alive */ m_d->rootLayer = 0; KisUpdateScheduler *scheduler = m_d->scheduler; m_d->scheduler = 0; delete scheduler; delete m_d->postExecutionUndoAdapter; delete m_d->legacyUndoAdapter; delete m_d->undoStore; delete m_d->compositeProgressProxy; delete m_d->signalRouter; delete m_d->perspectiveGrid; delete m_d->nserver; delete m_d; disconnect(); // in case Qt gets confused } void KisImage::aboutToAddANode(KisNode *parent, int index) { KisNodeGraphListener::aboutToAddANode(parent, index); SANITY_CHECK_LOCKED("aboutToAddANode"); } void KisImage::nodeHasBeenAdded(KisNode *parent, int index) { KisNodeGraphListener::nodeHasBeenAdded(parent, index); SANITY_CHECK_LOCKED("nodeHasBeenAdded"); m_d->signalRouter->emitNodeHasBeenAdded(parent, index); KisNodeSP newNode = parent->at(index); if (!dynamic_cast(newNode.data())) { stopIsolatedMode(); } } void KisImage::aboutToRemoveANode(KisNode *parent, int index) { KisNodeSP deletedNode = parent->at(index); if (!dynamic_cast(deletedNode.data())) { stopIsolatedMode(); } KisNodeGraphListener::aboutToRemoveANode(parent, index); SANITY_CHECK_LOCKED("aboutToRemoveANode"); m_d->signalRouter->emitAboutToRemoveANode(parent, index); } void KisImage::nodeChanged(KisNode* node) { KisNodeGraphListener::nodeChanged(node); requestStrokeEnd(); m_d->signalRouter->emitNodeChanged(node); } KisSelectionSP KisImage::globalSelection() const { KisSelectionMaskSP selectionMask = m_d->rootLayer->selectionMask(); if (selectionMask) { return selectionMask->selection(); } else { return 0; } } void KisImage::setGlobalSelection(KisSelectionSP globalSelection) { KisSelectionMaskSP selectionMask = m_d->rootLayer->selectionMask(); if (!globalSelection) { if (selectionMask) { removeNode(selectionMask); } } else { if (!selectionMask) { selectionMask = new KisSelectionMask(this); selectionMask->initSelection(m_d->rootLayer); addNode(selectionMask); // If we do not set the selection now, the setActive call coming next // can be very, very expensive, depending on the size of the image. selectionMask->setSelection(globalSelection); selectionMask->setActive(true); } else { selectionMask->setSelection(globalSelection); } Q_ASSERT(m_d->rootLayer->childCount() > 0); Q_ASSERT(m_d->rootLayer->selectionMask()); } m_d->deselectedGlobalSelection = 0; m_d->legacyUndoAdapter->emitSelectionChanged(); } void KisImage::deselectGlobalSelection() { KisSelectionSP savedSelection = globalSelection(); setGlobalSelection(0); m_d->deselectedGlobalSelection = savedSelection; } bool KisImage::canReselectGlobalSelection() { return m_d->deselectedGlobalSelection; } void KisImage::reselectGlobalSelection() { if(m_d->deselectedGlobalSelection) { setGlobalSelection(m_d->deselectedGlobalSelection); } } QString KisImage::nextLayerName() const { if (m_d->nserver->currentSeed() == 0) { m_d->nserver->number(); return i18n("background"); } return i18n("Layer %1", m_d->nserver->number()); } void KisImage::rollBackLayerName() { m_d->nserver->rollback(); } KisCompositeProgressProxy* KisImage::compositeProgressProxy() { return m_d->compositeProgressProxy; } bool KisImage::locked() const { return m_d->lockCount != 0; } void KisImage::barrierLock() { if (!locked()) { requestStrokeEnd(); if (m_d->scheduler) { m_d->scheduler->barrierLock(); } } m_d->lockCount++; } bool KisImage::tryBarrierLock() { bool result = true; if (!locked()) { if (m_d->scheduler) { result = m_d->scheduler->tryBarrierLock(); } } if (result) { m_d->lockCount++; } return result; } void KisImage::lock() { if (!locked()) { requestStrokeEnd(); if (m_d->scheduler) { m_d->scheduler->lock(); } } m_d->lockCount++; } void KisImage::unlock() { Q_ASSERT(locked()); if (locked()) { m_d->lockCount--; if (m_d->lockCount == 0) { if (m_d->scheduler) { m_d->scheduler->unlock(); } } } } void KisImage::blockUpdates() { m_d->scheduler->blockUpdates(); } void KisImage::unblockUpdates() { m_d->scheduler->unblockUpdates(); } void KisImage::setSize(const QSize& size) { m_d->width = size.width(); m_d->height = size.height(); } void KisImage::resizeImageImpl(const QRect& newRect, bool cropLayers) { if (newRect == bounds() && !cropLayers) return; KUndo2MagicString actionName = cropLayers ? kundo2_i18n("Crop Image") : kundo2_i18n("Resize Image"); KisImageSignalVector emitSignals; emitSignals << ComplexSizeChangedSignal(newRect, newRect.size()); emitSignals << ModifiedSignal; KisCropSavedExtraData *extraData = new KisCropSavedExtraData(cropLayers ? KisCropSavedExtraData::CROP_IMAGE : KisCropSavedExtraData::RESIZE_IMAGE, newRect); KisProcessingApplicator applicator(this, m_d->rootLayer, KisProcessingApplicator::RECURSIVE | KisProcessingApplicator::NO_UI_UPDATES, emitSignals, actionName, extraData); if (cropLayers || !newRect.topLeft().isNull()) { KisProcessingVisitorSP visitor = new KisCropProcessingVisitor(newRect, cropLayers, true); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); } applicator.applyCommand(new KisImageResizeCommand(this, newRect.size())); applicator.end(); } void KisImage::resizeImage(const QRect& newRect) { resizeImageImpl(newRect, false); } void KisImage::cropImage(const QRect& newRect) { resizeImageImpl(newRect, true); } void KisImage::cropNode(KisNodeSP node, const QRect& newRect) { bool isLayer = dynamic_cast(node.data()); KUndo2MagicString actionName = isLayer ? kundo2_i18n("Crop Layer") : kundo2_i18n("Crop Mask"); KisImageSignalVector emitSignals; emitSignals << ModifiedSignal; KisCropSavedExtraData *extraData = new KisCropSavedExtraData(KisCropSavedExtraData::CROP_LAYER, newRect, node); KisProcessingApplicator applicator(this, node, KisProcessingApplicator::RECURSIVE, emitSignals, actionName, extraData); KisProcessingVisitorSP visitor = new KisCropProcessingVisitor(newRect, true, false); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); applicator.end(); } void KisImage::scaleImage(const QSize &size, qreal xres, qreal yres, KisFilterStrategy *filterStrategy) { bool resolutionChanged = xres != xRes() && yres != yRes(); bool sizeChanged = size != this->size(); if (!resolutionChanged && !sizeChanged) return; KisImageSignalVector emitSignals; if (resolutionChanged) emitSignals << ResolutionChangedSignal; if (sizeChanged) emitSignals << ComplexSizeChangedSignal(bounds(), size); emitSignals << ModifiedSignal; KUndo2MagicString actionName = sizeChanged ? kundo2_i18n("Scale Image") : kundo2_i18n("Change Image Resolution"); KisProcessingApplicator::ProcessingFlags signalFlags = (resolutionChanged || sizeChanged) ? KisProcessingApplicator::NO_UI_UPDATES : KisProcessingApplicator::NONE; KisProcessingApplicator applicator(this, m_d->rootLayer, KisProcessingApplicator::RECURSIVE | signalFlags, emitSignals, actionName); qreal sx = qreal(size.width()) / this->size().width(); qreal sy = qreal(size.height()) / this->size().height(); QTransform shapesCorrection; if (resolutionChanged) { shapesCorrection = QTransform::fromScale(xRes() / xres, yRes() / yres); } KisProcessingVisitorSP visitor = new KisTransformProcessingVisitor(sx, sy, 0, 0, QPointF(), 0, 0, 0, filterStrategy, shapesCorrection); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); if (resolutionChanged) { KUndo2Command *parent = new KisResetShapesCommand(m_d->rootLayer); new KisImageSetResolutionCommand(this, xres, yres, parent); applicator.applyCommand(parent); } if (sizeChanged) { applicator.applyCommand(new KisImageResizeCommand(this, size)); } applicator.end(); } void KisImage::scaleNode(KisNodeSP node, qreal sx, qreal sy, KisFilterStrategy *filterStrategy) { KUndo2MagicString actionName(kundo2_i18n("Scale Layer")); KisImageSignalVector emitSignals; emitSignals << ModifiedSignal; KisProcessingApplicator applicator(this, node, KisProcessingApplicator::RECURSIVE, emitSignals, actionName); KisProcessingVisitorSP visitor = new KisTransformProcessingVisitor(sx, sy, 0, 0, QPointF(), 0, 0, 0, filterStrategy); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); applicator.end(); } void KisImage::rotateImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double radians) { QPointF offset; QSize newSize; { KisTransformWorker worker(0, 1.0, 1.0, 0, 0, 0, 0, radians, 0, 0, 0, 0); QTransform transform = worker.transform(); if (resizeImage) { QRect newRect = transform.mapRect(bounds()); newSize = newRect.size(); offset = -newRect.topLeft(); } else { QPointF origin = QRectF(rootNode->exactBounds()).center(); newSize = size(); offset = -(transform.map(origin) - origin); } } bool sizeChanged = resizeImage && (newSize.width() != width() || newSize.height() != height()); // These signals will be emitted after processing is done KisImageSignalVector emitSignals; if (sizeChanged) emitSignals << ComplexSizeChangedSignal(bounds(), newSize); emitSignals << ModifiedSignal; // These flags determine whether updates are transferred to the UI during processing KisProcessingApplicator::ProcessingFlags signalFlags = sizeChanged ? KisProcessingApplicator::NO_UI_UPDATES : KisProcessingApplicator::NONE; KisProcessingApplicator applicator(this, rootNode, KisProcessingApplicator::RECURSIVE | signalFlags, emitSignals, actionName); KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value("Bicubic"); KisProcessingVisitorSP visitor = new KisTransformProcessingVisitor(1.0, 1.0, 0.0, 0.0, QPointF(), radians, offset.x(), offset.y(), filter); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); if (sizeChanged) { applicator.applyCommand(new KisImageResizeCommand(this, newSize)); } applicator.end(); } void KisImage::rotateImage(double radians) { rotateImpl(kundo2_i18n("Rotate Image"), root(), true, radians); } void KisImage::rotateNode(KisNodeSP node, double radians) { rotateImpl(kundo2_i18n("Rotate Layer"), node, false, radians); } void KisImage::shearImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double angleX, double angleY, const QPointF &origin) { //angleX, angleY are in degrees const qreal pi = 3.1415926535897932385; const qreal deg2rad = pi / 180.0; qreal tanX = tan(angleX * deg2rad); qreal tanY = tan(angleY * deg2rad); QPointF offset; QSize newSize; { KisTransformWorker worker(0, 1.0, 1.0, tanX, tanY, origin.x(), origin.y(), 0, 0, 0, 0, 0); QRect newRect = worker.transform().mapRect(bounds()); newSize = newRect.size(); if (resizeImage) offset = -newRect.topLeft(); } if (newSize == size()) return; KisImageSignalVector emitSignals; if (resizeImage) emitSignals << ComplexSizeChangedSignal(bounds(), newSize); emitSignals << ModifiedSignal; KisProcessingApplicator::ProcessingFlags signalFlags = KisProcessingApplicator::RECURSIVE; if (resizeImage) signalFlags |= KisProcessingApplicator::NO_UI_UPDATES; KisProcessingApplicator applicator(this, rootNode, signalFlags, emitSignals, actionName); KisFilterStrategy *filter = KisFilterStrategyRegistry::instance()->value("Bilinear"); KisProcessingVisitorSP visitor = new KisTransformProcessingVisitor(1.0, 1.0, tanX, tanY, origin, 0, offset.x(), offset.y(), filter); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); if (resizeImage) { applicator.applyCommand(new KisImageResizeCommand(this, newSize)); } applicator.end(); } void KisImage::shearNode(KisNodeSP node, double angleX, double angleY) { QPointF shearOrigin = QRectF(bounds()).center(); shearImpl(kundo2_i18n("Shear layer"), node, false, angleX, angleY, shearOrigin); } void KisImage::shear(double angleX, double angleY) { shearImpl(kundo2_i18n("Shear Image"), m_d->rootLayer, true, angleX, angleY, QPointF()); } void KisImage::convertImageColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags) { if (!dstColorSpace) return; const KoColorSpace *srcColorSpace = m_d->colorSpace; undoAdapter()->beginMacro(kundo2_i18n("Convert Image Color Space")); undoAdapter()->addCommand(new KisImageLockCommand(KisImageWSP(this), true)); undoAdapter()->addCommand(new KisImageSetProjectionColorSpaceCommand(KisImageWSP(this), dstColorSpace)); KisColorSpaceConvertVisitor visitor(this, srcColorSpace, dstColorSpace, renderingIntent, conversionFlags); m_d->rootLayer->accept(visitor); undoAdapter()->addCommand(new KisImageLockCommand(KisImageWSP(this), false)); undoAdapter()->endMacro(); setModified(); } bool KisImage::assignImageProfile(const KoColorProfile *profile) { if (!profile) return false; const KoColorSpace *dstCs = KoColorSpaceRegistry::instance()->colorSpace(colorSpace()->colorModelId().id(), colorSpace()->colorDepthId().id(), profile); const KoColorSpace *srcCs = colorSpace(); if (!dstCs) return false; m_d->colorSpace = dstCs; KisChangeProfileVisitor visitor(srcCs, dstCs); return m_d->rootLayer->accept(visitor); } void KisImage::convertProjectionColorSpace(const KoColorSpace *dstColorSpace) { if (*m_d->colorSpace == *dstColorSpace) return; undoAdapter()->beginMacro(kundo2_i18n("Convert Projection Color Space")); undoAdapter()->addCommand(new KisImageLockCommand(KisImageWSP(this), true)); undoAdapter()->addCommand(new KisImageSetProjectionColorSpaceCommand(KisImageWSP(this), dstColorSpace)); undoAdapter()->addCommand(new KisImageLockCommand(KisImageWSP(this), false)); undoAdapter()->endMacro(); setModified(); } void KisImage::setProjectionColorSpace(const KoColorSpace * colorSpace) { m_d->colorSpace = colorSpace; m_d->rootLayer->resetCache(); m_d->signalRouter->emitNotification(ColorSpaceChangedSignal); } const KoColorSpace * KisImage::colorSpace() const { return m_d->colorSpace; } const KoColorProfile * KisImage::profile() const { return colorSpace()->profile(); } double KisImage::xRes() const { return m_d->xres; } double KisImage::yRes() const { return m_d->yres; } void KisImage::setResolution(double xres, double yres) { m_d->xres = xres; m_d->yres = yres; m_d->signalRouter->emitNotification(ResolutionChangedSignal); } QPointF KisImage::documentToPixel(const QPointF &documentCoord) const { return QPointF(documentCoord.x() * xRes(), documentCoord.y() * yRes()); } QPoint KisImage::documentToIntPixel(const QPointF &documentCoord) const { QPointF pixelCoord = documentToPixel(documentCoord); return QPoint((int)pixelCoord.x(), (int)pixelCoord.y()); } QRectF KisImage::documentToPixel(const QRectF &documentRect) const { return QRectF(documentToPixel(documentRect.topLeft()), documentToPixel(documentRect.bottomRight())); } QRect KisImage::documentToIntPixel(const QRectF &documentRect) const { return documentToPixel(documentRect).toAlignedRect(); } QPointF KisImage::pixelToDocument(const QPointF &pixelCoord) const { return QPointF(pixelCoord.x() / xRes(), pixelCoord.y() / yRes()); } QPointF KisImage::pixelToDocument(const QPoint &pixelCoord) const { return QPointF((pixelCoord.x() + 0.5) / xRes(), (pixelCoord.y() + 0.5) / yRes()); } QRectF KisImage::pixelToDocument(const QRectF &pixelCoord) const { return QRectF(pixelToDocument(pixelCoord.topLeft()), pixelToDocument(pixelCoord.bottomRight())); } qint32 KisImage::width() const { return m_d->width; } qint32 KisImage::height() const { return m_d->height; } KisGroupLayerSP KisImage::rootLayer() const { Q_ASSERT(m_d->rootLayer); return m_d->rootLayer; } KisPaintDeviceSP KisImage::projection() const { if (m_d->isolatedRootNode) { return m_d->isolatedRootNode->projection(); } Q_ASSERT(m_d->rootLayer); KisPaintDeviceSP projection = m_d->rootLayer->projection(); Q_ASSERT(projection); return projection; } qint32 KisImage::nlayers() const { QStringList list; list << "KisLayer"; KisCountVisitor visitor(list, KoProperties()); m_d->rootLayer->accept(visitor); return visitor.count(); } qint32 KisImage::nHiddenLayers() const { QStringList list; list << "KisLayer"; KoProperties properties; properties.setProperty("visible", false); KisCountVisitor visitor(list, properties); m_d->rootLayer->accept(visitor); return visitor.count(); } QRect realNodeExactBounds(KisNodeSP rootNode, QRect currentRect = QRect()) { KisNodeSP node = rootNode->firstChild(); while(node) { currentRect |= realNodeExactBounds(node, currentRect); node = node->nextSibling(); } // TODO: it would be better to count up changeRect inside // node's extent() method currentRect |= rootNode->projectionPlane()->changeRect(rootNode->exactBounds()); return currentRect; } void KisImage::refreshHiddenArea(KisNodeSP rootNode, const QRect &preparedArea) { QRect realNodeRect = realNodeExactBounds(rootNode); if (!preparedArea.contains(realNodeRect)) { QRegion dirtyRegion = realNodeRect; dirtyRegion -= preparedArea; foreach(const QRect &rc, dirtyRegion.rects()) { refreshGraph(rootNode, rc, realNodeRect); } } } void KisImage::flatten() { KisGroupLayerSP oldRootLayer = m_d->rootLayer; KisGroupLayerSP newRootLayer = new KisGroupLayer(this, "root", OPACITY_OPAQUE_U8); refreshHiddenArea(oldRootLayer, bounds()); lock(); KisPaintDeviceSP projectionCopy = new KisPaintDevice(oldRootLayer->projection()->colorSpace()); projectionCopy->makeCloneFrom(oldRootLayer->projection(), oldRootLayer->exactBounds()); unlock(); KisPaintLayerSP flattenLayer = new KisPaintLayer(this, nextLayerName(), OPACITY_OPAQUE_U8, projectionCopy); Q_CHECK_PTR(flattenLayer); addNode(flattenLayer, newRootLayer, 0); undoAdapter()->beginMacro(kundo2_i18n("Flatten Image")); // NOTE: KisImageChangeLayersCommand performs all the locking for us undoAdapter()->addCommand(new KisImageChangeLayersCommand(KisImageWSP(this), oldRootLayer, newRootLayer)); undoAdapter()->endMacro(); setModified(); } bool checkIsSourceForClone(KisNodeSP src, const QList &nodes) { foreach (KisNodeSP node, nodes) { if (node == src) continue; KisCloneLayer *clone = dynamic_cast(node.data()); if (clone && KisNodeSP(clone->copyFrom()) == src) { return true; } } return false; } void KisImage::safeRemoveMultipleNodes(QList nodes) { while (!nodes.isEmpty()) { QList::iterator it = nodes.begin(); while (it != nodes.end()) { if (!checkIsSourceForClone(*it, nodes)) { KisNodeSP node = *it; undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, node)); it = nodes.erase(it); } else { ++it; } } } } bool checkIsChildOf(KisNodeSP node, const QList &parents) { QList nodeParents; KisNodeSP parent = node->parent(); while (parent) { nodeParents << parent; parent = parent->parent(); } foreach(KisNodeSP perspectiveParent, parents) { if (nodeParents.contains(perspectiveParent)) { return true; } } return false; } void filterMergableNodes(QList &nodes) { QList::iterator it = nodes.begin(); while (it != nodes.end()) { if (!dynamic_cast(it->data()) || checkIsChildOf(*it, nodes)) { qDebug() << "Skipping node" << ppVar((*it)->name()); it = nodes.erase(it); } else { ++it; } } } void sortMergableNodes(KisNodeSP root, QList &inputNodes, QList &outputNodes) { QList::iterator it = std::find(inputNodes.begin(), inputNodes.end(), root); if (it != inputNodes.end()) { outputNodes << *it; inputNodes.erase(it); } if (inputNodes.isEmpty()) { return; } KisNodeSP child = root->firstChild(); while (child) { sortMergableNodes(child, inputNodes, outputNodes); child = child->nextSibling(); } /** * By the end of recursion \p inputNodes must be empty */ KIS_ASSERT_RECOVER_NOOP(root->parent() || inputNodes.isEmpty()); } +void fetchSelectionMasks(QList mergedNodes, QVector &selectionMasks) +{ + foreach (KisNodeSP node, mergedNodes) { + KisLayerSP layer = dynamic_cast(node.data()); + + KisSelectionMaskSP mask; + + if (layer && (mask = layer->selectionMask())) { + selectionMasks.append(mask); + } + } +} + +void reparentSelectionMasks(KisLayerSP newLayer, const QVector &selectionMasks) +{ + KisImageSP image = newLayer->image(); + foreach (KisSelectionMaskSP mask, selectionMasks) { + image->undoAdapter()->addCommand(new KisImageLayerMoveCommand(image, mask, newLayer, newLayer->lastChild())); + image->undoAdapter()->addCommand(new KisActivateSelectionMaskCommand(mask, false)); + } +} + +KisNodeSP tryMergeSelectionMasks(KisImageSP image, QList mergedNodes) +{ + if (mergedNodes.isEmpty()) return 0; + + QList selectionMasks; + + foreach (KisNodeSP node, mergedNodes) { + KisSelectionMaskSP mask = dynamic_cast(node.data()); + if (!mask) return 0; + + selectionMasks.append(mask); + } + + KisLayerSP parentLayer = dynamic_cast(selectionMasks.first()->parent().data()); + KIS_ASSERT_RECOVER(parentLayer) { return 0; } + + KisSelectionSP selection = new KisSelection(); + + foreach (KisMaskSP mask, selectionMasks) { + selection->pixelSelection()->applySelection( + mask->selection()->pixelSelection(), SELECTION_ADD); + } + + image->undoAdapter()->beginMacro(kundo2_i18n("Merge Selection Masks")); + + KisSelectionMaskSP mergedMask = new KisSelectionMask(image); + mergedMask->initSelection(parentLayer); + + image->undoAdapter()->addCommand(new KisImageLayerAddCommand(image, mergedMask, parentLayer, parentLayer->lastChild())); + mergedMask->setSelection(selection); + image->undoAdapter()->addCommand(new KisActivateSelectionMaskCommand(mergedMask, true)); + + image->safeRemoveMultipleNodes(mergedNodes); + + image->undoAdapter()->endMacro(); + + return mergedMask; +} + KisNodeSP KisImage::mergeMultipleLayers(QList mergedNodes, KisNodeSP putAfter) { + { + KisNodeSP mask; + if ((mask = tryMergeSelectionMasks(this, mergedNodes))) { + return mask; + } + } + filterMergableNodes(mergedNodes); { QList tempNodes; qSwap(mergedNodes, tempNodes); sortMergableNodes(m_d->rootLayer, tempNodes, mergedNodes); } if (mergedNodes.size() <= 1) return KisNodeSP(); + // fetch selection masks to move them into the destination layer + QVector selectionMasks; + fetchSelectionMasks(mergedNodes, selectionMasks); + foreach (KisNodeSP layer, mergedNodes) { refreshHiddenArea(layer, bounds()); } KisPaintDeviceSP mergedDevice = new KisPaintDevice(colorSpace()); KisPainter gc(mergedDevice); { KisImageBarrierLocker l(this); foreach (KisNodeSP layer, mergedNodes) { QRect rc = layer->exactBounds() | bounds(); layer->projectionPlane()->apply(&gc, rc); } } const QString mergedLayerSuffix = i18n("Merged"); QString mergedLayerName = mergedNodes.first()->name(); if (!mergedLayerName.endsWith(mergedLayerSuffix)) { mergedLayerName = QString("%1 %2") .arg(mergedLayerName).arg(mergedLayerSuffix); } - KisNodeSP newLayer = new KisPaintLayer(this, mergedLayerName, OPACITY_OPAQUE_U8, mergedDevice); + KisLayerSP newLayer = new KisPaintLayer(this, mergedLayerName, OPACITY_OPAQUE_U8, mergedDevice); undoAdapter()->beginMacro(kundo2_i18n("Merge Selected Nodes")); if (!putAfter) { putAfter = mergedNodes.last(); } // Add the new merged node on top of the active node -- checking // whether the parent is going to be deleted KisNodeSP parent = putAfter->parent(); while (mergedNodes.contains(parent)) { parent = parent->parent(); } if (parent == putAfter->parent()) { undoAdapter()->addCommand(new KisImageLayerAddCommand(this, newLayer, parent, putAfter)); } else { undoAdapter()->addCommand(new KisImageLayerAddCommand(this, newLayer, parent, parent->lastChild())); } + // reparent selection masks into the newly created node + reparentSelectionMasks(newLayer, selectionMasks); + safeRemoveMultipleNodes(mergedNodes); undoAdapter()->endMacro(); return newLayer; } KisLayerSP KisImage::mergeDown(KisLayerSP layer, const KisMetaData::MergeStrategy* strategy) { if (!layer->prevSibling()) return 0; // XXX: this breaks if we allow free mixing of masks and layers KisLayerSP prevLayer = dynamic_cast(layer->prevSibling().data()); if (!prevLayer) return 0; refreshHiddenArea(layer, bounds()); refreshHiddenArea(prevLayer, bounds()); + QVector selectionMasks; + { + QList mergedNodes; + mergedNodes << layer; + mergedNodes << prevLayer; + fetchSelectionMasks(mergedNodes, selectionMasks); + } + QRect layerProjectionExtent = this->projection()->extent(); QRect prevLayerProjectionExtent = prevLayer->projection()->extent(); // actual merging done by KisLayer::createMergedLayer (or specialized decendant) KisLayerSP mergedLayer = layer->createMergedLayer(prevLayer); Q_CHECK_PTR(mergedLayer); // Merge meta data QList srcs; srcs.append(prevLayer->metaData()); srcs.append(layer->metaData()); QList scores; int prevLayerArea = prevLayerProjectionExtent.width() * prevLayerProjectionExtent.height(); int layerArea = layerProjectionExtent.width() * layerProjectionExtent.height(); double norm = qMax(prevLayerArea, layerArea); scores.append(prevLayerArea / norm); scores.append(layerArea / norm); strategy->merge(mergedLayer->metaData(), srcs, scores); KisNodeSP parent = layer->parent(); // parent is set to null when the layer is removed from the node dbgImage << ppVar(parent); // FIXME: "Merge Down"? undoAdapter()->beginMacro(kundo2_i18n("Merge with Layer Below")); undoAdapter()->addCommand(new KisImageLayerAddCommand(this, mergedLayer, parent, layer)); + + // reparent selection masks into the newly created node + reparentSelectionMasks(mergedLayer, selectionMasks); + safeRemoveTwoNodes(layer, prevLayer); undoAdapter()->endMacro(); return mergedLayer; } /** * The removal of two nodes in one go may be a bit tricky, because one * of them may be the clone of another. If we remove the source of a * clone layer, it will reincarnate into a paint layer. In this case * the pointer to the second layer will be lost. * * That's why we need to care about the order of the nodes removal: * the clone --- first, the source --- last. */ void KisImage::safeRemoveTwoNodes(KisNodeSP node1, KisNodeSP node2) { KisCloneLayer *clone1 = dynamic_cast(node1.data()); if (clone1 && KisNodeSP(clone1->copyFrom()) == node2) { undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, node1)); undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, node2)); } else { undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, node2)); undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, node1)); } } KisLayerSP KisImage::flattenLayer(KisLayerSP layer) { if (!layer->firstChild()) return layer; refreshHiddenArea(layer, bounds()); bool resetComposition = false; KisPaintDeviceSP mergedDevice; lock(); if (layer->layerStyle()) { mergedDevice = new KisPaintDevice(layer->colorSpace()); mergedDevice->prepareClone(layer->projection()); QRect updateRect = layer->projection()->extent() | bounds(); KisPainter gc(mergedDevice); layer->projectionPlane()->apply(&gc, updateRect); resetComposition = true; } else { mergedDevice = new KisPaintDevice(*layer->projection()); } unlock(); KisPaintLayerSP newLayer = new KisPaintLayer(this, layer->name(), layer->opacity(), mergedDevice); if (!resetComposition) { newLayer->setCompositeOp(layer->compositeOp()->id()); newLayer->setChannelFlags(layer->channelFlags()); } undoAdapter()->beginMacro(kundo2_i18n("Flatten Layer")); undoAdapter()->addCommand(new KisImageLayerAddCommand(this, newLayer, layer->parent(), layer)); undoAdapter()->addCommand(new KisImageLayerRemoveCommand(this, layer)); QList srcs; srcs.append(layer->metaData()); const KisMetaData::MergeStrategy* strategy = KisMetaData::MergeStrategyRegistry::instance()->get("Smart"); QList scores; scores.append(1.0); //Just give some score, there only is one layer strategy->merge(newLayer->metaData(), srcs, scores); undoAdapter()->endMacro(); return newLayer; } void KisImage::setModified() { m_d->signalRouter->emitNotification(ModifiedSignal); } QImage KisImage::convertToQImage(QRect imageRect, const KoColorProfile * profile) { qint32 x; qint32 y; qint32 w; qint32 h; imageRect.getRect(&x, &y, &w, &h); return convertToQImage(x, y, w, h, profile); } QImage KisImage::convertToQImage(qint32 x, qint32 y, qint32 w, qint32 h, const KoColorProfile * profile) { KisPaintDeviceSP dev = projection(); if (!dev) return QImage(); QImage image = dev->convertToQImage(const_cast(profile), x, y, w, h, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); return image; } QImage KisImage::convertToQImage(const QRect& scaledRect, const QSize& scaledImageSize, const KoColorProfile *profile) { if (scaledRect.isEmpty() || scaledImageSize.isEmpty()) { return QImage(); } try { qint32 imageWidth = width(); qint32 imageHeight = height(); quint32 pixelSize = colorSpace()->pixelSize(); double xScale = static_cast(imageWidth) / scaledImageSize.width(); double yScale = static_cast(imageHeight) / scaledImageSize.height(); QRect srcRect; srcRect.setLeft(static_cast(scaledRect.left() * xScale)); srcRect.setRight(static_cast(ceil((scaledRect.right() + 1) * xScale)) - 1); srcRect.setTop(static_cast(scaledRect.top() * yScale)); srcRect.setBottom(static_cast(ceil((scaledRect.bottom() + 1) * yScale)) - 1); KisPaintDeviceSP mergedImage = projection(); quint8 *scaledImageData = new quint8[scaledRect.width() * scaledRect.height() * pixelSize]; quint8 *imageRow = new quint8[srcRect.width() * pixelSize]; const qint32 imageRowX = srcRect.x(); for (qint32 y = 0; y < scaledRect.height(); ++y) { qint32 dstY = scaledRect.y() + y; qint32 dstX = scaledRect.x(); qint32 srcY = (dstY * imageHeight) / scaledImageSize.height(); mergedImage->readBytes(imageRow, imageRowX, srcY, srcRect.width(), 1); quint8 *dstPixel = scaledImageData + (y * scaledRect.width() * pixelSize); quint32 columnsRemaining = scaledRect.width(); while (columnsRemaining > 0) { qint32 srcX = (dstX * imageWidth) / scaledImageSize.width(); memcpy(dstPixel, imageRow + ((srcX - imageRowX) * pixelSize), pixelSize); ++dstX; dstPixel += pixelSize; --columnsRemaining; } } delete [] imageRow; QImage image = colorSpace()->convertToQImage(scaledImageData, scaledRect.width(), scaledRect.height(), const_cast(profile), KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); delete [] scaledImageData; return image; } catch (std::bad_alloc) { warnKrita << "KisImage::convertToQImage ran out of memory"; return QImage(); } } void KisImage::notifyLayersChanged() { m_d->signalRouter->emitNotification(LayersChangedSignal); } QRect KisImage::bounds() const { return QRect(0, 0, width(), height()); } KisPostExecutionUndoAdapter* KisImage::postExecutionUndoAdapter() const { return m_d->postExecutionUndoAdapter; } void KisImage::setUndoStore(KisUndoStore *undoStore) { m_d->legacyUndoAdapter->setUndoStore(undoStore); m_d->postExecutionUndoAdapter->setUndoStore(undoStore); delete m_d->undoStore; m_d->undoStore = undoStore; } KisUndoStore* KisImage::undoStore() { return m_d->undoStore; } KisUndoAdapter* KisImage::undoAdapter() const { return m_d->legacyUndoAdapter; } KisActionRecorder* KisImage::actionRecorder() const { return m_d->recorder; } void KisImage::setDefaultProjectionColor(const KoColor &color) { KIS_ASSERT_RECOVER_RETURN(m_d->rootLayer); m_d->rootLayer->setDefaultProjectionColor(color); } KoColor KisImage::defaultProjectionColor() const { KIS_ASSERT_RECOVER(m_d->rootLayer) { return KoColor(Qt::transparent, m_d->colorSpace); } return m_d->rootLayer->defaultProjectionColor(); } void KisImage::setRootLayer(KisGroupLayerSP rootLayer) { stopIsolatedMode(); KoColor defaultProjectionColor(Qt::transparent, m_d->colorSpace); if (m_d->rootLayer) { m_d->rootLayer->setGraphListener(0); m_d->rootLayer->disconnect(); KisPaintDeviceSP original = m_d->rootLayer->original(); defaultProjectionColor.setColor(original->defaultPixel(), original->colorSpace()); } m_d->rootLayer = rootLayer; m_d->rootLayer->disconnect(); m_d->rootLayer->setGraphListener(this); KisPaintDeviceSP newOriginal = m_d->rootLayer->original(); defaultProjectionColor.convertTo(newOriginal->colorSpace()); newOriginal->setDefaultPixel(defaultProjectionColor.data()); setRoot(m_d->rootLayer.data()); } void KisImage::addAnnotation(KisAnnotationSP annotation) { // Find the icc annotation, if there is one vKisAnnotationSP_it it = m_d->annotations.begin(); while (it != m_d->annotations.end()) { if ((*it)->type() == annotation->type()) { *it = annotation; return; } ++it; } m_d->annotations.push_back(annotation); } KisAnnotationSP KisImage::annotation(const QString& type) { vKisAnnotationSP_it it = m_d->annotations.begin(); while (it != m_d->annotations.end()) { if ((*it)->type() == type) { return *it; } ++it; } return KisAnnotationSP(0); } void KisImage::removeAnnotation(const QString& type) { vKisAnnotationSP_it it = m_d->annotations.begin(); while (it != m_d->annotations.end()) { if ((*it)->type() == type) { m_d->annotations.erase(it); return; } ++it; } } vKisAnnotationSP_it KisImage::beginAnnotations() { return m_d->annotations.begin(); } vKisAnnotationSP_it KisImage::endAnnotations() { return m_d->annotations.end(); } void KisImage::notifyAboutToBeDeleted() { emit sigAboutToBeDeleted(); } KisPerspectiveGrid* KisImage::perspectiveGrid() { if (m_d->perspectiveGrid == 0) m_d->perspectiveGrid = new KisPerspectiveGrid(); return m_d->perspectiveGrid; } KisImageSignalRouter* KisImage::signalRouter() { return m_d->signalRouter; } void KisImage::waitForDone() { requestStrokeEnd(); if (m_d->scheduler) { m_d->scheduler->waitForDone(); } } KisStrokeId KisImage::startStroke(KisStrokeStrategy *strokeStrategy) { /** * Ask open strokes to end gracefully. All the strokes clients * (including the one calling this method right now) will get * a notification that they should probably end their strokes. * However this is purely their choice whether to end a stroke * or not. */ requestStrokeEnd(); /** * Some of the strokes can cancel their work with undoing all the * changes they did to the paint devices. The problem is that undo * stack will know nothing about it. Therefore, just notify it * explicitly */ if (strokeStrategy->clearsRedoOnStart()) { m_d->undoStore->purgeRedoState(); } KisStrokeId id; if (m_d->scheduler) { id = m_d->scheduler->startStroke(strokeStrategy); } return id; } -void KisImage::startIsolatedMode(KisNodeSP node) +void KisImage::KisImagePrivate::notifyProjectionUpdatedInPatches(const QRect &rc) { - barrierLock(); + KisImageConfig imageConfig; + int patchWidth = imageConfig.updatePatchWidth(); + int patchHeight = imageConfig.updatePatchHeight(); + + for (int y = 0; y < rc.height(); y += patchHeight) { + for (int x = 0; x < rc.width(); x += patchWidth) { + QRect patchRect(x, y, patchWidth, patchHeight); + patchRect &= rc; + + QtConcurrent::run(boost::bind(&KisImage::notifyProjectionUpdated, q, patchRect)); + } + } +} + +bool KisImage::startIsolatedMode(KisNodeSP node) +{ + if (!tryBarrierLock()) return false; + unlock(); m_d->isolatedRootNode = node; emit sigIsolatedModeChanged(); - notifyProjectionUpdated(bounds()); + // the GUI uses our thread to do the color space conversion so we + // need to emit this signal in multiple threads + m_d->notifyProjectionUpdatedInPatches(bounds()); + + return true; } void KisImage::stopIsolatedMode() { if (!m_d->isolatedRootNode) return; KisNodeSP oldRootNode = m_d->isolatedRootNode; m_d->isolatedRootNode = 0; emit sigIsolatedModeChanged(); - notifyProjectionUpdated(bounds()); + // the GUI uses our thread to do the color space conversion so we + // need to emit this signal in multiple threads + m_d->notifyProjectionUpdatedInPatches(bounds()); // TODO: Substitute notifyProjectionUpdated() with this code // when update optimization is implemented - // + // // QRect updateRect = bounds() | oldRootNode->extent(); // oldRootNode->setDirty(updateRect); } KisNodeSP KisImage::isolatedModeRoot() const { return m_d->isolatedRootNode; } void KisImage::addJob(KisStrokeId id, KisStrokeJobData *data) { KisUpdateTimeMonitor::instance()->reportJobStarted(data); if (m_d->scheduler) { m_d->scheduler->addJob(id, data); } } void KisImage::endStroke(KisStrokeId id) { if (m_d->scheduler) { m_d->scheduler->endStroke(id); } } bool KisImage::cancelStroke(KisStrokeId id) { bool result = false; if (m_d->scheduler) { result = m_d->scheduler->cancelStroke(id); } return result; } bool KisImage::KisImagePrivate::tryCancelCurrentStrokeAsync() { bool result = false; if (scheduler) { result = scheduler->tryCancelCurrentStrokeAsync(); } return result; } void KisImage::requestUndoDuringStroke() { emit sigUndoDuringStrokeRequested(); } void KisImage::requestStrokeCancellation() { if (!m_d->tryCancelCurrentStrokeAsync()) { emit sigStrokeCancellationRequested(); } } void KisImage::requestStrokeEnd() { emit sigStrokeEndRequested(); } void KisImage::refreshGraph(KisNodeSP root) { refreshGraph(root, bounds(), bounds()); } void KisImage::refreshGraph(KisNodeSP root, const QRect &rc, const QRect &cropRect) { if (!root) root = m_d->rootLayer; if (m_d->scheduler) { m_d->scheduler->fullRefresh(root, rc, cropRect); } } void KisImage::initialRefreshGraph() { /** * NOTE: Tricky part. We set crop rect to null, so the clones * will not rely on precalculated projections of their sources */ refreshGraphAsync(0, bounds(), QRect()); waitForDone(); } void KisImage::refreshGraphAsync(KisNodeSP root) { refreshGraphAsync(root, bounds(), bounds()); } void KisImage::refreshGraphAsync(KisNodeSP root, const QRect &rc) { refreshGraphAsync(root, rc, bounds()); } void KisImage::refreshGraphAsync(KisNodeSP root, const QRect &rc, const QRect &cropRect) { if (!root) root = m_d->rootLayer; if (m_d->scheduler) { m_d->scheduler->fullRefreshAsync(root, rc, cropRect); } } void KisImage::requestProjectionUpdateNoFilthy(KisNodeSP pseudoFilthy, const QRect &rc, const QRect &cropRect) { KIS_ASSERT_RECOVER_RETURN(pseudoFilthy); if (m_d->scheduler) { m_d->scheduler->updateProjectionNoFilthy(pseudoFilthy, rc, cropRect); } } void KisImage::addSpontaneousJob(KisSpontaneousJob *spontaneousJob) { if (m_d->scheduler) { m_d->scheduler->addSpontaneousJob(spontaneousJob); } } void KisImage::disableDirtyRequests() { m_d->disableDirtyRequests.ref(); } void KisImage::enableDirtyRequests() { m_d->disableDirtyRequests.deref(); } void KisImage::disableUIUpdates() { m_d->disableUIUpdateSignals.ref(); } void KisImage::enableUIUpdates() { m_d->disableUIUpdateSignals.deref(); } void KisImage::notifyProjectionUpdated(const QRect &rc) { KisUpdateTimeMonitor::instance()->reportUpdateFinished(rc); if (!m_d->disableUIUpdateSignals) { emit sigImageUpdated(rc); } } void KisImage::notifySelectionChanged() { /** * The selection is calculated asynchromously, so it is not * handled by disableUIUpdates() and other special signals of * KisImageSignalRouter */ m_d->legacyUndoAdapter->emitSelectionChanged(); /** * Editing of selection masks doesn't necessary produce a * setDirty() call, so in the end of the stroke we need to request * direct update of the UI's cache. */ if (m_d->isolatedRootNode && dynamic_cast(m_d->isolatedRootNode.data())) { notifyProjectionUpdated(bounds()); } } void KisImage::requestProjectionUpdateImpl(KisNode *node, const QRect &rect, const QRect &cropRect) { KisNodeGraphListener::requestProjectionUpdate(node, rect); if (m_d->scheduler) { m_d->scheduler->updateProjection(node, rect, cropRect); } } void KisImage::requestProjectionUpdate(KisNode *node, const QRect& rect) { if (m_d->disableDirtyRequests) return; /** * Here we use 'permitted' instead of 'active' intentively, * because the updates may come after the actual stroke has been * finished. And having some more updates for the stroke not * supporting the wrap-around mode will not make much harm. */ if (m_d->wrapAroundModePermitted) { QRect boundRect = bounds(); KisWrappedRect splitRect(rect, boundRect); foreach (const QRect &rc, splitRect) { requestProjectionUpdateImpl(node, rc, boundRect); } } else { requestProjectionUpdateImpl(node, rect, bounds()); } } QList KisImage::compositions() { return m_d->compositions; } void KisImage::addComposition(KisLayerComposition* composition) { m_d->compositions.append(composition); } void KisImage::removeComposition(KisLayerComposition* composition) { m_d->compositions.removeAll(composition); delete composition; } bool checkMasksNeedConversion(KisNodeSP root, const QRect &bounds) { KisSelectionMask *mask = dynamic_cast(root.data()); if (mask && (!bounds.contains(mask->paintDevice()->exactBounds()) || mask->selection()->hasShapeSelection())) { return true; } KisNodeSP node = root->firstChild(); while (node) { if (checkMasksNeedConversion(node, bounds)) { return true; } node = node->nextSibling(); } return false; } void KisImage::setWrapAroundModePermitted(bool value) { m_d->wrapAroundModePermitted = value; if (m_d->wrapAroundModePermitted && checkMasksNeedConversion(root(), bounds())) { KisProcessingApplicator applicator(this, root(), KisProcessingApplicator::RECURSIVE, KisImageSignalVector() << ModifiedSignal, kundo2_i18n("Crop Selections")); KisProcessingVisitorSP visitor = new KisCropSelectionsProcessingVisitor(bounds()); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); applicator.end(); } } bool KisImage::wrapAroundModePermitted() const { return m_d->wrapAroundModePermitted; } bool KisImage::wrapAroundModeActive() const { return m_d->wrapAroundModePermitted && m_d->scheduler && m_d->scheduler->wrapAroundModeSupported(); } void KisImage::notifyNodeCollpasedChanged() { emit sigNodeCollapsedChanged(); } #include "kis_image.moc" diff --git a/krita/image/kis_image.h b/krita/image/kis_image.h index d35aa7d2b8f..2417a83129f 100644 --- a/krita/image/kis_image.h +++ b/krita/image/kis_image.h @@ -1,833 +1,833 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2007 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_IMAGE_H_ #define KIS_IMAGE_H_ #include #include #include #include #include #include #include #include "kis_paint_device.h" // msvc cannot handle forward declarations, so include kis_paint_device here #include "kis_types.h" #include "kis_shared.h" #include "kis_node_graph_listener.h" #include "kis_node_facade.h" #include "kis_default_bounds.h" #include "kis_image_interfaces.h" -#include +#include class KisDocument; class KoColorSpace; class KoColor; class KisCompositeProgressProxy; class KisActionRecorder; class KisUndoStore; class KisUndoAdapter; class KisImageSignalRouter; class KisPostExecutionUndoAdapter; class KisFilterStrategy; class KoColorProfile; class KisPerspectiveGrid; class KisLayerComposition; class KisSpontaneousJob; namespace KisMetaData { class MergeStrategy; } /** * This is the image class, it contains a tree of KisLayer stack and * meta information about the image. And it also provides some * functions to manipulate the whole image. */ class KRITAIMAGE_EXPORT KisImage : public QObject, public KisStrokesFacade, public KisUpdatesFacade, public KisProjectionUpdateListener, public KisNodeFacade, public KisNodeGraphListener, public KisShared { Q_OBJECT public: /// @param colorSpace can be null. in that case it will be initialised to a default color space. KisImage(KisUndoStore *undoStore, qint32 width, qint32 height, const KoColorSpace * colorSpace, const QString& name, bool startProjection = true); virtual ~KisImage(); public: // KisNodeGraphListener implementation void aboutToAddANode(KisNode *parent, int index); void nodeHasBeenAdded(KisNode *parent, int index); void aboutToRemoveANode(KisNode *parent, int index); void nodeChanged(KisNode * node); void notifySelectionChanged(); void requestProjectionUpdate(KisNode *node, const QRect& rect); public: // KisProjectionUpdateListener implementation void notifyProjectionUpdated(const QRect &rc); public: /** * Render the projection onto a QImage. */ QImage convertToQImage(qint32 x1, qint32 y1, qint32 width, qint32 height, const KoColorProfile * profile); /** * Render the projection onto a QImage. * (this is an overloaded function) */ QImage convertToQImage(QRect imageRect, const KoColorProfile * profile); /** * XXX: docs! */ QImage convertToQImage(const QRect& scaledRect, const QSize& scaledImageSize, const KoColorProfile *profile); /** * Calls KisUpdateScheduler::lock */ void lock(); /** * Calls KisUpdateScheduler::unlock */ void unlock(); /** * Returns true if lock() has been called more often than unlock(). */ bool locked() const; /** * @return the global selection object or 0 if there is none. The * global selection is always read-write. */ KisSelectionSP globalSelection() const; /** * Retrieve the next automatic layername (XXX: fix to add option to return Mask X) */ QString nextLayerName() const; /** * Set the automatic layer name counter one back. */ void rollBackLayerName(); /** * @return the perspective grid associated to this image */ KisPerspectiveGrid* perspectiveGrid(); /** * Resize the image to the specified rect. The resize * method handles the creating on an undo step itself. * * @param newRect the rect describing the new width, height and offset * of the image */ void resizeImage(const QRect& newRect); /** * Crop the image to the specified rect. The crop * method handles the creating on an undo step itself. * * @param newRect the rect describing the new width, height and offset * of the image */ void cropImage(const QRect& newRect); /** * Crop a node to @newRect. The node will *not* be moved anywhere, * it just drops some content */ void cropNode(KisNodeSP node, const QRect& newRect); void scaleImage(const QSize &size, qreal xres, qreal yres, KisFilterStrategy *filterStrategy); void scaleNode(KisNodeSP node, qreal sx, qreal sy, KisFilterStrategy *filterStrategy); /** * Execute a rotate transform on all layers in this image. * Image is resized to fit rotated image. */ void rotateImage(double radians); /** * Execute a rotate transform on on a subtree of this image. * Image is not resized. */ void rotateNode(KisNodeSP node, double radians); /** * Execute a shear transform on all layers in this image. */ void shear(double angleX, double angleY); /** * Shear a node and all its children. * @param angleX, @param angleY are given in degrees. */ void shearNode(KisNodeSP node, double angleX, double angleY); /** * Convert the image and all its layers to the dstColorSpace */ void convertImageColorSpace(const KoColorSpace *dstColorSpace, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); /** * Set the color space of the projection (and the root layer) * to dstColorSpace. No conversion is done for other layers, * their colorspace can differ. * NOTE: Note conversion is done, only regeneration, so no rendering * intent needed */ void convertProjectionColorSpace(const KoColorSpace *dstColorSpace); // Get the profile associated with this image const KoColorProfile * profile() const; /** * Set the profile of the image to the new profile and do the same for * all layers that have the same colorspace and profile of the image. * It doesn't do any pixel conversion. * * This is essential if you have loaded an image that didn't * have an embedded profile to which you want to attach the right profile. * * This does not create an undo action; only call it when creating or * loading an image. * * @returns false if the profile could not be assigned */ bool assignImageProfile(const KoColorProfile *profile); /** * Returns the current undo adapter. You can add new commands to the * undo stack using the adapter. This adapter is used for a backward * compatibility for old commands created before strokes. It blocks * all the porcessing at the scheduler, waits until it's finished * adn executes commands exclusively. */ KisUndoAdapter* undoAdapter() const; /** * This adapter is used by the strokes system. The commands are added * to it *after* redo() is done (in the scheduler context). They are * wrapped into a special command and added to the undo stack. redo() * in not called. */ KisPostExecutionUndoAdapter* postExecutionUndoAdapter() const; /** * Replace current undo store with the new one. The old store * will be deleted. * This method is used by KisDocument for dropping all the commands * during file loading. */ void setUndoStore(KisUndoStore *undoStore); /** * Return current undo store of the image */ KisUndoStore* undoStore(); /** * @return the action recorder associated with this image */ KisActionRecorder* actionRecorder() const; /** * Tell the image it's modified; this emits the sigImageModified * signal. This happens when the image needs to be saved */ void setModified(); /** * The default colorspace of this image: new layers will have this * colorspace and the projection will have this colorspace. */ const KoColorSpace * colorSpace() const; /** * X resolution in pixels per pt */ double xRes() const; /** * Y resolution in pixels per pt */ double yRes() const; /** * Set the resolution in pixels per pt. */ void setResolution(double xres, double yres); /** * Convert a document coordinate to a pixel coordinate. * * @param documentCoord PostScript Pt coordinate to convert. */ QPointF documentToPixel(const QPointF &documentCoord) const; /** * Convert a document coordinate to an integer pixel coordinate. * * @param documentCoord PostScript Pt coordinate to convert. */ QPoint documentToIntPixel(const QPointF &documentCoord) const; /** * Convert a document rectangle to a pixel rectangle. * * @param documentRect PostScript Pt rectangle to convert. */ QRectF documentToPixel(const QRectF &documentRect) const; /** * Convert a document rectangle to an integer pixel rectangle. * * @param documentRect PostScript Pt rectangle to convert. */ QRect documentToIntPixel(const QRectF &documentRect) const; /** * Convert a pixel coordinate to a document coordinate. * * @param pixelCoord pixel coordinate to convert. */ QPointF pixelToDocument(const QPointF &pixelCoord) const; /** * Convert an integer pixel coordinate to a document coordinate. * The document coordinate is at the centre of the pixel. * * @param pixelCoord pixel coordinate to convert. */ QPointF pixelToDocument(const QPoint &pixelCoord) const; /** * Convert a document rectangle to an integer pixel rectangle. * * @param pixelCoord pixel coordinate to convert. */ QRectF pixelToDocument(const QRectF &pixelCoord) const; /** * Return the width of the image */ qint32 width() const; /** * Return the height of the image */ qint32 height() const; /** * Return the size of the image */ QSize size() const { return QSize(width(), height()); } /** * @return the root node of the image node graph */ KisGroupLayerSP rootLayer() const; /** * Return the projection; that is, the complete, composited * representation of this image. */ KisPaintDeviceSP projection() const; /** * Return the number of layers (not other nodes) that are in this * image. */ qint32 nlayers() const; /** * Return the number of layers (not other node types) that are in * this image and that are hidden. */ qint32 nHiddenLayers() const; /** * Merge all visible layers and discard hidden ones. */ void flatten(); /** * Merge the specified layer with the layer * below this layer, remove the specified layer. */ KisLayerSP mergeDown(KisLayerSP l, const KisMetaData::MergeStrategy* strategy); /** * flatten the layer: that is, the projection becomes the layer * and all subnodes are removed. If this is not a paint layer, it will morph * into a paint layer. */ KisLayerSP flattenLayer(KisLayerSP layer); /** * Removes \p nodes in a safe way, that is handling clone layers * reincarnation correctly */ void safeRemoveMultipleNodes(QList nodes); /** * Merges layers in \p mergedLayers and creates a new layer above * \p putAfter */ KisNodeSP mergeMultipleLayers(QList mergedLayers, KisNodeSP putAfter); /// This overrides interface for KisDefaultBounds /// @return the exact bounds of the image in pixel coordinates. QRect bounds() const; /// use if the layers have changed _completely_ (eg. when flattening) void notifyLayersChanged(); /** * Sets the default color of the root layer projection. All the layers * will be merged on top of this very color */ void setDefaultProjectionColor(const KoColor &color); /** * \see setDefaultProjectionColor() */ KoColor defaultProjectionColor() const; void setRootLayer(KisGroupLayerSP rootLayer); /** * Add an annotation for this image. This can be anything: Gamma, EXIF, etc. * Note that the "icc" annotation is reserved for the color strategies. * If the annotation already exists, overwrite it with this one. */ void addAnnotation(KisAnnotationSP annotation); /** get the annotation with the given type, can return 0 */ KisAnnotationSP annotation(const QString& type); /** delete the annotation, if the image contains it */ void removeAnnotation(const QString& type); /** * Start of an iteration over the annotations of this image (including the ICC Profile) */ vKisAnnotationSP_it beginAnnotations(); /** end of an iteration over the annotations of this image */ vKisAnnotationSP_it endAnnotations(); /** * Called before the image is delted and sends the sigAboutToBeDeleted signal */ void notifyAboutToBeDeleted(); KisImageSignalRouter* signalRouter(); /** * Returns whether we can reselect current global selection * * \see reselectGlobalSelection() */ bool canReselectGlobalSelection(); /** * Returns the layer compositions for the image */ QList compositions(); /** * Adds a new layer composition, will be saved with the image */ void addComposition(KisLayerComposition* composition); /** * Remove the layer compostion */ void removeComposition(KisLayerComposition* composition); /** * Permit or deny the wrap-around mode for all the paint devices * of the image. Note that permitting the wraparound mode will not * necessarily activate it right now. To be activated the wrap * around mode should be 1) permitted; 2) supported by the * currently running stroke. */ void setWrapAroundModePermitted(bool value); /** * \return whether the wrap-around mode is permitted for this * image. If the wrap around mode is permitted and the * currently running stroke supports it, the mode will be * activated for all paint devices of the image. * * \see setWrapAroundMode */ bool wrapAroundModePermitted() const; /** * \return whether the wraparound mode is activated for all the * devices of the image. The mode is activated when both * factors are true: the user permitted it and the stroke * supports it */ bool wrapAroundModeActive() const; /** * Notifies that the node collapsed state has changed */ void notifyNodeCollpasedChanged(); public: - void startIsolatedMode(KisNodeSP node); + bool startIsolatedMode(KisNodeSP node); void stopIsolatedMode(); KisNodeSP isolatedModeRoot() const; Q_SIGNALS: /** * Emitted whenever an action has caused the image to be * recomposited. * * @param rc The rect that has been recomposited. */ void sigImageUpdated(const QRect &); /** Emitted whenever the image has been modified, so that it doesn't match with the version saved on disk. */ void sigImageModified(); /** * The signal is emitted when the size of the image is changed. * \p oldStillPoint and \p newStillPoint give the receiver the * hint about how the new and old rect of the image correspond to * each other. They specify the point of the image around which * the conversion was done. This point will stay still on the * user's screen. That is the \p newStillPoint of the new image * will be painted at the same screen position, where \p * oldStillPoint of the old image was painted. * * \param oldStillPoint is a still point represented in *old* * image coordinates * * \param newStillPoint is a still point represented in *new* * image coordinates */ void sigSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint); void sigProfileChanged(const KoColorProfile * profile); void sigColorSpaceChanged(const KoColorSpace* cs); void sigResolutionChanged(double xRes, double yRes); /** * Inform the model that a node was changed */ void sigNodeChanged(KisNodeSP node); /** * Inform that the image is going to be deleted */ void sigAboutToBeDeleted(); /** * The signal is emitted right after a node has been connected * to the graph of the nodes. * * WARNING: you must not request any graph-related information * about the node being run in a not-scheduler thread. If you need * information about the parent/siblings of the node connect * with Qt::DirectConnection, get needed information and then * emit another Qt::AutoConnection signal to pass this information * to your thread. See details of the implementation * in KisDummiesfacadeBase. */ void sigNodeAddedAsync(KisNodeSP node); /** * This signal is emitted right before a node is going to removed * from the graph of the nodes. * * WARNING: you must not request any graph-related information * about the node being run in a not-scheduler thread. * * \see comment in sigNodeAddedAsync() */ void sigRemoveNodeAsync(KisNodeSP node); /** * Emitted when the root node of the image has changed. * It happens, e.g. when we flatten the image. When * this happens the receiver should reload information * about the image */ void sigLayersChangedAsync(); /** * Emitted when the UI has requested the undo of the last stroke's * operation. The point is, we cannot deal with the internals of * the stroke without its creator knowing about it (which most * probably cause a crash), so we just forward this request from * the UI to the creator of the stroke. * * If your tool supports undoing part of its work, just listen to * this signal and undo when it comes */ void sigUndoDuringStrokeRequested(); /** * Emitted when the UI has requested the cancellation of * the stroke. The point is, we cannot cancel the stroke * without its creator knowing about it (which most probably * cause a crash), so we just forward this request from the UI * to the creator of the stroke. * * If your tool supports cancelling of its work in the middle * of operation, just listen to this signal and cancel * the stroke when it comes */ void sigStrokeCancellationRequested(); /** * Emitted when the image decides that the stroke should better * be ended. The point is, we cannot just end the stroke * without its creator knowing about it (which most probably * cause a crash), so we just forward this request from the UI * to the creator of the stroke. * * If your tool supports long strokes that may involve multiple * mouse actions in one stroke, just listen to this signal and * end the stroke when it comes. */ void sigStrokeEndRequested(); /** * Emitted when the isolated mode status has changed. * * Can be used by the receivers to catch a fact of forcefully * stopping the isolated mode by the image when some complex * action was requested */ void sigIsolatedModeChanged(); /** * Emitted when one or more nodes changed the collapsed state * */ void sigNodeCollapsedChanged(); public Q_SLOTS: KisCompositeProgressProxy* compositeProgressProxy(); void barrierLock(); bool tryBarrierLock(); void waitForDone(); KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy); void addJob(KisStrokeId id, KisStrokeJobData *data); void endStroke(KisStrokeId id); bool cancelStroke(KisStrokeId id); void blockUpdates(); void unblockUpdates(); /** * Disables notification of the UI about the changes in the image. * This feature is used by KisProcessingApplicator. It is needed * when we change the size of the image. In this case, the whole * image will be reloaded into UI by sigSizeChanged(), so there is * no need to inform the UI about individual dirty rects. */ void disableUIUpdates(); /** * \see disableUIUpdates */ void enableUIUpdates(); /** * Disables the processing of all the setDirty() requests that * come to the image. The incoming requests are effectively * *dropped*. * * This feature is used by KisProcessingApplicator. For many cases * it provides its own updates interface, which recalculates the * whole subtree of nodes. But while we change any particular * node, it can ask for an update itself. This method is a way of * blocking such intermediate (and excessive) requests. */ void disableDirtyRequests(); /** * \see disableDirtyRequests() */ void enableDirtyRequests(); void refreshGraphAsync(KisNodeSP root = 0); void refreshGraphAsync(KisNodeSP root, const QRect &rc); void refreshGraphAsync(KisNodeSP root, const QRect &rc, const QRect &cropRect); /** * Triggers synchronous recomposition of the projection */ void refreshGraph(KisNodeSP root = 0); void refreshGraph(KisNodeSP root, const QRect& rc, const QRect &cropRect); void initialRefreshGraph(); /** * Initiate a stack regeneration skipping the recalculation of the * filthy node's projection. * * Works exactly as pseudoFilthy->setDirty() with the only * exception that pseudoFilthy::updateProjection() will not be * called. That is used by KisRecalculateTransformMaskJob to avoid * cyclic dependencies. */ void requestProjectionUpdateNoFilthy(KisNodeSP pseudoFilthy, const QRect &rc, const QRect &cropRect); /** * Adds a spontaneous job to the updates queue. * * A spontaneous job may do some trivial tasks in the background, * like updating the outline of selection or purging unused tiles * from the existing paint devices. */ void addSpontaneousJob(KisSpontaneousJob *spontaneousJob); /** * This method is called by the UI (*not* by the creator of the * stroke) when it thinks the current stroke should undo its last * action, for example, when the user presses Ctrl+Z while some * stroke is active. * * If the creator of the stroke supports undoing of intermediate * actions, it will be notified about this request and can undo * its last action. */ void requestUndoDuringStroke(); /** * This method is called by the UI (*not* by the creator of the * stroke) when it thinks current stroke should be cancelled. If * there is a running stroke that has already been detached from * its creator (ended or cancelled), it will be forcefully * cancelled and reverted. If there is an open stroke present, and * if its creator supports cancelling, it will be notified about * the request and the stroke will be cancelled */ void requestStrokeCancellation(); /** * This method is called when image or some other part of Krita * (*not* the creator of the stroke) decides that the stroke * should be ended. If the creator of the stroke supports it, it * will be notified and the stroke will be cancelled */ void requestStrokeEnd(); private: KisImage(const KisImage& rhs); KisImage& operator=(const KisImage& rhs); void emitSizeChanged(); void resizeImageImpl(const QRect& newRect, bool cropLayers); void rotateImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double radians); void shearImpl(const KUndo2MagicString &actionName, KisNodeSP rootNode, bool resizeImage, double angleX, double angleY, const QPointF &origin); void safeRemoveTwoNodes(KisNodeSP node1, KisNodeSP node2); void refreshHiddenArea(KisNodeSP rootNode, const QRect &preparedArea); void requestProjectionUpdateImpl(KisNode *node, const QRect& rect, const QRect &cropRect); friend class KisImageResizeCommand; void setSize(const QSize& size); friend class KisImageSetProjectionColorSpaceCommand; void setProjectionColorSpace(const KoColorSpace * colorSpace); friend class KisDeselectGlobalSelectionCommand; friend class KisReselectGlobalSelectionCommand; friend class KisSetGlobalSelectionCommand; friend class KisImageTest; /** * Replaces the current global selection with globalSelection. If * \p globalSelection is empty, removes the selection object, so that * \ref globalSelection() will return 0 after that. */ void setGlobalSelection(KisSelectionSP globalSelection); /** * Deselects current global selection. * \ref globalSelection() will return 0 after that. */ void deselectGlobalSelection(); /** * Reselects current deselected selection * * \see deselectGlobalSelection() */ void reselectGlobalSelection(); private: class KisImagePrivate; KisImagePrivate * const m_d; }; #endif // KIS_IMAGE_H_ diff --git a/krita/image/kis_image_config.h b/krita/image/kis_image_config.h index b305284c1ab..4a022d11933 100644 --- a/krita/image/kis_image_config.h +++ b/krita/image/kis_image_config.h @@ -1,86 +1,86 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_IMAGE_CONFIG_H_ #define KIS_IMAGE_CONFIG_H_ #include -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisImageConfig { public: KisImageConfig(); ~KisImageConfig(); bool enablePerfLog(bool requestDefault = false) const; void setEnablePerfLog(bool value); qreal transformMaskOffBoundsReadArea() const; int updatePatchHeight() const; void setUpdatePatchHeight(int value); int updatePatchWidth() const; void setUpdatePatchWidth(int value); qreal maxCollectAlpha() const; qreal maxMergeAlpha() const; qreal maxMergeCollectAlpha() const; qreal schedulerBalancingRatio() const; void setSchedulerBalancingRatio(qreal value); int maxSwapSize(bool requestDefault = false) const; void setMaxSwapSize(int value); int swapSlabSize() const; void setSwapSlabSize(int value); int swapWindowSize() const; void setSwapWindowSize(int value); int tilesHardLimit() const; // MiB int tilesSoftLimit() const; // MiB int poolLimit() const; // MiB qreal memoryHardLimitPercent(bool requestDefault = false) const; // % of total RAM qreal memorySoftLimitPercent(bool requestDefault = false) const; // % of memoryHardLimitPercent() * (1 - 0.01 * memoryPoolLimitPercent()) qreal memoryPoolLimitPercent(bool requestDefault = false) const; // % of memoryHardLimitPercent() void setMemoryHardLimitPercent(qreal value); void setMemorySoftLimitPercent(qreal value); void setMemoryPoolLimitPercent(qreal value); static int totalRAM(); // MiB /** * @return a specific directory for the swapfile, if set. If not set, return an * empty QString and use the default KDE directory. */ QString swapDir(bool requestDefault = false); void setSwapDir(const QString &swapDir); private: Q_DISABLE_COPY(KisImageConfig) private: KConfigGroup m_config; }; #endif /* KIS_IMAGE_CONFIG_H_ */ diff --git a/krita/image/kis_image_interfaces.h b/krita/image/kis_image_interfaces.h index 96a1d6539d0..5845dae5400 100644 --- a/krita/image/kis_image_interfaces.h +++ b/krita/image/kis_image_interfaces.h @@ -1,66 +1,66 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_IMAGE_INTERFACES_H #define __KIS_IMAGE_INTERFACES_H #include "kis_types.h" -#include +#include class QRect; class KisStrokeStrategy; class KisStrokeJobData; class KRITAIMAGE_EXPORT KisStrokesFacade { public: virtual ~KisStrokesFacade(); virtual KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy) = 0; virtual void addJob(KisStrokeId id, KisStrokeJobData *data) = 0; virtual void endStroke(KisStrokeId id) = 0; virtual bool cancelStroke(KisStrokeId id) = 0; }; class KRITAIMAGE_EXPORT KisUpdatesFacade { public: virtual ~KisUpdatesFacade(); virtual void blockUpdates() = 0; virtual void unblockUpdates() = 0; virtual void disableUIUpdates() = 0; virtual void enableUIUpdates() = 0; virtual void disableDirtyRequests() = 0; virtual void enableDirtyRequests() = 0; virtual void refreshGraphAsync(KisNodeSP root = 0) = 0; virtual void refreshGraphAsync(KisNodeSP root, const QRect &rc) = 0; virtual void refreshGraphAsync(KisNodeSP root, const QRect &rc, const QRect &cropRect) = 0; }; class KRITAIMAGE_EXPORT KisProjectionUpdateListener { public: virtual ~KisProjectionUpdateListener(); virtual void notifyProjectionUpdated(const QRect &rc) = 0; }; #endif /* __KIS_IMAGE_INTERFACES_H */ diff --git a/krita/image/kis_image_signal_router.h b/krita/image/kis_image_signal_router.h index b4489debabf..7b54723e680 100644 --- a/krita/image/kis_image_signal_router.h +++ b/krita/image/kis_image_signal_router.h @@ -1,142 +1,142 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_IMAGE_SIGNAL_ROUTER_H #define __KIS_IMAGE_SIGNAL_ROUTER_H #include #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_group_layer.h" class KoColorSpace; class KoColorProfile; enum KisImageSignalTypeEnum { LayersChangedSignal, ModifiedSignal, SizeChangedSignal, ProfileChangedSignal, ColorSpaceChangedSignal, ResolutionChangedSignal }; /** * A special signal which handles stillPoint capabilities of the image * * \see KisImage::sigSizeChanged() */ struct ComplexSizeChangedSignal { ComplexSizeChangedSignal() {} ComplexSizeChangedSignal(QPointF _oldStillPoint, QPointF _newStillPoint) : oldStillPoint(_oldStillPoint), newStillPoint(_newStillPoint) { } /** * A helper method calculating the still points from image areas * we process. It works as if the source image was "cropped" by \p * portionOfOldImage, and this portion formed the new image of size * \p transformedIntoImageOfSize. * * Note, that \p portionOfTheImage may be equal to the image bounds(). */ ComplexSizeChangedSignal(const QRect &portionOfOldImage, const QSize &transformedIntoImageOfSize) { oldStillPoint = QRectF(portionOfOldImage).center(); newStillPoint = QRectF(QPointF(), QSizeF(transformedIntoImageOfSize)).center(); } ComplexSizeChangedSignal inverted() const { return ComplexSizeChangedSignal(newStillPoint, oldStillPoint); } QPointF oldStillPoint; QPointF newStillPoint; }; struct KisImageSignalType { KisImageSignalType() {} KisImageSignalType(KisImageSignalTypeEnum _id) : id(_id) { } KisImageSignalType(ComplexSizeChangedSignal signal) : id(SizeChangedSignal), sizeChangedSignal(signal) { } KisImageSignalType inverted() const { KisImageSignalType t; t.id = id; t.sizeChangedSignal = sizeChangedSignal.inverted(); return t; } KisImageSignalTypeEnum id; ComplexSizeChangedSignal sizeChangedSignal; }; typedef QVector KisImageSignalVector; class KRITAIMAGE_EXPORT KisImageSignalRouter : public QObject { Q_OBJECT public: KisImageSignalRouter(KisImageWSP image); ~KisImageSignalRouter(); void emitNotification(KisImageSignalType type); void emitNotifications(KisImageSignalVector notifications); void emitNodeChanged(KisNodeSP node); void emitNodeHasBeenAdded(KisNode *parent, int index); void emitAboutToRemoveANode(KisNode *parent, int index); private Q_SLOTS: void slotNotification(KisImageSignalType type); Q_SIGNALS: void sigNotification(KisImageSignalType type); // Notifications void sigImageModified(); void sigSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint); void sigProfileChanged(const KoColorProfile * profile); void sigColorSpaceChanged(const KoColorSpace* cs); void sigResolutionChanged(double xRes, double yRes); // Graph change signals void sigNodeChanged(KisNodeSP node); void sigNodeAddedAsync(KisNodeSP node); void sigRemoveNodeAsync(KisNodeSP node); void sigLayersChangedAsync(); private: KisImageWSP m_image; }; #endif /* __KIS_IMAGE_SIGNAL_ROUTER_H */ diff --git a/krita/image/kis_indirect_painting_support.h b/krita/image/kis_indirect_painting_support.h index ae8a5431452..522ed114974 100644 --- a/krita/image/kis_indirect_painting_support.h +++ b/krita/image/kis_indirect_painting_support.h @@ -1,113 +1,113 @@ /* * Copyright (c) 2004 Bart Coppens * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_INDIRECT_PAINTING_SUPPORT_H_ #define KIS_INDIRECT_PAINTING_SUPPORT_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_node.h" class QBitArray; class KisUndoAdapter; class KisPostExecutionUndoAdapter; class KisPainter; class KUndo2MagicString; /** * For classes that support indirect painting. * * XXX: Name doesn't suggest an object -- is KisIndirectPaintingLayer * a better name? (BSAR) */ class KRITAIMAGE_EXPORT KisIndirectPaintingSupport { KisIndirectPaintingSupport(const KisIndirectPaintingSupport&); KisIndirectPaintingSupport& operator=(const KisIndirectPaintingSupport&); public: KisIndirectPaintingSupport(); virtual ~KisIndirectPaintingSupport(); bool hasTemporaryTarget() const; void setTemporaryTarget(KisPaintDeviceSP t); void setTemporaryCompositeOp(const KoCompositeOp* c); void setTemporaryOpacity(quint8 o); void setTemporaryChannelFlags(const QBitArray& channelFlags); void setTemporarySelection(KisSelectionSP selection); /** * Configures the painter to conform the painting parameters * stored for th temporary target, such as compositeOp, opacity, * channel flags and selection. Please do not setup them manually, * but use this function instead. */ void setupTemporaryPainter(KisPainter *painter) const; /** * Writes the temporary target into the paint device of the layer. * This action will lock the temporary target itself. */ void mergeToLayer(KisNodeSP layer, KisUndoAdapter *undoAdapter, const KUndo2MagicString &transactionText,int timedID = -1); void mergeToLayer(KisNodeSP layer, KisPostExecutionUndoAdapter *undoAdapter, const KUndo2MagicString &transactionText,int timedID = -1); /** * Lock the temporary target. * It should be done for guarding every access to * temporaryTarget() or original() * NOTE: well, not "every", but... */ void lockTemporaryTarget() const; /** * Unlock the temporary target * * \see lockTemporaryTarget() */ void unlockTemporaryTarget() const; KisPaintDeviceSP temporaryTarget(); const KisPaintDeviceSP temporaryTarget() const; private: friend class KisPainterBasedStrokeStrategy; /** * Only for debugging purposes. Please use setupTemporaryPainer() * instead. */ KisSelectionSP temporarySelection() const; private: template void mergeToLayerImpl(KisNodeSP layer, UndoAdapter *undoAdapter, const KUndo2MagicString &transactionText,int timedID = -1); void releaseResources(); private: struct Private; Private* const d; }; #endif /* KIS_INDIRECT_PAINTING_SUPPORT_H_ */ diff --git a/krita/image/kis_layer.cc b/krita/image/kis_layer.cc index a5e59f7efe4..8be7d653dd1 100644 --- a/krita/image/kis_layer.cc +++ b/krita/image/kis_layer.cc @@ -1,803 +1,809 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_layer.h" #include #include #include #include #include #include #include #include #include #include #include "kis_debug.h" #include "kis_image.h" #include "kis_painter.h" #include "kis_mask.h" #include "kis_effect_mask.h" #include "kis_selection_mask.h" #include "kis_meta_data_store.h" #include "kis_selection.h" #include "kis_paint_layer.h" #include "kis_clone_layer.h" #include "kis_psd_layer_style.h" #include "kis_layer_projection_plane.h" #include "layerstyles/kis_layer_style_projection_plane.h" class KisSafeProjection { public: KisPaintDeviceSP getDeviceLazy(KisPaintDeviceSP prototype) { QMutexLocker locker(&m_lock); if (!m_reusablePaintDevice) { m_reusablePaintDevice = new KisPaintDevice(*prototype); } if(!m_projection || !(*m_projection->colorSpace() == *prototype->colorSpace())) { m_projection = m_reusablePaintDevice; m_projection->makeCloneFromRough(prototype, prototype->extent()); } return m_projection; } void freeDevice() { QMutexLocker locker(&m_lock); m_projection = 0; if(m_reusablePaintDevice) { m_reusablePaintDevice->clear(); } } private: QMutex m_lock; KisPaintDeviceSP m_projection; KisPaintDeviceSP m_reusablePaintDevice; }; class KisCloneLayersList { public: void addClone(KisCloneLayerWSP cloneLayer) { m_clonesList.append(cloneLayer); } void removeClone(KisCloneLayerWSP cloneLayer) { m_clonesList.removeOne(cloneLayer); } void setDirty(const QRect &rect) { foreach(KisCloneLayerWSP clone, m_clonesList) { clone->setDirtyOriginal(rect); } } const QList registeredClones() const { return m_clonesList; } bool hasClones() const { return !m_clonesList.isEmpty(); } private: QList m_clonesList; }; struct KisLayer::Private { KisImageWSP image; QBitArray channelFlags; KisMetaData::Store* metaDataStore; KisSafeProjection safeProjection; KisCloneLayersList clonesList; KisPSDLayerStyleSP layerStyle; KisAbstractProjectionPlaneSP layerStyleProjectionPlane; KisAbstractProjectionPlaneSP projectionPlane; }; KisLayer::KisLayer(KisImageWSP image, const QString &name, quint8 opacity) : KisNode() , m_d(new Private) { setName(name); setOpacity(opacity); m_d->image = image; m_d->metaDataStore = new KisMetaData::Store(); m_d->projectionPlane = toQShared(new KisLayerProjectionPlane(this)); } KisLayer::KisLayer(const KisLayer& rhs) : KisNode(rhs) , m_d(new Private()) { if (this != &rhs) { m_d->image = rhs.m_d->image; m_d->metaDataStore = new KisMetaData::Store(*rhs.m_d->metaDataStore); setName(rhs.name()); m_d->projectionPlane = toQShared(new KisLayerProjectionPlane(this)); if (rhs.m_d->layerStyle) { setLayerStyle(rhs.m_d->layerStyle->clone()); } } } KisLayer::~KisLayer() { delete m_d->metaDataStore; delete m_d; } const KoColorSpace * KisLayer::colorSpace() const { if (m_d->image) return m_d->image->colorSpace(); return 0; } const KoCompositeOp * KisLayer::compositeOp() const { /** * FIXME: This function duplicates the same function from * KisMask. We can't move it to KisBaseNode as it doesn't * know anything about parent() method of KisNode * Please think it over... */ KisNodeSP parentNode = parent(); if (!parentNode) return 0; if (!parentNode->colorSpace()) return 0; const KoCompositeOp* op = parentNode->colorSpace()->compositeOp(compositeOpId()); return op ? op : parentNode->colorSpace()->compositeOp(COMPOSITE_OVER); } KisPSDLayerStyleSP KisLayer::layerStyle() const { return m_d->layerStyle; } void KisLayer::setLayerStyle(KisPSDLayerStyleSP layerStyle) { if (layerStyle) { m_d->layerStyle = layerStyle; KisAbstractProjectionPlaneSP plane = !layerStyle->isEmpty() ? KisAbstractProjectionPlaneSP(new KisLayerStyleProjectionPlane(this)) : KisAbstractProjectionPlaneSP(0); m_d->layerStyleProjectionPlane = plane; } else { m_d->layerStyleProjectionPlane.clear(); m_d->layerStyle.clear(); } } KisDocumentSectionModel::PropertyList KisLayer::sectionModelProperties() const { KisDocumentSectionModel::PropertyList l = KisBaseNode::sectionModelProperties(); l << KisDocumentSectionModel::Property(i18n("Opacity"), i18n("%1%", percentOpacity())); if (compositeOp()) { l << KisDocumentSectionModel::Property(i18n("Composite Mode"), compositeOp()->description()); } if (m_d->layerStyle && !m_d->layerStyle->isEmpty()) { l << KisDocumentSectionModel::Property(i18n("Layer Style"), koIcon("layer-style-enabled"), koIcon("layer-style-disabled"), m_d->layerStyle->isEnabled()); } l << KisDocumentSectionModel::Property(i18n("Inherit Alpha"), themedIcon("transparency-disabled"), themedIcon("transparency-enabled"), alphaChannelDisabled()); return l; } void KisLayer::setSectionModelProperties(const KisDocumentSectionModel::PropertyList &properties) { KisBaseNode::setSectionModelProperties(properties); foreach (const KisDocumentSectionModel::Property &property, properties) { if (property.name == i18n("Inherit Alpha")) { disableAlphaChannel(property.state.toBool()); } if (property.name == i18n("Layer Style")) { if (m_d->layerStyle) { m_d->layerStyle->setEnabled(property.state.toBool()); } } } } void KisLayer::disableAlphaChannel(bool disable) { QBitArray newChannelFlags = m_d->channelFlags; if(newChannelFlags.isEmpty()) newChannelFlags = colorSpace()->channelFlags(true, true); if(disable) newChannelFlags &= colorSpace()->channelFlags(true, false); else newChannelFlags |= colorSpace()->channelFlags(false, true); setChannelFlags(newChannelFlags); } bool KisLayer::alphaChannelDisabled() const { QBitArray flags = colorSpace()->channelFlags(false, true) & m_d->channelFlags; return flags.count(true) == 0 && !m_d->channelFlags.isEmpty(); } void KisLayer::setChannelFlags(const QBitArray & channelFlags) { Q_ASSERT(channelFlags.isEmpty() ||((quint32)channelFlags.count() == colorSpace()->channelCount())); if (!channelFlags.isEmpty() && channelFlags == QBitArray(channelFlags.size(), true)) { m_d->channelFlags.clear(); } else { m_d->channelFlags = channelFlags; } } QBitArray & KisLayer::channelFlags() const { return m_d->channelFlags; } bool KisLayer::temporary() const { return nodeProperties().boolProperty("temporary", false); } void KisLayer::setTemporary(bool t) { nodeProperties().setProperty("temporary", t); } KisImageWSP KisLayer::image() const { return m_d->image; } void KisLayer::setImage(KisImageWSP image) { m_d->image = image; for (uint i = 0; i < childCount(); ++i) { // Only layers know about the image - KisLayer * layer = dynamic_cast(at(i).data()); - if (layer) + KisLayer *layer = dynamic_cast(at(i).data()); + if (layer) { layer->setImage(image); + } + // We lied, through the defaultBounds, masks also know about the image + KisMask *mask = dynamic_cast(at(i).data()); + if (mask) { + mask->setImage(image); + } } } bool KisLayer::canMergeAndKeepBlendOptions(KisLayerSP otherLayer) { return this->compositeOpId() == otherLayer->compositeOpId() && this->opacity() == otherLayer->opacity() && this->channelFlags() == otherLayer->channelFlags() && !this->layerStyle() && !otherLayer->layerStyle() && (this->colorSpace() == otherLayer->colorSpace() || *this->colorSpace() == *otherLayer->colorSpace()); } KisLayerSP KisLayer::createMergedLayer(KisLayerSP prevLayer) { KisImageSP my_image = image(); QRect layerProjectionExtent = this->projection()->extent(); QRect prevLayerProjectionExtent = prevLayer->projection()->extent(); bool alphaDisabled = this->alphaChannelDisabled(); bool prevAlphaDisabled = prevLayer->alphaChannelDisabled(); KisPaintDeviceSP mergedDevice; bool keepBlendingOptions = canMergeAndKeepBlendOptions(prevLayer); if (!keepBlendingOptions) { KisNodeSP parentNode = parent(); const KoColorSpace *dstCs = parentNode && parentNode->colorSpace() ? parentNode->colorSpace() : my_image->colorSpace(); mergedDevice = new KisPaintDevice(dstCs, "merged"); KisPainter gc(mergedDevice); //Copy the pixels of previous layer with their actual alpha value prevLayer->disableAlphaChannel(false); prevLayer->projectionPlane()->apply(&gc, prevLayerProjectionExtent | my_image->bounds()); //Restore the previous prevLayer disableAlpha status for correct undo/redo prevLayer->disableAlphaChannel(prevAlphaDisabled); //Paint the pixels of the current layer, using their actual alpha value if (alphaDisabled == prevAlphaDisabled) { this->disableAlphaChannel(false); } this->projectionPlane()->apply(&gc, layerProjectionExtent | my_image->bounds()); //Restore the layer disableAlpha status for correct undo/redo this->disableAlphaChannel(alphaDisabled); } else { //Copy prevLayer my_image->lock(); mergedDevice = new KisPaintDevice(*prevLayer->projection()); my_image->unlock(); //Paint layer on the copy KisPainter gc(mergedDevice); gc.bitBlt(layerProjectionExtent.topLeft(), this->projection(), layerProjectionExtent); } KisLayerSP newLayer = new KisPaintLayer(my_image, prevLayer->name(), OPACITY_OPAQUE_U8, mergedDevice); if (keepBlendingOptions) { newLayer->setCompositeOp(compositeOpId()); newLayer->setOpacity(opacity()); newLayer->setChannelFlags(channelFlags()); } return newLayer; } void KisLayer::registerClone(KisCloneLayerWSP clone) { m_d->clonesList.addClone(clone); } void KisLayer::unregisterClone(KisCloneLayerWSP clone) { m_d->clonesList.removeClone(clone); } const QList KisLayer::registeredClones() const { return m_d->clonesList.registeredClones(); } bool KisLayer::hasClones() const { return m_d->clonesList.hasClones(); } void KisLayer::updateClones(const QRect &rect) { m_d->clonesList.setDirty(rect); } KisSelectionMaskSP KisLayer::selectionMask() const { KoProperties properties; properties.setProperty("active", true); QList masks = childNodes(QStringList("KisSelectionMask"), properties); // return the first visible mask foreach (KisNodeSP mask, masks) { if (mask->visible()) { return dynamic_cast(mask.data()); } } return 0; } KisSelectionSP KisLayer::selection() const { if (selectionMask()) { return selectionMask()->selection(); } else if (m_d->image) { return m_d->image->globalSelection(); } else { return 0; } } /////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////// QList KisLayer::effectMasks(KisNodeSP lastNode) const { QList masks; if (childCount() > 0) { KoProperties properties; properties.setProperty("visible", true); QList nodes = childNodes(QStringList("KisEffectMask"), properties); foreach(const KisNodeSP& node, nodes) { if (node == lastNode) break; KisEffectMaskSP mask = dynamic_cast(const_cast(node.data())); if (mask) masks.append(mask); } } return masks; } bool KisLayer::hasEffectMasks() const { if (childCount() == 0) return false; KisNodeSP node = firstChild(); while (node) { if (node->inherits("KisEffectMask") && node->visible()) { return true; } node = node->nextSibling(); } return false; } QRect KisLayer::masksChangeRect(const QList &masks, const QRect &requestedRect, bool &rectVariesFlag) const { rectVariesFlag = false; QRect prevChangeRect = requestedRect; /** * We set default value of the change rect for the case * when there is no mask at all */ QRect changeRect = requestedRect; foreach(const KisEffectMaskSP& mask, masks) { changeRect = mask->changeRect(prevChangeRect); if (changeRect != prevChangeRect) rectVariesFlag = true; prevChangeRect = changeRect; } return changeRect; } QRect KisLayer::masksNeedRect(const QList &masks, const QRect &changeRect, QStack &applyRects, bool &rectVariesFlag) const { rectVariesFlag = false; QRect prevNeedRect = changeRect; QRect needRect; for (qint32 i = masks.size() - 1; i >= 0; i--) { applyRects.push(prevNeedRect); needRect = masks[i]->needRect(prevNeedRect); if (prevNeedRect != needRect) rectVariesFlag = true; prevNeedRect = needRect; } return needRect; } KisNode::PositionToFilthy calculatePositionToFilthy(KisNodeSP nodeInQuestion, KisNodeSP filthy, KisNodeSP parent) { if (parent == filthy || parent != filthy->parent()) { return KisNode::N_ABOVE_FILTHY; } if (nodeInQuestion == filthy) { return KisNode::N_FILTHY; } KisNodeSP node = nodeInQuestion->prevSibling(); while (node) { if (node == filthy) { return KisNode::N_ABOVE_FILTHY; } node = node->prevSibling(); } return KisNode::N_BELOW_FILTHY; } QRect KisLayer::applyMasks(const KisPaintDeviceSP source, KisPaintDeviceSP destination, const QRect &requestedRect, KisNodeSP filthyNode, KisNodeSP lastNode) const { Q_ASSERT(source); Q_ASSERT(destination); QList masks = effectMasks(lastNode); QRect changeRect; QRect needRect; if (masks.isEmpty()) { changeRect = requestedRect; if (source != destination) { copyOriginalToProjection(source, destination, requestedRect); } } else { QStack applyRects; bool changeRectVaries; bool needRectVaries; /** * FIXME: Assume that varying of the changeRect has already * been taken into account while preparing walkers */ changeRectVaries = false; changeRect = requestedRect; //changeRect = masksChangeRect(masks, requestedRect, // changeRectVaries); needRect = masksNeedRect(masks, changeRect, applyRects, needRectVaries); if (!changeRectVaries && !needRectVaries) { /** * A bit of optimization: * All filters will read/write exactly from/to the requested * rect so we needn't create temporary paint device, * just apply it onto destination */ Q_ASSERT(needRect == requestedRect); if (source != destination) { copyOriginalToProjection(source, destination, needRect); } foreach(const KisEffectMaskSP& mask, masks) { const QRect maskApplyRect = applyRects.pop(); const QRect maskNeedRect = applyRects.isEmpty() ? needRect : applyRects.top(); PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast(this)); mask->apply(destination, maskApplyRect, maskNeedRect, maskPosition); } Q_ASSERT(applyRects.isEmpty()); } else { /** * We can't eliminate additional copy-op * as filters' behaviour may be quite insane here, * so let them work on their own paintDevice =) */ KisPaintDeviceSP tempDevice = new KisPaintDevice(colorSpace()); tempDevice->prepareClone(source); copyOriginalToProjection(source, tempDevice, needRect); QRect maskApplyRect = applyRects.pop(); QRect maskNeedRect = needRect; foreach(const KisEffectMaskSP& mask, masks) { PositionToFilthy maskPosition = calculatePositionToFilthy(mask, filthyNode, const_cast(this)); mask->apply(tempDevice, maskApplyRect, maskNeedRect, maskPosition); if (!applyRects.isEmpty()) { maskNeedRect = maskApplyRect; maskApplyRect = applyRects.pop(); } } Q_ASSERT(applyRects.isEmpty()); KisPainter::copyAreaOptimized(changeRect.topLeft(), tempDevice, destination, changeRect); } } return changeRect; } QRect KisLayer::updateProjection(const QRect& rect, KisNodeSP filthyNode) { QRect updatedRect = rect; KisPaintDeviceSP originalDevice = original(); if (!rect.isValid() || !visible() || !originalDevice) return QRect(); if (!needProjection() && !hasEffectMasks()) { m_d->safeProjection.freeDevice(); } else { if (!updatedRect.isEmpty()) { KisPaintDeviceSP projection = m_d->safeProjection.getDeviceLazy(originalDevice); updatedRect = applyMasks(originalDevice, projection, updatedRect, filthyNode, 0); } } return updatedRect; } QRect KisLayer::partialChangeRect(KisNodeSP lastNode, const QRect& rect) { bool changeRectVaries = false; QRect changeRect = outgoingChangeRect(rect); changeRect = masksChangeRect(effectMasks(lastNode), changeRect, changeRectVaries); return changeRect; } /** * \p rect is a dirty rect in layer's original() coordinates! */ void KisLayer::buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect& rect) { QRect changeRect = partialChangeRect(lastNode, rect); KisPaintDeviceSP originalDevice = original(); KIS_ASSERT_RECOVER_RETURN(needProjection() || hasEffectMasks()); if (!changeRect.isEmpty()) { applyMasks(originalDevice, projection, changeRect, this, lastNode); } } bool KisLayer::needProjection() const { return false; } void KisLayer::copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect& rect) const { KisPainter::copyAreaOptimized(rect.topLeft(), original, projection, rect); } KisAbstractProjectionPlaneSP KisLayer::projectionPlane() const { return m_d->layerStyleProjectionPlane ? m_d->layerStyleProjectionPlane : m_d->projectionPlane; } KisAbstractProjectionPlaneSP KisLayer::internalProjectionPlane() const { return m_d->projectionPlane; } KisPaintDeviceSP KisLayer::projection() const { KisPaintDeviceSP originalDevice = original(); return needProjection() || hasEffectMasks() ? m_d->safeProjection.getDeviceLazy(originalDevice) : originalDevice; } QRect KisLayer::changeRect(const QRect &rect, PositionToFilthy pos) const { QRect changeRect = rect; changeRect = incomingChangeRect(changeRect); if(pos == KisNode::N_FILTHY) { bool changeRectVaries; changeRect = outgoingChangeRect(changeRect); changeRect = masksChangeRect(effectMasks(), changeRect, changeRectVaries); } // TODO: string comparizon: optimize! if (pos != KisNode::N_FILTHY && pos != KisNode::N_FILTHY_PROJECTION && compositeOpId() != COMPOSITE_COPY) { changeRect |= rect; } return changeRect; } QRect KisLayer::incomingChangeRect(const QRect &rect) const { return rect; } QRect KisLayer::outgoingChangeRect(const QRect &rect) const { return rect; } QImage KisLayer::createThumbnail(qint32 w, qint32 h) { KisPaintDeviceSP originalDevice = original(); return originalDevice ? originalDevice->createThumbnail(w, h, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags) : QImage(); } qint32 KisLayer::x() const { KisPaintDeviceSP originalDevice = original(); return originalDevice ? originalDevice->x() : 0; } qint32 KisLayer::y() const { KisPaintDeviceSP originalDevice = original(); return originalDevice ? originalDevice->y() : 0; } void KisLayer::setX(qint32 x) { KisPaintDeviceSP originalDevice = original(); if (originalDevice) originalDevice->setX(x); } void KisLayer::setY(qint32 y) { KisPaintDeviceSP originalDevice = original(); if (originalDevice) originalDevice->setY(y); } QRect KisLayer::extent() const { KisPaintDeviceSP originalDevice = original(); return originalDevice ? originalDevice->extent() : QRect(); } QRect KisLayer::exactBounds() const { KisPaintDeviceSP originalDevice = original(); return originalDevice ? originalDevice->exactBounds() : QRect(); } KisLayerSP KisLayer::parentLayer() const { return dynamic_cast(parent().data()); } KisMetaData::Store* KisLayer::metaData() { return m_d->metaDataStore; } #include "kis_layer.moc" diff --git a/krita/image/kis_layer.h b/krita/image/kis_layer.h index 52bc3570436..3437953189f 100644 --- a/krita/image/kis_layer.h +++ b/krita/image/kis_layer.h @@ -1,382 +1,382 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * Copyright (c) 2007 Boudewijn Rempt * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LAYER_H_ #define KIS_LAYER_H_ #include #include #include #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "KisDocumentSectionModel.h" #include "kis_types.h" #include "kis_node.h" template class QStack; class QBitArray; class KisCloneLayer; class KisPSDLayerStyle; class KisAbstractProjectionPlane; namespace KisMetaData { class Store; } /** * Abstract class that represents the concept of a Layer in Krita. This is not related * to the paint devices: this is merely an abstraction of how layers can be stacked and * rendered differently. * Regarding the previous-, first-, next- and lastChild() calls, first means that it the layer * is at the top of the group in the layerlist, using next will iterate to the bottom to last, * whereas previous will go up to first again. * * * TODO: Add a layer mode whereby the projection of the layer is used * as a clipping path? **/ class KRITAIMAGE_EXPORT KisLayer : public KisNode { Q_OBJECT public: /** * @param image is the pointer of the image or null * @param opacity is a value between OPACITY_TRANSPARENT_U8 and OPACITY_OPAQUE_U8 **/ KisLayer(KisImageWSP image, const QString &name, quint8 opacity); KisLayer(const KisLayer& rhs); virtual ~KisLayer(); /// returns the image's colorSpace or null, if there is no image virtual const KoColorSpace * colorSpace() const; /// returns the layer's composite op for the colorspace of the layer's parent. const KoCompositeOp * compositeOp() const; KisPSDLayerStyleSP layerStyle() const; void setLayerStyle(KisPSDLayerStyleSP layerStyle); /** * \see a comment in KisNode::projectionPlane() */ virtual KisAbstractProjectionPlaneSP projectionPlane() const; /** * The projection plane representing the layer itself without any * styles or anything else. It is used by the layer styles projection * plane to stack up the planes. */ virtual KisAbstractProjectionPlaneSP internalProjectionPlane() const; QRect partialChangeRect(KisNodeSP lastNode, const QRect& rect); void buildProjectionUpToNode(KisPaintDeviceSP projection, KisNodeSP lastNode, const QRect& rect); virtual bool needProjection() const; /** * Return the fully rendered representation of this layer: its * data and its effect masks */ KisPaintDeviceSP projection() const; /** * Return the layer data before the effect masks have had their go * at it. */ virtual KisPaintDeviceSP original() const = 0; /** * @return the selection associated with this layer, if there is * one. Otherwise, return 0; */ virtual KisSelectionMaskSP selectionMask() const; /** * @return the selection contained in the first KisSelectionMask associated * with this layer or the image, if either exists, otherwise, return 0. */ virtual KisSelectionSP selection() const; virtual KisDocumentSectionModel::PropertyList sectionModelProperties() const; virtual void setSectionModelProperties(const KisDocumentSectionModel::PropertyList &properties); /** * set/unset the channel flag for the alpha channel of this layer */ void disableAlphaChannel(bool disable); /** * returns true if the channel flag for the alpha channel * of this layer is not set. * returns false otherwise. */ bool alphaChannelDisabled() const; /** * set the channelflags for this layer to the specified bit array. * The bit array must have exactly the same number of channels as * the colorspace this layer is in, or be empty, in which case all * channels are active. */ virtual void setChannelFlags(const QBitArray & channelFlags); /** * Return a bit array where each bit indicates whether a * particular channel is active or not. If the channelflags bit * array is empty, all channels are active. */ QBitArray & channelFlags() const; /** * Returns true if this layer is temporary: i.e., it should not * appear in the layerbox, even though it is temporarily in the * layer stack and taken into account on recomposition. */ bool temporary() const; /** * Set to true if this layer should not appear in the layerbox, * even though it is temporarily in the layer stack and taken into * account on recomposition. */ void setTemporary(bool t); /// returns the image this layer belongs to, or null if there is no image KisImageWSP image() const; /** * Set the image this layer belongs to. */ virtual void setImage(KisImageWSP image); /** * Create and return a layer that is the result of merging * this with layer. * * This method is designed to be called only within KisImage::mergeLayerDown(). * * Decendands override this to create specific merged types when possible. * The KisLayer one creates a KisPaintLayerSP via a bitBlt, and can work on all layer types. * * Decendants that perform there own version do NOT call KisLayer::createMergedLayer */ virtual KisLayerSP createMergedLayer(KisLayerSP prevLayer); /** * Clones should be informed about updates of the original * layer, so this is a way to register them */ void registerClone(KisCloneLayerWSP clone); /** * Deregisters the clone from the update list * * \see registerClone() */ void unregisterClone(KisCloneLayerWSP clone); /** * Return the list of the clones of this node. Be careful * with the list, because it is not thread safe. */ const QList registeredClones() const; /** * Returns whether we have a clone. * * Be careful with it. It is not thread safe to add/remove * clone while checking hasClones(). So there should be no updates. */ bool hasClones() const; /** * It is calles by the async merger after projection update is done */ void updateClones(const QRect &rect); public: qint32 x() const; qint32 y() const; void setX(qint32 x); void setY(qint32 y); /** * Returns an approximation of where the bounds * of actual data of this layer are */ QRect extent() const; /** * Returns the exact bounds of where the actual data * of this layer resides */ QRect exactBounds() const; QImage createThumbnail(qint32 w, qint32 h); public: /** * Returns true if there are any effect masks present */ bool hasEffectMasks() const; /** * @return the list of effect masks */ QList effectMasks(KisNodeSP lastNode = 0) const; /** * Get the group layer that contains this layer. */ KisLayerSP parentLayer() const; /** * @return the metadata object associated with this object. */ KisMetaData::Store* metaData(); protected: // override from KisNode QRect changeRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; protected: /** * Ask the layer to assemble its data & apply all the effect masks * to it. */ QRect updateProjection(const QRect& rect, KisNodeSP filthyNode); /** * Layers can override this method to get some special behavior * when copying data from \p original to \p projection, e.g. blend * in indirect painting device. If you need to modify data * outside \p rect, please also override outgoingChangeRect() * method. */ virtual void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect& rect) const; /** * For KisLayer classes change rect transformation consists of two * parts: incoming and outgoing. * * 1) incomingChangeRect(rect) chande rect transformation * performed by the transformations done basing on global * projection. It is performed in KisAsyncMerger + * KisUpdateOriginalVisitor classes. It happens before data * coming to KisLayer::original() therefore it is * 'incoming'. See KisAdjustmentLayer for example of usage. * * 2) outgoingChangeRect(rect) change rect transformation that * happens in KisLayer::copyOriginalToProjection(). It applies * *only* when the layer is 'filthy', that is was the cause of * the merge process. See KisCloneLayer for example of usage. * * The flow of changed areas can be illustrated in the * following way: * * 1. Current projection of size R1 is stored in KisAsyncMerger::m_currentProjection * | * | <-- KisUpdateOriginalVisitor writes data into layer's original() device. * | The changed area on KisLayer::original() is * | R2 = KisLayer::incomingChangeRect(R1) * | * 2. KisLayer::original() / changed rect: R2 * | * | <-- KisLayer::updateProjection() starts composing a layer * | It calls KisLayer::copyOriginalToProjection() which copies some area * | to a temporaty device. The temporary device now stores * | R3 = KisLayer::outgoingChangeRect(R2) * | * 3. Temporary device / changed rect: R3 * | * | <-- KisLayer::updateProjection() continues composing a layer. It merges a mask. * | R4 = KisMask::changeRect(R3) * | * 4. KisLayer::original() / changed rect: R4 * * So in the end rect R4 will be passed up to the next layers in the stack. */ virtual QRect incomingChangeRect(const QRect &rect) const; /** * \see incomingChangeRect() */ virtual QRect outgoingChangeRect(const QRect &rect) const; /** * @param rectVariesFlag (out param) a flag, showing whether * a rect varies from mask to mask * @return an area that should be updated because of * the change of @requestedRect of the layer */ QRect masksChangeRect(const QList &masks, const QRect &requestedRect, bool &rectVariesFlag) const; /** * Get needRects for all masks * @param changeRect requested rect to be updated on final * projection. Should be a return value * of @ref masksChangedRect() * @param applyRects (out param) a stack of the rects where filters * should be applied * @param rectVariesFlag (out param) a flag, showing whether * a rect varies from mask to mask * @return a needRect that should be prepared on the layer's * paintDevice for all masks to succeed */ QRect masksNeedRect(const QList &masks, const QRect &changeRect, QStack &applyRects, bool &rectVariesFlag) const; QRect applyMasks(const KisPaintDeviceSP source, KisPaintDeviceSP destination, const QRect &requestedRect, KisNodeSP filthyNode, KisNodeSP lastNode) const; bool canMergeAndKeepBlendOptions(KisLayerSP otherLayer); private: friend class KisLayerProjectionPlane; friend class KisTransformMask; friend class KisLayerTest; private: struct Private; Private * const m_d; }; Q_DECLARE_METATYPE(KisLayerSP) #endif // KIS_LAYER_H_ diff --git a/krita/image/kis_layer_composition.h b/krita/image/kis_layer_composition.h index 4b94efc8509..3f45810f406 100644 --- a/krita/image/kis_layer_composition.h +++ b/krita/image/kis_layer_composition.h @@ -1,89 +1,89 @@ /* * Copyright (c) 2012 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_LAYERCOMPOSITION_H #define _KIS_LAYERCOMPOSITION_H -#include "krita_export.h" +#include "kritaimage_export.h" #include #include #include #include #include "kis_image.h" /** * Storage class for layer compositions. Layer compositions allow to have several state for visible layers * e.g. used in storyboarding with one background and differnt foregrounds */ class KRITAIMAGE_EXPORT KisLayerComposition { public: KisLayerComposition(KisImageWSP image, const QString& name); ~KisLayerComposition(); /** * Sets name of the composition */ void setName(const QString& name); /** * Name of the composition as show in the docker * \return name of the composition */ QString name(); /** * Stores the current visibility of all layers in the composition */ void store(); /** * Applies the stored visibility to all the nodes */ void apply(); /** * Set the export enabled flag, if false the compositions will not be exported */ void setExportEnabled(bool enabled); /** * Export enabled flag, if false the compositions will not be exported * \return name of the composition */ bool isExportEnabled(); void setVisible(QUuid id, bool visible); void setCollapsed(QUuid id, bool collapsed); void save(QDomDocument& doc, QDomElement& element); private: KisImageWSP m_image; QString m_name; QMap m_visibilityMap; QMap m_collapsedMap; bool m_exportEnabled; friend class KisCompositionVisitor; }; #endif diff --git a/krita/image/kis_liquify_transform_worker.h b/krita/image/kis_liquify_transform_worker.h index d70935d2724..30a6148af44 100644 --- a/krita/image/kis_liquify_transform_worker.h +++ b/krita/image/kis_liquify_transform_worker.h @@ -1,92 +1,92 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LIQUIFY_TRANSFORM_WORKER_H #define __KIS_LIQUIFY_TRANSFORM_WORKER_H #include #include -#include +#include #include class QImage; class QRect; class QSize; class QTransform; class QDomElement; class KRITAIMAGE_EXPORT KisLiquifyTransformWorker : boost::equality_comparable { public: KisLiquifyTransformWorker(const QRect &srcBounds, KoUpdater *progress, int pixelPrecision = 8); KisLiquifyTransformWorker(const KisLiquifyTransformWorker &rhs); ~KisLiquifyTransformWorker(); bool operator==(const KisLiquifyTransformWorker &other) const; int pointToIndex(const QPoint &cellPt); QSize gridSize() const; void translatePoints(const QPointF &base, const QPointF &offset, qreal sigma, bool useWashMode, qreal flow); void scalePoints(const QPointF &base, qreal scale, qreal sigma, bool useWashMode, qreal flow); void rotatePoints(const QPointF &base, qreal angle, qreal sigma, bool useWashMode, qreal flow); void undoPoints(const QPointF &base, qreal amount, qreal sigma); const QVector& originalPoints() const; QVector& transformedPoints(); void run(KisPaintDeviceSP device); QImage runOnQImage(const QImage &srcImage, const QPointF &srcImageOffset, const QTransform &imageToThumbTransform, QPointF *newOffset); void toXML(QDomElement *e) const; static KisLiquifyTransformWorker* fromXML(const QDomElement &e); void translate(const QPointF &offset); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_LIQUIFY_TRANSFORM_WORKER_H */ diff --git a/krita/image/kis_mask.cc b/krita/image/kis_mask.cc index c41584c7ec9..84a3258d962 100644 --- a/krita/image/kis_mask.cc +++ b/krita/image/kis_mask.cc @@ -1,350 +1,359 @@ /* * Copyright (c) 2006 Boudewijn Rempt * (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_mask.h" #include // to prevent incomplete class types on "delete selection->flatten();" #include #include #include #include #include "kis_paint_device.h" #include "kis_selection.h" #include "kis_pixel_selection.h" #include "kis_painter.h" #include "kis_image.h" #include "kis_layer.h" #include "kis_cached_paint_device.h" #include "kis_mask_projection_plane.h" struct KisMask::Private { Private(KisMask *_q) : q(_q), projectionPlane(new KisMaskProjectionPlane(q)) { } mutable KisSelectionSP selection; KisCachedPaintDevice paintDeviceCache; KisMask *q; /** * Due to the design of the Kra format the X,Y offset of the paint * device belongs to the node, but not to the device itself. So * the offset is set when the node is created, but not when the * selection is initialized. This causes the X,Y values to be * lost, since the selection doen not exist at the moment. That is * why we save it separately. */ QScopedPointer deferredSelectionOffset; KisAbstractProjectionPlaneSP projectionPlane; void initSelectionImpl(KisSelectionSP copyFrom, KisLayerSP parentLayer, KisPaintDeviceSP copyFromDevice); }; KisMask::KisMask(const QString & name) : KisNode() , m_d(new Private(this)) { setName(name); } KisMask::KisMask(const KisMask& rhs) : KisNode(rhs) , KisIndirectPaintingSupport() , m_d(new Private(this)) { setName(rhs.name()); if (rhs.m_d->selection) { m_d->selection = new KisSelection(*rhs.m_d->selection.data()); m_d->selection->setParentNode(this); } } KisMask::~KisMask() { delete m_d; } +void KisMask::setImage(KisImageWSP image) +{ + KisDefaultBoundsBaseSP db = m_d->selection->pixelSelection()->defaultBounds(); + KisDefaultBounds *defaultBounds = dynamic_cast(db.data()); + if (defaultBounds) { + defaultBounds->setImage(image); + } +} + bool KisMask::allowAsChild(KisNodeSP node) const { Q_UNUSED(node); return false; } const KoColorSpace * KisMask::colorSpace() const { KisNodeSP parentNode = parent(); return parentNode ? parentNode->colorSpace() : 0; } const KoCompositeOp * KisMask::compositeOp() const { /** * FIXME: This function duplicates the same function from * KisLayer. We can't move it to KisBaseNode as it doesn't * know anything about parent() method of KisNode * Please think it over... */ KisNodeSP parentNode = parent(); if (!parentNode) return 0; if (!parentNode->colorSpace()) return 0; const KoCompositeOp* op = parentNode->colorSpace()->compositeOp(compositeOpId()); return op ? op : parentNode->colorSpace()->compositeOp(COMPOSITE_OVER); } void KisMask::initSelection(KisSelectionSP copyFrom, KisLayerSP parentLayer) { m_d->initSelectionImpl(copyFrom, parentLayer, 0); } void KisMask::initSelection(KisPaintDeviceSP copyFromDevice, KisLayerSP parentLayer) { m_d->initSelectionImpl(0, parentLayer, copyFromDevice); } void KisMask::initSelection(KisLayerSP parentLayer) { m_d->initSelectionImpl(0, parentLayer, 0); } void KisMask::Private::initSelectionImpl(KisSelectionSP copyFrom, KisLayerSP parentLayer, KisPaintDeviceSP copyFromDevice) { Q_ASSERT(parentLayer); KisPaintDeviceSP parentPaintDevice = parentLayer->original(); if (copyFrom) { /** * We can't use setSelection as we may not have parent() yet */ selection = new KisSelection(*copyFrom); selection->setDefaultBounds(new KisSelectionDefaultBounds(parentPaintDevice, parentLayer->image())); if (copyFrom->hasShapeSelection()) { delete selection->flatten(); } } else if (copyFromDevice) { selection = new KisSelection(new KisSelectionDefaultBounds(parentPaintDevice, parentLayer->image())); QRect rc(copyFromDevice->extent()); KisPainter::copyAreaOptimized(rc.topLeft(), copyFromDevice, selection->pixelSelection(), rc); selection->pixelSelection()->invalidateOutlineCache(); } else { selection = new KisSelection(new KisSelectionDefaultBounds(parentPaintDevice, parentLayer->image())); quint8 newDefaultPixel = MAX_SELECTED; selection->pixelSelection()->setDefaultPixel(&newDefaultPixel); if (deferredSelectionOffset) { selection->setX(deferredSelectionOffset->x()); selection->setY(deferredSelectionOffset->y()); deferredSelectionOffset.reset(); } } selection->setParentNode(q); selection->updateProjection(); } KisSelectionSP KisMask::selection() const { return m_d->selection; } KisPaintDeviceSP KisMask::paintDevice() const { return selection()->pixelSelection(); } KisPaintDeviceSP KisMask::original() const { return paintDevice(); } KisPaintDeviceSP KisMask::projection() const { return paintDevice(); } KisAbstractProjectionPlaneSP KisMask::projectionPlane() const { return m_d->projectionPlane; } void KisMask::setSelection(KisSelectionSP selection) { m_d->selection = selection; if (parent()) { const KisLayer *parentLayer = qobject_cast(parent()); m_d->selection->setDefaultBounds(new KisDefaultBounds(parentLayer->image())); } m_d->selection->setParentNode(this); } void KisMask::select(const QRect & rc, quint8 selectedness) { KisSelectionSP sel = selection(); KisPixelSelectionSP psel = sel->pixelSelection(); psel->select(rc, selectedness); sel->updateProjection(rc); } QRect KisMask::decorateRect(KisPaintDeviceSP &src, KisPaintDeviceSP &dst, const QRect & rc, PositionToFilthy maskPos) const { Q_UNUSED(src); Q_UNUSED(dst); Q_UNUSED(maskPos); Q_ASSERT_X(0, "KisMask::decorateRect", "Should be overridden by successors"); return rc; } void KisMask::apply(KisPaintDeviceSP projection, const QRect &applyRect, const QRect &needRect, PositionToFilthy maskPos) const { if (selection()) { m_d->selection->updateProjection(applyRect); if(!extent().intersects(applyRect)) return; KisPaintDeviceSP cacheDevice = m_d->paintDeviceCache.getDevice(projection); QRect updatedRect = decorateRect(projection, cacheDevice, applyRect, maskPos); // masks don't have any compositioning KisPainter::copyAreaOptimized(updatedRect.topLeft(), cacheDevice, projection, updatedRect, m_d->selection); m_d->paintDeviceCache.putDevice(cacheDevice); } else { KisPaintDeviceSP cacheDevice = m_d->paintDeviceCache.getDevice(projection); cacheDevice->makeCloneFromRough(projection, needRect); projection->clear(needRect); decorateRect(cacheDevice, projection, applyRect, maskPos); m_d->paintDeviceCache.putDevice(cacheDevice); } } QRect KisMask::needRect(const QRect &rect, PositionToFilthy pos) const { Q_UNUSED(pos); QRect resultRect = rect; if (m_d->selection) resultRect &= m_d->selection->selectedRect(); return resultRect; } QRect KisMask::changeRect(const QRect &rect, PositionToFilthy pos) const { Q_UNUSED(pos); QRect resultRect = rect; if (m_d->selection) resultRect &= m_d->selection->selectedRect(); return resultRect; } QRect KisMask::extent() const { return m_d->selection ? m_d->selection->selectedRect() : parent() ? parent()->extent() : QRect(); } QRect KisMask::exactBounds() const { return m_d->selection ? m_d->selection->selectedExactRect() : parent() ? parent()->exactBounds() : QRect(); } qint32 KisMask::x() const { return m_d->selection ? m_d->selection->x() : m_d->deferredSelectionOffset ? m_d->deferredSelectionOffset->x() : parent() ? parent()->x() : 0; } qint32 KisMask::y() const { return m_d->selection ? m_d->selection->y() : m_d->deferredSelectionOffset ? m_d->deferredSelectionOffset->y() : parent() ? parent()->y() : 0; } void KisMask::setX(qint32 x) { if (m_d->selection) { m_d->selection->setX(x); } else if (!m_d->deferredSelectionOffset) { m_d->deferredSelectionOffset.reset(new QPoint(x, 0)); } else { m_d->deferredSelectionOffset->rx() = x; } } void KisMask::setY(qint32 y) { if (m_d->selection) { m_d->selection->setY(y); } else if (!m_d->deferredSelectionOffset) { m_d->deferredSelectionOffset.reset(new QPoint(0, y)); } else { m_d->deferredSelectionOffset->ry() = y; } } QImage KisMask::createThumbnail(qint32 w, qint32 h) { KisPaintDeviceSP originalDevice = selection() ? selection()->projection() : 0; return originalDevice ? originalDevice->createThumbnail(w, h, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags) : QImage(); } void KisMask::testingInitSelection(const QRect &rect) { m_d->selection = new KisSelection(); m_d->selection->pixelSelection()->select(rect, OPACITY_OPAQUE_U8); m_d->selection->updateProjection(rect); m_d->selection->setParentNode(this); } #include "kis_mask.moc" diff --git a/krita/image/kis_mask.h b/krita/image/kis_mask.h index 33fc9858098..da4ff238e47 100644 --- a/krita/image/kis_mask.h +++ b/krita/image/kis_mask.h @@ -1,202 +1,204 @@ /* * Copyright (c) 2006 Boudewijn Rempt * (c) 2009 Dmitry Kazakov * * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_MASK_ #define _KIS_MASK_ #include #include "kis_types.h" #include "kis_node.h" #include "kis_global.h" #include "kis_indirect_painting_support.h" -#include +#include /** KisMask is the base class for all single channel mask-like paint devices in Krita. Masks can be rendered in different ways at different moments during the rendering stack. Masks are "owned" by layers (of any type), and cannot occur by themselves on themselves. The properties that masks implement are made available through the iterators created on their parent layer, or through iterators that can be created on the paint device that holds the mask data: masks are just paint devices, too. Masks should show up in the layerbox as sub-layers for the layer they are associated with and be ccp'able and draggable to other layers. Examples of masks are: - filter masks: like the alpha filter mask that is the most common type of mask and is simply known as "mask" in the gui. Other filter masks use any of krita's filters to filter the pixels of their parent. (In this they differ from adjustment layers, which filter all layers under them in their group stack). - selections: the selection mask is rendered after composition and zooming and determines the selectedness of the pixels of the parent layer. - painterly overlays: painterly overlays indicate a particular property of the pixel in the parent paint device they are associated with, like wetness, height or gravity. XXX: For now, all masks are 8 bit. Make the channel depth settable. */ class KRITAIMAGE_EXPORT KisMask : public KisNode, KisIndirectPaintingSupport { Q_OBJECT public: /** * Create a new KisMask. */ KisMask(const QString & name); /** * Copy the mask */ KisMask(const KisMask& rhs); virtual ~KisMask(); + void setImage(KisImageWSP image); + bool allowAsChild(KisNodeSP node) const; /** * @brief initSelection initializes the selection for the mask from * the given selection's projection. * @param copyFrom the selection we base the mask on * @param parentLayer the parent of this mask; it determines the default bounds of the mask. */ void initSelection(KisSelectionSP copyFrom, KisLayerSP parentLayer); /** * @brief initSelection initializes the selection for the mask from * the given paint device. * @param copyFromDevice the paint device we base the mask on * @param parentLayer the parent of this mask; it determines the default bounds of the mask. */ void initSelection(KisPaintDeviceSP copyFromDevice, KisLayerSP parentLayer); /** * @brief initSelection initializes an empty selection * @param parentLayer the parent of this mask; it determines the default bounds of the mask. */ void initSelection(KisLayerSP parentLayer); const KoColorSpace * colorSpace() const; const KoCompositeOp * compositeOp() const; /** * Return the selection associated with this mask. A selection can * contain both a paint device and shapes. */ KisSelectionSP selection() const; /** * @return the selection: if you paint on mask, you paint on the selections */ KisPaintDeviceSP paintDevice() const; /** * @return the same as paintDevice() */ KisPaintDeviceSP original() const; /** * @return the same as paintDevice() */ KisPaintDeviceSP projection() const; KisAbstractProjectionPlaneSP projectionPlane() const; /** * Change the selection to the specified selection object. The * selection is deep copied. */ void setSelection(KisSelectionSP selection); /** * Selected the specified rect with the specified amount of selectedness. */ void select(const QRect & rc, quint8 selectedness = MAX_SELECTED); /** * The extent and bounds of the mask are those of the selection inside */ QRect extent() const; QRect exactBounds() const; /** * overridden from KisBaseNode */ qint32 x() const; /** * overridden from KisBaseNode */ void setX(qint32 x); /** * overridden from KisBaseNode */ qint32 y() const; /** * overridden from KisBaseNode */ void setY(qint32 y); QRect needRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; QRect changeRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; QImage createThumbnail(qint32 w, qint32 h); void testingInitSelection(const QRect &rect); protected: /** * Apply the effect the projection using the mask as a selection. * Made public in KisEffectMask */ void apply(KisPaintDeviceSP projection, const QRect & applyRect, const QRect & needRect, PositionToFilthy maskPos) const; virtual QRect decorateRect(KisPaintDeviceSP &src, KisPaintDeviceSP &dst, const QRect & rc, PositionToFilthy maskPos) const; private: friend class KisMaskProjectionPlane; private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/kis_memory_leak_tracker.h b/krita/image/kis_memory_leak_tracker.h index ff7d0662269..7e9936eea80 100644 --- a/krita/image/kis_memory_leak_tracker.h +++ b/krita/image/kis_memory_leak_tracker.h @@ -1,79 +1,79 @@ /* * Copyright (c) 2010 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_MEMORY_LEAK_TRACKER_H_ #define _KIS_MEMORY_LEAK_TRACKER_H_ -#include +#include #include // Only linux support the memory leak tracker #ifndef Q_OS_LINUX #undef HAVE_MEMORY_LEAK_TRACKER #endif // Disable the memory leak tracker on release build #ifdef NDEBUG #undef HAVE_MEMORY_LEAK_TRACKER #endif /** * This class tracks what pointer is reference by who. It is used by * the smart pointers to detect leaks. * * Note that the KisMemoryLeakTracker is currently only available on Linux, * and translate to NOOP on other platforms. It is also just a debug tool, * and should not be used in a production build of krita. */ class KRITAIMAGE_EXPORT KisMemoryLeakTracker { KisMemoryLeakTracker(); ~KisMemoryLeakTracker(); public: static KisMemoryLeakTracker* instance(); void reference(const void* what, const void* bywho, const char* whatName = 0); void dereference(const void* what, const void* bywho); void dumpReferences(); void dumpReferences(const void* what); public: template void reference(const _T_* what, const void* bywho); template void dereference(const _T_* what, const void* bywho); private: struct Private; Private* const d; }; #include template void KisMemoryLeakTracker::reference(const _T_* what, const void* bywho) { reference((void*)what, bywho, typeid(what).name()); } template void KisMemoryLeakTracker::dereference(const _T_* what, const void* bywho) { dereference((void*)what, bywho); } #endif diff --git a/krita/image/kis_memory_statistics_server.h b/krita/image/kis_memory_statistics_server.h index cb7e734e125..fa0f9859830 100644 --- a/krita/image/kis_memory_statistics_server.h +++ b/krita/image/kis_memory_statistics_server.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_MEMORY_STATISTICS_SERVER_H #define __KIS_MEMORY_STATISTICS_SERVER_H #include #include #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" class KRITAIMAGE_EXPORT KisMemoryStatisticsServer : public QObject { Q_OBJECT public: struct Statistics { Statistics() : imageSize(0), totalMemorySize(0), realMemorySize(0), historicalMemorySize(0), poolSize(0), swapSize(0), totalMemoryLimit(0), tilesHardLimit(0), tilesSoftLimit(0), tilesPoolLimit(0) { } qint64 imageSize; qint64 totalMemorySize; qint64 realMemorySize; qint64 historicalMemorySize; qint64 poolSize; qint64 swapSize; qint64 totalMemoryLimit; qint64 tilesHardLimit; qint64 tilesSoftLimit; qint64 tilesPoolLimit; }; public: ~KisMemoryStatisticsServer(); static KisMemoryStatisticsServer* instance(); Statistics fetchMemoryStatistics(KisImageSP image) const; public Q_SLOTS: void notifyImageChanged(); Q_SIGNALS: void sigUpdateMemoryStatistics(); private: KisMemoryStatisticsServer(); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_MEMORY_STATISTICS_SERVER_H */ diff --git a/krita/image/kis_name_server.h b/krita/image/kis_name_server.h index c0e71e8dd39..9ec26ac9bc7 100644 --- a/krita/image/kis_name_server.h +++ b/krita/image/kis_name_server.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2002 Patrick Julien * * 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_NAMESERVER_H_ #define KIS_NAMESERVER_H_ #include -#include +#include class KRITAIMAGE_EXPORT KisNameServer { public: KisNameServer(qint32 seed = 1); ~KisNameServer(); qint32 number(); qint32 currentSeed() const; void rollback(); private: qint32 m_generator; QString m_prefix; }; #endif // KIS_NAMESERVER_H_ diff --git a/krita/image/kis_node.h b/krita/image/kis_node.h index f51211e84cd..2a9c965a008 100644 --- a/krita/image/kis_node.h +++ b/krita/image/kis_node.h @@ -1,361 +1,361 @@ /* * Copyright (c) 2007 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_NODE_H #define _KIS_NODE_H #include "kis_types.h" #include "kis_undo_adapter.h" #include "kis_base_node.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include class QRect; class QStringList; class KoProperties; class KisNodeVisitor; class KisNodeGraphListener; class KisNodeProgressProxy; class KisBusyProgressIndicator; class KisAbstractProjectionPlane; class KisProjectionLeaf; /** * A KisNode is a KisBaseNode that knows about its direct peers, parent * and children and whether it can have children. * * THREAD-SAFETY: All const methods of this class and setDirty calls * are considered to be thread-safe(!). All the others * especially add(), remove() and setParent() must be * protected externally. * * NOTE: your subclasses must have the Q_OBJECT declaration, even if * you do not define new signals or slots. */ class KRITAIMAGE_EXPORT KisNode : public KisBaseNode { friend class KisFilterMaskTest; Q_OBJECT public: /** * The struct describing the position of the node * against the filthy node. * NOTE: please change KisBaseRectsWalker::getPositionToFilthy * when changing this struct */ enum PositionToFilthy { N_ABOVE_FILTHY = 0x08, N_FILTHY_PROJECTION = 0x20, N_FILTHY = 0x40, N_BELOW_FILTHY = 0x80 }; /** * Create an empty node without a parent. */ KisNode(); /** * Create a copy of this node. The copy will not have a parent * node. */ KisNode(const KisNode & rhs); /** * Delete this node */ virtual ~KisNode(); virtual KisNodeSP clone() const = 0; virtual bool accept(KisNodeVisitor &v); virtual void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); /** * Re-implement this method to add constraints for the * subclasses that can be added as children to this node * * @return false if the given node is not allowed as a child to this node */ virtual bool allowAsChild(KisNodeSP) const = 0; /** * Set the entire node extent dirty; this percolates up to parent * nodes all the way to the root node. By default this is the * empty rect (through KisBaseNode::extent()) */ virtual void setDirty(); /** * Add the given rect to the set of dirty rects for this node; * this percolates up to parent nodes all the way to the root * node. */ virtual void setDirty(const QRect & rect); /** * Add the given rects to the set of dirty rects for this node; * this percolates up to parent nodes all the way to the root * node. */ virtual void setDirty(const QVector &rects); /** * Add the given region to the set of dirty rects for this node; * this percolates up to parent nodes all the way to the root * node, if propagate is true; */ virtual void setDirty(const QRegion ®ion); /** * \return a pointer to a KisAbstractProjectionPlane interface of * the node. This interface is used by the image merging * framework to get information and to blending for the * layer. * * Please note the difference between need/change/accessRect and * the projectionPlane() interface. The former one gives * information about internal composition of the layer, and the * latter one about the total composition, including layer styles, * pass-through blending and etc. */ virtual KisAbstractProjectionPlaneSP projectionPlane() const; /** * The rendering of the image may not always happen in the order * of the main graph. Pass-through nodes ake some subgraphs * linear, so it the order of rendering change. projectionLeaf() * is a special interface of KisNode that represents "a graph for * projection rendering". Therefore the nodes in projectionLeaf() * graph may have a different order the main one. */ virtual KisProjectionLeafSP projectionLeaf() const; protected: /** * \return internal changeRect() of the node. Do not mix with \see * projectionPlane() * * Some filters will cause a change of pixels those are outside * a requested rect. E.g. we change a rect of 2x2, then we want to * apply a convolution filter with kernel 4x4 (changeRect is * (2+2*3)x(2+2*3)=8x8) to that area. The rect that should be updated * on the layer will be exaclty 8x8. More than that the needRect for * that update will be 14x14. See \ref needeRect. */ virtual QRect changeRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; /** * \return internal needRect() of the node. Do not mix with \see * projectionPlane() * * Some filters need pixels outside the current processing rect to * compute the new value (for instance, convolution filters) * See \ref changeRect * See \ref accessRect */ virtual QRect needRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; /** * \return internal accessRect() of the node. Do not mix with \see * projectionPlane() * * Shows the area of image, that may be accessed during accessing * the node. * * Example. You have a layer that needs to prepare some rect on a * projection, say expectedRect. To perform this, the projection * of all the layers below of the size needRect(expectedRect) * should be calculeated by the merger beforehand and the layer * will access some other area of image inside the rect * accessRect(expectedRect) during updateProjection call. * * This knowledge about real access rect of a node is used by the * scheduler to avoid collisions between two multithreaded updaters * and so avoid flickering of the image. * * Currently, this method has nondefault value for shifted clone * layers only. */ virtual QRect accessRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; public: // Graph methods /** * @return the graph sequence number calculated by the associated * graph listener. You can use it for checking for changes in the * graph. */ int graphSequenceNumber() const; /** * @return the graph listener this node belongs to. 0 if the node * does not belong to a grap listener. */ KisNodeGraphListener * graphListener() const; /** * Set the graph listener for this node. The graphlistener will be * informed before and after the list of child nodes has changed. */ void setGraphListener(KisNodeGraphListener * graphListener); /** * Returns the parent node of this node. This is 0 only for a root * node; otherwise this will be an actual Node */ KisNodeSP parent() const; /** * Returns the first child node of this node, or 0 if there are no * child nodes. */ KisNodeSP firstChild() const; /** * Returns the last child node of this node, or 0 if there are no * child nodes. */ KisNodeSP lastChild() const; /** * Returns the previous sibling of this node in the parent's list. * This is the node *above* this node in the composition stack. 0 * is returned if this child has no more previous siblings (== * firstChild()) */ KisNodeSP prevSibling() const; /** * Returns the next sibling of this node in the parent's list. * This is the node *below* this node in the composition stack. 0 * is returned if this child has no more next siblings (== * lastChild()) */ KisNodeSP nextSibling() const; /** * Returns how many direct child nodes this node has (not * recursive). */ quint32 childCount() const; /** * Retrieve the child node at the specified index. * * @return 0 if there is no node at this index. */ KisNodeSP at(quint32 index) const; /** * Retrieve the index of the specified child node. * * @return -1 if the specified node is not a child node of this * node. */ int index(const KisNodeSP node) const; /** * Return a list of child nodes of the current node that conform * to the specified constraints. There are no guarantees about the * order of the nodes in the list. The function is not recursive. * * @param nodeTypes. if not empty, only nodes that inherit the * classnames in this stringlist will be returned. * @param properties. if not empty, only nodes for which * KisNodeBase::check(properties) returns true will be returned. */ QList childNodes(const QStringList & nodeTypes, const KoProperties & properties) const; public: /** * @return the node progress proxy used by this node, if this node has no progress * proxy, it will return the proxy of its parent, if the parent has no progress proxy * it will return 0 */ KisNodeProgressProxy* nodeProgressProxy() const; KisBusyProgressIndicator* busyProgressIndicator() const; private: /** * Create a node progress proxy for this node. You need to create a progress proxy only * if the node is going to appear in the layerbox, and it needs to be created before * the layer box is made aware of the proxy. */ void createNodeProgressProxy(); protected: KisBaseNodeSP parentCallback() const; void notifyParentVisibilityChanged(bool value); void baseNodeChangedCallback(); private: friend class KisNodeFacade; friend class KisNodeTest; friend class KisLayer; // Note: only for setting the preview mask! /** * Set the parent of this node. */ void setParent(KisNodeWSP parent); /** * Add the specified node above the specified node. If aboveThis * is 0, the node is added at the bottom. */ bool add(KisNodeSP newNode, KisNodeSP aboveThis); /** * Removes the node at the specified index from the child nodes. * * @return false if there is no node at this index */ bool remove(quint32 index); /** * Removes the node from the child nodes. * * @return false if there's no such node in this node. */ bool remove(KisNodeSP node); KisNodeSP prevChildImpl(KisNodeSP child); KisNodeSP nextChildImpl(KisNodeSP child); private: struct Private; Private * const m_d; }; Q_DECLARE_METATYPE(KisNodeSP) Q_DECLARE_METATYPE(KisNodeWSP) #endif diff --git a/krita/image/kis_node_facade.h b/krita/image/kis_node_facade.h index ce1da619c6d..7ab5299e8a9 100644 --- a/krita/image/kis_node_facade.h +++ b/krita/image/kis_node_facade.h @@ -1,140 +1,140 @@ /* * Copyright (c) 2007 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_NODE_FACADE_H #define _KIS_NODE_FACADE_H #include "kis_types.h" #include "kis_node.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * KisNodeFacade is the public interface to adding and removing nodes. */ class KRITAIMAGE_EXPORT KisNodeFacade { public: /** * Create a new, empty KisNodeFacade */ KisNodeFacade(); /** * Create a new kisnodefacade for the given root. */ KisNodeFacade(KisNodeSP root); virtual ~KisNodeFacade(); /** * Set the rootnode for this facade */ void setRoot(KisNodeSP root); /** * Return the root node for the graph this facade managed */ const KisNodeSP root() const; /** * Move the given node to specified position. If the node already * has a parent, it is removed from the parent's node list. */ bool moveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); /** * Move the givent node at the specified index. If the node already * has a parent, it is removed from the parent's node list. * * childCount() is a valid index and appends to the end. */ bool moveNode(KisNodeSP node, KisNodeSP parent, quint32 index); /** * Add an already existing node to the image. The node is put on top * of the nodes in the specified nodegroup. If parent is 0, then * the root is used as parent. * * @param node the node to be added * @param parent the parent node */ bool addNode(KisNodeSP node, KisNodeSP parent = 0); /** * Add already existing node to the graph. * * @param node the node to be added * @param parent the parent node * @param aboveThis in the list with child nodes of the specified * parent, add this node above the specified sibling. * if 0, the node is put in the lowermost position in * its group. * returns false if adding the node didn't work, true if the node got added */ bool addNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); /** * Adds the node as a child of the given parent at the specified * index. * * childCount() is a valid index and appends to the end. Fails and * returns false if the node is already in this group or any * other (remove it first.) */ bool addNode(KisNodeSP node, KisNodeSP parent, quint32 index); /** * Remove the specified node. * * @return false if removing the node failed */ bool removeNode(KisNodeSP node); /** * Move node up one slot, i.e., nextSibling becomes prevSibling */ bool raiseNode(KisNodeSP node); /** * Move node down one slot -- i.e, prevSibling becomes * nextSibling. * * @return false if moving the node failed */ bool lowerNode(KisNodeSP node); /** * Move the given node to the top-most position among its * siblings. * * @return false if moving the node failed. */ bool toTop(KisNodeSP node); /** * Move the given node to bottom-most position among its siblings. * * @return false if moving the node failed. */ bool toBottom(KisNodeSP node); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/kis_node_filter_interface.h b/krita/image/kis_node_filter_interface.h index 1d524794703..71d247532be 100644 --- a/krita/image/kis_node_filter_interface.h +++ b/krita/image/kis_node_filter_interface.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2008 Cyrille Berger * * 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_NODE_FILTER_INTERFACE_H_ #define _KIS_NODE_FILTER_INTERFACE_H_ -#include +#include #include #include "filter/kis_filter_configuration.h" /** * Define an interface for nodes that are associated with a filter. */ class KRITAIMAGE_EXPORT KisNodeFilterInterface { public: KisNodeFilterInterface(KisFilterConfiguration *filterConfig, bool useGeneratorRegistry); KisNodeFilterInterface(const KisNodeFilterInterface &rhs); virtual ~KisNodeFilterInterface(); /** * @return safe shared pointer to the filter configuration * associated with this node */ virtual KisSafeFilterConfigurationSP filter() const; /** * Sets the filter configuration for this node. The filter might * differ from the filter that is currently set up on this node. * * WARNING: the filterConfig becomes *owned* by the node right * after you've set it. Don't try to access the configuration * after you've associated it with the node. */ virtual void setFilter(KisFilterConfiguration *filterConfig); // the child classes should access the filter with the filter() method private: KisNodeFilterInterface& operator=(const KisNodeFilterInterface &other); KisSafeFilterConfigurationSP m_filter; bool m_useGeneratorRegistry; }; #endif diff --git a/krita/image/kis_node_graph_listener.h b/krita/image/kis_node_graph_listener.h index a4d6ede4fb8..51d92d3daae 100644 --- a/krita/image/kis_node_graph_listener.h +++ b/krita/image/kis_node_graph_listener.h @@ -1,113 +1,113 @@ /* * Copyright (c) 2007 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_NODE_GRAPH_LISTENER_H_ #define KIS_NODE_GRAPH_LISTENER_H_ -#include "krita_export.h" +#include "kritaimage_export.h" class KisNode; class QRect; /** * Implementations of this class are called by nodes whenever the node * graph changes. These implementations can then emit the right * signals so Qt interview models can be updated before and after * changes. * * The reason for this go-between is that we don't want our nodes to * be QObjects, nor to have sig-slot connections between every node * and every mode. * * It also manages the sequence number of the graph. This is a number * which can be used as a checksum for whether the graph has chenged * from some period of time or not. \see graphSequenceNumber() */ class KRITAIMAGE_EXPORT KisNodeGraphListener { public: KisNodeGraphListener(); virtual ~KisNodeGraphListener(); /** * Inform the model that we're going to add a node. */ virtual void aboutToAddANode(KisNode *parent, int index); /** * Inform the model we're done adding a node. */ virtual void nodeHasBeenAdded(KisNode *parent, int index); /** * Inform the model we're going to remove a node. */ virtual void aboutToRemoveANode(KisNode *parent, int index); /** * Inform the model we're done removing a node. */ virtual void nodeHasBeenRemoved(KisNode *parent, int index); /** * Inform the model we're about to start moving a node (which * includes removing and adding the same node) */ virtual void aboutToMoveNode(KisNode * node, int oldIndex, int newIndex); /** * Inform the model we're done moving the node: it has been * removed and added successfully */ virtual void nodeHasBeenMoved(KisNode * node, int oldIndex, int newIndex); virtual void nodeChanged(KisNode * node); /** * Inform the model that one of the selections in the graph is * changed. The sender is not passed to the function (at least for * now) because the UI should decide itself whether it needs to * fetch new selection of not. */ virtual void notifySelectionChanged(); /** * Inform the model that a node has been changed (setDirty) */ virtual void requestProjectionUpdate(KisNode * node, const QRect& rect); /** * Returns the sequence of the graph. * * Every time some operation performed, which might change the * hierarchy of the nodes, the sequence number grows by one. So * if you have any information about the graph which was acquired * when the sequence number was X and now it has become Y, it * means your information is outdated. * * It is used in the scheduler for checking whether queued walkers * should be regenerated. */ int graphSequenceNumber() const; private: struct Private; Private * const m_d; }; #endif diff --git a/krita/image/kis_node_progress_proxy.h b/krita/image/kis_node_progress_proxy.h index 9ecf75fc806..21051903c7f 100644 --- a/krita/image/kis_node_progress_proxy.h +++ b/krita/image/kis_node_progress_proxy.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2008 Cyrille Berger * * 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_NODE_PROGRESS_PROXY_H_ #define _KIS_NODE_PROGRESS_PROXY_H_ #include #include #include -#include "krita_export.h" +#include "kritaimage_export.h" /** * This class implements \ref KoProgressProxy and allows node to report progress. */ class KRITAIMAGE_EXPORT KisNodeProgressProxy : public QObject, public KoProgressProxy { Q_OBJECT friend class KisNode; /** * Create a proxy to report progress when processing, this proxy is associated * with a node, it will report progress in the node progress bar. This proxy * will be deleted when @p _node is deleted. */ KisNodeProgressProxy(KisNode* _node); ~KisNodeProgressProxy(); public: /** * @return the node associated with this proxy. */ const KisNodeSP node() const; virtual int maximum() const ; virtual void setValue(int value); virtual void setRange(int minimum, int maximum); virtual void setFormat(const QString & format); /** * @return the current percentage (return -1 if no progress) */ int percentage() const; Q_SIGNALS: /** * Emitted when the percentage of the proxy is changed. * @param _percentage is the progress value in percent * @param _node is the node that own this \ref KisNodeProgressProxy */ void percentageChanged(int _percentage, const KisNodeSP& _node); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_node_visitor.h b/krita/image/kis_node_visitor.h index 50024fecf27..17b82a7ea91 100644 --- a/krita/image/kis_node_visitor.h +++ b/krita/image/kis_node_visitor.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2005 C. Boemann * Copyright (c) 2007 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_NODE_VISITOR_H_ #define KIS_NODE_VISITOR_H_ #include "kis_node.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KisPaintLayer; class KisGroupLayer; class KisAdjustmentLayer; class KisExternalLayer; class KisCloneLayer; class KisFilterMask; class KisTransparencyMask; class KisSelectionMask; class KRITAIMAGE_EXPORT KisNodeVisitor { public: KisNodeVisitor() {} virtual ~KisNodeVisitor() {} public: virtual bool visit(KisNode *node) = 0; virtual bool visit(KisPaintLayer *layer) = 0; virtual bool visit(KisGroupLayer *layer) = 0; virtual bool visit(KisAdjustmentLayer *layer) = 0; virtual bool visit(KisExternalLayer *layer) = 0; virtual bool visit(KisGeneratorLayer *layer) = 0; virtual bool visit(KisCloneLayer *layer) = 0; virtual bool visit(KisFilterMask *mask) = 0; virtual bool visit(KisTransformMask *mask) = 0; virtual bool visit(KisTransparencyMask *mask) = 0; virtual bool visit(KisSelectionMask *mask) = 0; protected: /** * Visit all child nodes of the given node starting with the first one until one node returns * false. Then visitAll returns false, otherwise true. * * @param node the parent node whose children will be visited * @param breakOnFail break if one of the children returns false on accept * @return true if none of the childnodes returns false on * accepting the visitor. */ bool visitAll(KisNode * node, bool breakOnFail = false); /** * Visit all child nodes of the given node starting with the last one until one node returns * false. Then visitAll returns false, otherwise true. * * @param node the parent node whose children will be visited * @param breakOnFail break if one of the children returns false on accept * @return true if none of the childnodes returns false on * accepting the visitor. */ bool visitAllInverse(KisNode * node, bool breakOnFail = false); }; #endif // KIS_ NODE_VISITOR_H_ diff --git a/krita/image/kis_outline_generator.h b/krita/image/kis_outline_generator.h index af84a12a385..97f4a5aa5e9 100644 --- a/krita/image/kis_outline_generator.h +++ b/krita/image/kis_outline_generator.h @@ -1,104 +1,104 @@ /* * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2007,2010 Sven Langkamp * * Outline algorithm based of the limn of fontutils * Copyright (c) 1992 Karl Berry * Copyright (c) 1992 Kathryn Hargreaves * * 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_OUTLINE_GENERATOR_H #define KIS_OUTLINE_GENERATOR_H #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include class KoColorSpace; /** * Generates an 'outline' for a paint device. Used e.g. in for brushes and marching ants **/ class KRITAIMAGE_EXPORT KisOutlineGenerator { public: /** * Create an outline generator * @param cs colorspace for the buffer passed to the generator * @param defaultOpacity opacity of pixels that shouldn't be included in the outline **/ KisOutlineGenerator(const KoColorSpace* cs, quint8 defaultOpacity); /** * Generates the outline. * @param buffer buffer with the data for the outline * @param xOffset offset that will be used for the x coordinate of the polygon points * @param yOffset offset that will be used for the y coordinate of the polygon points * @param width width of the buffer * @param height height of the buffer * @returns list of polygons around every non-transparent area **/ QVector outline(quint8* buffer, qint32 xOffset, qint32 yOffset, qint32 width, qint32 height); QVector outline(const KisPaintDevice *buffer, qint32 xOffset, qint32 yOffset, qint32 width, qint32 height); /** * Set the generator to produce simpile outline, skipping outline that are fully enclosed * @param simple set simple mode, if true enclosed outline will be skipped **/ void setSimpleOutline(bool simple); private: private: enum EdgeType { TopEdge = 1, LeftEdge = 2, BottomEdge = 3, RightEdge = 0, NoEdge = 4 }; template QVector outlineImpl(typename StorageStrategy::StorageType buffer, qint32 xOffset, qint32 yOffset, qint32 width, qint32 height); template bool isOutlineEdge(StorageStrategy &storage, EdgeType edge, qint32 x, qint32 y, qint32 bufWidth, qint32 bufHeight); template void nextOutlineEdge(StorageStrategy &storage, EdgeType *edge, qint32 *row, qint32 *col, qint32 width, qint32 height); EdgeType nextEdge(EdgeType edge) { return edge == NoEdge ? edge : static_cast((edge + 1) % 4); } void appendCoordinate(QPolygon * path, int x, int y, EdgeType edge); private: const KoColorSpace* m_cs; quint8 m_defaultOpacity; bool m_simple; KisRandomConstAccessorSP m_accessor; }; #endif // KIS_OUTLINE_GENERATOR_H diff --git a/krita/image/kis_paint_device.h b/krita/image/kis_paint_device.h index 3f94e967005..ef93cb0bfc6 100644 --- a/krita/image/kis_paint_device.h +++ b/krita/image/kis_paint_device.h @@ -1,774 +1,774 @@ /* * Copyright (c) 2002 patrick julien * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PAINT_DEVICE_IMPL_H_ #define KIS_PAINT_DEVICE_IMPL_H_ #include #include #include #include "kis_debug.h" #include #include "kis_types.h" #include "kis_global.h" #include "kis_shared.h" #include "kis_default_bounds_base.h" -#include +#include class KUndo2Command; class QRect; class QImage; class QPoint; class QString; class QColor; class QIODevice; class KoColor; class KoColorSpace; class KoColorProfile; class KisDataManager; class KisPaintDeviceWriter; typedef KisSharedPtr KisDataManagerSP; /** * A paint device contains the actual pixel data and offers methods * to read and write pixels. A paint device has an integer x,y position * (i.e., are not positioned on the image with sub-pixel accuracy). * A KisPaintDevice doesn't have any fixed size, the size changes dynamically * when pixels are accessed by an iterator. */ class KRITAIMAGE_EXPORT KisPaintDevice : public QObject , public KisShared { Q_OBJECT public: /** * Create a new paint device with the specified colorspace. * * @param colorSpace the colorspace of this paint device * @param name for debugging purposes */ KisPaintDevice(const KoColorSpace * colorSpace, const QString& name = QString()); /** * Create a new paint device with the specified colorspace. The * parent node will be notified of changes to this paint device. * * @param parent the node that contains this paint device * @param colorSpace the colorspace of this paint device * @param defaultBounds boundaries of the device in case it is empty * @param name for debugging purposes */ KisPaintDevice(KisNodeWSP parent, const KoColorSpace * colorSpace, KisDefaultBoundsBaseSP defaultBounds = 0, const QString& name = QString()); KisPaintDevice(const KisPaintDevice& rhs); virtual ~KisPaintDevice(); protected: /** * A special constructor for usage in KisPixelSelection. It allows * two paint devices to share a data manager. * * @param explicitDataManager data manager to use inside paint device * @param src source paint device to copy parameters from * @param name for debugging purposes */ KisPaintDevice(KisDataManagerSP explicitDataManager, KisPaintDeviceSP src, const QString& name = QString()); public: /** * Write the pixels of this paint device into the specified file store. */ bool write(KisPaintDeviceWriter &store); /** * Fill this paint device with the pixels from the specified file store. */ bool read(QIODevice *stream); public: /** * set the parent node of the paint device */ void setParentNode(KisNodeWSP parent); /** * set the default bounds for the paint device when * the default pixel in not completely transarent */ void setDefaultBounds(KisDefaultBoundsBaseSP bounds); /** * the default bounds rect of the paint device */ KisDefaultBoundsBaseSP defaultBounds() const; /** * Moves the device to these new coordinates (so no incremental move or so) */ void move(qint32 x, qint32 y); /** * Convenience method for the above. */ virtual void move(const QPoint& pt); /** * The X offset of the paint device */ qint32 x() const; /** * The Y offset of the paint device */ qint32 y() const; /** * set the X offset of the paint device */ void setX(qint32 x); /** * set the Y offset of the paint device */ void setY(qint32 y); /** * Retrieve the bounds of the paint device. The size is not exact, * but may be larger if the underlying datamanager works that way. * For instance, the tiled datamanager keeps the extent to the nearest * multiple of 64. * * If default pixel is not transparent, then the actual extent * rect is united with the defaultBounds()->bounds() value * (the size of the image, usually). */ QRect extent() const; /// Convience method for the above void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const; /** * Get the exact bounds of this paint device. The real solution is * very slow because it does a linear scanline search, but it * uses caching, so calling to this function without changing * the device is quite cheap. * * Exactbounds follows these rules: * *
    *
  • if default pixel is transparent, then exact bounds * of actual pixel data are returned *
  • if default pixel is not transparent, then the union * (defaultBounds()->bounds() | nonDefaultPixelArea()) is * returned *
* \see calculateExactBounds() */ QRect exactBounds() const; /** * Retuns exact rectangle of the paint device that contains * non-default pixels. For paint devices with fully transparent * default pixel is equivalent to exactBounds(). * * nonDefaultPixelArea() follows these rules: * *
    *
  • if default pixel is transparent, then exact bounds * of actual pixel data are returned. The same as exactBounds() *
  • if default pixel is not transparent, then calculates the * rectangle of non-default pixels. May be smaller or greater * than image bounds *
* \see calculateExactBounds() */ QRect nonDefaultPixelArea() const; /** * Returns a rough approximation of region covered by device. * For tiled data manager, it region will consist of a number * of rects each corresponding to a tile. */ QRegion region() const; /** * Cut the paint device down to the specified rect. If the crop * area is bigger than the paint device, nothing will happen. */ void crop(qint32 x, qint32 y, qint32 w, qint32 h); /// Convience method for the above void crop(const QRect & r); /** * Complete erase the current paint device. Its size will become 0. This * does not take the selection into account. */ virtual void clear(); /** * Clear the given rectangle to transparent black. The paint device will expand to * contain the given rect. */ void clear(const QRect & rc); /** * Frees the memory occupied by the pixels containing default * values. The extents() and exactBounds() of the image will * probably also shrink */ void purgeDefaultPixels(); /** * Sets the default pixel. New data will be initialised with this pixel. The pixel is copied: the * caller still owns the pointer and needs to delete it to avoid memory leaks. */ void setDefaultPixel(const quint8 *defPixel); /** * Get a pointer to the default pixel. */ const quint8 *defaultPixel() const; /** * Fill the given rectangle with the given pixel. The paint device will expand to * contain the given rect. */ void fill(const QRect & rc, const KoColor &color); /** * Overloaded function. For legacy purposes only. * Please use fill(const QRect & rc, const KoColor &color) instead */ void fill(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *fillPixel); public: /** * Prepares the device for fastBitBlt opreration. It clears * the device, switches x,y shifts and colorspace if needed. * After this call fastBitBltPossible will return true. * May be used for initialization of temporary devices. */ void prepareClone(KisPaintDeviceSP src); /** * Make this device to become a clone of \a src. It will have the same * x,y shifts, colorspace and will share pixels inside \a rect. * After calling this function: * (this->extent() >= this->exactBounds() == rect). */ void makeCloneFrom(KisPaintDeviceSP src, const QRect &rect); /** * Make this device to become a clone of \a src. It will have the same * x,y shifts, colorspace and will share pixels inside \a rect. * Be careful, this function will copy *at least* \a rect * of pixels. Actual copy area will be a bigger - it will * be aligned by tiles borders. So after calling this function: * (this->extent() == this->exactBounds() >= rect). */ void makeCloneFromRough(KisPaintDeviceSP src, const QRect &minimalRect); protected: friend class KisPaintDeviceTest; friend class DataReaderThread; /** * Checks whether a src paint device can be used as source * of fast bitBlt operation. The result of the check may * depend on whether color spaces coinside, whether there is * any shift of tiles between the devices and etc. * * WARNING: This check must be done before performing any * fast bitBlt operation! * * \see fastBitBlt * \see fastBitBltRough */ bool fastBitBltPossible(KisPaintDeviceSP src); /** * Clones rect from another paint device. The cloned area will be * shared between both paint devices as much as possible using * copy-on-write. Parts of the rect that cannot be shared * (cross tiles) are deep-copied, * * \see fastBitBltPossible * \see fastBitBltRough */ void fastBitBlt(KisPaintDeviceSP src, const QRect &rect); /** * The same as \ref fastBitBlt() but reads old data */ void fastBitBltOldData(KisPaintDeviceSP src, const QRect &rect); /** * Clones rect from another paint device in a rough and fast way. * All the tiles touched by rect will be shared, between both * devices, that means it will copy a bigger area than was * requested. This method is supposed to be used for bitBlt'ing * into temporary paint devices. * * \see fastBitBltPossible * \see fastBitBlt */ void fastBitBltRough(KisPaintDeviceSP src, const QRect &rect); /** * The same as \ref fastBitBltRough() but reads old data */ void fastBitBltRoughOldData(KisPaintDeviceSP src, const QRect &rect); public: /** * Read the bytes representing the rectangle described by x, y, w, h into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * Reading from areas not previously initialized will read the default * pixel value into data but not initialize that region. */ void readBytes(quint8 * data, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Read the bytes representing the rectangle rect into * data. If data is not big enough, Krita will gladly overwrite the rest * of your precious memory. * * Since this is a copy, you need to make sure you have enough memory. * * Reading from areas not previously initialized will read the default * pixel value into data but not initialize that region. * @param data The address of the memory to receive the bytes read * @param rect The rectangle in the paint device to read from */ void readBytes(quint8 * data, const QRect &rect) const; /** * Copy the bytes in data into the rect specified by x, y, w, h. If the * data is too small or uninitialized, Krita will happily read parts of * memory you never wanted to be read. * * If the data is written to areas of the paint device not previously initialized, * the paint device will grow. */ void writeBytes(const quint8 * data, qint32 x, qint32 y, qint32 w, qint32 h); /** * Copy the bytes in data into the rectangle rect. If the * data is too small or uninitialized, Krita will happily read parts of * memory you never wanted to be read. * * If the data is written to areas of the paint device not previously initialized, * the paint device will grow. * @param data The address of the memory to write bytes from * @param rect The rectangle in the paint device to write to */ void writeBytes(const quint8 * data, const QRect &rect); /** * Copy the bytes in the paint device into a vector of arrays of bytes, * where the number of arrays is the number of channels in the * paint device. If the specified area is larger than the paint * device's extent, the default pixel will be read. */ QVector readPlanarBytes(qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Write the data in the separate arrays to the channes. If there * are less vectors than channels, the remaining channels will not * be copied. If any of the arrays points to 0, the channel in * that location will not be touched. If the specified area is * larger than the paint device, the paint device will be * extended. There are no guards: if the area covers more pixels * than there are bytes in the arrays, krita will happily fill * your paint device with areas of memory you never wanted to be * read. Krita may also crash. * * XXX: what about undo? */ void writePlanarBytes(QVector planes, qint32 x, qint32 y, qint32 w, qint32 h); /** * Converts the paint device to a different colorspace * * @return a command that can be used to undo the conversion. */ KUndo2Command* convertTo(const KoColorSpace * dstColorSpace, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags); /** * Changes the profile of the colorspace of this paint device to the given * profile. If the given profile is 0, nothing happens. */ void setProfile(const KoColorProfile * profile); /** * Fill this paint device with the data from image; starting at (offsetX, offsetY) * @param srcProfileName name of the RGB profile to interpret the image as. 0 is interpreted as sRGB */ void convertFromQImage(const QImage& image, const KoColorProfile *profile, qint32 offsetX = 0, qint32 offsetY = 0); /** * Create an RGBA QImage from a rectangle in the paint device. * * @param x Left coordinate of the rectangle * @param y Top coordinate of the rectangle * @param w Width of the rectangle in pixels * @param h Height of the rectangle in pixels * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). */ virtual QImage convertToQImage(const KoColorProfile *dstProfile, qint32 x, qint32 y, qint32 w, qint32 h, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; /** * Overridden method for convenience */ QImage convertToQImage(const KoColorProfile *dstProfile, const QRect &rc, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; /** * Create an RGBA QImage from a rectangle in the paint device. The * rectangle is defined by the parent image's bounds. * * @param dstProfile RGB profile to use in conversion. May be 0, in which * case it's up to the color strategy to choose a profile (most * like sRGB). */ QImage convertToQImage(const KoColorProfile * dstProfile, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags) const; /** * Creates a paint device thumbnail of the paint device, retaining * the aspect ratio. The width and height of the returned device * won't exceed \p maxw and \p maxw, but they may be smaller. * * @param maxw: maximum width * @param maxh: maximum height * @param rect: only this rect will be used for the thumbnail * */ KisPaintDeviceSP createThumbnailDevice(qint32 w, qint32 h, QRect rect = QRect()) const; /** * Creates a thumbnail of the paint device, retaining the aspect ratio. * The width and height of the returned QImage won't exceed \p maxw and \p maxw, but they may be smaller. * The colors are not corrected for display! * * @param maxw: maximum width * @param maxh: maximum height * @param rect: only this rect will be used for the thumbnail */ QImage createThumbnail(qint32 maxw, qint32 maxh, QRect rect, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags); /** * Cached version of createThumbnail(qint32 maxw, qint32 maxh, const KisSelection *selection, QRect rect) */ QImage createThumbnail(qint32 maxw, qint32 maxh, KoColorConversionTransformation::Intent renderingIntent = KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags = KoColorConversionTransformation::InternalConversionFlags); /** * Fill c and opacity with the values found at x and y. * * The color values will be transformed from the profile of * this paint device to the display profile. * * @return true if the operation was successful. */ bool pixel(qint32 x, qint32 y, QColor *c) const; /** * Fill kc with the values found at x and y. This method differs * from the above in using KoColor, which can be of any colorspace * * The color values will be transformed from the profile of * this paint device to the display profile. * * @return true if the operation was successful. */ bool pixel(qint32 x, qint32 y, KoColor * kc) const; /** * Set the specified pixel to the specified color. Note that this * bypasses KisPainter. the PaintDevice is here used as an equivalent * to QImage, not QPixmap. This means that this is not undoable; also, * there is no compositing with an existing value at this location. * * The color values will be transformed from the display profile to * the paint device profile. * * Note that this will use 8-bit values and may cause a significant * degradation when used on 16-bit or hdr quality images. * * @return true if the operation was successful */ bool setPixel(qint32 x, qint32 y, const QColor& c); /// Convience method for the above bool setPixel(qint32 x, qint32 y, const KoColor& kc); /** * @return the colorspace of the pixels in this paint device */ const KoColorSpace* colorSpace() const; /** * There is quite a common technique in Krita. It is used in * cases, when we want to paint something over a paint device * using the composition, opacity or selection. E.g. painting a * dab in a paint op, filling the selection in the Fill Tool. * Such work is usually done in the following way: * * 1) Create a paint device * * 2) Fill it with the desired color or data * * 3) Create a KisPainter and set all the properties of the * trasaction: selection, compositeOp, opacity and etc. * * 4) Paint a newly created paint device over the destination * device. * * The following two methods (createCompositionSourceDevice() or * createCompositionSourceDeviceFixed())should be used for the * accomplishing the step 1). The point is that the desired color * space of the temporary device may not coincide with the color * space of the destination. That is the case, for example, for * the alpha8() colorspace used in the selections. So for such * devices the temporary target would have a different (grayscale) * color space. * * So there are two rules of thumb: * * 1) If you need a temporary device which you are going to fill * with some data and then paint over the paint device, create * it with either createCompositionSourceDevice() or * createCompositionSourceDeviceFixed(). * * 2) Do *not* expect that the color spaces of the destination and * the temporary device would coincide. If you need to copy a * single pixel from one device to another, you can use * KisCrossDeviceColorPicker class, that will handle all the * necessary conversions for you. * * \see createCompositionSourceDeviceFixed() * \see compositionSourceColorSpace() * \see KisCrossDeviceColorPicker * \see KisCrossDeviceColorPickerInt */ KisPaintDeviceSP createCompositionSourceDevice() const; /** * The same as createCompositionSourceDevice(), but initializes the * newly created device with the content of \p cloneSource * * \see createCompositionSourceDevice() */ KisPaintDeviceSP createCompositionSourceDevice(KisPaintDeviceSP cloneSource) const; /** * The same as createCompositionSourceDevice(), but initializes * the newly created device with the *rough* \p roughRect of * \p cloneSource. * * "Rough rect" means that it may copy a bit more than * requested. It is expected that the caller will not use the area * outside \p roughRect. * * \see createCompositionSourceDevice() */ KisPaintDeviceSP createCompositionSourceDevice(KisPaintDeviceSP cloneSource, const QRect roughRect) const; /** * This is a convenience method for createCompositionSourceDevice() * * \see createCompositionSourceDevice() */ KisFixedPaintDeviceSP createCompositionSourceDeviceFixed() const; /** * This is a lowlevel method for the principle used in * createCompositionSourceDevice(). In most of the cases the paint * device creation methods should be used instead of this function. * * \see createCompositionSourceDevice() * \see createCompositionSourceDeviceFixed() */ virtual const KoColorSpace* compositionSourceColorSpace() const; /** * @return the internal datamanager that keeps the pixels. */ KisDataManagerSP dataManager() const; /** * Replace the pixel data, color strategy, and profile. */ void setDataManager(KisDataManagerSP data, const KoColorSpace * colorSpace = 0); /** * Return the number of bytes a pixel takes. */ quint32 pixelSize() const; /** * Return the number of channels a pixel takes */ quint32 channelCount() const; public: /** * Add the specified rect to the parent layer's set of dirty rects * (if there is a parent layer) */ void setDirty(const QRect & rc); /** * Add the specified region to the parent layer's dirty region * (if there is a parent layer) */ void setDirty(const QRegion & region); /** * Set the parent layer completely dirty, if this paint device has * as parent layer. */ void setDirty(); void setDirty(const QVector rects); public: KisHLineIteratorSP createHLineIteratorNG(qint32 x, qint32 y, qint32 w); KisHLineConstIteratorSP createHLineConstIteratorNG(qint32 x, qint32 y, qint32 w) const; KisVLineIteratorSP createVLineIteratorNG(qint32 x, qint32 y, qint32 h); KisVLineConstIteratorSP createVLineConstIteratorNG(qint32 x, qint32 y, qint32 h) const; KisRandomAccessorSP createRandomAccessorNG(qint32 x, qint32 y); KisRandomConstAccessorSP createRandomConstAccessorNG(qint32 x, qint32 y) const; /** * Create an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. * * @param rc indicates the rectangle that truly contains data */ KisRepeatHLineConstIteratorSP createRepeatHLineConstIterator(qint32 x, qint32 y, qint32 w, const QRect& _dataWidth) const; /** * Create an iterator that will "artificially" extend the paint device with the * value of the border when trying to access values outside the range of data. * * @param rc indicates the rectangle that trully contains data */ KisRepeatVLineConstIteratorSP createRepeatVLineConstIterator(qint32 x, qint32 y, qint32 h, const QRect& _dataWidth) const; /** * This function create a random accessor which can easily access to sub pixel values. * @param selection an up-to-date selection that has the same origin as the paint device */ KisRandomSubAccessorSP createRandomSubAccessor() const; /** Clear the selected pixels from the paint device */ void clearSelection(KisSelectionSP selection); Q_SIGNALS: void profileChanged(const KoColorProfile * profile); void colorSpaceChanged(const KoColorSpace *colorspace); public: friend class PaintDeviceCache; /** * Caclculates exact bounds of the device. Used internally * by a transparent caching system. The solution is very slow * because it does a linear scanline search. So the complexity * is n*n at worst. * * \see exactBounds(), nonDefaultPixelArea() */ QRect calculateExactBounds(bool nonDefaultOnly) const; public: struct MemoryReleaseObject : public QObject { ~MemoryReleaseObject(); }; static MemoryReleaseObject* createMemoryReleaseObject(); private: KisPaintDevice& operator=(const KisPaintDevice&); void init(KisDataManagerSP explicitDataManager, const KoColorSpace *colorSpace, KisDefaultBoundsBaseSP defaultBounds, KisNodeWSP parent, const QString& name); // Only KisPainter is allowed to have access to these low-level methods friend class KisPainter; /** * Return a vector with in order the size in bytes of the channels * in the colorspace of this paint device. */ QVector channelSizes() const; protected: friend class KisSelectionTest; KisNodeWSP parentNode() const; private: struct Private; Private * const m_d; }; #endif // KIS_PAINT_DEVICE_IMPL_H_ diff --git a/krita/image/kis_paint_device_writer.h b/krita/image/kis_paint_device_writer.h index 4b64e0c8cc7..f3db00002de 100644 --- a/krita/image/kis_paint_device_writer.h +++ b/krita/image/kis_paint_device_writer.h @@ -1,31 +1,31 @@ /* * Copyright (c) 2013 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_PAINT_DEVICE_WRITER_H #define KIS_PAINT_DEVICE_WRITER_H -#include +#include class KRITAIMAGE_EXPORT KisPaintDeviceWriter { public: virtual ~KisPaintDeviceWriter() {} virtual bool write(const QByteArray &data) = 0; virtual bool write(const char* data, qint64 length) = 0; }; #endif // KIS_PAINT_DEVICE_WRITER_H diff --git a/krita/image/kis_painter.h b/krita/image/kis_painter.h index 6013a786085..a660fe08dea 100644 --- a/krita/image/kis_painter.h +++ b/krita/image/kis_painter.h @@ -1,805 +1,805 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Clarence Dang * Copyright (c) 2008-2010 Lukáš Tvrdý * Copyright (c) 2010 José Luis Vergara Toloza * * 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_PAINTER_H_ #define KIS_PAINTER_H_ #include #include #include #include #include "kundo2magicstring.h" #include "kis_distance_information.h" #include "kis_global.h" #include "kis_types.h" -#include +#include class QPen; class KUndo2Command; class QRect; class QRectF; class QBitArray; class QPainterPath; class KoAbstractGradient; class KoUpdater; class KoColor; class KoCompositeOp; class KisUndoAdapter; class KisPostExecutionUndoAdapter; class KisTransaction; class KoPattern; class KisFilterConfiguration; class KisPaintInformation; class KisPaintOp; /** * KisPainter contains the graphics primitives necessary to draw on a * KisPaintDevice. This is the same kind of abstraction as used in Qt * itself, where you have QPainter and QPaintDevice. * * However, KisPainter works on a tiled image and supports different * color models, and that's a lot more complicated. * * KisPainter supports transactions that can group various paint operations * in one undoable step. * * For more complex operations, you might want to have a look at the subclasses * of KisPainter: KisConvolutionPainter, KisFillPainter and KisGradientPainter * * KisPainter sets a number of default values, like COMPOSITE_OVER for compositeop, * OPACITY_OPAQUE for opacity and no selection for selection. */ class KRITAIMAGE_EXPORT KisPainter { public: /// Construct painter without a device KisPainter(); /// Construct a painter, and begin painting on the device KisPainter(KisPaintDeviceSP device); /// Construct a painter, and begin painting on the device. All actions will be masked by the given selection. KisPainter(KisPaintDeviceSP device, KisSelectionSP selection); virtual ~KisPainter(); public: static void copyAreaOptimized(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect); static void copyAreaOptimizedOldData(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect); static void copyAreaOptimized(const QPoint &dstPt, KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &originalSrcRect, KisSelectionSP selection); /** * Start painting on the specified device. Not undoable. */ void begin(KisPaintDeviceSP device); /** * Start painting on the specified paint device. All actions will be masked by the given selection. */ void begin(KisPaintDeviceSP device, KisSelectionSP selection); /** * Finish painting on the current device */ void end(); /** * If set, the painter action is cancelable, if the action supports that. */ void setProgress(KoUpdater * progressUpdater); /// Begin an undoable paint operation void beginTransaction(const KUndo2MagicString& transactionName = KUndo2MagicString(),int timedID = -1); /// Cancel all the changes made by the painter void revertTransaction(); /// Finish the undoable paint operation void endTransaction(KisUndoAdapter *undoAdapter); /** * Finish transaction and load it to a special adapter for strokes */ void endTransaction(KisPostExecutionUndoAdapter *undoAdapter); /** * Finishes a transaction and returns a pointer to its undo command */ KUndo2Command* endAndTakeTransaction(); /** * Finish the transaction and delete it's undo information. * NOTE: Be careful, because all the previous transactions * will become non-undoable after execution of this method. */ void deleteTransaction(); /// continue a transaction started somewhere else void putTransaction(KisTransaction* transaction); /// take transaction out of the reach of KisPainter KisTransaction* takeTransaction(); /// Returns the current paint device. const KisPaintDeviceSP device() const; KisPaintDeviceSP device(); /** * Blast a region of srcWidth @param srcWidth and srcHeight @param srcHeight from @param * srcDev onto the current paint device. @param srcX and @param srcY set the x and y * positions of the origin top-left corner, @param dstX and @param dstY those of * the destination. * Any pixel read outside the limits of @param srcDev will return the * default pixel, this is a property of \ref KisPaintDevice. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param srcX the source x-coordinate * @param srcY the source y-coordinate * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bitBlt(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight); /** * Convenience method that uses QPoint and QRect. * * @param pos the destination coordinate, it replaces @param dstX and @param dstY. * @param srcDev the source device. * @param srcRect the rectangle describing the area to blast from @param srcDev into the current paint device. * @param srcRect replaces @param srcX, @param srcY, @param srcWidth and @param srcHeight. * */ void bitBlt(const QPoint & pos, const KisPaintDeviceSP srcDev, const QRect & srcRect); /** * The same as @ref bitBlt() but reads data from oldData() part of the device * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param srcX the source x-coordinate * @param srcY the source y-coordinate * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bitBltOldData(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight); /** * Convenience method that uses QPoint and QRect. * * @param pos the destination coordinate, it replaces @param dstX and @param dstY. * @param srcDev the source device. * @param srcRect the rectangle describing the area to blast from @param srcDev into the current paint device. * @param srcRect replaces @param srcX, @param srcY, @param srcWidth and @param srcHeight. * */ void bitBltOldData(const QPoint & pos, const KisPaintDeviceSP srcDev, const QRect & srcRect); /** * Blasts a @param selection of srcWidth @param srcWidth and srcHeight @param srcHeight * of @param srcDev on the current paint device. There is parameters * to control where the area begins in each distinct device, explained below. * @param selection can be used as a mask to shape @param srcDev to * something interesting in the same step it is rendered to the current * paint device. @param selection 's colorspace must be alpha8 (the * colorspace for selections/transparency), the rectangle formed by * @param selX, @param selY, @param srcWidth and @param srcHeight must not go * beyond its limits, and they must be different from zero. * @param selection and KisPainter's selection (the user selection) are * fused together through the composite operation COMPOSITE_MULT. * Any pixel read outside the limits of @param srcDev will return the * default pixel, this is a property of \ref KisPaintDevice. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param selection the custom selection to apply on the source device * @param selX the selection x-coordinate * @param selY the selection y-coordinate * @param srcX the source x-coordinate * @param srcY the source y-coordinate * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated * */ void bitBltWithFixedSelection(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, const KisFixedPaintDeviceSP selection, qint32 selX, qint32 selY, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight); /** * Convenience method that assumes @param selX, @param selY, @param srcX and @param srcY are * equal to 0. Best used when @param selection and the desired area of @param srcDev have exactly * the same dimensions and are specially made for each other. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param selection the custom selection to apply on the source device * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bitBltWithFixedSelection(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, const KisFixedPaintDeviceSP selection, qint32 srcWidth, qint32 srcHeight); /** * Blast a region of srcWidth @param srcWidth and srcHeight @param srcHeight from @param srcDev onto the current * paint device. @param srcX and @param srcY set the x and y positions of the * origin top-left corner, @param dstX and @param dstY those of the destination. * @param srcDev is a \ref KisFixedPaintDevice: this means that @param srcDev must have the same * colorspace as the destination device. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param srcX the source x-coordinate * @param srcY the source y-coordinate * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bltFixed(qint32 dstX, qint32 dstY, const KisFixedPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight); /** * Convenience method that uses QPoint and QRect. * * @param pos the destination coordinate, it replaces @param dstX and @param dstY. * @param srcDev the source device. * @param srcRect the rectangle describing the area to blast from @param srcDev into the current paint device. * @param srcRect replaces @param srcX, @param srcY, @param srcWidth and @param srcHeight. * */ void bltFixed(const QPoint & pos, const KisFixedPaintDeviceSP srcDev, const QRect & srcRect); /** * Blasts a @param selection of srcWidth @param srcWidth and srcHeight @param srcHeight * of @param srcDev on the current paint device. There is parameters to control * the top-left corner of the area in each respective paint device (@param dstX, * @param dstY, @param srcX, @param srcY). * @param selection can be used as a mask to shape @param srcDev to something * interesting in the same step it is rendered to the current paint device. * @param srcDev is a \ref KisFixedPaintDevice: this means that @param srcDev * must have the same colorspace as the destination device. * @param selection 's colorspace must be alpha8 (the colorspace for * selections/transparency). * The rectangle formed by the respective top-left coordinates of each device * and @param srcWidth and @param srcHeight must not go beyond their limits, and * they must be different from zero. * @param selection and KisPainter's selection (the user selection) are * fused together through the composite operation COMPOSITE_MULT. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param selection the selection stored in fixed device * @param selX the selection x-coordinate * @param selY the selection y-coordinate * @param srcX the source x-coordinate * @param srcY the source y-coordinate * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bltFixedWithFixedSelection(qint32 dstX, qint32 dstY, const KisFixedPaintDeviceSP srcDev, const KisFixedPaintDeviceSP selection, qint32 selX, qint32 selY, qint32 srcX, qint32 srcY, quint32 srcWidth, quint32 srcHeight); /** * Convenience method that assumes @param selX, @param selY, @param srcX and @param srcY are * equal to 0. Best used when @param selection and @param srcDev have exactly the same * dimensions and are specially made for each other. * * @param dstX the destination x-coordinate * @param dstY the destination y-coordinate * @param srcDev the source device * @param selection the custom selection to apply on the source device * @param srcWidth the width of the region to be manipulated * @param srcHeight the height of the region to be manipulated */ void bltFixedWithFixedSelection(qint32 dstX, qint32 dstY, const KisFixedPaintDeviceSP srcDev, const KisFixedPaintDeviceSP selection, quint32 srcWidth, quint32 srcHeight); /** * fills a region of width @param width and height @param height of the current * paint device with the color @param color. @param x and @param y set the x and y positions of the * origin top-left corner. * * @param x the destination x-coordinate * @param y the destination y-coordinate * @param width the width of the region to be manipulated * @param height the height of the region to be manipulated * @param color the color the area is filled with */ void fill(qint32 x, qint32 y, qint32 width, qint32 height, const KoColor& color); /** * First you need to setup the painter with setMirrorInformation, * then these set of methods provide way to render the devices mirrored * according the axesCenter vertically or horizontally or both. * * @param rc rectangle area covered by dab * @param dab this device will be mirrored in-place, it means that it will be changed */ void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab); void renderMirrorMask(QRect rc, KisFixedPaintDeviceSP dab, KisFixedPaintDeviceSP mask); void renderMirrorMask(QRect rc, KisPaintDeviceSP dab); void renderMirrorMask(QRect rc, KisPaintDeviceSP dab, int sx, int sy, KisFixedPaintDeviceSP mask); /** * Convenience method for renderMirrorMask(), allows to choose whether * we need to preserve out dab or do the transformations in-place. * * @param rc rectangle area covered by dab * @param dab the device to render * @param preserveDab states whether a temporary device should be * created to do the transformations */ void renderMirrorMaskSafe(QRect rc, KisFixedPaintDeviceSP dab, bool preserveDab); /** * Convenience method for renderMirrorMask(), allows to choose whether * we need to preserve our fixed mask or do the transformations in-place. * * @param rc rectangle area covered by dab * @param dab the device to render * @param mask mask to use for rendering * @param preserveMask states whether a temporary device should be * created to do the transformations */ void renderMirrorMaskSafe(QRect rc, KisPaintDeviceSP dab, int sx, int sy, KisFixedPaintDeviceSP mask, bool preserveMask); /** * A complex method that re-renders a dab on an \p rc area. * The \p rc area and all the dedicated mirroring areas are cleared * before the painting, so this method should be used by paintops * which do not update the canvas incrementally, but instead * regenerate some internal cache \p dab with the COMPOSITE_COPY op. * * \see KisExperimentPaintOp */ void renderDabWithMirroringNonIncremental(QRect rc, KisPaintDeviceSP dab); /** * The methods in this class do not tell the paintdevice to update, but they calculate the * dirty area. This method returns this dirty area and resets it. */ QVector takeDirtyRegion(); /** * Paint a line that connects the dots in points */ void paintPolyline(const QVector &points, int index = 0, int numPoints = -1); /** * Draw a line between pos1 and pos2 using the currently set brush and color. * If savedDist is less than zero, the brush is painted at pos1 before being * painted along the line using the spacing setting. * @return the drag distance, that is the remains of the distance between p1 and p2 not covered * because the currenlty set brush has a spacing greater than that distance. */ void paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2, KisDistanceInformation *curentDistance); /** * Draw a Bezier curve between pos1 and pos2 using control points 1 and 2. * If savedDist is less than zero, the brush is painted at pos1 before being * painted along the curve using the spacing setting. * @return the drag distance, that is the remains of the distance between p1 and p2 not covered * because the currenlty set brush has a spacing greater than that distance. */ void paintBezierCurve(const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2, KisDistanceInformation *currentDistance); /** * Fill the given vector points with the points needed to draw the Bezier curve between * pos1 and pos2 using control points 1 and 2, excluding the final pos2. */ void getBezierCurvePoints(const QPointF &pos1, const QPointF &control1, const QPointF &control2, const QPointF &pos2, vQPointF& points) const; /** * Paint a rectangle. * @param rect the rectangle to paint. */ void paintRect(const QRectF &rect); /** * Paint a rectangle. * * @param x x coordinate of the top-left corner * @param y y coordinate of the top-left corner * @param w the rectangle width * @param h the rectangle height */ void paintRect(const qreal x, const qreal y, const qreal w, const qreal h); /** * Paint the ellipse that fills the given rectangle. * * @param rect the rectangle containing the ellipse to paint. */ void paintEllipse(const QRectF &rect); /** * Paint the ellipse that fills the given rectangle. * * @param x x coordinate of the top-left corner * @param y y coordinate of the top-left corner * @param w the rectangle width * @param h the rectangle height */ void paintEllipse(const qreal x, const qreal y, const qreal w, const qreal h); /** * Paint the polygon with the points given in points. It automatically closes the polygon * by drawing the line from the last point to the first. */ void paintPolygon(const vQPointF& points); /** Draw a spot at pos using the currently set paint op, brush and color */ void paintAt(const KisPaintInformation &pos, KisDistanceInformation *savedDist); /** * Stroke the given QPainterPath. */ void paintPainterPath(const QPainterPath& path); /** * Fills the area enclosed by the given QPainterPath * Convenience method for fillPainterPath(path, rect) */ void fillPainterPath(const QPainterPath& path); /** * Fills the portion of an area enclosed by the given QPainterPath * * \param rect the portion of the path to fill */ void fillPainterPath(const QPainterPath& path, const QRect &requestedRect); /** * Draw the path using the Pen * * if \p requestedRect is null, the entire path is painted */ void drawPainterPath(const QPainterPath& path, const QPen& pen, const QRect &requestedRect); // convenience overload void drawPainterPath(const QPainterPath& path, const QPen& pen); /** * paint an unstroked one-pixel wide line from specified start position to the * specified end position. * */ void drawLine(const QPointF & start, const QPointF & end); /** * paint an unstroked line with thickness from specified start position to the * specified end position. Scanline algorithm is used. */ void drawLine(const QPointF &start, const QPointF &end, qreal width, bool antialias); /** * paints an unstroked, aliased one-pixel line using the DDA algorithm from specified start position to the * specified end position. * */ void drawDDALine(const QPointF & start, const QPointF & end); /** * Paint an unstroked, wobbly one-pixel wide line from the specified start to the specified * end position. * */ void drawWobblyLine(const QPointF & start, const QPointF & end); /** * Paint an unstroked, anti-aliased one-pixel wide line from the specified start to the specified * end position using the Wu algorithm */ void drawWuLine(const QPointF & start, const QPointF & end); /** * Paint an unstroked wide line from the specified start to the specified * end position with width varying from @param w1 at the start to @param w2 at * the end. * * XXX: the width should be set in doubles, not integers. */ void drawThickLine(const QPointF & start, const QPointF & end, int startWidth, int endWidth); /** * Set the channelflags: a bit array where true means that the * channel corresponding in position with the bit will be read * by the operation, and false means that it will not be affected. * * An empty channelFlags parameter means that all channels are * affected. * * @param the bit array that masks the source channels; only * the channels where the corresponding bit is true will will be * composited onto the destination device. */ void setChannelFlags(QBitArray channelFlags); /// @return the channel flags QBitArray channelFlags(); /** * Set the paintop preset to use. If @param image is given, * the paintop will be created using this image as parameter. * Some paintops really want to know about the image they work * for, e.g. the clone paintop. */ void setPaintOpPreset(KisPaintOpPresetSP preset, KisNodeSP node, KisImageSP image); /// Return the paintop preset KisPaintOpPresetSP preset() const; /** * Return the active paintop (which is created based on the specified preset and * will be deleted as soon as the KisPainter instance dies). */ KisPaintOp* paintOp() const; void setMirrorInformation(const QPointF &axesCenter, bool mirrorHorizontaly, bool mirrorVerticaly); /** * copy the mirror information to other painter */ void copyMirrorInformation(KisPainter * painter); /** * Returns whether the mirroring methods will do any * work when called */ bool hasMirroring() const; /// Set the current pattern void setPattern(const KoPattern * pattern); /// Returns the currently set pattern const KoPattern * pattern() const; /** * Set the color that will be used to paint with, and convert it * to the color space of the current paint device. */ void setPaintColor(const KoColor& color); /// Returns the color that will be used to paint with const KoColor &paintColor() const; /** * Set the current background color, and convert it * to the color space of the current paint device. */ void setBackgroundColor(const KoColor& color); /// Returns the current background color const KoColor &backgroundColor() const; /// Set the current generator (a generator can be used to fill an area void setGenerator(const KisFilterConfiguration * generator); /// @return the current generator configuration const KisFilterConfiguration * generator() const; /// This enum contains the styles with which we can fill things like polygons and ellipses enum FillStyle { FillStyleNone, FillStyleForegroundColor, FillStyleBackgroundColor, FillStylePattern, FillStyleGradient, FillStyleStrokes, FillStyleGenerator }; /// Set the current style with which to fill void setFillStyle(FillStyle fillStyle); /// Returns the current fill style FillStyle fillStyle() const; /// Set whether a polygon's filled area should be anti-aliased or not. The default is true. void setAntiAliasPolygonFill(bool antiAliasPolygonFill); /// Return whether a polygon's filled area should be anti-aliased or not bool antiAliasPolygonFill(); /// The style of the brush stroke around polygons and so enum StrokeStyle { StrokeStyleNone, StrokeStyleBrush }; /// Set the current brush stroke style void setStrokeStyle(StrokeStyle strokeStyle); /// Returns the current brush stroke style StrokeStyle strokeStyle() const; void setFlow(quint8 flow); quint8 flow() const; /** * Sets the opacity of the painting and recalculates the * mean opacity of the stroke. This mean value is used to * make ALPHA_DARKEN painting look correct */ void setOpacityUpdateAverage(quint8 opacity); /// Set the opacity which is used in painting (like filling polygons) void setOpacity(quint8 opacity); /// Returns the opacity that is used in painting quint8 opacity() const; /// Set the composite op for this painter void setCompositeOp(const KoCompositeOp * op); const KoCompositeOp * compositeOp(); /// Set the composite op for this painter by string. /// Note: the colorspace must be set previously! void setCompositeOp(const QString& op); /** * Add the r to the current dirty rect. */ void addDirtyRect(const QRect & r); /** * Reset the selection to the given selection. All painter actions will be * masked by the specified selection. */ void setSelection(KisSelectionSP selection); /** * @return the selection set on this painter. */ KisSelectionSP selection(); void setGradient(const KoAbstractGradient* gradient); const KoAbstractGradient* gradient() const; /** * Set the size of the tile in fillPainterPath, useful when optimizing the use of fillPainterPath * e.g. Spray paintop uses more small tiles, although selections uses bigger tiles. QImage::fill * is quite expensive so with smaller images you can save instructions * Default and maximum size is 256x256 image */ void setMaskImageSize(qint32 width, qint32 height); // /** // * If the alpha channel is locked, the alpha values of the paint device we are painting on // * will not change. // */ // void setLockAlpha(bool protect); // bool alphaLocked() const; /** * set the rendering intent in case pixels need to be converted before painting */ void setRenderingIntent(KoColorConversionTransformation::Intent intent); /** * set the conversion flags in case pixels need to be converted before painting */ void setColorConversionFlags(KoColorConversionTransformation::ConversionFlags conversionFlags); protected: /// Initialize, set everything to '0' or defaults void init(); /// Fill the polygon defined by points with the fillStyle void fillPolygon(const vQPointF& points, FillStyle fillStyle); private: KisPainter(const KisPainter&); KisPainter& operator=(const KisPainter&); float frac(float value) { float tmp = 0; return modff(value , &tmp); } float invertFrac(float value) { float tmp = 0; return 1.0f - modff(value , &tmp); } protected: KoUpdater * progressUpdater(); private: template void bitBltImpl(qint32 dstX, qint32 dstY, const KisPaintDeviceSP srcDev, qint32 srcX, qint32 srcY, qint32 srcWidth, qint32 srcHeight); inline void compositeOnePixel(quint8 *dst, const KoColor &color); private: struct Private; Private* const d; }; #endif // KIS_PAINTER_H_ diff --git a/krita/image/kis_perspective_grid.h b/krita/image/kis_perspective_grid.h index 4e4d71b7b99..91a18400d8e 100644 --- a/krita/image/kis_perspective_grid.h +++ b/krita/image/kis_perspective_grid.h @@ -1,138 +1,138 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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_H #define KIS_PERSPECTIVE_GRID_H #include #include #include #include #include -#include +#include class KisPerspectiveGridNode; typedef KisSharedPtr KisPerspectiveGridNodeSP; class KisSubPerspectiveGrid; /** * This class is the corner of sub perspective grid, it can be shared between various grid. */ class KRITAIMAGE_EXPORT KisPerspectiveGridNode : public QPointF, public KisShared { friend class KisSubPerspectiveGrid; public: KisPerspectiveGridNode(double x, double y); KisPerspectiveGridNode(QPointF p); KisPerspectiveGridNode(const KisPerspectiveGridNode&); ~KisPerspectiveGridNode(); void mergeWith(KisPerspectiveGridNodeSP); private: void registerSubPerspectiveGrid(KisSubPerspectiveGrid*); void unRegisterSubPerspectiveGrid(KisSubPerspectiveGrid*); bool containsSubPerspectiveGrid(KisSubPerspectiveGrid*); private: struct Private; Private* const d; }; /** * This class contains the information of a sub perspective grid. */ class KRITAIMAGE_EXPORT KisSubPerspectiveGrid { public: KisSubPerspectiveGrid(KisPerspectiveGridNodeSP topLeft, KisPerspectiveGridNodeSP topRight, KisPerspectiveGridNodeSP bottomRight, KisPerspectiveGridNodeSP bottomLeft); ~KisSubPerspectiveGrid(); QPointF topBottomVanishingPoint(); QPointF leftRightVanishingPoint(); /** * @return the top left corner of the grid */ const KisPerspectiveGridNodeSP topLeft() const; KisPerspectiveGridNodeSP topLeft(); void setTopLeft(KisPerspectiveGridNodeSP); const KisPerspectiveGridNodeSP topRight() const; KisPerspectiveGridNodeSP topRight(); void setTopRight(KisPerspectiveGridNodeSP); const KisPerspectiveGridNodeSP bottomLeft() const; KisPerspectiveGridNodeSP bottomLeft(); void setBottomLeft(KisPerspectiveGridNodeSP); const KisPerspectiveGridNodeSP bottomRight() const; KisPerspectiveGridNodeSP bottomRight(); void setBottomRight(KisPerspectiveGridNodeSP); int subdivisions() const; /** * @return the center of the sub perspective grid */ QPointF center() const; /** * Return the index of the subgrid, the value is automatically set when the KisSubPerspectiveGrid, it is useful for * drawing the perspective grid, to avoid drawing twice the same border, or points */ int index() const; /** * @return true if the point p is contain by the grid */ bool contains(const QPointF p) const; private: inline QPointF computeVanishingPoint(KisPerspectiveGridNodeSP p11, KisPerspectiveGridNodeSP p12, KisPerspectiveGridNodeSP p21, KisPerspectiveGridNodeSP p22); private: struct Private; Private* const d; }; /** * This class contains the list of sub perspective grid */ class KRITAIMAGE_EXPORT KisPerspectiveGrid { public: KisPerspectiveGrid(); ~KisPerspectiveGrid(); /** * @return false if the grid wasn't added, note that subgrids must be attached to an other grid, except if it's the first grid */ bool addNewSubGrid(KisSubPerspectiveGrid* ng); QList::const_iterator begin() const; QList::const_iterator end() const; bool hasSubGrids() const; void clearSubGrids(); int countSubGrids() const; /** * Delete the grid given as argument and remove it from the list of grids. */ void deleteSubGrid(KisSubPerspectiveGrid* grid); /** * @return the first grid hit by the point p */ KisSubPerspectiveGrid* gridAt(QPointF p); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_perspective_math.h b/krita/image/kis_perspective_math.h index f4bf96f6588..9ccfe4fd3a1 100644 --- a/krita/image/kis_perspective_math.h +++ b/krita/image/kis_perspective_math.h @@ -1,53 +1,53 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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_MATH_H_ #define _KIS_PERSPECTIVE_MATH_H_ #include "kis_vec.h" #include #include typedef Eigen::Matrix Matrix3qreal; typedef Eigen::Matrix Matrix9qreal; typedef Eigen::Matrix Vector9qreal; typedef Eigen::Hyperplane LineEquation; -#include +#include class QRect; class KRITAIMAGE_EXPORT KisPerspectiveMath { private: KisPerspectiveMath() { } public: static Matrix3qreal computeMatrixTransfo(const QPointF& topLeft1, const QPointF& topRight1, const QPointF& bottomLeft1, const QPointF& bottomRight1, const QPointF& topLeft2, const QPointF& topRight2, const QPointF& bottomLeft2, const QPointF& bottomRight2); static Matrix3qreal computeMatrixTransfoToPerspective(const QPointF& topLeft, const QPointF& topRight, const QPointF& bottomLeft, const QPointF& bottomRight, const QRect& r); static Matrix3qreal computeMatrixTransfoFromPerspective(const QRect& r, const QPointF& topLeft, const QPointF& topRight, const QPointF& bottomLeft, const QPointF& bottomRight); /// TODO: get rid of this in 2.0 static inline QPointF matProd(const Matrix3qreal& m, const QPointF& p) { qreal s = qreal(1) / (p.x() * m.coeff(2, 0) + p.y() * m.coeff(2, 1) + 1.0); return QPointF((p.x() * m.coeff(0, 0) + p.y() * m.coeff(0, 1) + m.coeff(0, 2)) * s, (p.x() * m.coeff(1, 0) + p.y() * m.coeff(1, 1) + m.coeff(1, 2)) * s); } }; #endif diff --git a/krita/image/kis_perspectivetransform_worker.h b/krita/image/kis_perspectivetransform_worker.h index 796fd24c3ae..f148ea61a2d 100644 --- a/krita/image/kis_perspectivetransform_worker.h +++ b/krita/image/kis_perspectivetransform_worker.h @@ -1,69 +1,69 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * Copyright (c) 2010 Marc Pegon * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PERSPECTIVETRANSFORM_WORKER_H #define KIS_PERSPECTIVETRANSFORM_WORKER_H #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include #include #include #include class KRITAIMAGE_EXPORT KisPerspectiveTransformWorker { public: KisPerspectiveTransformWorker(KisPaintDeviceSP dev, QPointF center, double aX, double aY, double distance, KoUpdaterPtr progress); KisPerspectiveTransformWorker(KisPaintDeviceSP dev, const QTransform &transform, KoUpdaterPtr progress); ~KisPerspectiveTransformWorker(); void run(); void runPartialDst(KisPaintDeviceSP srcDev, KisPaintDeviceSP dstDev, const QRect &dstRect); void setForwardTransform(const QTransform &transform); QTransform forwardTransform() const; QTransform backwardTransform() const; private: void init(const QTransform &transform); void fillParams(const QRectF &srcRect, const QRect &dstBaseClipRect, QRegion *dstRegion, QPolygonF *dstClipPolygon); private: KisPaintDeviceSP m_dev; KoUpdaterPtr m_progressUpdater; QRegion m_dstRegion; QRectF m_srcRect; QTransform m_backwardTransform; QTransform m_forwardTransform; bool m_isIdentity; }; #endif diff --git a/krita/image/kis_pixel_selection.h b/krita/image/kis_pixel_selection.h index da78ef2a861..3178d3236b2 100644 --- a/krita/image/kis_pixel_selection.h +++ b/krita/image/kis_pixel_selection.h @@ -1,161 +1,161 @@ /* * Copyright (c) 2004 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_PIXEL_SELECTION_H_ #define KIS_PIXEL_SELECTION_H_ #include #include #include "kis_types.h" #include "kis_paint_device.h" #include "kis_selection_component.h" #include "kis_selection.h" -#include +#include /** * KisPixelSelection contains a byte-map representation of a layer, where * the value of a byte signifies whether a corresponding pixel is selected, or not. */ class KRITAIMAGE_EXPORT KisPixelSelection : public KisPaintDevice, public KisSelectionComponent { public: /** * Create a new KisPixelSelection. This selection will not have a * parent paint device. */ KisPixelSelection(KisDefaultBoundsBaseSP defaultBounds = 0, KisSelectionWSP parentSelection = 0); /** * Copy the selection */ KisPixelSelection(const KisPixelSelection& rhs); virtual ~KisPixelSelection(); KisSelectionComponent* clone(KisSelection*); const KoColorSpace* compositionSourceColorSpace() const; bool read(QIODevice *stream); /** * Fill the specified rect with the specified selectedness. */ void select(const QRect & r, quint8 selectedness = MAX_SELECTED); /** * Invert the total selection. This will also invert the default value * of the selection paint device, from MIN_SELECTED to MAX_SELECTED or * back. */ void invert(); /** * Set the specified rect to MIN_SELECTED. */ void clear(const QRect & r); /** * Reset the entire selection. The selectedRect and selectedExactRect * will be empty. The selection will be completely deselected. */ void clear(); /** * Apply a selection to the selection using the specified selection mode */ void applySelection(KisPixelSelectionSP selection, SelectionAction action); /// Tests if the rect is totally outside the selection bool isTotallyUnselected(const QRect & r) const; /** * Rough, but fastish way of determining the area * of the tiles used by the selection. */ QRect selectedRect() const; /** * Slow, but exact way of determining the rectangle * that encloses the selection. */ QRect selectedExactRect() const; /** * @brief outline returns the outline of the current selection * @return a vector of polygons that can be used to draw the outline */ QVector outline() const; /** * Overridden from KisPaintDevice to handle outline cache moves */ void move(const QPoint& pt); using KisPaintDevice::move; bool isEmpty() const; QPainterPath outlineCache() const; bool outlineCacheValid() const; void recalculateOutlineCache(); void setOutlineCache(const QPainterPath &cache); void invalidateOutlineCache(); bool thumbnailImageValid() const; QImage thumbnailImage() const; QTransform thumbnailImageTransform() const; void recalculateThumbnailImage(const QColor &maskColor); void setParentSelection(KisSelectionWSP selection); KisSelectionWSP parentSelection() const; virtual void renderToProjection(KisPaintDeviceSP projection); virtual void renderToProjection(KisPaintDeviceSP projection, const QRect& r); private: /** * Add a selection */ void addSelection(KisPixelSelectionSP selection); /** * Subtracts a selection */ void subtractSelection(KisPixelSelectionSP selection); /** * Intersects a selection using min-T-norm for this. */ void intersectSelection(KisPixelSelectionSP selection); private: // We don't want these methods to be used on selections: using KisPaintDevice::extent; using KisPaintDevice::exactBounds; private: struct Private; Private * const m_d; }; #endif // KIS_PIXEL_SELECTION_H_ diff --git a/krita/image/kis_polygonal_gradient_shape_strategy.h b/krita/image/kis_polygonal_gradient_shape_strategy.h index 8c32ecbecb0..3808ed57a0e 100644 --- a/krita/image/kis_polygonal_gradient_shape_strategy.h +++ b/krita/image/kis_polygonal_gradient_shape_strategy.h @@ -1,50 +1,50 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_POLYGONAL_GRADIENT_SHAPE_STRATEGY_H #define __KIS_POLYGONAL_GRADIENT_SHAPE_STRATEGY_H #include "kis_gradient_shape_strategy.h" #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisPolygonalGradientShapeStrategy : public KisGradientShapeStrategy { public: KisPolygonalGradientShapeStrategy(const QPainterPath &selectionPath, qreal exponent); ~KisPolygonalGradientShapeStrategy(); double valueAt(double x, double y) const; static QPointF testingCalculatePathCenter(int numSamples, const QPainterPath &path, qreal exponent, bool searchForMax); private: QPainterPath m_selectionPath; qreal m_exponent; qreal m_minWeight; qreal m_maxWeight; qreal m_scaleCoeff; }; #endif /* __KIS_POLYGONAL_GRADIENT_SHAPE_STRATEGY_H */ diff --git a/krita/image/kis_post_execution_undo_adapter.h b/krita/image/kis_post_execution_undo_adapter.h index 504e93bb9ef..12bb6d243cc 100644 --- a/krita/image/kis_post_execution_undo_adapter.h +++ b/krita/image/kis_post_execution_undo_adapter.h @@ -1,58 +1,58 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_POST_EXECUTION_UNDO_ADAPTER_H #define __KIS_POST_EXECUTION_UNDO_ADAPTER_H -#include +#include #include "kis_types.h" class KUndo2MagicString; class KisUndoStore; class KisSavedMacroCommand; class KisStrokesFacade; /** * KisPostExecutionUndoAdapter -- used by the strokes. It doesn't * call redo() when you add a command. It is assumed, that you have * already executed the command yourself and now just notify * the system about it. Warning: it doesn't inherit KisUndoAdapter * because it doesn't fit the contract of this class. And, more * important, KisTransaction should work differently with this class. */ class KRITAIMAGE_EXPORT KisPostExecutionUndoAdapter { public: KisPostExecutionUndoAdapter(KisUndoStore *undoStore, KisStrokesFacade *strokesFacade); void addCommand(KUndo2CommandSP command); KisSavedMacroCommand* createMacro(const KUndo2MagicString& macroName); void addMacro(KisSavedMacroCommand *macro); inline void setUndoStore(KisUndoStore *undoStore) { m_undoStore = undoStore; } private: KisUndoStore *m_undoStore; KisStrokesFacade *m_strokesFacade; }; #endif /* __KIS_POST_EXECUTION_UNDO_ADAPTER_H */ diff --git a/krita/image/kis_processing_applicator.h b/krita/image/kis_processing_applicator.h index be3c27d67a8..bdc52c61246 100644 --- a/krita/image/kis_processing_applicator.h +++ b/krita/image/kis_processing_applicator.h @@ -1,94 +1,94 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_PROCESSING_APPLICATOR_H #define __KIS_PROCESSING_APPLICATOR_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_stroke_job_strategy.h" #include "kis_image_signal_router.h" #include "kundo2magicstring.h" #include "kundo2commandextradata.h" class KRITAIMAGE_EXPORT KisProcessingApplicator { public: enum ProcessingFlag { NONE = 0x0, RECURSIVE = 0x1, NO_UI_UPDATES = 0x2, SUPPORTS_WRAPAROUND_MODE = 0x4 }; Q_DECLARE_FLAGS(ProcessingFlags, ProcessingFlag) public: KisProcessingApplicator(KisImageWSP image, KisNodeSP node, ProcessingFlags flags = NONE, KisImageSignalVector emitSignals = KisImageSignalVector(), const KUndo2MagicString &name = KUndo2MagicString(), KUndo2CommandExtraData *extraData = 0); ~KisProcessingApplicator(); void applyVisitor(KisProcessingVisitorSP visitor, KisStrokeJobData::Sequentiality sequentiality = KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity = KisStrokeJobData::NORMAL); void applyCommand(KUndo2Command *command, KisStrokeJobData::Sequentiality sequentiality = KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::Exclusivity exclusivity = KisStrokeJobData::NORMAL); /** * This method emits all the final update signals of the stroke * without actually ending the stroke. This can be used for * long-running strokes which are kept open to implement preview * of the actions. * * WARNING: you cannot add new commands/processings after the * final signals has been emitted. You should either call end() or * cancel(). */ void explicitlyEmitFinalSignals(); void end(); void cancel(); private: void visitRecursively(KisNodeSP node, KisProcessingVisitorSP visitor, KisStrokeJobData::Sequentiality sequentiality, KisStrokeJobData::Exclusivity exclusivity); private: KisImageWSP m_image; KisNodeSP m_node; ProcessingFlags m_flags; KisImageSignalVector m_emitSignals; KisStrokeId m_strokeId; bool m_finalSignalsEmitted; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KisProcessingApplicator::ProcessingFlags) #endif /* __KIS_PROCESSING_APPLICATOR_H */ diff --git a/krita/image/kis_processing_information.h b/krita/image/kis_processing_information.h index 87e75b82ce4..9b14dbe22ec 100644 --- a/krita/image/kis_processing_information.h +++ b/krita/image/kis_processing_information.h @@ -1,78 +1,78 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_PROCESSING_INFORMATION_H_ #define _KIS_PROCESSING_INFORMATION_H_ #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * This class is used in KisFilter to contain information needed to apply a filter * on a paint device. * This one have only a const paint device and holds information about the source. */ class KRITAIMAGE_EXPORT KisConstProcessingInformation { public: KisConstProcessingInformation(const KisPaintDeviceSP device, const QPoint& topLeft, const KisSelectionSP selection = 0); KisConstProcessingInformation(const KisConstProcessingInformation& _rhs); KisConstProcessingInformation& operator=(const KisConstProcessingInformation& _rhs); ~KisConstProcessingInformation(); /** * @return the paint device */ const KisPaintDeviceSP paintDevice() const; /** * @return the active selection */ const KisSelectionSP selection() const; /** * @return the top left pixel that need to process */ const QPoint& topLeft() const; private: struct Private; Private* const d; }; /** * This class is used in KisFilter to contain information needed to apply a filter * on a paint device. * This one can have a non const paint device and holds information about the destination. */ class KRITAIMAGE_EXPORT KisProcessingInformation : public KisConstProcessingInformation { public: KisProcessingInformation(KisPaintDeviceSP device, const QPoint& topLeft, const KisSelectionSP selection = 0); KisProcessingInformation(const KisProcessingInformation& _rhs); KisProcessingInformation& operator=(const KisProcessingInformation& _rhs); ~KisProcessingInformation(); /** * @return the paint device */ KisPaintDeviceSP paintDevice(); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_processing_visitor.h b/krita/image/kis_processing_visitor.h index 2c03dd6f8ed..9a187a4da9d 100644 --- a/krita/image/kis_processing_visitor.h +++ b/krita/image/kis_processing_visitor.h @@ -1,77 +1,77 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_PROCESSING_VISITOR_H #define __KIS_PROCESSING_VISITOR_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_shared.h" #include class KisNode; class KoUpdater; class KoProgressUpdater; class KisUndoAdapter; class KisPaintLayer; class KisGroupLayer; class KisAdjustmentLayer; class KisExternalLayer; class KisCloneLayer; class KisFilterMask; class KisTransformMask; class KisTransparencyMask; class KisSelectionMask; class KisGeneratorLayer; /** * A visitor that processes a single layer; it does not recurse into the * layer's children. Classes inheriting KisProcessingVisitor must not * emit signals or ask the image to update the projection. */ class KRITAIMAGE_EXPORT KisProcessingVisitor : public KisShared { public: virtual ~KisProcessingVisitor(); virtual void visit(KisNode *node, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisPaintLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisGroupLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisAdjustmentLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisExternalLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisGeneratorLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisCloneLayer *layer, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisFilterMask *mask, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisTransformMask *mask, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisTransparencyMask *mask, KisUndoAdapter *undoAdapter) = 0; virtual void visit(KisSelectionMask *mask, KisUndoAdapter *undoAdapter) = 0; public: class KRITAIMAGE_EXPORT ProgressHelper { public: ProgressHelper(const KisNode *node); ~ProgressHelper(); KoUpdater* updater() const; private: KoProgressUpdater *m_progressUpdater; mutable QMutex m_progressMutex; }; }; #endif /* __KIS_PROCESSING_VISITOR_H */ diff --git a/krita/image/kis_progress_interface.h b/krita/image/kis_progress_interface.h index 704274717a8..e60facd4afe 100644 --- a/krita/image/kis_progress_interface.h +++ b/krita/image/kis_progress_interface.h @@ -1,37 +1,37 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 2009 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_PROGRESS_INTERFACE_H #define KIS_PROGRESS_INTERFACE_H -#include +#include class KoProgressUpdater; class KRITAIMAGE_EXPORT KisProgressInterface { public: virtual ~KoProgressInterface(); virtual void detachUpdater(KoProgressUpdater* updater) = 0; virtual void attachUpdater(KoProgressUpdater* updater) = 0; }; #endif // KIS_PROGRESS_INTERFACE_H diff --git a/krita/image/kis_progress_updater.h b/krita/image/kis_progress_updater.h index 21744ce80c8..23234ee422c 100644 --- a/krita/image/kis_progress_updater.h +++ b/krita/image/kis_progress_updater.h @@ -1,53 +1,53 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 2009 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_PROGRESS_UPDATER_H #define KIS_PROGRESS_UPDATER_H #include -#include +#include class KRITAIMAGE_EXPORT KisProgressInterface { public: virtual ~KisProgressInterface() {}; virtual void detachUpdater(KoProgressUpdater* updater) = 0; virtual void attachUpdater(KoProgressUpdater* updater) = 0; }; /** * KisProgressUpdater is an updater that disengages itself automatically * from the updater widget when done. */ class KRITAIMAGE_EXPORT KisProgressUpdater : public KoProgressUpdater { public: KisProgressUpdater(KisProgressInterface* progressInterface, KoProgressProxy* proxy, KoProgressUpdater::Mode mode = KoProgressUpdater::Threaded); virtual ~KisProgressUpdater(); private: KisProgressInterface* m_interface; }; #endif // KIS_PROGRESS_UPDATER_H diff --git a/krita/image/kis_projection_leaf.h b/krita/image/kis_projection_leaf.h index 83ad1c485bd..a18b1c746cf 100644 --- a/krita/image/kis_projection_leaf.h +++ b/krita/image/kis_projection_leaf.h @@ -1,70 +1,70 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_PROJECTION_LEAF_H #define __KIS_PROJECTION_LEAF_H #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" class KisNodeVisitor; class KRITAIMAGE_EXPORT KisProjectionLeaf { public: KisProjectionLeaf(KisNode *node); virtual ~KisProjectionLeaf(); KisProjectionLeafSP parent() const; KisProjectionLeafSP firstChild() const; KisProjectionLeafSP lastChild() const; KisProjectionLeafSP prevSibling() const; KisProjectionLeafSP nextSibling() const; bool hasChildren() const; KisNodeSP node() const; KisAbstractProjectionPlaneSP projectionPlane() const; bool accept(KisNodeVisitor &visitor); KisPaintDeviceSP original(); KisPaintDeviceSP projection(); bool isRoot() const; bool isLayer() const; bool isMask() const; bool canHaveChildLayers() const; bool dependsOnLowerNodes() const; bool visible() const; quint8 opacity() const; QBitArray channelFlags() const; bool isStillInGraph() const; bool isDroppedMask() const; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_PROJECTION_LEAF_H */ diff --git a/krita/image/kis_properties_configuration.h b/krita/image/kis_properties_configuration.h index 523d300ee75..7db74f64af0 100644 --- a/krita/image/kis_properties_configuration.h +++ b/krita/image/kis_properties_configuration.h @@ -1,157 +1,157 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_PROPERTIES_CONFIGURATION_H_ #define _KIS_PROPERTIES_CONFIGURATION_H_ #include #include #include #include #include #include class QDomElement; class QDomDocument; #include "kis_serializable_configuration.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * KisPropertiesConfiguration is a map-based properties class that can * be serialized and deserialized. * * It differs from the base class KisSerializableConfiguration in that * it provides a number of convenience methods to get at the data and */ class KRITAIMAGE_EXPORT KisPropertiesConfiguration : public KisSerializableConfiguration { public: /** * Create a new properties config. */ KisPropertiesConfiguration(); virtual ~KisPropertiesConfiguration(); /** * Deep copy the properties configFile */ KisPropertiesConfiguration(const KisPropertiesConfiguration& rhs); public: /** * Fill the properties configuration object from the XML encoded representation in s. * This function use the "Legacy" style XML of the 1.x .kra file format. */ virtual void fromXML(const QString&); /** * Fill the properties configuration object from the XML encoded representation in s. * This function use the "Legacy" style XML of the 1.x .kra file format. */ virtual void fromXML(const QDomElement&); /** * Create a serialized version of this properties config * This function use the "Legacy" style XML of the 1.x .kra file format. */ virtual void toXML(QDomDocument&, QDomElement&) const; /** * Create a serialized version of this properties config * This function use the "Legacy" style XML of the 1.x .kra file format. */ virtual QString toXML() const; /** * @return true if the map contains a property with the specified name */ bool hasProperty(const QString& name) const; /** * Set the property with name to value. */ virtual void setProperty(const QString & name, const QVariant & value); /** * Set value to the value associated with property name * * XXX: API alert: a setter that is prefixed with get? * * @return false if the specified property did not exist. */ virtual bool getProperty(const QString & name, QVariant & value) const; virtual QVariant getProperty(const QString & name) const; template T getPropertyLazy(const QString & name, const T &defaultValue) const { QVariant value = getProperty(name); return value.isValid() ? value.value() : defaultValue; } int getInt(const QString & name, int def = 0) const; double getDouble(const QString & name, double def = 0.0) const; float getFloat(const QString& name, float def = 0.0) const; bool getBool(const QString & name, bool def = false) const; QString getString(const QString & name, const QString & def = QString()) const; KisCubicCurve getCubicCurve(const QString & name, const KisCubicCurve & curve = KisCubicCurve()) const; KoColor getColor(const QString& name, const KoColor& color = KoColor()) const; QMap getProperties() const; /// Clear the map of properties void clearProperties(); ///Marks a property that should not be saved by toXML void setPropertyNotSaved(const QString & name); void removeProperty(const QString & name); public: void dump() const; private: struct Private; Private* const d; }; class KRITAIMAGE_EXPORT KisPropertiesConfigurationFactory : public KisSerializableConfigurationFactory { public: KisPropertiesConfigurationFactory(); virtual ~KisPropertiesConfigurationFactory(); virtual KisSerializableConfiguration* createDefault(); virtual KisSerializableConfiguration* create(const QDomElement& e); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_psd_layer_style.h b/krita/image/kis_psd_layer_style.h index 07215df3dca..7110f8b50bb 100644 --- a/krita/image/kis_psd_layer_style.h +++ b/krita/image/kis_psd_layer_style.h @@ -1,98 +1,98 @@ /* * Copyright (c) 2014 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_PSD_LAYER_STYLE_H #define KIS_PSD_LAYER_STYLE_H class QIODevice; struct QUuid; #include #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" /** * @brief The KisPSDLayerStyle class implements loading, saving and applying * the PSD layer effects. * * See http://www.tonton-pixel.com/Photoshop%20Additional%20File%20Formats/styles-file-format.html * */ class KRITAIMAGE_EXPORT KisPSDLayerStyle { public: explicit KisPSDLayerStyle(); virtual ~KisPSDLayerStyle(); KisPSDLayerStyle(const KisPSDLayerStyle& rhs); KisPSDLayerStyle operator=(const KisPSDLayerStyle& rhs); KisPSDLayerStyleSP clone() const; void clear(); QString name() const; void setName(const QString &value); QUuid uuid() const; void setUuid(const QUuid &value) const; QString psdUuid() const; void setPsdUuid(const QString &value) const; /** * \return true if all the styles are disabled */ bool isEmpty() const; bool isEnabled() const; void setEnabled(bool value); const psd_layer_effects_context* context() const; const psd_layer_effects_drop_shadow* dropShadow() const; const psd_layer_effects_inner_shadow* innerShadow() const; const psd_layer_effects_outer_glow* outerGlow() const; const psd_layer_effects_inner_glow* innerGlow() const; const psd_layer_effects_satin* satin() const; const psd_layer_effects_color_overlay* colorOverlay() const; const psd_layer_effects_gradient_overlay* gradientOverlay() const; const psd_layer_effects_pattern_overlay* patternOverlay() const; const psd_layer_effects_stroke* stroke() const; const psd_layer_effects_bevel_emboss* bevelAndEmboss() const; psd_layer_effects_context* context(); psd_layer_effects_drop_shadow* dropShadow(); psd_layer_effects_inner_shadow* innerShadow(); psd_layer_effects_outer_glow* outerGlow(); psd_layer_effects_inner_glow* innerGlow(); psd_layer_effects_satin* satin(); psd_layer_effects_color_overlay* colorOverlay(); psd_layer_effects_gradient_overlay* gradientOverlay(); psd_layer_effects_pattern_overlay* patternOverlay(); psd_layer_effects_stroke* stroke(); psd_layer_effects_bevel_emboss* bevelAndEmboss(); private: struct Private; Private * const d; }; #endif // KIS_PSD_LAYER_STYLE_H diff --git a/krita/image/kis_queues_progress_updater.h b/krita/image/kis_queues_progress_updater.h index 17e060f541a..953207648f2 100644 --- a/krita/image/kis_queues_progress_updater.h +++ b/krita/image/kis_queues_progress_updater.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_QUEUES_PROGRESS_UPDATER_H #define __KIS_QUEUES_PROGRESS_UPDATER_H #include -#include "krita_export.h" +#include "kritaimage_export.h" class KoProgressProxy; class KRITAIMAGE_EXPORT KisQueuesProgressUpdater : public QObject { Q_OBJECT public: KisQueuesProgressUpdater(KoProgressProxy *progressProxy); ~KisQueuesProgressUpdater(); void updateProgress(int queueSizeMetric, const QString &jobName); void hide(); private Q_SLOTS: void updateProxy(); private: struct Private; Private * const m_d; }; #endif /* __KIS_QUEUES_PROGRESS_UPDATER_H */ diff --git a/krita/image/kis_random_generator.h b/krita/image/kis_random_generator.h index 7bfb27b2d0f..08b2b2d12bd 100644 --- a/krita/image/kis_random_generator.h +++ b/krita/image/kis_random_generator.h @@ -1,58 +1,58 @@ /* * This file is part of the KDE project * * Copyright (c) 2008 Cyrille Berger * * 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_RANDOM_GENERATOR_H_ #define _KIS_RANDOM_GENERATOR_H_ -#include +#include #include /** * This is a class that return a pseudo-random number that will be constant for a given * pixel coordinate. * The rational is that filters that use random number (such as noises, or raindrops) * needs to always get the same random value at each run, or else the result will constantly * changes when used as an adjustement layer. */ class KRITAIMAGE_EXPORT KisRandomGenerator { public: /** * Creates a new instance of a random generator with the given seed. */ KisRandomGenerator(quint64 seed); ~KisRandomGenerator(); /** * @return the constant random value corresponding to a given pixel, the value is between 0 * and RAND_MAX */ quint64 randomAt(qint64 x, qint64 y); /** * @return the constant random value correspoding to a given pixel, the value is between 0 * and 1.0 */ double doubleRandomAt(qint64 x, qint64 y); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_random_sub_accessor.h b/krita/image/kis_random_sub_accessor.h index 6b664e3a287..2b3cca8c632 100644 --- a/krita/image/kis_random_sub_accessor.h +++ b/krita/image/kis_random_sub_accessor.h @@ -1,62 +1,62 @@ /* * This file is part of the KDE project * * Copyright (c) 2006 Cyrille Berger * * 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_RANDOM_SUB_ACCESSOR_H #define KIS_RANDOM_SUB_ACCESSOR_H #include "kis_random_accessor_ng.h" #include "kis_types.h" -#include +#include #include "kis_shared.h" /** * Gives a random access to the sampled subpixels of an image. Use the * moveTo function to select the pixel. And then rawData to access the * value of a pixel. */ class KRITAIMAGE_EXPORT KisRandomSubAccessor : public KisShared { public: KisRandomSubAccessor(KisPaintDeviceSP device); ~KisRandomSubAccessor(); /** * Copy the sampled old value to destination */ void sampledOldRawData(quint8* dst); /** * Copy the sampled value to destination */ void sampledRawData(quint8* dst); inline void moveTo(double x, double y) { m_currentPoint.setX(x); m_currentPoint.setY(y); } inline void moveTo(const QPointF& p) { m_currentPoint = p; } private: KisPaintDeviceSP m_device; QPointF m_currentPoint; KisRandomConstAccessorSP m_randomAccessor; }; #endif diff --git a/krita/image/kis_rect_mask_generator.h b/krita/image/kis_rect_mask_generator.h index ac483c8c93d..f1d027a9b49 100644 --- a/krita/image/kis_rect_mask_generator.h +++ b/krita/image/kis_rect_mask_generator.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2008-2009 Cyrille Berger * * 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_RECT_MASK_GENERATOR_H_ #define _KIS_RECT_MASK_GENERATOR_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_mask_generator.h" /** * Represent, serialize and deserialize a rectangular 8-bit mask. */ class KRITAIMAGE_EXPORT KisRectangleMaskGenerator : public KisMaskGenerator { public: KisRectangleMaskGenerator(qreal radius, qreal ratio, qreal fh, qreal fv, int spikes, bool antialiasEdges); virtual ~KisRectangleMaskGenerator(); virtual bool shouldSupersample() const; virtual quint8 valueAt(qreal x, qreal y) const; void setScale(qreal scaleX, qreal scaleY); void setSoftness(qreal softness); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/kis_runnable.h b/krita/image/kis_runnable.h index 291cc8aa840..8d87b051785 100644 --- a/krita/image/kis_runnable.h +++ b/krita/image/kis_runnable.h @@ -1,31 +1,31 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_RUNNABLE_H #define __KIS_RUNNABLE_H -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisRunnable { public: virtual ~KisRunnable() {}; virtual void run() = 0; }; #endif /* __KIS_RUNNABLE_H */ diff --git a/krita/image/kis_safe_transform.h b/krita/image/kis_safe_transform.h index b958c67b5a9..fda50bddeac 100644 --- a/krita/image/kis_safe_transform.h +++ b/krita/image/kis_safe_transform.h @@ -1,58 +1,58 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SAFE_TRANSFORM_H #define __KIS_SAFE_TRANSFORM_H #include -#include "krita_export.h" +#include "kritaimage_export.h" class QTransform; class QRect; class QRectF; class QPolygonF; class KRITAIMAGE_EXPORT KisSafeTransform { public: KisSafeTransform(const QTransform &transform, const QRect &bounds, const QRect &srcInterestRect); ~KisSafeTransform(); QPolygonF srcClipPolygon() const; QPolygonF dstClipPolygon() const; QPolygonF mapForward(const QPolygonF &p); QPolygonF mapBackward(const QPolygonF &p); QRectF mapRectForward(const QRectF &rc); QRectF mapRectBackward(const QRectF &rc); QRect mapRectForward(const QRect &rc); QRect mapRectBackward(const QRect &rc); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_SAFE_TRANSFORM_H */ diff --git a/krita/image/kis_selection.h b/krita/image/kis_selection.h index b2679d81606..fd0656481e2 100644 --- a/krita/image/kis_selection.h +++ b/krita/image/kis_selection.h @@ -1,217 +1,217 @@ /* * Copyright (c) 2004 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_SELECTION_H_ #define KIS_SELECTION_H_ #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_paint_device.h" enum SelectionMode { PIXEL_SELECTION, SHAPE_PROTECTION }; enum SelectionAction { SELECTION_REPLACE, SELECTION_ADD, SELECTION_SUBTRACT, SELECTION_INTERSECT, SELECTION_DEFAULT }; #include "kis_pixel_selection.h" class KisSelectionComponent; /** * KisSelection is a composite object. It may contain an instance * of KisPixelSelection and a KisShapeSelection object. Both these * selections are merged into a projection of the KisSelection. * * Every pixel in the paint device can indicate a degree of selectedness, varying * between MIN_SELECTED and MAX_SELECTED. * * The projection() paint device itself is only a projection: you can * read from it, but not write to it. You need to keep track of * the need for updating the projection yourself: there is no * automatic updating after changing the contents of one or more * of the selection components. */ class KRITAIMAGE_EXPORT KisSelection : public KisShared { public: /** * Create a new KisSelection. * * @param defaultBounds defines the bounds of the selection when * Select All is initiated. */ KisSelection(KisDefaultBoundsBaseSP defaultBounds = 0); /** * Copy the selection. The selection components are copied, too. */ KisSelection(const KisSelection& rhs); KisSelection& operator=(const KisSelection &rhs); /** * Delete the selection. The shape selection component is deleted, the * pixel selection component is contained in a shared pointer, so that * may still be valid. */ virtual ~KisSelection(); /** * The paint device of the pixel selection should report * about it's setDirty events to its parent. The creator * should set the parent manually if it wants to get the * signals */ void setParentNode(KisNodeWSP node); bool hasPixelSelection() const; bool hasShapeSelection() const; bool outlineCacheValid() const; QPainterPath outlineCache() const; void recalculateOutlineCache(); /** * Tells whether the cached thumbnail of the selection is still valid */ bool thumbnailImageValid() const; /** * Recalculates the thumbnail of the selection */ void recalculateThumbnailImage(const QColor &maskColor); /** * Returns the thumbnail of the selection. */ QImage thumbnailImage() const; /** * Returns the transformation which should be applied to the thumbnail before * being painted over the image */ QTransform thumbnailImageTransform() const; /** * return the pixel selection component of this selection. Pixel * selection component is always present in the selection. In case * the user wants a vector selection, pixel selection will store * the pixelated version of it. * * NOTE: use pixelSelection() for changing the selection only. For * reading the selection and passing the data to bitBlt function use * projection(). Although projection() and pixelSelection() currently * point ot the same paint device, this behavior may change in the * future. */ KisPixelSelectionSP pixelSelection() const; /** * return the vector selection component of this selection or zero * if hasShapeSelection() returns false. */ KisSelectionComponent* shapeSelection() const; void setShapeSelection(KisSelectionComponent* shapeSelection); /** * Returns the projection of the selection. It may be the same * as pixel selection. You must read selection data from this * paint device only */ KisPixelSelectionSP projection() const; /** * Updates the projection of the selection. You should call this * method after the every change of the selection components. * There is no automatic updates framework present */ void updateProjection(const QRect& rect); void updateProjection(); void setVisible(bool visible); bool isVisible(); /** * Convenience functions. Just call the corresponding methods * of the underlying projection */ bool isTotallyUnselected(const QRect & r) const; QRect selectedRect() const; /** * @brief Slow, but exact way of determining the rectangle * that encloses the selection. * * Default pixel of the selection device may vary and you would get wrong bounds. * selectedExactRect() handles all these cases. * */ QRect selectedExactRect() const; void setX(qint32 x); void setY(qint32 y); qint32 x() const; qint32 y() const; void setDefaultBounds(KisDefaultBoundsBaseSP bounds); void clear(); /** * @brief flatten creates a new pixel selection component from the shape selection * and throws away the shape selection. This has no effect if there is no * shape selection. */ KUndo2Command* flatten(); void notifySelectionChanged(); /// XXX: This method was marked KDE_DEPRECATED but without information on what to /// replace it with. Undeprecate, therefore. quint8 selected(qint32 x, qint32 y) const; private: friend class KisSelectionTest; friend class KisMaskTest; friend class KisAdjustmentLayerTest; KisNodeWSP parentNode() const; void copyFrom(const KisSelection &rhs); private: struct Private; Private * const m_d; }; #endif // KIS_SELECTION_H_ diff --git a/krita/image/kis_selection_based_layer.h b/krita/image/kis_selection_based_layer.h index 43d2979cc9a..42cb6bb2f12 100644 --- a/krita/image/kis_selection_based_layer.h +++ b/krita/image/kis_selection_based_layer.h @@ -1,208 +1,208 @@ /* * Copyright (c) 2006 Boudewijn Rempt * (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, * MA 02110-1301, USA. */ #ifndef KIS_SELECTION_BASED_LAYER_H_ #define KIS_SELECTION_BASED_LAYER_H_ #include #include "kis_types.h" #include "kis_layer.h" #include "kis_indirect_painting_support.h" -#include +#include #include "kis_node_filter_interface.h" class KisFilterConfiguration; /** * @class KisSelectionBasedLayer describes base behaviour for * selection base classes like KisAdjustmentLayer and KisGeneratorLayer. * These classes should have a persistent selection that controls * the area where filter/generators are applied. The area outside * this selection is not affected by the layer */ class KRITAIMAGE_EXPORT KisSelectionBasedLayer : public KisLayer, public KisIndirectPaintingSupport, public KisNodeFilterInterface { Q_OBJECT public: /** * creates a new layer with the given selection. * Note that the selection will be _copied_ (with COW, though). * @param image the image to set this layer to * @param name name of the layer * @param selection is a mask used by the layer to know * where to apply the filter/generator. */ KisSelectionBasedLayer(KisImageWSP image, const QString &name, KisSelectionSP selection, KisFilterConfiguration *filterConfig, bool useGeneratorRegistry = false); KisSelectionBasedLayer(const KisSelectionBasedLayer& rhs); virtual ~KisSelectionBasedLayer(); /** * tells whether the @node can be a child of this layer * @param node to be connected node * @return tells if to be connected is a child of KisMask */ bool allowAsChild(KisNodeSP node) const; void setImage(KisImageWSP image); KisPaintDeviceSP original() const; KisPaintDeviceSP paintDevice() const; bool needProjection() const; /** * resets cached projection of lower layer to a new device * @return void */ void resetCache(const KoColorSpace *colorSpace = 0); /** * for KisLayer::setDirty(const QRegion&) */ using KisLayer::setDirty; /** * Mark a layer as dirty. We can't use KisLayer's one * as our extent() function doesn't fit for this */ void setDirty(); void setDirty(const QRect & rect); public: /** * Returns the selection of the layer * * Do not mix it with selection() which returns * the currently active selection of the image */ KisSelectionSP internalSelection() const; /** * sets the selection of this layer to a copy of * selection * @param selection the selection to set * @return void */ void setInternalSelection(KisSelectionSP selection); /** * When painted in indirect painting mode, the internal selection * might not contain actual selection, because a part of it is * stored on an indirect painting device. This method returns the * merged copy of the real selection. The area in \p rect only is * guaranteed to be prepared. The content of the rest of the * selection is undefined. */ KisSelectionSP fetchComposedInternalSelection(const QRect &rect) const; /** * gets this layer's x coordinate, taking selection into account * @return x-coordinate value */ qint32 x() const; /** * gets this layer's y coordinate, taking selection into account * @return y-coordinate value */ qint32 y() const; /** * sets this layer's y coordinate, taking selection into account * @param x x coordinate */ void setX(qint32 x); /** * sets this layer's y coordinate, taking selection into account * @param y y coordinate */ void setY(qint32 y); public: /** * gets an approximation of where the bounds on actual data * are in this layer, taking selection into account */ QRect extent() const; /** * returns the exact bounds of where the actual data resides * in this layer, taking selection into account */ QRect exactBounds() const; /** * copies the image and reformats it to thumbnail size * and returns the new thumbnail image. * @param w width of the thumbnail to create * @param h height of the thumbnail to create * @return the thumbnail image created. */ QImage createThumbnail(qint32 w, qint32 h); protected: // override from KisLayer void copyOriginalToProjection(const KisPaintDeviceSP original, KisPaintDeviceSP projection, const QRect& rect) const; // override from KisNode QRect needRect(const QRect &rect, PositionToFilthy pos = N_FILTHY) const; protected: void initSelection(); QRect cropChangeRectBySelection(const QRect &rect) const; /** * Sets if the selection should be used in * copyOriginalToProjection() method. * * Default value is 'true'. The descendants should override it to * get desired behaviour. * * Must be called only once in the child's constructor */ void setUseSelectionInProjection(bool value) const; public Q_SLOTS: /** * gets this layer. Overriddes function in * KisIndirectPaintingSupport * @return this AdjustmentLayer */ KisLayer* layer() { return this; } private: struct Private; Private * const m_d; }; #endif /* KIS_SELECTION_BASED_LAYER_H_ */ diff --git a/krita/image/kis_selection_component.h b/krita/image/kis_selection_component.h index a5b26cf14a3..d0fbc9e5569 100644 --- a/krita/image/kis_selection_component.h +++ b/krita/image/kis_selection_component.h @@ -1,58 +1,58 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SELECTION_COMPONENT_H #define KIS_SELECTION_COMPONENT_H -#include +#include #include class QRect; class KUndo2Command; class KisSelection; #include "kis_types.h" class KRITAIMAGE_EXPORT KisSelectionComponent { public: KisSelectionComponent() {} virtual ~KisSelectionComponent() {} virtual KisSelectionComponent* clone(KisSelection* selection) = 0; virtual void renderToProjection(KisPaintDeviceSP projection) = 0; virtual void renderToProjection(KisPaintDeviceSP projection, const QRect& r) = 0; virtual void moveX(qint32 x) { Q_UNUSED(x); } virtual void moveY(qint32 y) { Q_UNUSED(y); } virtual KUndo2Command* transform(const QTransform &transform) { Q_UNUSED(transform); return 0; } virtual bool isEmpty() const = 0; virtual QPainterPath outlineCache() const = 0; virtual bool outlineCacheValid() const = 0; virtual void recalculateOutlineCache() = 0; virtual KUndo2Command* resetToEmpty() { return 0; } }; #endif diff --git a/krita/image/kis_selection_filters.h b/krita/image/kis_selection_filters.h index 796db921a3c..1f39fa776bc 100644 --- a/krita/image/kis_selection_filters.h +++ b/krita/image/kis_selection_filters.h @@ -1,154 +1,154 @@ /* * Copyright (c) 2005 Michael Thaler * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SELECTION_FILTERS_H #define KIS_SELECTION_FILTERS_H #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include #include class KUndo2MagicString; class KRITAIMAGE_EXPORT KisSelectionFilter { public: virtual ~KisSelectionFilter(); virtual void process(KisPixelSelectionSP pixelSelection, const QRect &rect) = 0; virtual KUndo2MagicString name(); virtual QRect changeRect(const QRect &rect); protected: void computeBorder(qint32 *circ, qint32 xradius, qint32 yradius); void rotatePointers(quint8 **p, quint32 n); void computeTransition(quint8* transition, quint8** buf, qint32 width); }; class KRITAIMAGE_EXPORT KisErodeSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisDilateSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisBorderSelectionFilter : public KisSelectionFilter { public: KisBorderSelectionFilter(qint32 xRadius, qint32 yRadius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; }; class KRITAIMAGE_EXPORT KisFeatherSelectionFilter : public KisSelectionFilter { public: KisFeatherSelectionFilter(qint32 radius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_radius; }; class KRITAIMAGE_EXPORT KisGrowSelectionFilter : public KisSelectionFilter { public: KisGrowSelectionFilter(qint32 xRadius, qint32 yRadius); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; }; class KRITAIMAGE_EXPORT KisShrinkSelectionFilter : public KisSelectionFilter { public: KisShrinkSelectionFilter(qint32 xRadius, qint32 yRadius, bool edgeLock); KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); private: qint32 m_xRadius; qint32 m_yRadius; qint32 m_edgeLock; }; class KRITAIMAGE_EXPORT KisSmoothSelectionFilter : public KisSelectionFilter { public: KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; class KRITAIMAGE_EXPORT KisInvertSelectionFilter : public KisSelectionFilter { KUndo2MagicString name(); QRect changeRect(const QRect &rect); void process(KisPixelSelectionSP pixelSelection, const QRect &rect); }; #endif // KIS_SELECTION_FILTERS_H diff --git a/krita/image/kis_serializable_configuration.h b/krita/image/kis_serializable_configuration.h index 8decbd28573..dec4d5a97cd 100644 --- a/krita/image/kis_serializable_configuration.h +++ b/krita/image/kis_serializable_configuration.h @@ -1,76 +1,77 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_SERIALIZABLE_CONFIGURATION_H_ #define _KIS_SERIALIZABLE_CONFIGURATION_H_ class QDomElement; class QDomDocument; +class QString; -#include "krita_export.h" +#include "kritaimage_export.h" /** * This is an interface for objects that are serializable and unserializable. * It can be used together with the factory in case the type of configuration object * is also unknown at creation time. */ class KRITAIMAGE_EXPORT KisSerializableConfiguration { public: virtual ~KisSerializableConfiguration() {}; /** * Fill the object from the XML encoded representation in s. */ virtual void fromXML(const QString&); /** * Fill the object from the XML encoded representation in s. */ virtual void fromXML(const QDomElement&) = 0; /** * Create a serialized version of this object */ virtual void toXML(QDomDocument&, QDomElement&) const = 0; /** * Create a serialized version of this object */ virtual QString toXML() const; }; /** * This is an interface for a factory of serializable configuration objects. */ class KRITAIMAGE_EXPORT KisSerializableConfigurationFactory { public: virtual ~KisSerializableConfigurationFactory(); /** * @return an empty object with a sane default configuration */ virtual KisSerializableConfiguration* createDefault() = 0; /** * @return an unserialied version of the configuration */ virtual KisSerializableConfiguration* create(const QDomElement&) = 0; }; #endif diff --git a/krita/image/kis_shared.h b/krita/image/kis_shared.h index 6d87c3f83e6..59f6d95603f 100644 --- a/krita/image/kis_shared.h +++ b/krita/image/kis_shared.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2006 Cyrille Berger * * 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_SHARED_H_ #define _KIS_SHARED_H_ #include -#include +#include class KRITAIMAGE_EXPORT KisShared { private: KisShared(const KisShared& ); KisShared& operator=(const KisShared& ); protected: KisShared(); ~KisShared(); public: int refCount() { return _ref; } bool ref() { return _ref.ref(); } bool deref() { Q_ASSERT(_ref > 0); return _ref.deref(); } // see note in kis_shared.cc QAtomicInt* sharedWeakReference() { if(!_sharedWeakReference) { _sharedWeakReference = new QAtomicInt(); _sharedWeakReference->ref(); } return _sharedWeakReference; } private: QAtomicInt _ref; QAtomicInt *_sharedWeakReference; }; #endif diff --git a/krita/image/kis_signal_compressor.h b/krita/image/kis_signal_compressor.h index 5f1798b1a7b..e66b5c37e09 100644 --- a/krita/image/kis_signal_compressor.h +++ b/krita/image/kis_signal_compressor.h @@ -1,59 +1,59 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SIGNAL_COMPRESSOR_H #define __KIS_SIGNAL_COMPRESSOR_H #include -#include "krita_export.h" +#include "kritaimage_export.h" class QTimer; class KRITAIMAGE_EXPORT KisSignalCompressor : public QObject { Q_OBJECT public: enum Mode { POSTPONE, /* every start() porspones event by \p delay ms */ FIRST_ACTIVE, /* fist call to start() emits a signal, the latter will happen not earlier after \p delay ms */ FIRST_INACTIVE /* the first signal will be emitted not earlier that after \p delay ms after the first call to start() */ }; public: KisSignalCompressor(int delay, Mode mode, QObject *parent = 0); bool isActive() const; void setDelay(int delay); public Q_SLOTS: void start(); void stop(); private Q_SLOTS: void slotTimerExpired(); Q_SIGNALS: void timeout(); private: QTimer *m_timer; Mode m_mode; bool m_gotSignals; }; #endif /* __KIS_SIGNAL_COMPRESSOR_H */ diff --git a/krita/image/kis_stroke.h b/krita/image/kis_stroke.h index 9880f6e483e..6b7ad6c3b7a 100644 --- a/krita/image/kis_stroke.h +++ b/krita/image/kis_stroke.h @@ -1,87 +1,87 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_STROKE_H #define __KIS_STROKE_H #include #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_stroke_job.h" class KisStrokeStrategy; class KUndo2MagicString; class KRITAIMAGE_EXPORT KisStroke { public: KisStroke(KisStrokeStrategy *strokeStrategy); ~KisStroke(); void addJob(KisStrokeJobData *data); KUndo2MagicString name() const; bool hasJobs() const; qint32 numJobs() const; KisStrokeJob* popOneJob(); void endStroke(); void cancelStroke(); bool isInitialized() const; bool isEnded() const; bool isExclusive() const; bool supportsWrapAroundMode() const; bool prevJobSequential() const; bool nextJobSequential() const; bool nextJobBarrier() const; private: void enqueue(KisStrokeJobStrategy *strategy, KisStrokeJobData *data); KisStrokeJob* dequeue(); void clearQueue(); private: // for testing use only, do not use in real code friend class KisStrokeTest; friend class KisStrokeStrategyUndoCommandBasedTest; QQueue& testingGetQueue() { return m_jobsQueue; } private: // the strategies are owned by the stroke KisStrokeStrategy *m_strokeStrategy; KisStrokeJobStrategy *m_initStrategy; KisStrokeJobStrategy *m_dabStrategy; KisStrokeJobStrategy *m_cancelStrategy; KisStrokeJobStrategy *m_finishStrategy; QQueue m_jobsQueue; bool m_strokeInitialized; bool m_strokeEnded; bool m_isCancelled; // cancelled strokes are always 'ended' as well bool m_prevJobSequential; }; #endif /* __KIS_STROKE_H */ diff --git a/krita/image/kis_stroke_job_strategy.h b/krita/image/kis_stroke_job_strategy.h index 64d1debd2cd..f66f6266195 100644 --- a/krita/image/kis_stroke_job_strategy.h +++ b/krita/image/kis_stroke_job_strategy.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_STROKE_JOB_STRATEGY_H #define __KIS_STROKE_JOB_STRATEGY_H -#include "krita_export.h" +#include "kritaimage_export.h" class KRITAIMAGE_EXPORT KisStrokeJobData { public: enum Sequentiality { CONCURRENT, SEQUENTIAL, BARRIER }; enum Exclusivity { NORMAL, EXCLUSIVE }; public: KisStrokeJobData(Sequentiality sequentiality = SEQUENTIAL, Exclusivity exclusivity = NORMAL); virtual ~KisStrokeJobData(); bool isBarrier() const; bool isSequential() const; bool isExclusive() const; Sequentiality sequentiality() { return m_sequentiality; }; Exclusivity exclusivity() { return m_exclusivity; }; private: Sequentiality m_sequentiality; Exclusivity m_exclusivity; }; class KRITAIMAGE_EXPORT KisStrokeJobStrategy { public: KisStrokeJobStrategy(); virtual ~KisStrokeJobStrategy(); virtual void run(KisStrokeJobData *data) = 0; private: }; #endif /* __KIS_STROKE_JOB_STRATEGY_H */ diff --git a/krita/image/kis_strokes_queue.h b/krita/image/kis_strokes_queue.h index 46c53ff8085..94e80d1a24d 100644 --- a/krita/image/kis_strokes_queue.h +++ b/krita/image/kis_strokes_queue.h @@ -1,66 +1,66 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_STROKES_QUEUE_H #define __KIS_STROKES_QUEUE_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_stroke_job_strategy.h" #include "kis_stroke_strategy.h" class KisUpdaterContext; class KisStroke; class KRITAIMAGE_EXPORT KisStrokesQueue { public: KisStrokesQueue(); ~KisStrokesQueue(); KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy); void addJob(KisStrokeId id, KisStrokeJobData *data); void endStroke(KisStrokeId id); bool cancelStroke(KisStrokeId id); bool tryCancelCurrentStrokeAsync(); void processQueue(KisUpdaterContext &updaterContext, bool externalJobsPending); bool needsExclusiveAccess() const; bool isEmpty() const; qint32 sizeMetric() const; KUndo2MagicString currentStrokeName() const; bool hasOpenedStrokes() const; bool wrapAroundModeSupported() const; private: bool processOneJob(KisUpdaterContext &updaterContext, bool externalJobsPending); bool checkStrokeState(bool hasStrokeJobsRunning); bool checkExclusiveProperty(qint32 numMergeJobs, qint32 numStrokeJobs); bool checkSequentialProperty(qint32 numMergeJobs, qint32 numStrokeJobs); bool checkBarrierProperty(qint32 numMergeJobs, qint32 numStrokeJobs, bool externalJobsPending); private: struct Private; Private * const m_d; }; #endif /* __KIS_STROKES_QUEUE_H */ diff --git a/krita/image/kis_thread_safe_signal_compressor.h b/krita/image/kis_thread_safe_signal_compressor.h index 547c805eaa2..f2cc646ace0 100644 --- a/krita/image/kis_thread_safe_signal_compressor.h +++ b/krita/image/kis_thread_safe_signal_compressor.h @@ -1,56 +1,56 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_THREAD_SAFE_SIGNAL_COMPRESSOR_H #define __KIS_THREAD_SAFE_SIGNAL_COMPRESSOR_H #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_signal_compressor.h" /** * A special class which works exactly like KisSignalCompressor, but * supports calling \p start() method from within the context of * another thread. If it happens, it posts a message to Qt's event * loop and the \p start() signal is delivered when event loop gets * executes again. * * WARNING: After creation this object moves itself into the main * thread, so one must *not* delete it explicitly. Use * deleteLater() instead. Moving into another thread is * another reason why it cannot have parent QObject. */ class KRITAIMAGE_EXPORT KisThreadSafeSignalCompressor : public QObject { Q_OBJECT public: KisThreadSafeSignalCompressor(int delay, KisSignalCompressor::Mode mode); public Q_SLOTS: void start(); Q_SIGNALS: void timeout(); void internalRequestSignal(); private: KisSignalCompressor *m_compressor; }; #endif /* __KIS_THREAD_SAFE_SIGNAL_COMPRESSOR_H */ diff --git a/krita/image/kis_transaction.h b/krita/image/kis_transaction.h index 118929eec66..cefeb81c8f9 100644 --- a/krita/image/kis_transaction.h +++ b/krita/image/kis_transaction.h @@ -1,138 +1,137 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TRANSACTION_H_ #define KIS_TRANSACTION_H_ #include #include "kis_types.h" -#include #include "kis_transaction_data.h" #include "kis_paint_device.h" #include "kis_pixel_selection.h" #include "kis_undo_adapter.h" #include "kis_post_execution_undo_adapter.h" class KisTransaction { public: KisTransaction(KisPaintDeviceSP device, KUndo2Command* parent = 0,int timedID = -1) { m_transactionData = new KisTransactionData(KUndo2MagicString(), device, true, parent); m_transactionData->setTimedID(timedID); } KisTransaction(const KUndo2MagicString& name, KisPaintDeviceSP device, KUndo2Command* parent = 0,int timedID = -1) { m_transactionData = new KisTransactionData(name, device, true, parent); m_transactionData->setTimedID(timedID); } virtual ~KisTransaction() { delete m_transactionData; } KUndo2Command* undoCommand() { return m_transactionData; } void commit(KisUndoAdapter* undoAdapter) { Q_ASSERT_X(m_transactionData, "KisTransaction::commit()", "the transaction has been tried to be committed twice"); m_transactionData->endTransaction(); undoAdapter->addCommand(m_transactionData); m_transactionData = 0; } void commit(KisPostExecutionUndoAdapter* undoAdapter) { Q_ASSERT_X(m_transactionData, "KisTransaction::commit()", "the transaction has been tried to be committed twice"); m_transactionData->endTransaction(); m_transactionData->redo(); undoAdapter->addCommand(KUndo2CommandSP(m_transactionData)); m_transactionData = 0; } KUndo2Command* endAndTake() { Q_ASSERT_X(m_transactionData, "KisTransaction::endAndTake()", "the transaction has been tried to be committed twice"); KisTransactionData *transactionData = m_transactionData; m_transactionData = 0; transactionData->endTransaction(); return transactionData; } void end() { Q_ASSERT_X(m_transactionData, "KisTransaction::end()", "nothing to end!"); /** * We will not call endTransaction for m_transactionData, * we'll just kill it, and it'll report about it's death to * the memento manager, so no commit will be made */ delete m_transactionData; m_transactionData = 0; } void revert() { Q_ASSERT_X(m_transactionData, "KisTransaction::reverted()", "the transaction is tried to be reverted()" "after it has already been added to undo adapter"); m_transactionData->endTransaction(); /** * FIXME: Should we emulate first redo() here? */ m_transactionData->undo(); delete m_transactionData; m_transactionData = 0; } KUndo2MagicString text() const { Q_ASSERT_X(m_transactionData, "KisTransaction::text()", "the name has been requested after the transaction" "has already been ended"); return m_transactionData->text(); } protected: KisTransaction() : m_transactionData(0) {} KisTransactionData* m_transactionData; }; class KisSelectionTransaction : public KisTransaction { public: KisSelectionTransaction(KisPixelSelectionSP pixelSelection, KUndo2Command* parent = 0) { m_transactionData = new KisTransactionData(KUndo2MagicString(), pixelSelection, false, parent); } KisSelectionTransaction(const KUndo2MagicString& name, KisPixelSelectionSP pixelSelection, KUndo2Command* parent = 0) { m_transactionData = new KisTransactionData(name, pixelSelection, false, parent); } }; #endif /* KIS_TRANSACTION_H_ */ diff --git a/krita/image/kis_transaction_data.h b/krita/image/kis_transaction_data.h index c6b86e18533..bbc56d9ba95 100644 --- a/krita/image/kis_transaction_data.h +++ b/krita/image/kis_transaction_data.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2002 Patrick Julien * * 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_TRANSACTION_DATA_H_ #define KIS_TRANSACTION_DATA_H_ #include #include "kis_types.h" -#include +#include /** * A tile based undo command. * * Ordinary KUndo2Command subclasses store parameters and apply the action in * the redo() command, however, Krita doesn't work like this. Undo replaces * the current tiles in a paint device with the old tiles, redo replaces them * again with the new tiles without actually executing the command that changed * the image data again. */ class KRITAIMAGE_EXPORT KisTransactionData : public KUndo2Command { public: KisTransactionData(const KUndo2MagicString& name, KisPaintDeviceSP device, bool resetSelectionOutlineCache, KUndo2Command* parent); virtual ~KisTransactionData(); public: virtual void redo(); virtual void undo(); virtual void endTransaction(); protected: virtual void saveSelectionOutlineCache(); virtual void restoreSelectionOutlineCache(bool undo); private: void init(KisPaintDeviceSP device); void startUpdates(); void possiblyNotifySelectionChanged(); void possiblyResetOutlineCache(); private: class Private; Private * const m_d; }; #endif /* KIS_TRANSACTION_DATA_H_ */ diff --git a/krita/image/kis_transform_mask_params_factory_registry.h b/krita/image/kis_transform_mask_params_factory_registry.h index 14cb8420dc2..27bbca1b7c9 100644 --- a/krita/image/kis_transform_mask_params_factory_registry.h +++ b/krita/image/kis_transform_mask_params_factory_registry.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TRANSFORM_MASK_PARAMS_FACTORY_REGISTRY_H #define __KIS_TRANSFORM_MASK_PARAMS_FACTORY_REGISTRY_H #include #include #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" class QDomElement; typedef boost::function KisTransformMaskParamsFactory; typedef QMap KisTransformMaskParamsFactoryMap; class KRITAIMAGE_EXPORT KisTransformMaskParamsFactoryRegistry { private: KisTransformMaskParamsFactoryRegistry(); ~KisTransformMaskParamsFactoryRegistry(); public: void addFactory(const QString &id, const KisTransformMaskParamsFactory &factory); KisTransformMaskParamsInterfaceSP createParams(const QString &id, const QDomElement &e); static KisTransformMaskParamsFactoryRegistry* instance(); private: KisTransformMaskParamsFactoryMap m_map; }; #endif /* __KIS_TRANSFORM_MASK_PARAMS_FACTORY_REGISTRY_H */ diff --git a/krita/image/kis_transform_mask_params_interface.h b/krita/image/kis_transform_mask_params_interface.h index 709b3b50df7..397aa6650f9 100644 --- a/krita/image/kis_transform_mask_params_interface.h +++ b/krita/image/kis_transform_mask_params_interface.h @@ -1,80 +1,80 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TRANSFORM_MASK_PARAMS_INTERFACE_H #define __KIS_TRANSFORM_MASK_PARAMS_INTERFACE_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include class QTransform; class QDomElement; class KRITAIMAGE_EXPORT KisTransformMaskParamsInterface { public: virtual ~KisTransformMaskParamsInterface(); virtual QTransform finalAffineTransform() const = 0; virtual bool isAffine() const = 0; virtual bool isHidden() const = 0; virtual void transformDevice(KisNodeSP node, KisPaintDeviceSP src, KisPaintDeviceSP dst) const = 0; virtual QString id() const = 0; virtual void toXML(QDomElement *e) const = 0; virtual void translate(const QPointF &offset) = 0; }; class QDomElement; class KRITAIMAGE_EXPORT KisDumbTransformMaskParams : public KisTransformMaskParamsInterface { public: KisDumbTransformMaskParams(); KisDumbTransformMaskParams(const QTransform &transform); KisDumbTransformMaskParams(bool isHidden); ~KisDumbTransformMaskParams(); QTransform finalAffineTransform() const; bool isAffine() const; bool isHidden() const; void transformDevice(KisNodeSP node, KisPaintDeviceSP src, KisPaintDeviceSP dst) const; QString id() const; void toXML(QDomElement *e) const; static KisTransformMaskParamsInterfaceSP fromXML(const QDomElement &e); void translate(const QPointF &offset); // for tesing purposes only QTransform testingGetTransform() const; void testingSetTransform(const QTransform &t); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_TRANSFORM_MASK_PARAMS_INTERFACE_H */ diff --git a/krita/image/kis_transform_worker.h b/krita/image/kis_transform_worker.h index d02ed4f7785..5599b30da6f 100644 --- a/krita/image/kis_transform_worker.h +++ b/krita/image/kis_transform_worker.h @@ -1,160 +1,160 @@ /* * Copyright (c) 2004 Michael Thaler * Copyright (c) 2005 C. Boemann * Copyright (c) 2010 Marc Pegon * * 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_TRANSFORM_WORKER_H_ #define KIS_TRANSFORM_WORKER_H_ #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include #include class KisPaintDevice; class KisFilterStrategy; class QTransform; class KRITAIMAGE_EXPORT KisTransformWorker { /* What are xshearOrigin, yshearOrigin : * * let's keep it simple and say we only have horizontal shearing (it's similar with vertical shearing) * that means we will apply the transformation : * x' = x + xshear * y and y' = y, where x,y are the old coordinates of the pixels, and x' y' the new coordinates * that means, the more we go down in the image (y++), the more x' is different from x * most of the times, we want to shear a part of the image centered at y = y0 != 0. * i.e. we want x' = x at y = y0 * in that case, it's good to apply instead x' = x + xshear * (y - yshearOrigin), y' = y. * please note that it's still possible to obtain the same result by copying the part you want to shear at * in another paintDevice at y = -y0 and use the transformWorker with yshearOrigin = 0. */ public: KisTransformWorker(KisPaintDeviceSP dev, double xscale, double yscale, double xshear, double yshear, double xshearOrigin, double yshearOrigin, double rotation, qint32 xtranslate, qint32 ytranslate, KoUpdaterPtr progress, KisFilterStrategy *filter); ~KisTransformWorker(); /** * Mirror the specified device along the X or Y axis at the * coordinate \p axis. */ static void mirror(KisPaintDeviceSP dev, qreal axis, Qt::Orientation orientation); /** * Convenience methods for mirror(dev, axis, orientation) */ static void mirrorX(KisPaintDeviceSP dev, qreal axis); static void mirrorY(KisPaintDeviceSP dev, qreal axis); /** * Mirror the device relative to the center of its exactBounds() */ static void mirrorX(KisPaintDeviceSP dev); static void mirrorY(KisPaintDeviceSP dev); /** * Offset the specified device with wraping around edges of rect specified as QRect(0,0,wrapSize.width, wrapSize.height)* * @param device device to be offset * @param offsetPosition position where the new origin will be * @param wrapSize width and height of the wrap edge, usual scenario is to use canvas width&height * **/ static void offset(KisPaintDeviceSP device, const QPoint &offsetPosition, const QRect &wrapRect); public: // returns false if interrupted bool run(); bool runPartial(const QRect &processRect); /** * Returns a matrix of the transformation executed by the worker. * Resulting transformation has the following form (in Qt's matrix * notation (all the matrices are trasposed)): * * transform = TS.inverted() * S * TS * SC * R * T * * ,where: * TS - shear origin transpose * S - shear itself (shearX * shearY) * SC - scale * R - rotation (@rotation parameter) * T - transpose (@xtranslate, @ytranslate) * * WARNING: due to some rounding problems in the worker * the work it does does not correspond to the matrix exactly! * The result always differs 1-3 pixel. So be careful with it * (or fix it) */ QTransform transform() const; /** * Transforms the outline of the pixel selection (if it is valid) */ void transformPixelSelectionOutline(KisPixelSelectionSP pixelSelection) const; private: // XXX (BSAR): Why didn't we use the shared-pointer versions of the paint device classes? // CBR: because the template functions used within don't work if it's not true pointers template void transformPass(KisPaintDevice* src, KisPaintDevice* dst, double xscale, double shear, double dx, KisFilterStrategy *filterStrategy, int portion); friend class KisTransformWorkerTest; static QRect rotateRight90(KisPaintDeviceSP dev, QRect boundRect, KoUpdaterPtr progressUpdater, int portion); static QRect rotateLeft90(KisPaintDeviceSP dev, QRect boundRect, KoUpdaterPtr progressUpdater, int portion); static QRect rotate180(KisPaintDeviceSP dev, QRect boundRect, KoUpdaterPtr progressUpdater, int portion); private: KisPaintDeviceSP m_dev; double m_xscale, m_yscale; double m_xshear, m_yshear, m_rotation; double m_xshearOrigin, m_yshearOrigin; qint32 m_xtranslate, m_ytranslate; KoUpdaterPtr m_progressUpdater; KisFilterStrategy *m_filter; QRect m_boundRect; }; #endif // KIS_TRANSFORM_VISITOR_H_ diff --git a/krita/image/kis_undo_adapter.h b/krita/image/kis_undo_adapter.h index 850c105256a..86f88d8bf68 100644 --- a/krita/image/kis_undo_adapter.h +++ b/krita/image/kis_undo_adapter.h @@ -1,65 +1,65 @@ /* * Copyright (c) 2003 Patrick Julien * * 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_UNDO_ADAPTER_H_ #define KIS_UNDO_ADAPTER_H_ #include -#include +#include #include "kis_types.h" #include "kis_undo_store.h" class KRITAIMAGE_EXPORT KisUndoAdapter : public QObject { Q_OBJECT public: KisUndoAdapter(KisUndoStore *undoStore); virtual ~KisUndoAdapter(); public: void emitSelectionChanged(); virtual const KUndo2Command* presentCommand() = 0; virtual void undoLastCommand() = 0; virtual void addCommand(KUndo2Command *cmd) = 0; virtual void beginMacro(const KUndo2MagicString& macroName) = 0; virtual void endMacro() = 0; inline void setUndoStore(KisUndoStore *undoStore) { m_undoStore = undoStore; } Q_SIGNALS: void selectionChanged(); protected: inline KisUndoStore* undoStore() { return m_undoStore; } private: Q_DISABLE_COPY(KisUndoAdapter) KisUndoStore *m_undoStore; }; #endif // KIS_UNDO_ADAPTER_H_ diff --git a/krita/image/kis_undo_store.h b/krita/image/kis_undo_store.h index af1b81bb085..ca8f2696454 100644 --- a/krita/image/kis_undo_store.h +++ b/krita/image/kis_undo_store.h @@ -1,82 +1,82 @@ /* * Copyright (c) 2003 Patrick Julien * * 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_UNDO_STORE_H_ #define KIS_UNDO_STORE_H_ #include #include -#include +#include #include "kis_types.h" class KUndo2Command; class KUndo2MagicString; /** * See also: http://community.kde.org/Krita/Undo_adapter_vs_Undo_store * * Split the functionality of KisUndoAdapter into two classes: * KisUndoStore and KisUndoAdapter. The former one works as an * interface to an external storage of the undo information: * undo stack, KisDocument, /dev/null. The latter one defines the * behavior of the system when someone wants to add a command. There * are three variants: * 1) KisSurrogateUndoAdapter -- saves commands directly to the * internal stack. Used for wrapping around legacy code into * a single command. * 2) KisLegacyUndoAdapter -- blocks the strokes and updates queue, * and then adds the command to a store * 3) KisPostExecutionUndoAdapter -- used by the strokes. It doesn't * call redo() when you add a command. It is assumed, that you have * already executed the command yourself and now just notify * the system about it. Warning: it doesn't inherit KisUndoAdapter * because it doesn't fit the contract of this class. And, more * important, KisTransaction should work differently with this class. * * The ownership on the KisUndoStore (that substituted KisUndoAdapter * in the document's code) now belongs to the image. It means that * KisDocument::createUndoStore() is just a factory method, the document * doesn't store the undo store itself. */ class KRITAIMAGE_EXPORT KisUndoStore { public: KisUndoStore(); virtual ~KisUndoStore(); public: /** * WARNING: All these methods are not considered as thread-safe */ virtual const KUndo2Command* presentCommand() = 0; virtual void undoLastCommand() = 0; virtual void addCommand(KUndo2Command *cmd) = 0; virtual void beginMacro(const KUndo2MagicString& macroName) = 0; virtual void endMacro() = 0; virtual void purgeRedoState() = 0; private: Q_DISABLE_COPY(KisUndoStore) }; #endif // KIS_UNDO_STORE_H_ diff --git a/krita/image/kis_update_scheduler.h b/krita/image/kis_update_scheduler.h index ab0f1f36954..6378ae9a94a 100644 --- a/krita/image/kis_update_scheduler.h +++ b/krita/image/kis_update_scheduler.h @@ -1,190 +1,190 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_UPDATE_SCHEDULER_H #define __KIS_UPDATE_SCHEDULER_H #include -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include "kis_image_interfaces.h" class QRect; class KoProgressProxy; class KisProjectionUpdateListener; class KisSpontaneousJob; class KRITAIMAGE_EXPORT KisUpdateScheduler : public QObject, public KisStrokesFacade { Q_OBJECT public: KisUpdateScheduler(KisProjectionUpdateListener *projectionUpdateListener); virtual ~KisUpdateScheduler(); /** * Sets the proxy that is going to be notified about the progress * of processing of the queues. If you want to switch the proxy * on runtime, you should do it under the lock held. * * \see lock(), unlock() */ void setProgressProxy(KoProgressProxy *progressProxy); /** * Blocks processing of the queues. * The function will wait until all the executing jobs * are finished. * NOTE: you may add new jobs while the block held, but they * will be delayed until unlock() is called. * * \see unlock() */ void lock(); /** * Unblocks the process and calls processQueues() * * \see processQueues() */ void unlock(); /** * Called when it is necessary to reread configuration */ void updateSettings(); /** * Waits until all the running jobs are finished. * * If some other thread adds jobs in parallel, then you may * wait forever. If you you don't want it, consider lock() instead. * * \see lock() */ void waitForDone(); /** * Waits until the queues become empty, then blocks the processing. * To unblock processing you should use unlock(). * * If some other thread adds jobs in parallel, then you may * wait forever. If you you don't want it, consider lock() instead. * * \see unlock(), lock() */ void barrierLock(); /** * Works like barrier lock, but returns false immediately if barrierLock * can't be acquired. * * \see barrierLock() */ bool tryBarrierLock(); /** * Blocks all the updates from execution. It doesn't affect * strokes execution in any way. This tipe of lock is supposed * to be held by the strokes themselves when they need a short * access to some parts of the projection of the image. * From all the other places you should use usual lock()/unlock() * methods * * \see lock(), unlock() */ void blockUpdates(); /** * Unblocks updates from execution previously locked by blockUpdates() * * \see blockUpdates() */ void unblockUpdates(); void updateProjection(KisNodeSP node, const QRect& rc, const QRect &cropRect); void updateProjectionNoFilthy(KisNodeSP node, const QRect& rc, const QRect &cropRect); void fullRefreshAsync(KisNodeSP root, const QRect& rc, const QRect &cropRect); void fullRefresh(KisNodeSP root, const QRect& rc, const QRect &cropRect); void addSpontaneousJob(KisSpontaneousJob *spontaneousJob); KisStrokeId startStroke(KisStrokeStrategy *strokeStrategy); void addJob(KisStrokeId id, KisStrokeJobData *data); void endStroke(KisStrokeId id); bool cancelStroke(KisStrokeId id); /** * tryCancelCurrentStrokeAsync() checks whether there is a * *running* stroke (which is being executed at this very moment) * which is not still open by the owner (endStroke() or * cancelStroke() have already been called) and cancels it. * * \return true if some stroke has been found and cancelled * * \note This method is *not* part of KisStrokesFacade! It is too * low level for KisImage. In KisImage it is combined with * more high level requestStrokeCancellation(). */ bool tryCancelCurrentStrokeAsync(); bool wrapAroundModeSupported() const; protected: // Trivial constructor for testing support KisUpdateScheduler(); void connectSignals(); void processQueues(); private Q_SLOTS: void continueUpdate(const QRect &rect); void doSomeUsefulWork(); void spareThreadAppeared(); private: friend class UpdatesBlockTester; bool haveUpdatesRunning(); void tryProcessUpdatesQueue(); void wakeUpWaitingThreads(); void progressUpdate(); protected: struct Private; Private * const m_d; }; class KisTestableUpdaterContext; class KisTestableSimpleUpdateQueue; class KRITAIMAGE_EXPORT KisTestableUpdateScheduler : public KisUpdateScheduler { public: KisTestableUpdateScheduler(KisProjectionUpdateListener *projectionUpdateListener, qint32 threadCount); KisTestableUpdaterContext* updaterContext(); KisTestableSimpleUpdateQueue* updateQueue(); using KisUpdateScheduler::processQueues; }; #endif /* __KIS_UPDATE_SCHEDULER_H */ diff --git a/krita/image/kis_update_time_monitor.h b/krita/image/kis_update_time_monitor.h index b56930ad697..dc47a80da8d 100644 --- a/krita/image/kis_update_time_monitor.h +++ b/krita/image/kis_update_time_monitor.h @@ -1,56 +1,56 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_UPDATE_TIME_MONITOR_H #define __KIS_UPDATE_TIME_MONITOR_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_types.h" #include class QPointF; class QRect; class KRITAIMAGE_EXPORT KisUpdateTimeMonitor { public: static KisUpdateTimeMonitor* instance(); ~KisUpdateTimeMonitor(); void startStrokeMeasure(); void endStrokeMeasure(); void reportPaintOpPreset(KisPaintOpPresetSP preset); void reportMouseMove(const QPointF &pos); void printValues(); void reportJobStarted(void *key); void reportJobFinished(void *key, const QVector &rects); void reportUpdateFinished(const QRect &rect); private: KisUpdateTimeMonitor(); private: struct Private; Private * const m_d; }; #endif /* __KIS_UPDATE_TIME_MONITOR_H */ diff --git a/krita/image/kis_warptransform_worker.h b/krita/image/kis_warptransform_worker.h index 084620be433..d95d698455d 100644 --- a/krita/image/kis_warptransform_worker.h +++ b/krita/image/kis_warptransform_worker.h @@ -1,83 +1,83 @@ /* * kis_warptransform_worker.h - part of Krita * * Copyright (c) 2010 Marc Pegon * * 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_WARPTRANSFORM_WORKER_H #define KIS_WARPTRANSFORM_WORKER_H #include "kis_types.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_paint_device.h" #include #include #include #include #include #include /** * Class to apply a transformation (affine, similitude, MLS) to a paintDevice * or a QImage according an original set of points p, a new set of points q, * and the constant alpha. * The algorithms are based a paper entitled "Image Deformation Using * Moving Least Squares", by Scott Schaefer (Texas A&M University), Travis * McPhail (Rice University) and Joe Warren (Rice University) */ class KRITAIMAGE_EXPORT KisWarpTransformWorker : public QObject { Q_OBJECT public: typedef enum WarpType_ {AFFINE_TRANSFORM = 0, SIMILITUDE_TRANSFORM, RIGID_TRANSFORM, N_MODES} WarpType; static QPointF affineTransformMath(QPointF v, QVector p, QVector q, qreal alpha); static QPointF similitudeTransformMath(QPointF v, QVector p, QVector q, qreal alpha); static QPointF rigidTransformMath(QPointF v, QVector p, QVector q, qreal alpha); static QImage transformQImage(WarpType warpType, const QVector &origPoint, const QVector &transfPoint, qreal alpha, const QImage& srcImage, const QPointF &srcQImageOffset, QPointF *newOffset); // Prepare the transformation on dev KisWarpTransformWorker(WarpType warpType, KisPaintDeviceSP dev, QVector origPoint, QVector transfPoint, qreal alpha, KoUpdater *progress); ~KisWarpTransformWorker(); // Perform the prepated transformation void run(); private: struct FunctionTransformOp; typedef QPointF (*WarpMathFunction)(QPointF, QVector, QVector, qreal); private: WarpMathFunction m_warpMathFunction; QVector m_origPoint; QVector m_transfPoint; qreal m_alpha; KisPaintDeviceSP m_dev; KoUpdater *m_progress; }; #endif diff --git a/krita/image/krita_utils.h b/krita/image/krita_utils.h index 07b9fb6f85a..4bc9a7c543a 100644 --- a/krita/image/krita_utils.h +++ b/krita/image/krita_utils.h @@ -1,67 +1,67 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KRITA_UTILS_H #define __KRITA_UTILS_H class QRect; class QRectF; class QSize; class QPen; class QPointF; class QPainterPath; class QBitArray; #include -#include "krita_export.h" +#include "kritaimage_export.h" namespace KritaUtils { QSize KRITAIMAGE_EXPORT optimalPatchSize(); QVector KRITAIMAGE_EXPORT splitRectIntoPatches(const QRect &rc, const QSize &patchSize); QRegion KRITAIMAGE_EXPORT splitTriangles(const QPointF ¢er, const QVector &points); QRegion KRITAIMAGE_EXPORT splitPath(const QPainterPath &path); void KRITAIMAGE_EXPORT initAntsPen(QPen *antsPen, QPen *outlinePen, int antLength = 4, int antSpace = 4); QString KRITAIMAGE_EXPORT prettyFormatReal(qreal value); qreal KRITAIMAGE_EXPORT maxDimensionPortion(const QRectF &bounds, qreal portion, qreal minValue); QPainterPath KRITAIMAGE_EXPORT trySimplifyPath(const QPainterPath &path, qreal lengthThreshold); /** * Split a path \p path into a set of disjoint (non-intersectable) * paths if possible. * * It tries to follow odd-even fill rule, but has a small problem: * If you have three selections included into each other twice, * then the smallest selection will be included into the final subpath, * although it shouldn't according to odd-even-fill rule. It is still * to be fixed. */ QList KRITAIMAGE_EXPORT splitDisjointPaths(const QPainterPath &path); quint8 KRITAIMAGE_EXPORT mergeOpacity(quint8 opacity, quint8 parentOpacity); QBitArray KRITAIMAGE_EXPORT mergeChannelFlags(const QBitArray &flags, const QBitArray &parentFlags); } #endif /* __KRITA_UTILS_H */ diff --git a/krita/image/krita_export.h b/krita/image/kritaimage_export.h similarity index 62% copy from krita/image/krita_export.h copy to krita/image/kritaimage_export.h index 586d01fc6b2..1e88d86fc50 100644 --- a/krita/image/krita_export.h +++ b/krita/image/kritaimage_export.h @@ -1,99 +1,59 @@ /* This file is part of krita Copyright (c) 2008 Boudewijn Rempt Copyright (c) 2008 Thomas Zander 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 KRITA_EXPORT_H -#define KRITA_EXPORT_H +#ifndef KRITAIMAGE_EXPORT_H +#define KRITAIMAGE_EXPORT_H #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ #if defined(_WIN32) || defined(_WIN64) -#ifndef KRITASKETCH_EXPORT -# ifdef MAKE_KRITASKETCHLIB_LIB -# define KRITASKETCH_EXPORT KDE_EXPORT -# else -# define KRITASKETCH_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef KRITAUI_EXPORT -# ifdef MAKE_KRITAUI_LIB -# define KRITAUI_EXPORT KDE_EXPORT -# else -# define KRITAUI_EXPORT KDE_IMPORT -# endif -#endif - #ifndef KRITAIMAGE_EXPORT # ifdef MAKE_KRITAIMAGE_LIB # define KRITAIMAGE_EXPORT KDE_EXPORT # else # define KRITAIMAGE_EXPORT KDE_IMPORT # endif #endif -#ifndef PAINTOP_EXPORT -# ifdef MAKE_KRITALIBPAINTOP_LIB -# define PAINTOP_EXPORT KDE_EXPORT -# else -# define PAINTOP_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef BRUSH_EXPORT -# ifdef MAKE_KRITALIBBRUSH_LIB -# define BRUSH_EXPORT KDE_EXPORT -# else -# define BRUSH_EXPORT KDE_IMPORT -# endif -#endif - #else // not windows -#define KRITASKETCH_EXPORT KDE_EXPORT -#define KRITAUI_EXPORT KDE_EXPORT #define KRITAIMAGE_EXPORT KDE_EXPORT -#define PAINTOP_EXPORT KDE_EXPORT -#define BRUSH_EXPORT KDE_EXPORT #endif /* not windows */ /* Now the same for Krita*_TEST_EXPORT, if compiling with unit tests enabled */ #ifdef COMPILING_TESTS # if defined _WIN32 || defined _WIN64 -# if defined(MAKE_KRITAUI_LIB) || defined(MAKE_KRITAIMAGE_LIB) +# if defined(MAKE_KRITAIMAGE_LIB) # define KRITAIMAGE_TEST_EXPORT KDE_EXPORT -# define KRITAUI_TEST_EXPORT KDE_EXPORT # else # define KRITAIMAGE_TEST_EXPORT KDE_IMPORT -# define KRITAUI_TEST_EXPORT KDE_IMPORT # endif # else /* not windows */ # define KRITAIMAGE_TEST_EXPORT KDE_EXPORT -# define KRITAUI_TEST_EXPORT KDE_EXPORT # endif #else /* not compiling tests */ # define KRITAIMAGE_TEST_EXPORT -# define KRITAUI_TEST_EXPORT #endif -#endif /* KRITA_EXPORT_H */ +#endif /* KRITAIMAGE_EXPORT_H */ diff --git a/krita/image/layerstyles/gimp_bump_map.h b/krita/image/layerstyles/gimp_bump_map.h index aa8ee80ca63..358c21df99b 100644 --- a/krita/image/layerstyles/gimp_bump_map.h +++ b/krita/image/layerstyles/gimp_bump_map.h @@ -1,77 +1,77 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * gimp_bump_map contains code taken from gimp-bumpmap.c, original copyright: * * Copyright (C) 1997 Federico Mena Quintero * Copyright (C) 1997-2000 Jens Lautenbacher * Copyright (C) 2000 Sven Neumann * * 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 __GIMP_BUMP_MAP_H #define __GIMP_BUMP_MAP_H #include #include "kis_types.h" enum BumpmapType { LINEAR = 0, SPHERICAL, SINUSOIDAL }; struct bumpmap_vals_t { bumpmap_vals_t() : bumpmap_id(0), azimuth(0), elevation(30), depth(50), xofs(0), yofs(0), waterlevel(0), ambient(10), compensate(true), invert(false), type(0), tiled(false) { } const qint32 bumpmap_id; double azimuth; double elevation; int depth; const int xofs; const int yofs; const int waterlevel; int ambient; bool compensate; bool invert; int type; const bool tiled; }; -void KDE_EXPORT bumpmap (KisPixelSelectionSP device, - const QRect &selectionRect, - const bumpmap_vals_t &bmvals); +void KRITAIMAGE_EXPORT bumpmap (KisPixelSelectionSP device, + const QRect &selectionRect, + const bumpmap_vals_t &bmvals); #endif /* __GIMP_BUMP_MAP_H */ diff --git a/krita/image/layerstyles/kis_layer_style_filter.h b/krita/image/layerstyles/kis_layer_style_filter.h index 3efa51bbc1c..194b0b1c622 100644 --- a/krita/image/layerstyles/kis_layer_style_filter.h +++ b/krita/image/layerstyles/kis_layer_style_filter.h @@ -1,67 +1,68 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LAYER_STYLE_FILTER_H #define __KIS_LAYER_STYLE_FILTER_H #include "kis_types.h" #include "kis_shared.h" +#include "kritaimage_export.h" #include class KisPSDLayerStyle; class KisLayerStyleFilterEnvironment; -class KDE_EXPORT KisLayerStyleFilter : public KisShared +class KRITAIMAGE_EXPORT KisLayerStyleFilter : public KisShared { public: KisLayerStyleFilter(const KoID &id); virtual ~KisLayerStyleFilter(); /** * \return Unique identifier for this filter */ QString id() const; virtual void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const = 0; /** * Some filters need pixels outside the current processing rect to compute the new * value (for instance, convolution filters) */ virtual QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const = 0; /** * Similar to \ref neededRect: some filters will alter a lot of pixels that are * near to each other at the same time. So when you changed a single rectangle * in a device, the actual rectangle that will feel the influence of this change * might be bigger. Use this function to determine that rect. */ virtual QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const = 0; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_LAYER_STYLE_FILTER_H */ diff --git a/krita/image/layerstyles/kis_layer_style_filter_environment.h b/krita/image/layerstyles/kis_layer_style_filter_environment.h index 0866e02d716..b5ba9cdb954 100644 --- a/krita/image/layerstyles/kis_layer_style_filter_environment.h +++ b/krita/image/layerstyles/kis_layer_style_filter_environment.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LAYER_STYLE_FILTER_ENVIRONMENT_H #define __KIS_LAYER_STYLE_FILTER_ENVIRONMENT_H #include #include -#include +#include class KisPainter; class KisLayer; class QPainterPath; class QBitArray; -class KDE_EXPORT KisLayerStyleFilterEnvironment +class KRITAIMAGE_EXPORT KisLayerStyleFilterEnvironment { public: KisLayerStyleFilterEnvironment(KisLayer *sourceLayer); ~KisLayerStyleFilterEnvironment(); QRect layerBounds() const; QRect defaultBounds() const; QPainterPath layerOutlineCache() const; void setupFinalPainter(KisPainter *gc, quint8 opacity, const QBitArray &channelFlags) const; private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_LAYER_STYLE_FILTER_ENVIRONMENT_H */ diff --git a/krita/image/layerstyles/kis_layer_style_projection_plane.h b/krita/image/layerstyles/kis_layer_style_projection_plane.h index 9f1aab44b10..6cd1de216f3 100644 --- a/krita/image/layerstyles/kis_layer_style_projection_plane.h +++ b/krita/image/layerstyles/kis_layer_style_projection_plane.h @@ -1,58 +1,59 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LAYER_STYLE_PROJECTION_PLANE_H #define __KIS_LAYER_STYLE_PROJECTION_PLANE_H #include "kis_abstract_projection_plane.h" #include #include "kis_types.h" +#include class KRITAIMAGE_EXPORT KisLayerStyleProjectionPlane : public KisAbstractProjectionPlane { public: KisLayerStyleProjectionPlane(KisLayer *sourceLayer); ~KisLayerStyleProjectionPlane(); QRect recalculate(const QRect& rect, KisNodeSP filthyNode); void apply(KisPainter *painter, const QRect &rect); QRect needRect(const QRect &rect, KisLayer::PositionToFilthy pos) const; QRect changeRect(const QRect &rect, KisLayer::PositionToFilthy pos) const; QRect accessRect(const QRect &rect, KisLayer::PositionToFilthy pos) const; // a method for registering on KisLayerStyleProjectionPlaneFactory static KisAbstractProjectionPlaneSP factoryObject(KisLayer *sourceLayer); private: friend class KisLayerStyleProjectionPlaneTest; KisLayerStyleProjectionPlane(KisLayer *sourceLayer, KisPSDLayerStyleSP style); void init(KisLayer *sourceLayer, KisPSDLayerStyleSP layerStyle); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_LAYER_STYLE_PROJECTION_PLANE_H */ diff --git a/krita/image/layerstyles/kis_ls_bevel_emboss_filter.h b/krita/image/layerstyles/kis_ls_bevel_emboss_filter.h index 43c19152b56..ffbf36e1c58 100644 --- a/krita/image/layerstyles/kis_ls_bevel_emboss_filter.h +++ b/krita/image/layerstyles/kis_ls_bevel_emboss_filter.h @@ -1,52 +1,53 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LS_BEVEL_EMBOSS_FILTER_H #define KIS_LS_BEVEL_EMBOSS_FILTER_H #include #include "kis_layer_style_filter.h" +#include struct psd_layer_effects_bevel_emboss; struct psd_layer_effects_context; -class KDE_EXPORT KisLsBevelEmbossFilter : public KisLayerStyleFilter +class KRITAIMAGE_EXPORT KisLsBevelEmbossFilter : public KisLayerStyleFilter { public: KisLsBevelEmbossFilter(); void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const; QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const; QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const; private: void applyBevelEmboss(KisPaintDeviceSP srcDevice, KisPaintDeviceSP dstDevice, const QRect &applyRect, const psd_layer_effects_bevel_emboss *config, KisLayerStyleFilterEnvironment *env) const; }; #endif diff --git a/krita/image/layerstyles/kis_ls_drop_shadow_filter.h b/krita/image/layerstyles/kis_ls_drop_shadow_filter.h index c75fdfb78ea..b51f2db6097 100644 --- a/krita/image/layerstyles/kis_ls_drop_shadow_filter.h +++ b/krita/image/layerstyles/kis_ls_drop_shadow_filter.h @@ -1,58 +1,59 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LS_DROP_SHADOW_FILTER_H #define KIS_LS_DROP_SHADOW_FILTER_H #include #include "kis_layer_style_filter.h" +#include -struct psd_layer_effects_shadow_base; +class psd_layer_effects_shadow_base; -class KDE_EXPORT KisLsDropShadowFilter : public KisLayerStyleFilter +class KRITAIMAGE_EXPORT KisLsDropShadowFilter : public KisLayerStyleFilter { public: enum Mode { DropShadow, InnerShadow, OuterGlow, InnerGlow }; KisLsDropShadowFilter(Mode mode = DropShadow); void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const; QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const; QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const; private: const psd_layer_effects_shadow_base* getShadowStruct(KisPSDLayerStyleSP style) const; private: const Mode m_mode; }; #endif diff --git a/krita/image/layerstyles/kis_ls_overlay_filter.h b/krita/image/layerstyles/kis_ls_overlay_filter.h index 9ce0d12255f..81eb52c8fca 100644 --- a/krita/image/layerstyles/kis_ls_overlay_filter.h +++ b/krita/image/layerstyles/kis_ls_overlay_filter.h @@ -1,64 +1,65 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LS_OVERLAY_FILTER_H #define KIS_LS_OVERLAY_FILTER_H #include #include "kis_layer_style_filter.h" +#include struct psd_layer_effects_overlay_base; struct psd_layer_effects_context; -class KDE_EXPORT KisLsOverlayFilter : public KisLayerStyleFilter +class KRITAIMAGE_EXPORT KisLsOverlayFilter : public KisLayerStyleFilter { public: enum Mode { Color, Gradient, Pattern }; public: KisLsOverlayFilter(Mode mode); void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const; QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const; QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const; private: const psd_layer_effects_overlay_base* getOverlayStruct(KisPSDLayerStyleSP style) const; void applyOverlay(KisPaintDeviceSP srcDevice, KisPaintDeviceSP dstDevice, const QRect &applyRect, const psd_layer_effects_overlay_base *config, KisLayerStyleFilterEnvironment *env) const; private: Mode m_mode; }; #endif diff --git a/krita/image/layerstyles/kis_ls_satin_filter.h b/krita/image/layerstyles/kis_ls_satin_filter.h index e680c73b14f..a4ece6183bf 100644 --- a/krita/image/layerstyles/kis_ls_satin_filter.h +++ b/krita/image/layerstyles/kis_ls_satin_filter.h @@ -1,44 +1,45 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LS_SATIN_FILTER_H #define KIS_LS_SATIN_FILTER_H #include #include "kis_layer_style_filter.h" +#include -struct psd_layer_effects_shadow_base; +class psd_layer_effects_shadow_base; -class KDE_EXPORT KisLsSatinFilter : public KisLayerStyleFilter +class KRITAIMAGE_EXPORT KisLsSatinFilter : public KisLayerStyleFilter { public: KisLsSatinFilter(); void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const; QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const; QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const; }; #endif diff --git a/krita/image/layerstyles/kis_ls_stroke_filter.h b/krita/image/layerstyles/kis_ls_stroke_filter.h index 430c5ff0928..d8d22280d01 100644 --- a/krita/image/layerstyles/kis_ls_stroke_filter.h +++ b/krita/image/layerstyles/kis_ls_stroke_filter.h @@ -1,52 +1,53 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_LS_STROKE_FILTER_H #define KIS_LS_STROKE_FILTER_H #include +#include #include "kis_layer_style_filter.h" struct psd_layer_effects_stroke; struct psd_layer_effects_context; -class KDE_EXPORT KisLsStrokeFilter : public KisLayerStyleFilter +class KRITAIMAGE_EXPORT KisLsStrokeFilter : public KisLayerStyleFilter { public: KisLsStrokeFilter(); void processDirectly(KisPaintDeviceSP src, KisPaintDeviceSP dst, const QRect &applyRect, KisPSDLayerStyleSP style, KisLayerStyleFilterEnvironment *env) const; QRect neededRect(const QRect & rect, KisPSDLayerStyleSP style) const; QRect changedRect(const QRect & rect, KisPSDLayerStyleSP style) const; private: void applyStroke(KisPaintDeviceSP srcDevice, KisPaintDeviceSP dstDevice, const QRect &applyRect, const psd_layer_effects_stroke *config, KisLayerStyleFilterEnvironment *env) const; }; #endif diff --git a/krita/image/layerstyles/kis_ls_utils.h b/krita/image/layerstyles/kis_ls_utils.h index b1d00793737..26694141fdf 100644 --- a/krita/image/layerstyles/kis_ls_utils.h +++ b/krita/image/layerstyles/kis_ls_utils.h @@ -1,94 +1,94 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_LS_UTILS_H #define __KIS_LS_UTILS_H #include "kis_types.h" struct psd_layer_effects_context; -struct psd_layer_effects_shadow_base; +class psd_layer_effects_shadow_base; struct psd_layer_effects_overlay_base; class KisLayerStyleFilterEnvironment; class KoPattern; namespace KisLsUtils { QRect growSelectionUniform(KisPixelSelectionSP selection, int growSize, const QRect &applyRect); KisSelectionSP selectionFromAlphaChannel(KisPaintDeviceSP device, const QRect &srcRect); void findEdge(KisPixelSelectionSP selection, const QRect &applyRect, const bool edgeHidden); QRect growRectFromRadius(const QRect &rc, int radius); void applyGaussian(KisPixelSelectionSP selection, const QRect &applyRect, qreal radius); static const int FULL_PERCENT_RANGE = 100; void adjustRange(KisPixelSelectionSP selection, const QRect &applyRect, const int range); void applyContourCorrection(KisPixelSelectionSP selection, const QRect &applyRect, const quint8 *lookup_table, bool antiAliased, bool edgeHidden); extern const int noiseNeedBorder; void applyNoise(KisPixelSelectionSP selection, const QRect &applyRect, int noise, const psd_layer_effects_context *context); void knockOutSelection(KisPixelSelectionSP selection, KisPixelSelectionSP knockOutSelection, const QRect &srcRect, const QRect &dstRect, const QRect &totalNeedRect, const bool knockOutInverted); void fillPattern(KisPaintDeviceSP fillDevice, const QRect &applyRect, KisLayerStyleFilterEnvironment *env, int scale, KoPattern *pattern, int horizontalPhase, int verticalPhase, bool alignWithLayer); void fillOverlayDevice(KisPaintDeviceSP fillDevice, const QRect &applyRect, const psd_layer_effects_overlay_base *config, KisLayerStyleFilterEnvironment *env); void applyFinalSelection(KisSelectionSP baseSelection, KisPaintDeviceSP srcDevice, KisPaintDeviceSP dstDevice, const QRect &srcRect, const QRect &dstRect, const psd_layer_effects_context *context, const psd_layer_effects_shadow_base *config, const KisLayerStyleFilterEnvironment *env); } #endif /* __KIS_LS_UTILS_H */ diff --git a/krita/image/metadata/kis_meta_data_entry.h b/krita/image/metadata/kis_meta_data_entry.h index 2eef10639d7..178a5f9743c 100644 --- a/krita/image/metadata/kis_meta_data_entry.h +++ b/krita/image/metadata/kis_meta_data_entry.h @@ -1,96 +1,97 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_ENTRY_H_ #define _KIS_META_DATA_ENTRY_H_ -#include +#include +#include class QString; namespace KisMetaData { class Value; class Store; class Schema; /** * Represent a metadata entry, a name and a value (\ref KisMetaData::Value). */ class KRITAIMAGE_EXPORT Entry { struct Private; friend class Store; public: /** * Create an invalid entry */ Entry(); /** * Create a new entry. * @param name * @param namespacePrefix * @param value */ Entry(const KisMetaData::Schema* schema, QString name, const KisMetaData::Value& value); Entry(const Entry&); ~Entry(); /** * @return the name of this entry */ QString name() const; /** * @return the namespace of this entry */ const KisMetaData::Schema* schema() const; /** * @return the qualified name of this entry, which is the concatenation of the * namespace and of the name */ QString qualifiedName() const; /** * @return the value of this entry */ const KisMetaData::Value& value() const; /** * @return the value of this entry */ KisMetaData::Value& value(); /** * @return true if this entry is valid */ bool isValid() const; /** * @return true if the name in argument is valid entry name. */ static bool isValidName(const QString& _name); /** * Affect the content of entry to this entry if entry is valid */ Entry& operator=(const Entry& entry); bool operator==(const Entry&) const; private: void setSchema(const KisMetaData::Schema* schema); private: Private* const d; }; } KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisMetaData::Entry &c); #endif diff --git a/krita/image/metadata/kis_meta_data_filter.h b/krita/image/metadata/kis_meta_data_filter.h index 9ad5b5af6d8..dadab01fdf1 100644 --- a/krita/image/metadata/kis_meta_data_filter.h +++ b/krita/image/metadata/kis_meta_data_filter.h @@ -1,51 +1,52 @@ /* * Copyright (c) 2007-2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_FILTER_H_ #define _KIS_META_DATA_FILTER_H_ -#include +#include +class QString; namespace KisMetaData { class Store; /** * This class is a base class for filtering a meta data store to alter some * information. For instance, remove author information or change edition * date. */ class Filter { public: virtual ~Filter(); /// @return true if the filter is enabled by default when exporting virtual bool defaultEnabled() const = 0; /// @return the id of this filter virtual QString id() const = 0; /// @return the name of this filter virtual QString name() const = 0; /// @return a description of this filter virtual QString description() const = 0; /** * Apply a filter on a meta data store. */ virtual void filter(KisMetaData::Store*) const = 0; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_filter_registry.h b/krita/image/metadata/kis_meta_data_filter_registry.h index 1709735ff83..3630d6f1018 100644 --- a/krita/image/metadata/kis_meta_data_filter_registry.h +++ b/krita/image/metadata/kis_meta_data_filter_registry.h @@ -1,43 +1,43 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_FILTER_REGISTRY_H_ #define _KIS_META_DATA_FILTER_REGISTRY_H_ -#include +#include #include "KoGenericRegistry.h" #include "kis_meta_data_filter.h" namespace KisMetaData { class KRITAIMAGE_EXPORT FilterRegistry : public KoGenericRegistry { public: virtual ~FilterRegistry(); static FilterRegistry* instance(); private: FilterRegistry(); FilterRegistry(const FilterRegistry&); FilterRegistry& operator=(const FilterRegistry&); }; } #endif diff --git a/krita/image/metadata/kis_meta_data_io_backend.h b/krita/image/metadata/kis_meta_data_io_backend.h index 2201a843dc8..d1b34fb5c71 100644 --- a/krita/image/metadata/kis_meta_data_io_backend.h +++ b/krita/image/metadata/kis_meta_data_io_backend.h @@ -1,117 +1,117 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_IO_BACKEND_H_ #define _KIS_META_DATA_IO_BACKEND_H_ -#include +#include #include class QIODevice; namespace KisMetaData { class Store; /** * This is a the interface for input or output backend to KisMetaData. * For instance, to add support to exif or xmp or iptc or dublin core * or anything else, it is needed to extend this interface. */ class KRITAIMAGE_EXPORT IOBackend { public: /** * Tell whether the backend input/output from/to binary data * or text (XML or RDF) data. */ enum BackendType { Binary, Text }; enum HeaderType { NoHeader, ///< Don't append any header JpegHeader ///< Append Jpeg-style header }; public: virtual ~IOBackend() {}; virtual QString id() const = 0; virtual QString name() const = 0; /** * @return the type of the backend */ virtual BackendType type() const = 0; /** * @return tell if this backend support saving */ virtual bool supportSaving() const = 0; /** * @param store the list of metadata to save * @param ioDevice the device to where the metadata will be saved * @param headerType determine if an header must be prepend to the binary header, and if it does, * which type of header * @return true if the save was successful (XXX: actually, all backends always return true...) */ virtual bool saveTo(Store* store, QIODevice* ioDevice, HeaderType headerType = NoHeader) const = 0; /** * @param store the list of metadata * @return true if this backend is capable of saving all the metadata * of the store */ virtual bool canSaveAllEntries(Store* store) const = 0; /** * @return true if this backend support loading */ virtual bool supportLoading() const = 0; /** * @param store the list of metadata to load * @param ioDevice the device from where the metadata will be loaded * @return true if the load was successful */ virtual bool loadFrom(Store* store, QIODevice* ioDevice) const = 0; }; class KRITAIMAGE_EXPORT IOBackendRegistry : public KoGenericRegistry { public: static IOBackendRegistry* instance(); private: IOBackendRegistry(); ~IOBackendRegistry(); }; } #endif diff --git a/krita/image/metadata/kis_meta_data_merge_strategy.h b/krita/image/metadata/kis_meta_data_merge_strategy.h index eb7ce1790a0..61b735493e6 100644 --- a/krita/image/metadata/kis_meta_data_merge_strategy.h +++ b/krita/image/metadata/kis_meta_data_merge_strategy.h @@ -1,62 +1,62 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_MERGE_STRATEGY_H_ #define _KIS_META_DATA_MERGE_STRATEGY_H_ #include -#include +#include class QString; namespace KisMetaData { class Store; /** * This is an interface which serves as a base class for meta data store merge * strategy. * This is used to decide which entries of a metadata store is kept, or how they * are modified when a list of meta data stores are merged together. */ class KRITAIMAGE_EXPORT MergeStrategy { public: virtual ~MergeStrategy(); /// @return the id of this merge strategy virtual QString id() const = 0; /// @return the name of this merge strategy virtual QString name() const = 0; /// @return a description of this merge strategy virtual QString description() const = 0; /** * Call this function to merge a list of meta data stores in one. * @param dst the destination store * @param srcs the list of source meta data store * @param scores a list of score which defines the importance of each store compared to the other * the sum of score is expected to be equal to 1.0. * One way to attribute a score is to compute the area of each layer and then * to give a higher score to the biggest layer. * srcs and scores list must have the same size. */ virtual void merge(Store* dst, QList srcs, QList scores) const = 0; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_merge_strategy_registry.h b/krita/image/metadata/kis_meta_data_merge_strategy_registry.h index 1f2b643c206..8d0320506b3 100644 --- a/krita/image/metadata/kis_meta_data_merge_strategy_registry.h +++ b/krita/image/metadata/kis_meta_data_merge_strategy_registry.h @@ -1,43 +1,43 @@ /* * Copyright (c) 2008 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_MERGE_STRATEGY_REGISTRY_H_ #define _KIS_META_DATA_MERGE_STRATEGY_REGISTRY_H_ -#include +#include #include "KoGenericRegistry.h" #include "kis_meta_data_merge_strategy.h" namespace KisMetaData { class KRITAIMAGE_EXPORT MergeStrategyRegistry : public KoGenericRegistry { public: virtual ~MergeStrategyRegistry(); static MergeStrategyRegistry* instance(); private: MergeStrategyRegistry(); MergeStrategyRegistry(const MergeStrategyRegistry&); MergeStrategyRegistry& operator=(const MergeStrategyRegistry&); }; } #endif diff --git a/krita/image/metadata/kis_meta_data_parser.h b/krita/image/metadata/kis_meta_data_parser.h index ed255ed881a..591a91ed854 100644 --- a/krita/image/metadata/kis_meta_data_parser.h +++ b/krita/image/metadata/kis_meta_data_parser.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_PARSER_H_ #define _KIS_META_DATA_PARSER_H_ -#include +#include #include namespace KisMetaData { class TypeInfo; class Value; /** * This class allow to parse from a string and return a value. */ class KRITAIMAGE_EXPORT Parser { friend class TypeInfo; public: virtual ~Parser(); virtual Value parse(const QString&) const = 0; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_schema.h b/krita/image/metadata/kis_meta_data_schema.h index edb982cef0c..1f0431eea45 100644 --- a/krita/image/metadata/kis_meta_data_schema.h +++ b/krita/image/metadata/kis_meta_data_schema.h @@ -1,74 +1,75 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_SCHEMA_H_ #define _KIS_META_DATA_SCHEMA_H_ -#include +#include +#include class QString; namespace KisMetaData { class SchemaRegistry; class TypeInfo; class KRITAIMAGE_EXPORT Schema { friend class SchemaRegistry; public: virtual ~Schema(); static const QString TIFFSchemaUri; static const QString EXIFSchemaUri; static const QString DublinCoreSchemaUri; static const QString XMPSchemaUri; static const QString XMPRightsSchemaUri; static const QString XMPMediaManagementUri; static const QString MakerNoteSchemaUri; static const QString IPTCSchemaUri; static const QString PhotoshopSchemaUri; private: Schema(); Schema(const QString & _uri, const QString & _ns); public: /** * @return the \ref TypeInfo associated with a given a property ( @p _propertyName ). */ const TypeInfo* propertyType(const QString& _propertyName) const; /** * @return the \ref TypeInfo describing a given structure of that scheam */ const TypeInfo* structure(const QString& _structureName) const; public: QString uri() const; QString prefix() const; QString generateQualifiedName(const QString &) const; private: struct Private; Private* const d; }; } KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisMetaData::Schema &c); #endif diff --git a/krita/image/metadata/kis_meta_data_schema_registry.h b/krita/image/metadata/kis_meta_data_schema_registry.h index bc5361a0552..42dd7f7216a 100644 --- a/krita/image/metadata/kis_meta_data_schema_registry.h +++ b/krita/image/metadata/kis_meta_data_schema_registry.h @@ -1,68 +1,69 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_SCHEMA_REGISTRY_H_ #define _KIS_META_DATA_SCHEMA_REGISTRY_H_ -#include +#include class QString; +class QDebug; namespace KisMetaData { class Schema; class KRITAIMAGE_EXPORT SchemaRegistry { struct Private; SchemaRegistry(); ~SchemaRegistry(); public: /** * Creates a new schema. * @param uri the name of the schema * @param prefix the namespace prefix used for this schema * @return the schema associated with the uri (it can return 0, if no schema exist * for the uri, but the prefix was already used, and it can be an already existing * schema if the uri was already included) */ const KisMetaData::Schema* create(const QString & uri, const QString & prefix); /** * @return the schema for this uri */ const Schema* schemaFromUri(const QString & uri) const; /** * @return the schema for this prefix */ const Schema* schemaFromPrefix(const QString & prefix) const; /** * Return an instance of the SchemaRegistry. * Creates an instance if that has never happened before and returns * the singleton instance. * Initialize it with default schemas. */ static KisMetaData::SchemaRegistry* instance(); private: Private* const d; }; } KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisMetaData::Schema &c); #endif diff --git a/krita/image/metadata/kis_meta_data_store.h b/krita/image/metadata/kis_meta_data_store.h index 87f3dc57d60..2275d61c7f2 100644 --- a/krita/image/metadata/kis_meta_data_store.h +++ b/krita/image/metadata/kis_meta_data_store.h @@ -1,182 +1,182 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_STORE_H_ #define _KIS_META_DATA_STORE_H_ -#include +#include #include namespace KisMetaData { class Schema; class Entry; class Filter; class Value; /** * This class holds the list of metadata entries and schemas (for instance the * author of the image, copyright holder, license, aperture, speed...) */ class KRITAIMAGE_EXPORT Store { struct Private; public: Store(); Store(const Store&); ~Store(); public: /** * Copy the entries from store inside this store */ void copyFrom(const Store* store); /** * @return true if there is no metadata in this store. */ bool empty() const; bool isEmpty() const; /** * Insert a new entry. * * @param entry the new entry to insert in the metadata store, it * must be a key which doesn't already exist * * @return false if the entry couldn't be included whether because the key already * exists */ bool addEntry(const Entry& entry); /** * Give access to a metadata entry * @param entryKey the entryKey as the qualified name of the entry */ Entry& getEntry(const QString & entryKey); /** * Give access to a metadata entry * @param uri the uri of the schema * @param entryName the name of the entry */ Entry& getEntry(const QString & uri, const QString & entryName); /** * Give access to a metadata entry * @param schema the schema * @param entryName the name of the entry */ Entry& getEntry(const KisMetaData::Schema* schema, const QString & entryName); /** * Give access to a metadata entry * @param entryKey the entryKey as the qualified name of the entry */ const Entry& getEntry(const QString & entryKey) const; /** * Give access to a metadata entry * @param uri the uri of the schema * @param entryName the name of the entry */ const Entry& getEntry(const QString & uri, const QString & entryName) const; /** * Give access to a metadata entry * @param schema the schema * @param entryName the name of the entry */ const Entry& getEntry(const KisMetaData::Schema* schema, const QString & entryName) const; /** * Remove an entry. * @param entryKey the entryKey as the qualified name of the entry */ void removeEntry(const QString & entryKey); /** * Remove an entry. * @param uri the uri of the schema * @param entryName the name of the entry */ void removeEntry(const QString & uri, const QString & entryName); /** * Remove an entry. * @param schema the schema * @param entryName the name of the entry */ void removeEntry(const KisMetaData::Schema* schema, const QString & entryName); /** * Return the value associated with this entry name and uri. * @param uri * @param entryName * @return the value */ const Value& getValue(const QString & uri, const QString & entryName) const; QHash::const_iterator begin() const; QHash::const_iterator end() const; /** * @param entryKey the entryKey as the qualified name of the entry * @return true if an entry with the given key exist in the store */ bool containsEntry(const QString & entryKey) const; /** * @return true if the store contains this entry */ bool containsEntry(const KisMetaData::Schema* schema, const QString & entryName) const; /** * @param uri * @param entryName * @return true if an entry with the given uri and entry name exist in the store */ bool containsEntry(const QString & uri, const QString & entryName) const; /** * Dump on kdDebug the metadata store. */ void debugDump() const; /** * Apply a list of filters on a store */ void applyFilters(const QList & filters); /** * @return the list of keys */ QList keys() const; /** * @return the list of entries */ QList entries() const; private: Private* const d; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_type_info.h b/krita/image/metadata/kis_meta_data_type_info.h index 37314b0a9fe..8ee20ed4c75 100644 --- a/krita/image/metadata/kis_meta_data_type_info.h +++ b/krita/image/metadata/kis_meta_data_type_info.h @@ -1,101 +1,101 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_TYPE_INFO_H_ #define _KIS_META_DATA_TYPE_INFO_H_ #include #include -#include +#include namespace KisMetaData { class Parser; class Schema; class Value; class KRITAIMAGE_EXPORT TypeInfo { public: enum PropertyType { BooleanType, IntegerType, DateType, TextType, OrderedArrayType, UnorderedArrayType, AlternativeArrayType, LangArrayType, StructureType, RationalType, GPSCoordinateType, OpenedChoice, ClosedChoice }; class KRITAIMAGE_EXPORT Choice { public: Choice(const Value&, const QString& hint); Choice(const Choice&); Choice& operator=(const Choice&); ~Choice(); public: const Value& value() const; const QString& hint() const; private: struct Private; Private* const d; }; private: TypeInfo(PropertyType _propertiesType); /** * Create a \ref TypeInfo for a */ TypeInfo(PropertyType _propertiesType, const TypeInfo* _embedded); /** * Create a \ref TypeInfo for a choice (either open or closed). * @param _propertiesType either OpenedChoice or ClosedChoice */ TypeInfo(PropertyType _propertiesType, const TypeInfo* _embedded, const QList< Choice >&); /** * Create a \ref TypeInfo for a structure. */ TypeInfo(Schema* _structureSchema, const QString& name); ~TypeInfo(); public: PropertyType propertyType() const; const TypeInfo* embeddedPropertyType() const; const QList< Choice >& choices() const; Schema* structureSchema() const; const QString& structureName() const; const Parser* parser() const; /** * @return true if @p value has a type that is correct for this \ref TypeInfo */ bool hasCorrectType(const Value& value) const; /** * @return true if @p value has a value acceptable for this \ref TypeInfo */ bool hasCorrectValue(const Value& value) const; public: struct Private; private: Private* const d; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_validator.h b/krita/image/metadata/kis_meta_data_validator.h index 2672a3c353a..325a86acf66 100644 --- a/krita/image/metadata/kis_meta_data_validator.h +++ b/krita/image/metadata/kis_meta_data_validator.h @@ -1,77 +1,77 @@ /* * Copyright (c) 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_VALIDATION_RESULT_H_ #define _KIS_META_DATA_VALIDATION_RESULT_H_ #include #include -#include +#include namespace KisMetaData { class Store; /** * This class contains information on the validation results of a \ref KisMetaData::Store . */ class KRITAIMAGE_EXPORT Validator { public: class KRITAIMAGE_EXPORT Reason { friend class Validator; friend class QMap; public: enum Type { UNKNOWN_REASON, UNKNOWN_ENTRY, INVALID_TYPE, INVALID_VALUE }; private: Reason(Type type = UNKNOWN_REASON); Reason(const Reason&); Reason& operator=(const Reason&); public: ~Reason(); Type type() const; private: struct Private; Private* const d; }; public: /** * Validate a store. This constructore will call the \ref revalidate function. */ Validator(const Store*); ~Validator(); int countInvalidEntries() const; int countValidEntries() const; const QMap& invalidEntries() const; /** * Call this function to revalidate the store. */ void revalidate(); private: struct Private; Private* const d; }; } #endif diff --git a/krita/image/metadata/kis_meta_data_value.h b/krita/image/metadata/kis_meta_data_value.h index 269bb8ffed5..c38d29b9b5f 100644 --- a/krita/image/metadata/kis_meta_data_value.h +++ b/krita/image/metadata/kis_meta_data_value.h @@ -1,132 +1,132 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_META_DATA_VALUE_H_ #define _KIS_META_DATA_VALUE_H_ #include #include -#include +#include class QVariant; namespace KisMetaData { struct Rational { explicit Rational(qint32 n = 0, qint32 d = 1) : numerator(n), denominator(d) {} qint32 numerator; qint32 denominator; bool operator==(const Rational& ur) const { return numerator == ur.numerator && denominator == ur.denominator; } }; /** * Value is build on top of QVariant to extend it to support the various types * and extensions through property qualifiers. */ class KRITAIMAGE_EXPORT Value { struct Private; public: /// Define the possible value type enum ValueType { Invalid, Variant, OrderedArray, UnorderedArray, AlternativeArray, LangArray, Structure, Rational }; public: Value(); Value(const QVariant& value); /** * @param type is one of OrderedArray, UnorderedArray, AlternativeArray * or LangArray */ Value(const QList& array, ValueType type = OrderedArray); Value(const QMap& structure); Value(const KisMetaData::Rational& rational); Value(const Value& v); Value& operator=(const Value& v); ~Value(); public: void addPropertyQualifier(const QString& _name, const Value&); const QMap& propertyQualifiers() const; public: /// @return the type of this Value ValueType type() const; /** * @return the value as a double, or null if it's not possible, rationals are evaluated */ double asDouble() const; /** * @return the value as an integer, or null if it's not possible, rationals are evaluated */ int asInteger() const; /** * @return the Variant hold by this Value, or an empty QVariant if this Value is not a Variant */ QVariant asVariant() const; /** * Set this Value to the given variant, or does nothing if this Value is not a Variant. * @return true if the value was changed */ bool setVariant(const QVariant& variant); bool setStructureVariant(const QString& fieldNAme, const QVariant& variant); bool setArrayVariant(int index, const QVariant& variant); /** * @return the Rational hold by this Value, or a null rational if this Value is not * an Rational */ KisMetaData::Rational asRational() const; /** * @return the array hold by this Value, or an empty array if this Value is not either * an OrderedArray, UnorderedArray or AlternativeArray */ QList asArray() const; /** * @return true if this Value is either an OrderedArray, UnorderedArray or AlternativeArray */ bool isArray() const; /** * @return the structure hold by this Value, or an empty structure if this Value is not a Structure */ QMap asStructure() const; /** * It's a convenient function that build a map from a LangArray using the property * qualifier "xml:lang" for the key of the map. */ QMap asLangArray() const; QString toString() const; public: bool operator==(const Value&) const; Value& operator+=(const Value&); private: Private* const d; }; } KRITAIMAGE_EXPORT QDebug operator<<(QDebug debug, const KisMetaData::Value &v); #endif diff --git a/krita/image/recorder/kis_action_recorder.h b/krita/image/recorder/kis_action_recorder.h index 9f1ca62db2a..4a12bfe709a 100644 --- a/krita/image/recorder/kis_action_recorder.h +++ b/krita/image/recorder/kis_action_recorder.h @@ -1,49 +1,49 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_ACTION_RECORDER_H_ #define _KIS_ACTION_RECORDER_H_ #include -#include "krita_export.h" +#include "kritaimage_export.h" class KisRecordedAction; /** * This class allows other \ref KisMacro to connect to it * to get the action that are currently created. */ class KRITAIMAGE_EXPORT KisActionRecorder : public QObject { Q_OBJECT public: KisActionRecorder(QObject* parent = 0); ~KisActionRecorder(); public Q_SLOTS: void addAction(const KisRecordedAction& action, const KisRecordedAction* before = 0); Q_SIGNALS: /** * This signal is emitted each time an action is added to this recorder. */ void addedAction(const KisRecordedAction& action); }; #endif diff --git a/krita/image/recorder/kis_macro.h b/krita/image/recorder/kis_macro.h index 0bf2ae51f84..ecf5f9bb69d 100644 --- a/krita/image/recorder/kis_macro.h +++ b/krita/image/recorder/kis_macro.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_MACRO_H_ #define _KIS_MACRO_H_ #include #include -#include +#include #include "kis_serializable_configuration.h" #include "kis_types.h" class KisRecordedAction; class KisRecordedActionLoadContext; class KisRecordedActionSaveContext; /** * This is the base class for macro in Krita. It's basically a list of recorded action,KisRecordedAction * that can be stored as XML, played, and edited. */ class KRITAIMAGE_EXPORT KisMacro : public QObject { Q_OBJECT public: KisMacro(QObject* parent = 0); KisMacro(const QList& _actions); ~KisMacro(); public: /** * Append a list of actions, and make clone of them. */ void appendActions(const QList& actions); /** * Remove the list of actions. Actions are deleted. */ void removeActions(const QList& actions); /** * Move the action before an other one. * @param before if null, the action is moved to the end */ void moveAction(const KisRecordedAction* action, const KisRecordedAction* before); public: // serialization functions virtual void fromXML(const QDomElement&, const KisRecordedActionLoadContext* loadContext); virtual void toXML(QDomDocument& doc, QDomElement& e, KisRecordedActionSaveContext* saveContext) const; const QList& actions() const; public Q_SLOTS: /** * add a single action, and make a clone of it. * @param before if non null, the action will be added before that action, * otherwise, if null, the action will be added at the end. */ virtual void addAction(const KisRecordedAction& action, const KisRecordedAction* before = 0); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/recorder/kis_macro_player.h b/krita/image/recorder/kis_macro_player.h index 3fee80ef094..4444fea4094 100644 --- a/krita/image/recorder/kis_macro_player.h +++ b/krita/image/recorder/kis_macro_player.h @@ -1,49 +1,49 @@ /* * Copyright (c) 2011 Cyrille Berger * * 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_MACRO_PLAYER_H_ #define _KIS_MACRO_PLAYER_H_ #include -#include +#include #include class KisMacro; class KisPlayInfo; class KoUpdater; /** * This class play a macro inside a thread. */ class KRITAIMAGE_EXPORT KisMacroPlayer : public QThread { Q_OBJECT public: KisMacroPlayer(KisMacro* _macro, const KisPlayInfo& info, KoUpdater * updater = 0, QObject* _parent = 0); virtual ~KisMacroPlayer(); public Q_SLOTS: void pause(); void resume(); protected: virtual void run(); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/recorder/kis_node_query_path.h b/krita/image/recorder/kis_node_query_path.h index 2debed9e2da..31bad05ae3a 100644 --- a/krita/image/recorder/kis_node_query_path.h +++ b/krita/image/recorder/kis_node_query_path.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_NODE_QUERY_PATH_H_ #define _KIS_NODE_QUERY_PATH_H_ #include -#include +#include /** * This class represent a path to access a node starting from an other node. */ class KRITAIMAGE_EXPORT KisNodeQueryPath { KisNodeQueryPath(); public: ~KisNodeQueryPath(); KisNodeQueryPath(const KisNodeQueryPath&); KisNodeQueryPath& operator=(const KisNodeQueryPath&); QList queryNodes(KisImageWSP image, KisNodeSP currentNode) const; bool isRelative() const; // Use "///" style because of the needed "/*" /// This function return a string representing this path. Which is a list separated by '\' of: /// - '*': represents all layers /// - '..': represents the parent layer /// - number: index of the layer /// - '.': represents the current layer /// /// For instance: "1/*" return all children of the first layer, "../3" return the third layer of the parent /// of the current layer /// If the string starts with "/" then it's an aboslute path, otherwise it's a relative path. QString toString() const; /** * @param path * @param err if non null, it will be filled with an error message * @see toString for an explanation of the string format */ static KisNodeQueryPath fromString(const QString& path); static KisNodeQueryPath absolutePath(KisNodeSP node); private: struct Private; Private* const d; }; #endif diff --git a/krita/image/recorder/kis_play_info.h b/krita/image/recorder/kis_play_info.h index fc70650f250..9f54df938e0 100644 --- a/krita/image/recorder/kis_play_info.h +++ b/krita/image/recorder/kis_play_info.h @@ -1,42 +1,42 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_PLAY_INFO_H_ #define _KIS_PLAY_INFO_H_ #include -#include +#include class KisUndoAdapter; class KRITAIMAGE_EXPORT KisPlayInfo { public: KisPlayInfo(KisImageWSP image, KisNodeSP currentNodes); KisPlayInfo(const KisPlayInfo& _rhs); KisPlayInfo& operator=(const KisPlayInfo& _rhs); ~KisPlayInfo(); KisUndoAdapter* undoAdapter() const; KisImageWSP image() const; KisNodeSP currentNode() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/image/recorder/kis_recorded_action.h b/krita/image/recorder/kis_recorded_action.h index 70e898b1a24..c66b79a2982 100644 --- a/krita/image/recorder/kis_recorded_action.h +++ b/krita/image/recorder/kis_recorded_action.h @@ -1,78 +1,78 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_RECORDED_ACTION_H_ #define _KIS_RECORDED_ACTION_H_ class QDomDocument; class QDomElement; class QString; class KisUndoAdapter; class KisNodeQueryPath; class KisPlayInfo; class KisRecordedActionLoadContext; class KisRecordedActionSaveContext; class KoUpdater; -#include +#include #include /** * This class represent an action. */ class KRITAIMAGE_EXPORT KisRecordedAction { public: KisRecordedAction(const QString& id, const QString& name); KisRecordedAction(const KisRecordedAction&); virtual ~KisRecordedAction(); /** * Play the action. */ virtual void play(const KisPlayInfo& _info, KoUpdater* _updater = 0) const = 0; /** * Clone this action. */ virtual KisRecordedAction* clone() const = 0; virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; public: const QString& id() const; const QString& name() const; void setName(const QString& name); private: struct Private; Private* const d; }; /** * This class is used to create recorded action. */ class KRITAIMAGE_EXPORT KisRecordedActionFactory { public: KisRecordedActionFactory(QString id); virtual ~KisRecordedActionFactory(); virtual KisRecordedAction* fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*) = 0; QString id() const; QString name() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/image/recorder/kis_recorded_action_factory_registry.h b/krita/image/recorder/kis_recorded_action_factory_registry.h index f87b54174f5..83cd5fdb14f 100644 --- a/krita/image/recorder/kis_recorded_action_factory_registry.h +++ b/krita/image/recorder/kis_recorded_action_factory_registry.h @@ -1,36 +1,36 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_RECORDED_ACTION_FACTORY_REGISTRY_H_ #define _KIS_RECORDED_ACTION_FACTORY_REGISTRY_H_ #include class KisRecordedActionFactory; -#include +#include class KRITAIMAGE_EXPORT KisRecordedActionFactoryRegistry : public KoGenericRegistry { public: KisRecordedActionFactoryRegistry(); ~KisRecordedActionFactoryRegistry(); static KisRecordedActionFactoryRegistry* instance(); }; #endif diff --git a/krita/image/recorder/kis_recorded_action_load_context.h b/krita/image/recorder/kis_recorded_action_load_context.h index 116359ddbde..940fc3123b1 100644 --- a/krita/image/recorder/kis_recorded_action_load_context.h +++ b/krita/image/recorder/kis_recorded_action_load_context.h @@ -1,35 +1,35 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_RECORDED_ACTION_LOAD_CONTEXT_H_ #define _KIS_RECORDED_ACTION_LOAD_CONTEXT_H_ -#include "krita_export.h" +#include "kritaimage_export.h" class KoAbstractGradient; class KoPattern; class QString; class KRITAIMAGE_EXPORT KisRecordedActionLoadContext { public: virtual ~KisRecordedActionLoadContext(); virtual KoAbstractGradient* gradient(const QString& name) const = 0; virtual KoPattern* pattern(const QString& name) const = 0; }; #endif diff --git a/krita/image/recorder/kis_recorded_action_save_context.h b/krita/image/recorder/kis_recorded_action_save_context.h index 155e0633adf..c52ecf5ce37 100644 --- a/krita/image/recorder/kis_recorded_action_save_context.h +++ b/krita/image/recorder/kis_recorded_action_save_context.h @@ -1,34 +1,34 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_RECORDED_ACTION_SAVE_CONTEXT_H_ #define _KIS_RECORDED_ACTION_SAVE_CONTEXT_H_ -#include "krita_export.h" +#include "kritaimage_export.h" class KoAbstractGradient; class KoPattern; class KRITAIMAGE_EXPORT KisRecordedActionSaveContext { public: virtual ~KisRecordedActionSaveContext(); virtual void saveGradient(const KoAbstractGradient* gradient) = 0; virtual void savePattern(const KoPattern* pattern) = 0; }; #endif diff --git a/krita/image/recorder/kis_recorded_fill_paint_action.h b/krita/image/recorder/kis_recorded_fill_paint_action.h index 7a443778193..f51475c6960 100644 --- a/krita/image/recorder/kis_recorded_fill_paint_action.h +++ b/krita/image/recorder/kis_recorded_fill_paint_action.h @@ -1,65 +1,65 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_RECORDED_FILL_PAINT_ACTION_H_ #define _KIS_RECORDED_FILL_PAINT_ACTION_H_ #include "recorder/kis_recorded_action.h" #include "recorder/kis_recorded_paint_action.h" #include "kis_types.h" -#include +#include /** * This class will record the painting of a bezier curve. */ class KRITAIMAGE_EXPORT KisRecordedFillPaintAction : public KisRecordedPaintAction { public: KisRecordedFillPaintAction(const KisNodeQueryPath& path, const QPoint& pt, const KisNodeQueryPath& projectionPath); KisRecordedFillPaintAction(const KisRecordedFillPaintAction&); ~KisRecordedFillPaintAction(); virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; virtual KisRecordedAction* clone() const; protected: virtual KisPainter* createPainter(KisPaintDeviceSP device) const; virtual void playPaint(const KisPlayInfo& info, KisPainter* painter) const; private: struct Private; Private* const d; }; class KisRecordedFillPaintActionFactory : public KisRecordedPaintActionFactory { public: KisRecordedFillPaintActionFactory(); virtual ~KisRecordedFillPaintActionFactory(); virtual KisRecordedAction* fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*); }; #endif diff --git a/krita/image/recorder/kis_recorded_filter_action.h b/krita/image/recorder/kis_recorded_filter_action.h index d15f34702ca..691b374c4da 100644 --- a/krita/image/recorder/kis_recorded_filter_action.h +++ b/krita/image/recorder/kis_recorded_filter_action.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_RECORDED_FILTER_ACTION_H_ #define _KIS_RECORDED_FILTER_ACTION_H_ #include "recorder/kis_recorded_node_action.h" -#include +#include class QString; class KisFilterConfiguration; /** * Action representing a filter. */ class KRITAIMAGE_EXPORT KisRecordedFilterAction : public KisRecordedNodeAction { public: /** * @param config the filter configuration, the ownership of config remains in the caller. */ KisRecordedFilterAction(QString name, const KisNodeQueryPath& path, const KisFilter* filter, const KisFilterConfiguration* config); KisRecordedFilterAction(const KisRecordedFilterAction&); virtual ~KisRecordedFilterAction(); using KisRecordedNodeAction::play; virtual void play(KisNodeSP node, const KisPlayInfo& _info, KoUpdater* _updater = 0) const; virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; virtual KisRecordedAction* clone() const; const KisFilter* filter() const; const KisFilterConfiguration* filterConfiguration() const; /** * Set the configuration, and takes the ownership of the config object. */ void setFilterConfiguration(KisFilterConfiguration* config); private: struct Private; Private* const d; }; class KisRecordedFilterActionFactory : public KisRecordedActionFactory { public: KisRecordedFilterActionFactory(); virtual ~KisRecordedFilterActionFactory(); virtual KisRecordedAction* fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*); }; #endif diff --git a/krita/image/recorder/kis_recorded_paint_action.h b/krita/image/recorder/kis_recorded_paint_action.h index 1adf0c706d0..7a800ba7d0f 100644 --- a/krita/image/recorder/kis_recorded_paint_action.h +++ b/krita/image/recorder/kis_recorded_paint_action.h @@ -1,110 +1,110 @@ /* * Copyright (c) 2007,2010 Cyrille Berger * * 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_RECORDED_PAINT_ACTION_H_ #define _KIS_RECORDED_PAINT_ACTION_H_ #include "recorder/kis_recorded_node_action.h" #include "kis_types.h" #include "kis_painter.h" class KisPainter; class KoColor; -#include +#include /** * Base class for paint action. */ class KRITAIMAGE_EXPORT KisRecordedPaintAction : public KisRecordedNodeAction { public: KisRecordedPaintAction(const QString & id, const QString & name, const KisNodeQueryPath& path, KisPaintOpPresetSP paintOpPreset); KisRecordedPaintAction(const KisRecordedPaintAction&); ~KisRecordedPaintAction(); virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; using KisRecordedNodeAction::play; virtual void play(KisNodeSP node, const KisPlayInfo& info, KoUpdater* _updater = 0) const; protected: /** * This function will create a painter for the given device. The default * implementation creates a KisPainter, subclass can reimplement it if * they want to use one of the subclass of KisPainter. */ virtual KisPainter* createPainter(KisPaintDeviceSP device) const; /** * Reimplement this function in a subclass to play the painting. */ virtual void playPaint(const KisPlayInfo&, KisPainter* painter) const = 0; public: KisPaintOpPresetSP paintOpPreset() const; void setPaintOpPreset(KisPaintOpPresetSP preset); /** * @return the opacity in the range 0.0->1.0 */ qreal opacity() const; void setOpacity(qreal ); KoColor paintColor() const; void setPaintColor(const KoColor& color); KoColor backgroundColor() const; void setBackgroundColor(const KoColor& color); QString compositeOp(); void setCompositeOp(const QString& ); void setPaintIncremental(bool ); void setStrokeStyle(KisPainter::StrokeStyle ); void setFillStyle(KisPainter::FillStyle ); KisPainter::FillStyle fillStyle() const; void setPattern(const KoPattern* ); void setGradient(const KoAbstractGradient* gradient); void setGenerator(const KisFilterConfiguration * generator); private: struct Private; Private* const d; }; class KisRecordedPaintActionFactory : public KisRecordedActionFactory { public: KisRecordedPaintActionFactory(const QString & id) : KisRecordedActionFactory(id) {} virtual ~KisRecordedPaintActionFactory() {} protected: void setupPaintAction(KisRecordedPaintAction* action, const QDomElement& elt, const KisRecordedActionLoadContext*); KisPaintOpPresetSP paintOpPresetFromXML(const QDomElement& elt); KoColor paintColorFromXML(const QDomElement& elt); KoColor backgroundColorFromXML(const QDomElement& elt); KoColor colorFromXML(const QDomElement& elt, const QString& elementName); qreal opacityFromXML(const QDomElement& elt); bool paintIncrementalFromXML(const QDomElement& elt); QString compositeOpFromXML(const QDomElement& elt); KisNodeQueryPath nodeQueryPathFromXML(const QDomElement& elt); }; #endif diff --git a/krita/image/recorder/kis_recorded_path_paint_action.h b/krita/image/recorder/kis_recorded_path_paint_action.h index 494ce16509c..0194c36b3a5 100644 --- a/krita/image/recorder/kis_recorded_path_paint_action.h +++ b/krita/image/recorder/kis_recorded_path_paint_action.h @@ -1,77 +1,77 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_RECORDED_PATH_PAINT_ACTIONS_H_ #define _KIS_RECORDED_PATH_PAINT_ACTIONS_H_ #include "recorder/kis_recorded_action.h" #include "recorder/kis_recorded_paint_action.h" #include "kis_types.h" class KisPaintInformation; class KisPainter; -#include +#include /** * This class will record the painting of a bezier curve. */ class KRITAIMAGE_EXPORT KisRecordedPathPaintAction : public KisRecordedPaintAction { public: KisRecordedPathPaintAction(const KisNodeQueryPath& path, const KisPaintOpPresetSP paintOpPreset); KisRecordedPathPaintAction(const KisRecordedPathPaintAction&); ~KisRecordedPathPaintAction(); void addPoint(const KisPaintInformation& info); void addLine(const KisPaintInformation& point1, const KisPaintInformation& point2); void addPolyLine(const QList& points); void addCurve(const KisPaintInformation& point1, const QPointF& control1, const QPointF& control2, const KisPaintInformation& point2); virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; virtual KisRecordedAction* clone() const; protected: virtual void playPaint(const KisPlayInfo& info, KisPainter* painter) const; private: struct Private; Private* const d; }; class KisRecordedPathPaintActionFactory : public KisRecordedPaintActionFactory { public: KisRecordedPathPaintActionFactory(); virtual ~KisRecordedPathPaintActionFactory(); virtual KisRecordedAction* fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*); }; #endif diff --git a/krita/image/recorder/kis_recorded_shape_paint_action.h b/krita/image/recorder/kis_recorded_shape_paint_action.h index 9ca1634b7bf..af776557c1d 100644 --- a/krita/image/recorder/kis_recorded_shape_paint_action.h +++ b/krita/image/recorder/kis_recorded_shape_paint_action.h @@ -1,72 +1,72 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_RECORDED_ELLIPSE_PAINT_ACTION_H_ #define _KIS_RECORDED_ELLIPSE_PAINT_ACTION_H_ #include "recorder/kis_recorded_action.h" #include "recorder/kis_recorded_paint_action.h" #include "kis_types.h" -#include +#include /** * This class will record the painting of a bezier curve. */ class KRITAIMAGE_EXPORT KisRecordedShapePaintAction : public KisRecordedPaintAction { public: enum Shape { Ellipse, Rectangle }; public: KisRecordedShapePaintAction(const KisNodeQueryPath& path, const KisPaintOpPresetSP paintOpPreset, Shape shape, const QRectF& rect); KisRecordedShapePaintAction(const KisRecordedShapePaintAction&); ~KisRecordedShapePaintAction(); virtual void toXML(QDomDocument& doc, QDomElement& elt, KisRecordedActionSaveContext* ) const; virtual KisRecordedAction* clone() const; protected: virtual void playPaint(const KisPlayInfo& info, KisPainter* painter) const; private: struct Private; Private* const d; }; class KisRecordedShapePaintActionFactory : public KisRecordedPaintActionFactory { public: KisRecordedShapePaintActionFactory(); virtual ~KisRecordedShapePaintActionFactory(); virtual KisRecordedAction* fromXML(const QDomElement& elt, const KisRecordedActionLoadContext*); }; #endif diff --git a/krita/image/tiles3/kis_hline_iterator.h b/krita/image/tiles3/kis_hline_iterator.h index 04d258ab749..034d1ac3b5e 100644 --- a/krita/image/tiles3/kis_hline_iterator.h +++ b/krita/image/tiles3/kis_hline_iterator.h @@ -1,89 +1,89 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_HLINE_ITERATOR_H_ #define _KIS_HLINE_ITERATOR_H_ #include "kis_base_iterator.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_iterator_ng.h" class KRITAIMAGE_EXPORT KisHLineIterator2 : public KisHLineIteratorNG, public KisBaseIterator { KisHLineIterator2(const KisHLineIterator2&); KisHLineIterator2& operator=(const KisHLineIterator2&); public: struct KisTileInfo { KisTileSP tile; KisTileSP oldtile; quint8* data; quint8* oldData; }; public: KisHLineIterator2(KisDataManager *dataManager, qint32 x, qint32 y, qint32 w, qint32 offsetX, qint32 offsetY, bool writable); ~KisHLineIterator2(); virtual bool nextPixel(); virtual void nextRow(); virtual const quint8* oldRawData() const; virtual const quint8* rawDataConst() const; virtual quint8* rawData(); virtual qint32 nConseqPixels() const; virtual bool nextPixels(qint32 n); virtual qint32 x() const; virtual qint32 y() const; virtual void resetPixelPos(); virtual void resetRowPos(); private: qint32 m_offsetX; qint32 m_offsetY; qint32 m_x; // current x position qint32 m_y; // current y position qint32 m_row; // current row in tilemgr quint32 m_index; // current col in tilemgr quint32 m_tileWidth; quint8 *m_data; quint8 *m_oldData; bool m_havePixels; qint32 m_right; qint32 m_left; qint32 m_top; qint32 m_leftCol; qint32 m_rightCol; qint32 m_rightmostInTile; // limited by the current tile border only qint32 m_leftInLeftmostTile; qint32 m_yInTile; QVector m_tilesCache; quint32 m_tilesCacheSize; private: void switchToTile(qint32 xInTile); void fetchTileDataForCache(KisTileInfo& kti, qint32 col, qint32 row); void preallocateTiles(); }; #endif diff --git a/krita/image/tiles3/kis_tile_data_store.h b/krita/image/tiles3/kis_tile_data_store.h index 396829606a0..f6674cc95de 100644 --- a/krita/image/tiles3/kis_tile_data_store.h +++ b/krita/image/tiles3/kis_tile_data_store.h @@ -1,187 +1,187 @@ /* * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TILE_DATA_STORE_H_ #define KIS_TILE_DATA_STORE_H_ -#include "krita_export.h" +#include "kritaimage_export.h" #include #include "kis_tile_data_interface.h" #include "kis_tile_data_pooler.h" #include "swap/kis_tile_data_swapper.h" #include "swap/kis_swapped_data_store.h" class KisTileDataStoreIterator; class KisTileDataStoreReverseIterator; class KisTileDataStoreClockIterator; /** * Stores tileData objects. When needed compresses them and swaps. */ class KRITAIMAGE_EXPORT KisTileDataStore { private: KisTileDataStore(); public: static KisTileDataStore* instance(); ~KisTileDataStore(); void debugPrintList(); struct MemoryStatistics { qint64 totalMemorySize; qint64 realMemorySize; qint64 historicalMemorySize; qint64 poolSize; qint64 swapSize; }; MemoryStatistics memoryStatistics(); /** * Returns total number of tiles present: in memory * or in a swap file */ inline qint32 numTiles() const { return m_numTiles + m_swappedStore.numTiles(); } /** * Returns the number of tiles present in memory only */ inline qint32 numTilesInMemory() const { return m_numTiles; } inline void checkFreeMemory() { m_swapper.checkFreeMemory(); } /** * \see m_memoryMetric */ inline qint64 memoryMetric() const { return m_memoryMetric; } KisTileDataStoreIterator* beginIteration(); void endIteration(KisTileDataStoreIterator* iterator); KisTileDataStoreReverseIterator* beginReverseIteration(); void endIteration(KisTileDataStoreReverseIterator* iterator); KisTileDataStoreClockIterator* beginClockIteration(); void endIteration(KisTileDataStoreClockIterator* iterator); inline KisTileData* createDefaultTileData(qint32 pixelSize, const quint8 *defPixel) { return allocTileData(pixelSize, defPixel); } // Called by The Memento Manager after every commit inline void kickPooler() { m_pooler.kick(); //FIXME: maybe, rename a function? m_swapper.kick(); } /** * Try swap out the tile data. * It may fail in case the tile is being accessed * at the same moment of time. */ bool trySwapTileData(KisTileData *td); /** * WARN: The following three method are only for usage * in KisTileData. Do not call them directly! */ KisTileData *duplicateTileData(KisTileData *rhs); void freeTileData(KisTileData *td); /** * Ensures that the tile data is totally present in memory * and it's swapping is blocked by holding td->m_swapLock * in a read mode. * PRECONDITIONS: td->m_swapLock is *unlocked* * m_listRWLock is *unlocked* * POSTCONDITIONS: td->m_data is in memory and * td->m_swapLock is locked * m_listRWLock is unlocked */ void ensureTileDataLoaded(KisTileData *td); private: KisTileData *allocTileData(qint32 pixelSize, const quint8 *defPixel); void registerTileData(KisTileData *td); void unregisterTileData(KisTileData *td); inline void registerTileDataImp(KisTileData *td); inline void unregisterTileDataImp(KisTileData *td); void freeRegisteredTiles(); friend class DeadlockyThread; friend class KisLowMemoryTests; void debugSwapAll(); void debugClear(); friend class KisTiledDataManagerTest; void testingSuspendPooler(); void testingResumePooler(); friend class KisLowMemoryBenchmark; void testingRereadConfig(); private: KisTileDataPooler m_pooler; KisTileDataSwapper m_swapper; friend class KisTileDataStoreTest; friend class KisTileDataPoolerTest; KisSwappedDataStore m_swappedStore; KisTileDataListIterator m_clockIterator; QMutex m_listLock; KisTileDataList m_tileDataList; qint32 m_numTiles; /** * This metric is used for computing the volume * of memory occupied by tile data objects. * metric = num_bytes / (KisTileData::WIDTH * KisTileData::HEIGHT) */ qint64 m_memoryMetric; }; template inline T MiB_TO_METRIC(T value) { unsigned long long __MiB = 1ULL << 20; return value * (__MiB / (KisTileData::WIDTH * KisTileData::HEIGHT)); } #endif /* KIS_TILE_DATA_STORE_H_ */ diff --git a/krita/image/tiles3/kis_tiled_data_manager.h b/krita/image/tiles3/kis_tiled_data_manager.h index 014ffaa3fa6..f644a651c6b 100644 --- a/krita/image/tiles3/kis_tiled_data_manager.h +++ b/krita/image/tiles3/kis_tiled_data_manager.h @@ -1,394 +1,394 @@ /* * Copyright (c) 2004 Boudewijn Rempt * (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TILEDDATAMANAGER_H_ #define KIS_TILEDDATAMANAGER_H_ #include #include #include #include #include //#include "kis_debug.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_tile_hash_table.h" #include "kis_memento_manager.h" #include "kis_memento.h" class KisTiledDataManager; typedef KisSharedPtr KisTiledDataManagerSP; class KisTiledIterator; class KisTiledRandomAccessor; class KisPaintDeviceWriter; class QIODevice; /** * KisTiledDataManager implements the interface that KisDataManager defines * * The interface definition is enforced by KisDataManager calling all the methods * which must also be defined in KisTiledDataManager. It is not allowed to change the interface * as other datamangers may also rely on the same interface. * * * Storing undo/redo data * * Offering ordered and unordered iterators over rects of pixels * * (eventually) efficiently loading and saving data in a format * that may allow deferred loading. * * A datamanager knows nothing about the type of pixel data except * how many quint8's a single pixel takes. */ class KRITAIMAGE_EXPORT KisTiledDataManager : public KisShared { private: static const qint32 LEGACY_VERSION = 1; static const qint32 CURRENT_VERSION = 2; protected: /*FIXME:*/ public: KisTiledDataManager(quint32 pixelSize, const quint8 *defPixel); virtual ~KisTiledDataManager(); KisTiledDataManager(const KisTiledDataManager &dm); KisTiledDataManager & operator=(const KisTiledDataManager &dm); protected: // Allow the baseclass of iterators access to the interior // derived iterator classes must go through KisTiledIterator friend class KisTiledIterator; friend class KisBaseIterator; friend class KisTiledRandomAccessor; friend class KisRandomAccessor2; friend class KisStressJob; public: void setDefaultPixel(const quint8 *defPixel); const quint8 *defaultPixel() const { return m_defaultPixel; } inline KisTileSP getTile(qint32 col, qint32 row, bool writable) { if (writable) { bool newTile; KisTileSP tile = m_hashTable->getTileLazy(col, row, newTile); if (newTile) updateExtent(tile->col(), tile->row()); return tile; } else { return m_hashTable->getReadOnlyTileLazy(col,row); } } inline KisTileSP getOldTile(qint32 col, qint32 row) { KisTileSP tile = m_mementoManager->getCommitedTile(col, row); return tile ? tile : getTile(col, row, false); } KisMementoSP getMemento() { QWriteLocker locker(&m_lock); KisMementoSP memento = m_mementoManager->getMemento(); memento->saveOldDefaultPixel(m_defaultPixel, m_pixelSize); return memento; } /** * Finishes having already started transaction */ void commit() { QWriteLocker locker(&m_lock); KisMementoSP memento = m_mementoManager->currentMemento(); if(memento) { memento->saveNewDefaultPixel(m_defaultPixel, m_pixelSize); } m_mementoManager->commit(); } void rollback(KisMementoSP memento) { commit(); QWriteLocker locker(&m_lock); m_mementoManager->rollback(m_hashTable); const quint8 *defaultPixel = memento->oldDefaultPixel(); if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) { setDefaultPixelImpl(defaultPixel); } recalculateExtent(); } void rollforward(KisMementoSP memento) { commit(); QWriteLocker locker(&m_lock); m_mementoManager->rollforward(m_hashTable); const quint8 *defaultPixel = memento->newDefaultPixel(); if(memcmp(m_defaultPixel, defaultPixel, m_pixelSize)) { setDefaultPixelImpl(defaultPixel); } recalculateExtent(); } bool hasCurrentMemento() const { return m_mementoManager->hasCurrentMemento(); //return true; } /** * Removes all the history that preceds the revision * pointed by oldestMemento. That is after calling to * purgeHistory(someMemento) you won't be able to do * rollback(someMemento) anymore. */ void purgeHistory(KisMementoSP oldestMemento) { QWriteLocker locker(&m_lock); m_mementoManager->purgeHistory(oldestMemento); } static void releaseInternalPools(); protected: /** * Reads and writes the tiles */ bool write(KisPaintDeviceWriter &store); bool read(QIODevice *stream); void purge(const QRect& area); inline quint32 pixelSize() const { return m_pixelSize; } /* FIXME:*/ public: void extent(qint32 &x, qint32 &y, qint32 &w, qint32 &h) const; void setExtent(qint32 x, qint32 y, qint32 w, qint32 h); QRect extent() const; void setExtent(QRect newRect); QRegion region() const; void clear(QRect clearRect, quint8 clearValue); void clear(QRect clearRect, const quint8 *clearPixel); void clear(qint32 x, qint32 y, qint32 w, qint32 h, quint8 clearValue); void clear(qint32 x, qint32 y, qint32 w, qint32 h, const quint8 *clearPixel); void clear(); /** * Clones rect from another datamanager. The cloned area will be * shared between both datamanagers as much as possible using * copy-on-write. Parts of the rect that cannot be shared * (cross tiles) are deep-copied, */ void bitBlt(KisTiledDataManager *srcDM, const QRect &rect); /** * The same as \ref bitBlt(), but reads old data */ void bitBltOldData(KisTiledDataManager *srcDM, const QRect &rect); /** * Clones rect from another datamanager in a rough and fast way. * All the tiles touched by rect will be shared, between both * managers, that means it will copy a bigger area than was * requested. This method is supposed to be used for bitBlt'ing * into temporary paint devices. */ void bitBltRough(KisTiledDataManager *srcDM, const QRect &rect); /** * The same as \ref bitBltRough(), but reads old data */ void bitBltRoughOldData(KisTiledDataManager *srcDM, const QRect &rect); /** * write the specified data to x, y. There is no checking on pixelSize! */ void setPixel(qint32 x, qint32 y, const quint8 * data); /** * Copy the bytes in the specified rect to a vector. The caller is responsible * for managing the vector. * * \param dataRowStride is the step (in bytes) which should be * added to \p bytes pointer to get to the * next row */ void readBytes(quint8 * bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride = -1) const; /** * Copy the bytes in the vector to the specified rect. If there are bytes left * in the vector after filling the rect, they will be ignored. If there are * not enough bytes, the rest of the rect will be filled with the default value * given (by default, 0); * * \param dataRowStride is the step (in bytes) which should be * added to \p bytes pointer to get to the * next row */ void writeBytes(const quint8 * bytes, qint32 x, qint32 y, qint32 w, qint32 h, qint32 dataRowStride = -1); /** * Copy the bytes in the paint device into a vector of arrays of bytes, * where the number of arrays is the number of channels in the * paint device. If the specified area is larger than the paint * device's extent, the default pixel will be read. */ QVector readPlanarBytes(QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const; /** * Write the data in the separate arrays to the channels. If there * are less vectors than channels, the remaining channels will not * be copied. If any of the arrays points to 0, the channel in * that location will not be touched. If the specified area is * larger than the paint device, the paint device will be * extended. There are no guards: if the area covers more pixels * than there are bytes in the arrays, krita will happily fill * your paint device with areas of memory you never wanted to be * read. Krita may also crash. */ void writePlanarBytes(QVector planes, QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h); /** * Get the number of contiguous columns starting at x, valid for all values * of y between minY and maxY. */ qint32 numContiguousColumns(qint32 x, qint32 minY, qint32 maxY) const; /** * Get the number of contiguous rows starting at y, valid for all values * of x between minX and maxX. */ qint32 numContiguousRows(qint32 y, qint32 minX, qint32 maxX) const; /** * Get the row stride at pixel (x, y). This is the number of bytes to add to a * pointer to pixel (x, y) to access (x, y + 1). */ qint32 rowStride(qint32 x, qint32 y) const; private: KisTileHashTable *m_hashTable; KisMementoManager *m_mementoManager; quint8* m_defaultPixel; qint32 m_pixelSize; /** * Extents stuff */ qint32 m_extentMinX; qint32 m_extentMaxX; qint32 m_extentMinY; qint32 m_extentMaxY; mutable QReadWriteLock m_lock; private: // Allow compression routines to calculate (col,row) coordinates // and pixel size friend class KisAbstractTileCompressor; friend class KisTileDataWrapper; qint32 xToCol(qint32 x) const; qint32 yToRow(qint32 y) const; private: void setDefaultPixelImpl(const quint8 *defPixel); QRect extentImpl() const; bool writeTilesHeader(KisPaintDeviceWriter &store, quint32 numTiles); bool processTilesHeader(QIODevice *stream, quint32 &numTiles); qint32 divideRoundDown(qint32 x, const qint32 y) const; void updateExtent(qint32 col, qint32 row); void recalculateExtent(); quint8* duplicatePixel(qint32 num, const quint8 *pixel); template void bitBltImpl(KisTiledDataManager *srcDM, const QRect &rect); template void bitBltRoughImpl(KisTiledDataManager *srcDM, const QRect &rect); void writeBytesBody(const quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride = -1); void readBytesBody(quint8 *data, qint32 x, qint32 y, qint32 width, qint32 height, qint32 dataRowStride = -1) const; template void writePlanarBytesBody(QVector planes, QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h); QVector readPlanarBytesBody(QVector channelsizes, qint32 x, qint32 y, qint32 w, qint32 h) const; public: void debugPrintInfo() { m_mementoManager->debugPrintInfo(); } }; inline qint32 KisTiledDataManager::divideRoundDown(qint32 x, const qint32 y) const { /** * Equivalent to the following: * -(( -x + (y-1) ) / y) */ return x >= 0 ? x / y : -(((-x - 1) / y) + 1); } inline qint32 KisTiledDataManager::xToCol(qint32 x) const { return divideRoundDown(x, KisTileData::WIDTH); } inline qint32 KisTiledDataManager::yToRow(qint32 y) const { return divideRoundDown(y, KisTileData::HEIGHT); } // during development the following line helps to check the interface is correct // it should be safe to keep it here even during normal compilation //#include "kis_datamanager.h" #endif // KIS_TILEDDATAMANAGER_H_ diff --git a/krita/image/tiles3/kis_vline_iterator.h b/krita/image/tiles3/kis_vline_iterator.h index d5a6563b9c8..875dffb5799 100644 --- a/krita/image/tiles3/kis_vline_iterator.h +++ b/krita/image/tiles3/kis_vline_iterator.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2010 Cyrille Berger * * 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_VLINE_ITERATOR_H_ #define _KIS_VLINE_ITERATOR_H_ #include "kis_base_iterator.h" -#include "krita_export.h" +#include "kritaimage_export.h" #include "kis_iterator_ng.h" class KRITAIMAGE_EXPORT KisVLineIterator2 : public KisVLineIteratorNG, KisBaseIterator { KisVLineIterator2(const KisVLineIterator2&); KisVLineIterator2& operator=(const KisVLineIterator2&); public: struct KisTileInfo { KisTileSP tile; KisTileSP oldtile; quint8* data; quint8* oldData; }; public: KisVLineIterator2(KisDataManager *dataManager, qint32 x, qint32 y, qint32 h, qint32 offsetX, qint32 offsetY, bool writable); ~KisVLineIterator2(); virtual void resetPixelPos(); virtual void resetColumnPos(); virtual bool nextPixel(); virtual void nextColumn(); virtual const quint8* rawDataConst() const; virtual const quint8* oldRawData() const; virtual quint8* rawData(); virtual qint32 nConseqPixels() const; virtual bool nextPixels(qint32 n); virtual qint32 x() const; virtual qint32 y() const; private: qint32 m_offsetX; qint32 m_offsetY; qint32 m_x; // current x position qint32 m_y; // current y position qint32 m_column; // current column in tilemgr qint32 m_index; // current row in tilemgr qint32 m_tileSize; quint8 *m_data; quint8 *m_dataBottom; quint8 *m_oldData; bool m_havePixels; qint32 m_top; qint32 m_bottom; qint32 m_left; qint32 m_topRow; qint32 m_bottomRow; qint32 m_topInTopmostTile; qint32 m_xInTile; qint32 m_lineStride; QVector m_tilesCache; qint32 m_tilesCacheSize; private: void switchToTile(qint32 xInTile); void fetchTileDataForCache(KisTileInfo& kti, qint32 col, qint32 row); void preallocateTiles(); }; #endif diff --git a/krita/image/tiles3/swap/kis_abstract_compression.h b/krita/image/tiles3/swap/kis_abstract_compression.h index b05a6b296dc..31e7ca0a73f 100644 --- a/krita/image/tiles3/swap/kis_abstract_compression.h +++ b/krita/image/tiles3/swap/kis_abstract_compression.h @@ -1,87 +1,88 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ABSTRACT_COMPRESSION_H #define __KIS_ABSTRACT_COMPRESSION_H -#include "krita_export.h" +#include "kritaimage_export.h" +#include /** * Base class for compression operations */ class KRITAIMAGE_EXPORT KisAbstractCompression { public: KisAbstractCompression(); virtual ~KisAbstractCompression(); /** * Compresses \a input buffer into \a output buffer. * WARNING: Be careful, output buffer must be at least * outputBufferSize(inputLength) size! * \param outputLength is not used! * \return number of bytes written to the output buffer * and 0 if error occurred. * * \see outputBufferSize() */ virtual qint32 compress(const quint8* input, qint32 inputLength, quint8* output, qint32 outputLength) = 0; /** * Decompresses \a input buffer into \a output buffer. * WARNING: output buffer must be able to fit the input data * \param outputLength is not used! * \return number of bytes written to the output buffer * and 0 if error occurred. */ virtual qint32 decompress(const quint8* input, qint32 inputLength, quint8* output, qint32 outputLength) = 0; /** * Returns minimal allowed size of output buffer for compression */ virtual qint32 outputBufferSize(qint32 dataSize) = 0; /** * Some algorithms may decide to optimize them work depending on * the usual size of the data. * Default implementation of KisAbstractCompression class does nothing. */ virtual void adjustForDataSize(qint32 dataSize); public: /** * Additional interface for jumbling color channels order */ /** * e.g. RGBARGBARGBA -> RRRGGGBBBAAA * NOTE: performs mixing of bytes, not channels! */ static void linearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize); /** * e.g. RRRGGGBBBAAA -> RGBARGBARGBA * NOTE: performs mixing of bytes, not channels! */ static void delinearizeColors(quint8 *input, quint8 *output, qint32 dataSize, qint32 pixelSize); }; #endif /* __KIS_ABSTRACT_COMPRESSION_H */ diff --git a/krita/image/tiles3/swap/kis_abstract_tile_compressor.h b/krita/image/tiles3/swap/kis_abstract_tile_compressor.h index 3124c5aeba3..d5cbdfb6cd4 100644 --- a/krita/image/tiles3/swap/kis_abstract_tile_compressor.h +++ b/krita/image/tiles3/swap/kis_abstract_tile_compressor.h @@ -1,103 +1,103 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ABSTRACT_TILE_COMPRESSOR_H #define __KIS_ABSTRACT_TILE_COMPRESSOR_H -#include "krita_export.h" +#include "kritaimage_export.h" #include "../kis_tile.h" #include "../kis_tiled_data_manager.h" class KisPaintDeviceWriter; /** * Base class for compressing a tile and wrapping it with a header */ class KisAbstractTileCompressor; typedef KisSharedPtr KisAbstractTileCompressorSP; class KRITAIMAGE_EXPORT KisAbstractTileCompressor : public KisShared { public: KisAbstractTileCompressor(); virtual ~KisAbstractTileCompressor(); public: /** * Compresses the \a tile and writes it into the \a stream. * Used by datamanager in load/save routines * * \see compressTile() */ virtual bool writeTile(KisTileSP tile, KisPaintDeviceWriter &store) = 0; /** * Decompresses the \a tile from the \a stream. * Used by datamanager in load/save routines * * \see decompressTile() */ virtual bool readTile(QIODevice *stream, KisTiledDataManager *dm) = 0; /** * Compresses a \a tileData and writes it into the \a buffer. * The buffer must be at least tileDataBufferSize() bytes long. * Actual number of bytes written is returned using out-parameter * \a bytesWritten * * \param tileData an existing tile data. It should be created * and acquired by the caller. * * \see tileDataBufferSize() */ virtual void compressTileData(KisTileData *tileData,quint8 *buffer, qint32 bufferSize, qint32 &bytesWritten) = 0; /** * Decompresses a \a tileData from a given \a buffer. * * \param tileData an existing tile data wrere the result * will be written to. It should be created and acquired * by the caller. * */ virtual bool decompressTileData(quint8 *buffer, qint32 bufferSize, KisTileData *tileData) = 0; /** * Return the number of bytes needed for compressing one tile */ virtual qint32 tileDataBufferSize(KisTileData *tileData) = 0; protected: inline qint32 xToCol(KisTiledDataManager *dm, qint32 x) { return dm->xToCol(x); } inline qint32 yToRow(KisTiledDataManager *dm, qint32 y) { return dm->yToRow(y); } inline qint32 pixelSize(KisTiledDataManager *dm) { return dm->pixelSize(); } }; #endif /* __KIS_ABSTRACT_TILE_COMPRESSOR_H */ diff --git a/krita/image/tiles3/swap/kis_chunk_allocator.h b/krita/image/tiles3/swap/kis_chunk_allocator.h index cec96612d11..084d61acd93 100644 --- a/krita/image/tiles3/swap/kis_chunk_allocator.h +++ b/krita/image/tiles3/swap/kis_chunk_allocator.h @@ -1,164 +1,164 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CHUNK_LIST_H #define __KIS_CHUNK_LIST_H -#include "krita_export.h" +#include "kritaimage_export.h" #include #define MiB (1ULL << 20) #define DEFAULT_STORE_SIZE (4096*MiB) #define DEFAULT_SLAB_SIZE (64*MiB) //#define DEBUG_SLAB_FAILS #ifdef DEBUG_SLAB_FAILS #define WINDOW_SIZE 2000 #define DECLARE_FAIL_COUNTER() quint64 __failCount #define INIT_FAIL_COUNTER() __failCount = 0 #define START_COUNTING() quint64 __numSteps = 0 #define REGISTER_STEP() if(++__numSteps > WINDOW_SIZE) {__numSteps=0; __failCount++;} #define REGISTER_FAIL() __failCount++ #define DEBUG_FAIL_COUNTER() qDebug() << "Slab fail count:\t" << __failCount #else #define DECLARE_FAIL_COUNTER() #define INIT_FAIL_COUNTER() #define START_COUNTING() #define REGISTER_STEP() #define REGISTER_FAIL() #define DEBUG_FAIL_COUNTER() #endif /* DEBUG_SLAB_FAILS */ class KisChunkData; typedef QLinkedList KisChunkDataList; typedef KisChunkDataList::iterator KisChunkDataListIterator; class KisChunkData { public: KisChunkData(quint64 begin, quint64 size) { setChunk(begin, size); } inline void setChunk(quint64 begin, quint64 size) { m_begin = begin; m_end = begin + size - 1; } inline quint64 size() const { return m_end - m_begin +1; } bool operator== (const KisChunkData& other) const { Q_ASSERT(m_begin!=other.m_begin || m_end==other.m_end); /** * Chunks cannot overlap, so it is enough to check * the beginning of the interval only */ return m_begin == other.m_begin; } quint64 m_begin; quint64 m_end; }; class KisChunk { public: KisChunk() {} KisChunk(KisChunkDataListIterator iterator) : m_iterator(iterator) { } inline quint64 begin() const { return m_iterator->m_begin; } inline quint64 end() const { return m_iterator->m_end; } inline quint64 size() const { return m_iterator->size(); } inline KisChunkDataListIterator position() { return m_iterator; } inline const KisChunkData& data() { return *m_iterator; } private: KisChunkDataListIterator m_iterator; }; class KRITAIMAGE_EXPORT KisChunkAllocator { public: KisChunkAllocator(quint64 slabSize = DEFAULT_SLAB_SIZE, quint64 storeSize = DEFAULT_STORE_SIZE); ~KisChunkAllocator(); inline quint64 numChunks() const { return m_list.size(); } KisChunk getChunk(quint64 size); void freeChunk(KisChunk chunk); void debugChunks(); bool sanityCheck(bool pleaseCrash = true); qreal debugFragmentation(bool toStderr = true); private: bool tryInsertChunk(KisChunkDataList &list, KisChunkDataListIterator &iterator, quint64 size); private: quint64 m_storeMaxSize; quint64 m_storeSlabSize; KisChunkDataList m_list; KisChunkDataListIterator m_iterator; quint64 m_storeSize; DECLARE_FAIL_COUNTER() }; #endif /* __KIS_CHUNK_ALLOCATOR_H */ diff --git a/krita/image/tiles3/swap/kis_memory_window.h b/krita/image/tiles3/swap/kis_memory_window.h index c0f8dee92bd..1d8c5649780 100644 --- a/krita/image/tiles3/swap/kis_memory_window.h +++ b/krita/image/tiles3/swap/kis_memory_window.h @@ -1,83 +1,83 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_MEMORY_WINDOW_H #define __KIS_MEMORY_WINDOW_H -#include "krita_export.h" +#include "kritaimage_export.h" #include #include "kis_chunk_allocator.h" #define DEFAULT_WINDOW_SIZE (16*MiB) class KRITAIMAGE_EXPORT KisMemoryWindow { public: /** * @param swapDir. If the dir doesn't exist, it'll be created, if it's empty QDir::tempPath will be used. */ KisMemoryWindow(const QString &swapDir, quint64 writeWindowSize = DEFAULT_WINDOW_SIZE); ~KisMemoryWindow(); inline quint8* getReadChunkPtr(KisChunk readChunk) { return getReadChunkPtr(readChunk.data()); } inline quint8* getWriteChunkPtr(KisChunk writeChunk) { return getWriteChunkPtr(writeChunk.data()); } quint8* getReadChunkPtr(const KisChunkData &readChunk); quint8* getWriteChunkPtr(const KisChunkData &writeChunk); private: struct MappingWindow { MappingWindow(quint64 _defaultSize) : chunk(0,0), window(0), defaultSize(_defaultSize) { } quint8* calculatePointer(const KisChunkData &other) const { return window + other.m_begin - chunk.m_begin; } KisChunkData chunk; quint8 *window; const quint64 defaultSize; }; private: void adjustWindow(const KisChunkData &requestedChunk, MappingWindow *adjustingWindow, MappingWindow *otherWindow); private: QTemporaryFile m_file; MappingWindow m_readWindowEx; MappingWindow m_writeWindowEx; }; #endif /* __KIS_MEMORY_WINDOW_H */ diff --git a/krita/image/tiles3/swap/kis_swapped_data_store.h b/krita/image/tiles3/swap/kis_swapped_data_store.h index fd416b8adcc..5862203784d 100644 --- a/krita/image/tiles3/swap/kis_swapped_data_store.h +++ b/krita/image/tiles3/swap/kis_swapped_data_store.h @@ -1,92 +1,92 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SWAPPED_DATA_STORE_H #define __KIS_SWAPPED_DATA_STORE_H -#include "krita_export.h" +#include "kritaimage_export.h" #include #include class QMutex; class KisTileData; class KisAbstractTileCompressor; class KisChunkAllocator; class KisMemoryWindow; class KRITAIMAGE_EXPORT KisSwappedDataStore { public: KisSwappedDataStore(); ~KisSwappedDataStore(); /** * Returns number of swapped out tile data objects */ quint64 numTiles() const; /** * Swap out the data stored in the \a td to the swap file * and free memory occupied by td->data(). * LOCKING: the lock on the tile data should be taken * by the caller before making a call. */ void swapOutTileData(KisTileData *td); /** * Restore the data of a \a td basing on information * stored in the swap file. * LOCKING: the lock on the tile data should be taken * by the caller before making a call. */ void swapInTileData(KisTileData *td); /** * Forget all the information linked with the tile data. * This should be done before deleting of the tile data, * whose actual data is swapped-out */ void forgetTileData(KisTileData *td); /** * Retorns the metric of the total memory stored in the swap * in *uncompressed* form! */ qint64 totalMemoryMetric() const; /** * Some debugging output */ void debugStatistics(); private: QByteArray m_buffer; KisAbstractTileCompressor *m_compressor; KisChunkAllocator *m_allocator; KisMemoryWindow *m_swapSpace; QMutex m_lock; qint64 m_memoryMetric; }; #endif /* __KIS_SWAPPED_DATA_STORE_H */ diff --git a/krita/image/tiles3/swap/kis_tile_data_swapper.h b/krita/image/tiles3/swap/kis_tile_data_swapper.h index 0d2d1dcf41a..7488d7da226 100644 --- a/krita/image/tiles3/swap/kis_tile_data_swapper.h +++ b/krita/image/tiles3/swap/kis_tile_data_swapper.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TILE_DATA_SWAPPER_H_ #define KIS_TILE_DATA_SWAPPER_H_ #include #include -#include "krita_export.h" +#include "kritaimage_export.h" class KisTileDataStore; class KisTileData; class KRITAIMAGE_EXPORT KisTileDataSwapper : public QThread { Q_OBJECT public: KisTileDataSwapper(KisTileDataStore *store); virtual ~KisTileDataSwapper(); void kick(); void terminateSwapper(); void checkFreeMemory(); void testingRereadConfig(); private: void waitForWork(); void run(); void doJob(); template qint64 pass(qint64 needToFreeMetric); private: static const qint32 TIMEOUT; static const qint32 DELAY; private: struct Private; Private * const m_d; }; #endif /* KIS_TILE_DATA_SWAPPER_H_ */ diff --git a/krita/krita.action b/krita/krita.action index f024c2375ba..a702640923a 100644 --- a/krita/krita.action +++ b/krita/krita.action @@ -1,340 +1,329 @@ - - - - - - - - - - - diff --git a/krita/krita.rc b/krita/krita.rc index dceb6dbf10b..c0c58844b83 100644 --- a/krita/krita.rc +++ b/krita/krita.rc @@ -1,335 +1,326 @@ &File &Edit &View &Canvas - - Grid Spacing - - - - - - - &Image &Rotate &Layer New &Import/Export Import &Convert S&plit Alpha &Rotate &Select Filte&r &Tools Recording Macros Setti&ngs &Help File Brushes and Stuff diff --git a/krita/libbrush/kis_abr_brush.cpp b/krita/libbrush/kis_abr_brush.cpp index ad717d4122b..f6a582eb813 100644 --- a/krita/libbrush/kis_abr_brush.cpp +++ b/krita/libbrush/kis_abr_brush.cpp @@ -1,113 +1,101 @@ /* * Copyright (c) 2010 Boudewijn Rempt * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2007 Eric Lamarque * * 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_abr_brush.h" #include "kis_brush.h" #include #include #include #include #include #include #include -#include #include #include #include "kis_datamanager.h" #include "kis_paint_device.h" #include "kis_global.h" #include "kis_image.h" #define DEFAULT_SPACING 0.25 KisAbrBrush::KisAbrBrush(const QString& filename, const QByteArray &parentMD5, KisAbrBrushCollection *parent) : KisBrush(filename) , m_parentMD5(parentMD5) , m_parent(parent) { setBrushType(INVALID); setHasColor(false); setSpacing(DEFAULT_SPACING); } bool KisAbrBrush::load() { return true; } bool KisAbrBrush::loadFromDevice(QIODevice */*dev*/) { return true; } bool KisAbrBrush::save() { //Return true, otherwise the brush won't be added to the //resource server if the brush is loaded via import return true; } bool KisAbrBrush::saveToDevice(QIODevice* /*dev*/) const { return true; } void KisAbrBrush::setBrushTipImage(const QImage& image) { setValid(true); setBrushType(MASK); setHasColor(false); -#if QT_VERSION >= 0x040700 - QByteArray ba = QByteArray::fromRawData((const char*)image.constBits(), image.byteCount()); -#else - QByteArray ba = QByteArray::fromRawData((const char*)image.bits(), image.byteCount()); -#endif - - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - md5.addData(m_parentMD5); - setMD5(md5.result()); - KisBrush::setBrushTipImage(image); } void KisAbrBrush::toXML(QDomDocument& d, QDomElement& e) const { e.setAttribute("name", name()); // legacy predefinedBrushToXML("abr_brush", e); KisBrush::toXML(d, e); } QString KisAbrBrush::defaultFileExtension() const { return QString(); } QImage KisAbrBrush::brushTipImage() const { if (KisBrush::brushTipImage().isNull() && m_parent) { m_parent->load(); } return KisBrush::brushTipImage(); } diff --git a/krita/libbrush/kis_abr_brush.h b/krita/libbrush/kis_abr_brush.h index 115598c35b2..3c613fe69fe 100644 --- a/krita/libbrush/kis_abr_brush.h +++ b/krita/libbrush/kis_abr_brush.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2010 Boudewijn Rempt * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2007 Eric Lamarque * * 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_ABR_BRUSH_ #define KIS_ABR_BRUSH_ #include #include #include "kis_brush.h" #include "kis_types.h" #include "kis_shared.h" #include "kis_paint_information.h" #include "kis_abr_brush_collection.h" -#include "krita_export.h" +#include "kritabrush_export.h" class KisQImagemask; typedef KisSharedPtr KisQImagemaskSP; class QString; class QIODevice; class BRUSH_EXPORT KisAbrBrush : public KisBrush { public: /// Construct brush to load filename later as brush KisAbrBrush(const QString& filename, const QByteArray &parentMD5, KisAbrBrushCollection *parent); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; /** * @return default file extension for saving the brush */ virtual QString defaultFileExtension() const; virtual QImage brushTipImage() const; friend class KisAbrBrushCollection; virtual void setBrushTipImage(const QImage& image); void toXML(QDomDocument& d, QDomElement& e) const; private: QByteArray m_parentMD5; KisAbrBrushCollection *m_parent; }; #endif // KIS_ABR_BRUSH_ diff --git a/krita/libbrush/kis_abr_brush_collection.cpp b/krita/libbrush/kis_abr_brush_collection.cpp index 554865be48d..593de46894e 100644 --- a/krita/libbrush/kis_abr_brush_collection.cpp +++ b/krita/libbrush/kis_abr_brush_collection.cpp @@ -1,609 +1,600 @@ /* * Copyright (c) 2010 Boudewijn Rempt * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2007 Eric Lamarque * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "kis_abr_brush_collection.h" #include "kis_abr_brush.h" #include #include #include #include #include #include #include #include #include #include -#include -#include #include #include struct AbrInfo { //big endian short version; short subversion; // count of the images (brushes) in the abr file short count; }; /// save the QImages as png files to directory image_tests static QImage convertToQImage(char * buffer, qint32 width, qint32 height) { // create 8-bit indexed image QImage img(width, height, QImage::Format_RGB32); int pos = 0; int value = 0; for (int y = 0; y < height; y++) { QRgb *pixel = reinterpret_cast(img.scanLine(y)); for (int x = 0; x < width; x++, pos++) { value = 255 - buffer[pos]; pixel[x] = qRgb(value, value , value); } } return img; } static qint32 rle_decode(QDataStream & abr, char *buffer, qint32 height) { qint32 n; char ptmp; char ch; int i, j, c; short *cscanline_len; char *data = buffer; // read compressed size foreach scanline cscanline_len = new short[ height ]; for (i = 0; i < height; i++) { // short abr >> cscanline_len[i]; } // unpack each scanline data for (i = 0; i < height; i++) { for (j = 0; j < cscanline_len[i];) { // char if (!abr.device()->getChar(&ptmp)) { break; } n = ptmp; j++; if (n >= 128) // force sign n -= 256; if (n < 0) { // copy the following char -n + 1 times if (n == -128) // it's a nop continue; n = -n + 1; // char if (!abr.device()->getChar(&ch)) { break; } j++; for (c = 0; c < n; c++, data++) { *data = ch; } } else { // read the following n + 1 chars (no compr) for (c = 0; c < n + 1; c++, j++, data++) { // char if (!abr.device()->getChar(data)) { break; } } } } } delete [] cscanline_len; return 0; } static QString abr_v1_brush_name(const QString filename, qint32 id) { QString result = filename; int pos = filename.lastIndexOf('.'); result.remove(pos, 4); QTextStream(&result) << "_" << id; return result; } static bool abr_supported_content(AbrInfo *abr_hdr) { switch (abr_hdr->version) { case 1: case 2: return true; break; case 6: if (abr_hdr->subversion == 1 || abr_hdr->subversion == 2) return true; break; } return false; } static bool abr_reach_8BIM_section(QDataStream & abr, const QString name) { char tag[4]; char tagname[5]; qint32 section_size = 0; int r; // find 8BIMname section while (!abr.atEnd()) { r = abr.readRawData(tag, 4); if (r != 4) { - qDebug() << "Error: Cannot read 8BIM tag "; + qWarning() << "Error: Cannot read 8BIM tag "; return false; } if (strncmp(tag, "8BIM", 4)) { - qDebug() << "Error: Start tag not 8BIM but " << (int)tag[0] << (int)tag[1] << (int)tag[2] << (int)tag[3] << " at position " << abr.device()->pos(); + qWarning() << "Error: Start tag not 8BIM but " << (int)tag[0] << (int)tag[1] << (int)tag[2] << (int)tag[3] << " at position " << abr.device()->pos(); return false; } r = abr.readRawData(tagname, 4); if (r != 4) { - qDebug() << "Error: Cannot read 8BIM tag name"; + qWarning() << "Error: Cannot read 8BIM tag name"; return false; } tagname[4] = '\0'; QString s1 = QString::fromLatin1(tagname, 4); if (!s1.compare(name)) { return true; } // long abr >> section_size; abr.device()->seek(abr.device()->pos() + section_size); } return true; } static qint32 find_sample_count_v6(QDataStream & abr, AbrInfo *abr_info) { qint64 origin; qint32 sample_section_size; qint32 sample_section_end; qint32 samples = 0; qint32 data_start; qint32 brush_size; qint32 brush_end; if (!abr_supported_content(abr_info)) return 0; origin = abr.device()->pos(); if (!abr_reach_8BIM_section(abr, "samp")) { // reset to origin abr.device()->seek(origin); return 0; } // long abr >> sample_section_size; sample_section_end = sample_section_size + abr.device()->pos(); data_start = abr.device()->pos(); while ((!abr.atEnd()) && (abr.device()->pos() < sample_section_end)) { // read long abr >> brush_size; brush_end = brush_size; // complement to 4 while (brush_end % 4 != 0) brush_end++; abr.device()->seek(abr.device()->pos() + brush_end); samples++; } // set stream to samples data abr.device()->seek(data_start); //qDebug() <<"samples : "<< samples; return samples; } static bool abr_read_content(QDataStream & abr, AbrInfo *abr_hdr) { abr >> abr_hdr->version; abr_hdr->subversion = 0; abr_hdr->count = 0; switch (abr_hdr->version) { case 1: case 2: abr >> abr_hdr->count; break; case 6: abr >> abr_hdr->subversion; abr_hdr->count = find_sample_count_v6(abr, abr_hdr); break; default: // unknown versions break; } // next bytes in abr are samples data return true; } static QString abr_read_ucs2_text(QDataStream & abr) { quint32 name_size; quint32 buf_size; uint i; /* two-bytes characters encoded (UCS-2) * format: * long : size - number of characters in string * data : zero terminated UCS-2 string */ // long abr >> name_size; if (name_size == 0) { return QString(); } //buf_size = name_size * 2; buf_size = name_size; //name_ucs2 = (char*) malloc (buf_size * sizeof (char)); //name_ucs2 = new char[buf_size]; ushort * name_ucs2 = new ushort[buf_size]; for (i = 0; i < buf_size ; i++) { //* char*/ //abr >> name_ucs2[i]; // I will use ushort as that is input to fromUtf16 abr >> name_ucs2[i]; } QString name_utf8 = QString::fromUtf16(name_ucs2, buf_size); delete [] name_ucs2; return name_utf8; } quint32 KisAbrBrushCollection::abr_brush_load_v6(QDataStream & abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id) { - qDebug() << "abr_brush_load_v6()" << filename; Q_UNUSED(image_ID); qint32 brush_size = 0; qint32 brush_end = 0; qint32 next_brush = 0; qint32 top, left, bottom, right; top = left = bottom = right = 0; short depth; char compression; qint32 width = 0; qint32 height = 0; qint32 size = 0; qint32 layer_ID = -1; char *buffer; abr >> brush_size; brush_end = brush_size; // complement to 4 while (brush_end % 4 != 0) { brush_end++; } next_brush = abr.device()->pos() + brush_end; // discard key abr.device()->seek(abr.device()->pos() + 37); if (abr_hdr->subversion == 1) // discard short coordinates and unknown short abr.device()->seek(abr.device()->pos() + 10); else // discard unknown bytes abr.device()->seek(abr.device()->pos() + 264); // long abr >> top; abr >> left; abr >> bottom; abr >> right; // short abr >> depth; // char abr.device()->getChar(&compression); width = right - left; height = bottom - top; size = width * (depth >> 3) * height; // remove .abr and add some id, so something like test.abr -> test_12345 QString name = abr_v1_brush_name(filename, id); buffer = (char*)malloc(size); // data decoding if (!compression) { // not compressed - read raw bytes as brush data //fread (buffer, size, 1, abr); abr.readRawData(buffer, size); } else { rle_decode(abr, buffer, height); } if (width < quint16_MAX && height < quint16_MAX) { // filename - filename of the file , e.g. test.abr // name - test_number_of_the_brush, e.g test_1, test_2 KisAbrBrush* abrBrush = 0; if (m_abrBrushes.contains(name)) { abrBrush = m_abrBrushes[name]; } else { abrBrush = new KisAbrBrush(name, md5(), this); } abrBrush->setBrushTipImage(convertToQImage(buffer, width, height)); // XXX: call extra setters on abrBrush for other options of ABR brushes abrBrush->setValid(true); abrBrush->setName(name); m_abrBrushes[name] = abrBrush; } free(buffer); abr.device()->seek(next_brush); layer_ID = id; return layer_ID; } qint32 KisAbrBrushCollection::abr_brush_load_v12(QDataStream & abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id) { - qDebug() << "abr_brush_load_v12()" << filename; - Q_UNUSED(image_ID); short brush_type; qint32 brush_size; qint32 next_brush; qint32 top, left, bottom, right; qint16 depth; char compression; QString name; qint32 width, height; qint32 size; qint32 layer_ID = -1; char *buffer; // short abr >> brush_type; // long abr >> brush_size; next_brush = abr.device()->pos() + brush_size; if (brush_type == 1) { // computed brush // FIXME: support it! warnKrita << "WARNING: computed brush unsupported, skipping."; abr.device()->seek(abr.device()->pos() + next_brush); // TODO: test also this one abr.skipRawData(next_brush); } else if (brush_type == 2) { // sampled brush // discard 4 misc bytes and 2 spacing bytes abr.device()->seek(abr.device()->pos() + 6); if (abr_hdr->version == 2) name = abr_read_ucs2_text(abr); if (name.isNull()) { name = abr_v1_brush_name(filename, id); } // discard 1 byte for antialiasing and 4 x short for short bounds abr.device()->seek(abr.device()->pos() + 9); // long abr >> top; abr >> left; abr >> bottom; abr >> right; // short abr >> depth; // char abr.device()->getChar(&compression); width = right - left; height = bottom - top; size = width * (depth >> 3) * height; /* FIXME: support wide brushes */ if (height > 16384) { warnKrita << "WARNING: wide brushes not supported"; abr.device()->seek(next_brush); } else { buffer = (char*)malloc(size); if (!compression) { // not compressed - read raw bytes as brush data abr.readRawData(buffer, size); } else { rle_decode(abr, buffer, height); } KisAbrBrush* abrBrush = 0; if (m_abrBrushes.contains(name)) { abrBrush = m_abrBrushes[name]; } else { abrBrush = new KisAbrBrush(name, md5(), this); } abrBrush->setBrushTipImage(convertToQImage(buffer, width, height)); // XXX: call extra setters on abrBrush for other options of ABR brushes free (buffer); abrBrush->setValid(true); abrBrush->setName(name); m_abrBrushes[name] = abrBrush; layer_ID = 1; } } else { warnKrita << "Unknown ABR brush type, skipping."; abr.device()->seek(next_brush); } return layer_ID; } qint32 KisAbrBrushCollection::abr_brush_load(QDataStream & abr, AbrInfo *abr_hdr, const QString filename, qint32 image_ID, qint32 id) { qint32 layer_ID = -1; switch (abr_hdr->version) { case 1: // fall through, version 1 and 2 are compatible case 2: layer_ID = abr_brush_load_v12(abr, abr_hdr, filename, image_ID, id); break; case 6: layer_ID = abr_brush_load_v6(abr, abr_hdr, filename, image_ID, id); break; } return layer_ID; } KisAbrBrushCollection::KisAbrBrushCollection(const QString& filename) : KisBrush(filename) { } bool KisAbrBrushCollection::load() { QFile file(filename()); // check if the file is open correctly if (!file.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KisAbrBrushCollection::loadFromDevice(QIODevice *dev) { AbrInfo abr_hdr; qint32 image_ID; int i; qint32 layer_ID; QByteArray ba = dev->readAll(); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - setMD5(md5.result()); - QBuffer buf(&ba); buf.open(QIODevice::ReadOnly); QDataStream abr(&buf); if (!abr_read_content(abr, &abr_hdr)) { warnKrita << "Error: cannot parse ABR file: " << filename(); return false; } if (!abr_supported_content(&abr_hdr)) { warnKrita << "ERROR: unable to decode abr format version " << abr_hdr.version << "(subver " << abr_hdr.subversion << ")"; return false; } if (abr_hdr.count == 0) { errKrita << "ERROR: no sample brush found in " << filename(); return false; } image_ID = 123456; for (i = 0; i < abr_hdr.count; i++) { layer_ID = abr_brush_load(abr, &abr_hdr, shortFilename(), image_ID, i + 1); if (layer_ID == -1) { warnKrita << "Warning: problem loading brush #" << i << " in " << filename(); } } return true; } bool KisAbrBrushCollection::save() { return false; } bool KisAbrBrushCollection::saveToDevice(QIODevice */*dev*/) const { return false; } QImage KisAbrBrushCollection::image() const { return QImage(); } void KisAbrBrushCollection::toXML(QDomDocument& d, QDomElement& e) const { Q_UNUSED(d); Q_UNUSED(e); // Do nothing... } QString KisAbrBrushCollection::defaultFileExtension() const { return QString(".abr"); } diff --git a/krita/libbrush/kis_auto_brush.cpp b/krita/libbrush/kis_auto_brush.cpp index 86cc379d74b..e458940aede 100644 --- a/krita/libbrush/kis_auto_brush.cpp +++ b/krita/libbrush/kis_auto_brush.cpp @@ -1,363 +1,341 @@ /* * Copyright (c) 2004,2007-2009 Cyrille Berger * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2012 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_auto_brush.h" #include #include #include #include #include #include #include -#include +#include +#include #include #include #include #include "kis_datamanager.h" #include "kis_fixed_paint_device.h" #include "kis_paint_device.h" #include "kis_paint_information.h" #include "kis_mask_generator.h" #include "kis_boundary.h" #if defined(_WIN32) || defined(_WIN64) #include #define srand48 srand inline double drand48() { return double(rand()) / RAND_MAX; } #endif struct KisAutoBrush::Private { KisMaskGenerator* shape; qreal randomness; qreal density; int idealThreadCountCached; }; KisAutoBrush::KisAutoBrush(KisMaskGenerator* as, qreal angle, qreal randomness, qreal density) : KisBrush() , d(new Private) { d->shape = as; d->randomness = randomness; d->density = density; d->idealThreadCountCached = QThread::idealThreadCount(); setBrushType(MASK); setWidth(qMax(qreal(1.0), d->shape->width())); setHeight(qMax(qreal(1.0), d->shape->height())); QImage image = createBrushPreview(); setBrushTipImage(image); // Set angle here so brush tip image is generated unrotated setAngle(angle); image = createBrushPreview(); setImage(image); } KisAutoBrush::~KisAutoBrush() { delete d->shape; delete d; } inline void fillPixelOptimized_4bytes(quint8 *color, quint8 *buf, int size) { /** * This version of filling uses low granularity of data transfers * (32-bit chunks) and internal processor's parallelism. It reaches * 25% better performance in KisStrokeBenchmark in comparison to * per-pixel memcpy version (tested on Sandy Bridge). */ int block1 = size / 8; int block2 = size % 8; quint32 *src = reinterpret_cast(color); quint32 *dst = reinterpret_cast(buf); // check whether all buffers are 4 bytes aligned // (uncomment if experience some problems) // Q_ASSERT(((qint64)src & 3) == 0); // Q_ASSERT(((qint64)dst & 3) == 0); for (int i = 0; i < block1; i++) { *dst = *src; *(dst + 1) = *src; *(dst + 2) = *src; *(dst + 3) = *src; *(dst + 4) = *src; *(dst + 5) = *src; *(dst + 6) = *src; *(dst + 7) = *src; dst += 8; } for (int i = 0; i < block2; i++) { *dst = *src; dst++; } } inline void fillPixelOptimized_general(quint8 *color, quint8 *buf, int size, int pixelSize) { /** * This version uses internal processor's parallelism and gives * 20% better performance in KisStrokeBenchmark in comparison to * per-pixel memcpy version (tested on Sandy Bridge (+20%) and * on Merom (+10%)). */ int block1 = size / 8; int block2 = size % 8; for (int i = 0; i < block1; i++) { quint8 *d1 = buf; quint8 *d2 = buf + pixelSize; quint8 *d3 = buf + 2 * pixelSize; quint8 *d4 = buf + 3 * pixelSize; quint8 *d5 = buf + 4 * pixelSize; quint8 *d6 = buf + 5 * pixelSize; quint8 *d7 = buf + 6 * pixelSize; quint8 *d8 = buf + 7 * pixelSize; for (int j = 0; j < pixelSize; j++) { *(d1 + j) = color[j]; *(d2 + j) = color[j]; *(d3 + j) = color[j]; *(d4 + j) = color[j]; *(d5 + j) = color[j]; *(d6 + j) = color[j]; *(d7 + j) = color[j]; *(d8 + j) = color[j]; } buf += 8 * pixelSize; } for (int i = 0; i < block2; i++) { memcpy(buf, color, pixelSize); buf += pixelSize; } } void KisAutoBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, KisBrush::ColoringInformation* coloringInformation, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX , double subPixelY, qreal softnessFactor) const { Q_UNUSED(info); // Generate the paint device from the mask const KoColorSpace* cs = dst->colorSpace(); quint32 pixelSize = cs->pixelSize(); // mask dimension methods already includes KisBrush::angle() int dstWidth = maskWidth(scaleX, angle, subPixelX, subPixelY, info); int dstHeight = maskHeight(scaleY, angle, subPixelX, subPixelY, info); QPointF hotSpot = this->hotSpot(scaleX, scaleY, angle, info); // mask size and hotSpot function take the KisBrush rotation into account angle += KisBrush::angle(); // if there's coloring information, we merely change the alpha: in that case, // the dab should be big enough! if (coloringInformation) { // old bounds QRect oldBounds = dst->bounds(); // new bounds. we don't care if there is some extra memory occcupied. dst->setRect(QRect(0, 0, dstWidth, dstHeight)); if (dstWidth * dstHeight <= oldBounds.width() * oldBounds.height()) { // just clear the data in dst, memset(dst->data(), OPACITY_TRANSPARENT_U8, dstWidth * dstHeight * dst->pixelSize()); } else { // enlarge the data dst->initialize(); } } else { if (dst->data() == 0 || dst->bounds().isEmpty()) { qWarning() << "Creating a default black dab: no coloring info and no initialized paint device to mask"; dst->clear(QRect(0, 0, dstWidth, dstHeight)); } Q_ASSERT(dst->bounds().width() >= dstWidth && dst->bounds().height() >= dstHeight); } quint8* dabPointer = dst->data(); quint8* color = 0; if (coloringInformation) { if (dynamic_cast(coloringInformation)) { color = const_cast(coloringInformation->color()); } } double centerX = hotSpot.x() - 0.5 + subPixelX; double centerY = hotSpot.y() - 0.5 + subPixelY; d->shape->setScale(scaleX, scaleY); d->shape->setSoftness(softnessFactor); if (coloringInformation) { if (color && pixelSize == 4) { fillPixelOptimized_4bytes(color, dabPointer, dstWidth * dstHeight); } else if (color) { fillPixelOptimized_general(color, dabPointer, dstWidth * dstHeight, pixelSize); } else { for (int y = 0; y < dstHeight; y++) { for (int x = 0; x < dstWidth; x++) { memcpy(dabPointer, coloringInformation->color(), pixelSize); coloringInformation->nextColumn(); dabPointer += pixelSize; } coloringInformation->nextRow(); } } } MaskProcessingData data(dst, cs, d->randomness, d->density, centerX, centerY, angle); KisBrushMaskApplicatorBase *applicator = d->shape->applicator(); applicator->initializeData(&data); int jobs = d->idealThreadCountCached; if (dstHeight > 100 && jobs >= 4) { int splitter = dstHeight / jobs; QVector rects; for (int i = 0; i < jobs - 1; i++) { rects << QRect(0, i * splitter, dstWidth, splitter); } rects << QRect(0, (jobs - 1)*splitter, dstWidth, dstHeight - (jobs - 1)*splitter); OperatorWrapper wrapper(applicator); QtConcurrent::blockingMap(rects, wrapper); } else { QRect rect(0, 0, dstWidth, dstHeight); applicator->process(rect); } } void KisAutoBrush::toXML(QDomDocument& doc, QDomElement& e) const { QDomElement shapeElt = doc.createElement("MaskGenerator"); d->shape->toXML(doc, shapeElt); e.appendChild(shapeElt); e.setAttribute("type", "auto_brush"); e.setAttribute("spacing", QString::number(spacing())); e.setAttribute("useAutoSpacing", QString::number(autoSpacingActive())); e.setAttribute("autoSpacingCoeff", QString::number(autoSpacingCoeff())); e.setAttribute("angle", QString::number(KisBrush::angle())); e.setAttribute("randomness", QString::number(d->randomness)); e.setAttribute("density", QString::number(d->density)); KisBrush::toXML(doc, e); } QImage KisAutoBrush::createBrushPreview() { srand(0); srand48(0); int width = maskWidth(1.0, 0.0, 0.0, 0.0, KisPaintInformation()); int height = maskHeight(1.0, 0.0, 0.0, 0.0, KisPaintInformation()); KisPaintInformation info(QPointF(width * 0.5, height * 0.5), 0.5, 0, 0, angle(), 0, 0, 0, 0); KisFixedPaintDeviceSP fdev = new KisFixedPaintDevice(KoColorSpaceRegistry::instance()->rgb8()); fdev->setRect(QRect(0, 0, width, height)); fdev->initialize(); mask(fdev, KoColor(Qt::black, fdev->colorSpace()), 1.0, 1.0, 0.0, info); return fdev->convertToQImage(0); } const KisMaskGenerator* KisAutoBrush::maskGenerator() const { return d->shape; } qreal KisAutoBrush::density() const { return d->density; } -QByteArray KisAutoBrush::generateMD5() const -{ - QByteArray ba; - if (!brushTipImage().isNull()) { -#if QT_VERSION >= 0x040700 - ba = QByteArray::fromRawData((const char*)brushTipImage().constBits(), brushTipImage().byteCount()); -#else - ba = QByteArray::fromRawData((const char*)brushTipImage().bits(), brushTipImage().byteCount()); -#endif - } - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - - QDomDocument doc; - QDomElement root = doc.createElement("autobrush"); - toXML(doc, root); - doc.appendChild(root); - md5.addData(doc.toByteArray()); - - return md5.result(); - -} - qreal KisAutoBrush::randomness() const { return d->randomness; } QPainterPath KisAutoBrush::outline() const { bool simpleOutline = (d->density < 1.0); if (simpleOutline) { QPainterPath path; QRectF brushBoundingbox(0, 0, width(), height()); if (maskGenerator()->type() == KisMaskGenerator::CIRCLE) { path.addEllipse(brushBoundingbox); } else { // if (maskGenerator()->type() == KisMaskGenerator::RECTANGLE) path.addRect(brushBoundingbox); } return path; } return KisBrush::boundary()->path(); } diff --git a/krita/libbrush/kis_auto_brush.h b/krita/libbrush/kis_auto_brush.h index c537697d9b5..27dc2c1d428 100644 --- a/krita/libbrush/kis_auto_brush.h +++ b/krita/libbrush/kis_auto_brush.h @@ -1,91 +1,87 @@ /* * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2010 Lukáš Tvrdý * * 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_RESOURCE_H_ #define _KIS_AUTOBRUSH_RESOURCE_H_ -#include "krita_export.h" +#include "kritabrush_export.h" #include "kis_brush.h" class KisMaskGenerator; /** * XXX: docs! */ class BRUSH_EXPORT KisAutoBrush : public KisBrush { public: KisAutoBrush(KisMaskGenerator* as, qreal angle, qreal randomness, qreal density = 1.0); virtual ~KisAutoBrush(); public: virtual KisFixedPaintDeviceSP paintDevice(const KoColorSpace*, double, double, const KisPaintInformation&, double = 0, double = 0) const { return 0; // The autobrush does NOT support images! } virtual void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, KisBrush::ColoringInformation* src, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; virtual QPainterPath outline() const; public: bool load() { return false; } virtual bool loadFromDevice(QIODevice *) { return false; } bool save() { return false; } bool saveToDevice(QIODevice*) const { return false; } void toXML(QDomDocument& , QDomElement&) const; const KisMaskGenerator* maskGenerator() const; qreal randomness() const; qreal density() const; -protected: - - virtual QByteArray generateMD5() const; - private: QImage createBrushPreview(); struct Private; Private* const d; }; #endif // _KIS_AUTOBRUSH_RESOURCE_H_ diff --git a/krita/libbrush/kis_boundary.h b/krita/libbrush/kis_boundary.h index 5fcccbc059f..9c96fa727df 100644 --- a/krita/libbrush/kis_boundary.h +++ b/krita/libbrush/kis_boundary.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2005 Bart Coppens * * 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_H_ #define _KIS_BOUNDARY_H_ #include #include #include -#include +#include #include "kis_types.h" /** * Generates an 'outline' for a paint device. It should look a bit like the outline of a * marching ants selection. * * It's not really optimized, so it's not recommended to do big things with it and expect * it to be fast. * * Usage: construct a KisBoundary, and then run a generateBoundary(w, h) on it. After that, * you can use the KisBoundaryPainter::paint method to let it paint the outline, or get a pixmap. * * If you are debugging the brush outlines, be aware that the pipeline for this * data is somewhat complex, involving such user classes: * KisBoundary, KisBrush, KisBrushBasedPaintOpSettings, KisTool, KisCurrentOutlineFetcher **/ class BRUSH_EXPORT KisBoundary { public: KisBoundary(KisFixedPaintDeviceSP dev); ~KisBoundary(); void generateBoundary(); void paint(QPainter& painter) const; /// returns the outline saved in QPainterPath QPainterPath path() const; private: struct Private; Private* const d; }; #endif // _KIS_BOUNDARY_H_ diff --git a/krita/libbrush/kis_brush.cpp b/krita/libbrush/kis_brush.cpp index efa78a4d161..ac12227a835 100644 --- a/krita/libbrush/kis_brush.cpp +++ b/krita/libbrush/kis_brush.cpp @@ -1,638 +1,625 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004-2008 Boudewijn Rempt * Copyright (c) 2004 Adrian Page * Copyright (c) 2005 Bart Coppens * Copyright (c) 2007 Cyrille Berger * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_brush.h" #include #include #include #include -#include #include #include #include #include #include #include #include "kis_datamanager.h" #include "kis_paint_device.h" #include "kis_global.h" #include "kis_boundary.h" #include "kis_image.h" #include "kis_iterator_ng.h" #include "kis_brush_registry.h" #include #include #include KisBrush::ColoringInformation::~ColoringInformation() { } KisBrush::PlainColoringInformation::PlainColoringInformation(const quint8* color) : m_color(color) { } KisBrush::PlainColoringInformation::~PlainColoringInformation() { } const quint8* KisBrush::PlainColoringInformation::color() const { return m_color; } void KisBrush::PlainColoringInformation::nextColumn() { } void KisBrush::PlainColoringInformation::nextRow() { } KisBrush::PaintDeviceColoringInformation::PaintDeviceColoringInformation(const KisPaintDeviceSP source, int width) : m_source(source) , m_iterator(m_source->createHLineConstIteratorNG(0, 0, width)) { } KisBrush::PaintDeviceColoringInformation::~PaintDeviceColoringInformation() { } const quint8* KisBrush::PaintDeviceColoringInformation::color() const { return m_iterator->oldRawData(); } void KisBrush::PaintDeviceColoringInformation::nextColumn() { m_iterator->nextPixel(); } void KisBrush::PaintDeviceColoringInformation::nextRow() { m_iterator->nextRow(); } struct KisBrush::Private { Private() : boundary(0) , angle(0) , scale(1.0) , hasColor(false) , brushType(INVALID) , brushPyramid(0) , autoSpacingActive(false) , autoSpacingCoeff(1.0) {} ~Private() { delete boundary; } mutable KisBoundary* boundary; qreal angle; qreal scale; bool hasColor; enumBrushType brushType; qint32 width; qint32 height; double spacing; QPointF hotSpot; mutable KisQImagePyramid *brushPyramid; QImage brushTipImage; bool autoSpacingActive; qreal autoSpacingCoeff; }; KisBrush::KisBrush() : KoResource("") , d(new Private) { } KisBrush::KisBrush(const QString& filename) : KoResource(filename) , d(new Private) { } KisBrush::KisBrush(const KisBrush& rhs) : KoResource("") , KisShared() , d(new Private) { setBrushTipImage(rhs.brushTipImage()); d->brushType = rhs.d->brushType; d->width = rhs.d->width; d->height = rhs.d->height; d->spacing = rhs.d->spacing; d->hotSpot = rhs.d->hotSpot; d->hasColor = rhs.d->hasColor; d->angle = rhs.d->angle; d->scale = rhs.d->scale; d->autoSpacingActive = rhs.d->autoSpacingActive; d->autoSpacingCoeff = rhs.d->autoSpacingCoeff; setFilename(rhs.filename()); clearBrushPyramid(); // don't copy the boundary, it will be regenerated -- see bug 291910 } KisBrush::~KisBrush() { clearBrushPyramid(); delete d; } QImage KisBrush::brushTipImage() const { if (d->brushTipImage.isNull()) { const_cast(this)->load(); } return d->brushTipImage; } qint32 KisBrush::width() const { return d->width; } void KisBrush::setWidth(qint32 width) { d->width = width; } qint32 KisBrush::height() const { return d->height; } void KisBrush::setHeight(qint32 height) { d->height = height; } void KisBrush::setHotSpot(QPointF pt) { double x = pt.x(); double y = pt.y(); if (x < 0) x = 0; else if (x >= width()) x = width() - 1; if (y < 0) y = 0; else if (y >= height()) y = height() - 1; d->hotSpot = QPointF(x, y); } QPointF KisBrush::hotSpot(double scaleX, double scaleY, double rotation, const KisPaintInformation& info) const { Q_UNUSED(info); QSizeF metric = characteristicSize(scaleX, scaleY, rotation); qreal w = metric.width(); qreal h = metric.height(); // The smallest brush we can produce is a single pixel. if (w < 1) { w = 1; } if (h < 1) { h = 1; } // XXX: This should take d->hotSpot into account, though it // isn't specified by gimp brushes so it would default to the center // anyway. QPointF p(w / 2, h / 2); return p; } bool KisBrush::hasColor() const { return d->hasColor; } void KisBrush::setHasColor(bool hasColor) { d->hasColor = hasColor; } bool KisBrush::isPiercedApprox() const { QImage image = brushTipImage(); qreal w = image.width(); qreal h = image.height(); qreal xPortion = qMin(0.1, 5.0 / w); qreal yPortion = qMin(0.1, 5.0 / h); int x0 = std::floor((0.5 - xPortion) * w); int x1 = std::ceil((0.5 + xPortion) * w); int y0 = std::floor((0.5 - yPortion) * h); int y1 = std::ceil((0.5 + yPortion) * h); const int maxNumSamples = (x1 - x0 + 1) * (y1 - y0 + 1); const int failedPixelsThreshold = 0.1 * maxNumSamples; const int thresholdValue = 0.95 * 255; int failedPixels = 0; for (int y = y0; y <= y1; y++) { for (int x = x0; x <= x1; x++) { QRgb pixel = image.pixel(x,y); if (qRed(pixel) > thresholdValue) { failedPixels++; } } } return failedPixels > failedPixelsThreshold; } bool KisBrush::canPaintFor(const KisPaintInformation& /*info*/) { return true; } void KisBrush::setBrushTipImage(const QImage& image) { //Q_ASSERT(!image.isNull()); d->brushTipImage = image; if (!image.isNull()) { if (image.width() > 128 || image.height() > 128) { KoResource::setImage(image.scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation)); } else { KoResource::setImage(image); } setWidth(image.width()); setHeight(image.height()); } clearBrushPyramid(); } void KisBrush::setBrushType(enumBrushType type) { d->brushType = type; } enumBrushType KisBrush::brushType() const { return d->brushType; } void KisBrush::predefinedBrushToXML(const QString &type, QDomElement& e) const { e.setAttribute("type", type); e.setAttribute("filename", shortFilename()); e.setAttribute("spacing", QString::number(spacing())); e.setAttribute("useAutoSpacing", QString::number(autoSpacingActive())); e.setAttribute("autoSpacingCoeff", QString::number(autoSpacingCoeff())); e.setAttribute("angle", QString::number(angle())); e.setAttribute("scale", QString::number(scale())); } -QByteArray KisBrush::generateMD5() const -{ - if (!filename().isNull() && !filename().startsWith("bundle://") && QFileInfo(filename()).exists()) { - QFile f(filename()); - f.open(QFile::ReadOnly); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(f.readAll()); - return md5.result(); - } - return QByteArray(); -} - void KisBrush::toXML(QDomDocument& /*document*/ , QDomElement& element) const { element.setAttribute("BrushVersion", "2"); } KisBrushSP KisBrush::fromXML(const QDomElement& element) { KisBrushSP brush = KisBrushRegistry::instance()->getOrCreateBrush(element); if (brush && element.attribute("BrushVersion", "1") == "1") { brush->setScale(brush->scale() * 2.0); } return brush; } QSizeF KisBrush::characteristicSize(double scaleX, double scaleY, double rotation) const { Q_UNUSED(scaleY); qreal angle = normalizeAngle(rotation + d->angle); qreal scale = scaleX * d->scale; return KisQImagePyramid::characteristicSize(QSize(width(), height()), scale, angle); } qint32 KisBrush::maskWidth(double scale, double angle, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const { Q_UNUSED(info); angle = normalizeAngle(angle + d->angle); scale *= d->scale; return KisQImagePyramid::imageSize(QSize(width(), height()), scale, angle, subPixelX, subPixelY).width(); } qint32 KisBrush::maskHeight(double scale, double angle, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const { Q_UNUSED(info); angle = normalizeAngle(angle + d->angle); scale *= d->scale; return KisQImagePyramid::imageSize(QSize(width(), height()), scale, angle, subPixelX, subPixelY).height(); } double KisBrush::maskAngle(double angle) const { return normalizeAngle(angle + d->angle); } quint32 KisBrush::brushIndex(const KisPaintInformation& info) const { Q_UNUSED(info); return 0; } void KisBrush::setSpacing(double s) { if (s < 0.02) s = 0.02; d->spacing = s; } double KisBrush::spacing() const { return d->spacing; } void KisBrush::setAutoSpacing(bool active, qreal coeff) { d->autoSpacingCoeff = coeff; d->autoSpacingActive = active; } bool KisBrush::autoSpacingActive() const { return d->autoSpacingActive; } qreal KisBrush::autoSpacingCoeff() const { return d->autoSpacingCoeff; } void KisBrush::notifyCachedDabPainted() { } void KisBrush::prepareBrushPyramid() const { if (!d->brushPyramid) { d->brushPyramid = new KisQImagePyramid(brushTipImage()); } } void KisBrush::clearBrushPyramid() { delete d->brushPyramid; d->brushPyramid = 0; } void KisBrush::mask(KisFixedPaintDeviceSP dst, double scaleX, double scaleY, double angle, const KisPaintInformation& info , double subPixelX, double subPixelY, qreal softnessFactor) const { generateMaskAndApplyMaskOrCreateDab(dst, 0, scaleX, scaleY, angle, info, subPixelX, subPixelY, softnessFactor); } void KisBrush::mask(KisFixedPaintDeviceSP dst, const KoColor& color, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY, qreal softnessFactor) const { PlainColoringInformation pci(color.data()); generateMaskAndApplyMaskOrCreateDab(dst, &pci, scaleX, scaleY, angle, info, subPixelX, subPixelY, softnessFactor); } void KisBrush::mask(KisFixedPaintDeviceSP dst, const KisPaintDeviceSP src, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY, qreal softnessFactor) const { PaintDeviceColoringInformation pdci(src, maskWidth(scaleX, angle, subPixelX, subPixelY, info)); generateMaskAndApplyMaskOrCreateDab(dst, &pdci, scaleX, scaleY, angle, info, subPixelX, subPixelY, softnessFactor); } void KisBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, ColoringInformation* coloringInformation, double scaleX, double scaleY, double angle, const KisPaintInformation& info_, double subPixelX, double subPixelY, qreal softnessFactor) const { Q_ASSERT(valid()); Q_UNUSED(info_); Q_UNUSED(softnessFactor); angle = normalizeAngle(angle + d->angle); scaleX *= d->scale; scaleY *= d->scale; double scale = 0.5 * (scaleX + scaleY); prepareBrushPyramid(); QImage outputImage = d->brushPyramid->createImage(scale, -angle, subPixelX, subPixelY); qint32 maskWidth = outputImage.width(); qint32 maskHeight = outputImage.height(); dst->setRect(QRect(0, 0, maskWidth, maskHeight)); dst->initialize(); quint8* color = 0; if (coloringInformation) { if (dynamic_cast(coloringInformation)) { color = const_cast(coloringInformation->color()); } } const KoColorSpace *cs = dst->colorSpace(); qint32 pixelSize = cs->pixelSize(); quint8 *dabPointer = dst->data(); quint8 *rowPointer = dabPointer; quint8 *alphaArray = new quint8[maskWidth]; bool hasColor = this->hasColor(); for (int y = 0; y < maskHeight; y++) { #if QT_VERSION >= 0x040700 const quint8* maskPointer = outputImage.constScanLine(y); #else const quint8* maskPointer = outputImage.scanLine(y); #endif if (coloringInformation) { for (int x = 0; x < maskWidth; x++) { if (color) { memcpy(dabPointer, color, pixelSize); } else { memcpy(dabPointer, coloringInformation->color(), pixelSize); coloringInformation->nextColumn(); } dabPointer += pixelSize; } } if (hasColor) { const quint8 *src = maskPointer; quint8 *dst = alphaArray; for (int x = 0; x < maskWidth; x++) { const QRgb *c = reinterpret_cast(src); *dst = KoColorSpaceMaths::multiply(255 - qGray(*c), qAlpha(*c)); src += 4; dst++; } } else { const quint8 *src = maskPointer; quint8 *dst = alphaArray; for (int x = 0; x < maskWidth; x++) { const QRgb *c = reinterpret_cast(src); *dst = KoColorSpaceMaths::multiply(255 - *src, qAlpha(*c)); src += 4; dst++; } } cs->applyAlphaU8Mask(rowPointer, alphaArray, maskWidth); rowPointer += maskWidth * pixelSize; dabPointer = rowPointer; if (!color && coloringInformation) { coloringInformation->nextRow(); } } delete[] alphaArray; } KisFixedPaintDeviceSP KisBrush::paintDevice(const KoColorSpace * colorSpace, double scale, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY) const { Q_ASSERT(valid()); Q_UNUSED(info); angle = normalizeAngle(angle + d->angle); scale *= d->scale; prepareBrushPyramid(); QImage outputImage = d->brushPyramid->createImage(scale, -angle, subPixelX, subPixelY); KisFixedPaintDeviceSP dab = new KisFixedPaintDevice(colorSpace); Q_CHECK_PTR(dab); dab->convertFromQImage(outputImage, ""); return dab; } void KisBrush::resetBoundary() { delete d->boundary; d->boundary = 0; } void KisBrush::generateBoundary() const { KisFixedPaintDeviceSP dev; if (brushType() == IMAGE || brushType() == PIPE_IMAGE) { dev = paintDevice(KoColorSpaceRegistry::instance()->rgb8(), 1.0 / scale(), -angle(), KisPaintInformation()); } else { const KoColorSpace* cs = KoColorSpaceRegistry::instance()->rgb8(); dev = new KisFixedPaintDevice(cs); mask(dev, KoColor(Qt::black, cs) , 1.0 / scale(), 1.0 / scale(), -angle(), KisPaintInformation()); } d->boundary = new KisBoundary(dev); d->boundary->generateBoundary(); } const KisBoundary* KisBrush::boundary() const { if (!d->boundary) generateBoundary(); return d->boundary; } void KisBrush::setScale(qreal _scale) { d->scale = _scale; } qreal KisBrush::scale() const { return d->scale; } void KisBrush::setAngle(qreal _rotation) { d->angle = _rotation; } qreal KisBrush::angle() const { return d->angle; } QPainterPath KisBrush::outline() const { return boundary()->path(); } diff --git a/krita/libbrush/kis_brush.h b/krita/libbrush/kis_brush.h index 6faf597f216..0feb3349ed3 100644 --- a/krita/libbrush/kis_brush.h +++ b/krita/libbrush/kis_brush.h @@ -1,367 +1,366 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_ #define KIS_BRUSH_ #include #include #include #include -#include +#include class KisQImagemask; typedef KisSharedPtr KisQImagemaskSP; class QString; class QPoint; class KoColor; class KoColorSpace; class KisPaintInformation; class KisBoundary; enum enumBrushType { INVALID, MASK, IMAGE, PIPE_MASK, PIPE_IMAGE, AIRBRUSH }; static const qreal DEFAULT_SOFTNESS_FACTOR = 1.0; class KisBrush; typedef KisSharedPtr KisBrushSP; /** * KisBrush is the base class for brush resources. A brush resource * defines one or more images that are used to potato-stamp along * the drawn path. The brush type defines how this brush is used -- * the important difference is between masks (which take the current * painting color) and images (which do not). It is up to the paintop * to make use of this feature. * * Brushes must be serializable to an xml representation and provide * a factory class that can recreate or retrieve the brush based on * this representation. * * XXX: This api is still a big mess -- it needs a good refactoring. * And the whole KoResource architecture is way over-designed. */ class BRUSH_EXPORT KisBrush : public KoResource, public KisShared { public: class ColoringInformation { public: virtual ~ColoringInformation(); virtual const quint8* color() const = 0; virtual void nextColumn() = 0; virtual void nextRow() = 0; }; protected: class PlainColoringInformation : public ColoringInformation { public: PlainColoringInformation(const quint8* color); virtual ~PlainColoringInformation(); virtual const quint8* color() const ; virtual void nextColumn(); virtual void nextRow(); private: const quint8* m_color; }; class PaintDeviceColoringInformation : public ColoringInformation { public: PaintDeviceColoringInformation(const KisPaintDeviceSP source, int width); virtual ~PaintDeviceColoringInformation(); virtual const quint8* color() const ; virtual void nextColumn(); virtual void nextRow(); private: const KisPaintDeviceSP m_source; KisHLineConstIteratorSP m_iterator; }; public: KisBrush(); KisBrush(const QString& filename); virtual ~KisBrush(); virtual bool load() { return false; } virtual bool loadFromDevice(QIODevice *) { return false; } virtual bool save() { return false; } virtual bool saveToDevice(QIODevice* ) const { return false; } /** * @brief brushImage the image the brush tip can paint with. Not all brush types have a single * image. * @return a valid QImage. */ virtual QImage brushTipImage() const; /** * Change the spacing of the brush. * @param spacing a spacing of 1.0 means that strokes will be separated from one time the size * of the brush. */ virtual void setSpacing(double spacing); /** * @return the spacing between two strokes for this brush */ double spacing() const; void setAutoSpacing(bool active, qreal coeff); bool autoSpacingActive() const; qreal autoSpacingCoeff() const; /** * @return the width (for scale == 1.0) */ qint32 width() const; /** * @return the height (for scale == 1.0) */ qint32 height() const; /** * @return the width of the mask for the given scale and angle */ virtual qint32 maskWidth(double scale, double angle, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; /** * @return the height of the mask for the given scale and angle */ virtual qint32 maskHeight(double scale, double angle, qreal subPixelX, qreal subPixelY, const KisPaintInformation& info) const; /** * @return the logical size of the brush, that is the size measured * in floating point value. * * This value should not be used for calculating future dab sizes * because it doesn't take any rounding into account. The only use * of this metric is calculation of brush-size derivatives like * hotspots and spacing. */ QSizeF characteristicSize(double scaleX, double scaleY, double rotation) const; /** * @return the angle of the mask adding the given angle */ double maskAngle(double angle = 0) const; /** * @return the index of the brush * if the brush consists of multiple images */ virtual quint32 brushIndex(const KisPaintInformation& info) const; /** * The brush type defines how the brush is used. */ virtual enumBrushType brushType() const; QPointF hotSpot(double scaleX, double scaleY, double rotation, const KisPaintInformation& info) const; /** * Returns true if this brush can return something useful for the info. This is used * by Pipe Brushes that can't paint sometimes **/ virtual bool canPaintFor(const KisPaintInformation& /*info*/); /** * Is called by the cache, when cache hit has happened. * Having got this notification the brush can update the counters * of dabs, generate some new random values if needed. * * Currently, this is used by pipe'd brushes to implement * incremental and random parasites */ void notifyCachedDabPainted(); /** * Return a fixed paint device that contains a correctly scaled image dab. */ virtual KisFixedPaintDeviceSP paintDevice(const KoColorSpace * colorSpace, double scale, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0) const; /** * Apply the brush mask to the pixels in dst. Dst should be big enough! */ void mask(KisFixedPaintDeviceSP dst, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; /** * clear dst fill it with a mask colored with KoColor */ void mask(KisFixedPaintDeviceSP dst, const KoColor& color, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; /** * clear dst and fill it with a mask colored with the corresponding colors of src */ void mask(KisFixedPaintDeviceSP dst, const KisPaintDeviceSP src, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; virtual bool hasColor() const; /** * Create a mask and either mask dst (that is, change all alpha values of the * existing pixels to those of the mask) or, if coloringInfo is present, clear * dst and fill dst with pixels according to coloringInfo, masked according to the * generated mask. * * @param dst the destination that will be draw on the image, and this function * will edit its alpha channel * @param coloringInfo coloring information that will be copied on the dab, it can be null * @param scale a scale applied on the alpha mask * @param angle a rotation applied on the alpha mask * @param info the painting information (this is only and should only be used by * KisImagePipeBrush and only to be backward compatible with the Gimp, * KisImagePipeBrush is ignoring scale and angle information) * @param subPixelX sub position of the brush (contained between 0.0 and 1.0) * @param subPixelY sub position of the brush (contained between 0.0 and 1.0) * * @return a mask computed from the grey-level values of the * pixels in the brush. */ virtual void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, ColoringInformation* coloringInfo, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; /** * Serialize this brush to XML. */ virtual void toXML(QDomDocument& , QDomElement&) const; static KisBrushSP fromXML(const QDomElement& element); virtual const KisBoundary* boundary() const; virtual QPainterPath outline() const; virtual void setScale(qreal _scale); qreal scale() const; virtual void setAngle(qreal _angle); qreal angle() const; void prepareBrushPyramid() const; void clearBrushPyramid(); //protected: KisBrush(const KisBrush& rhs); void setWidth(qint32 width); void setHeight(qint32 height); void setHotSpot(QPointF); /** * The image is used to represent the brush in the gui, and may also, depending on the brush type * be used to define the actual brush instance. */ virtual void setBrushTipImage(const QImage& image); /** * XXX */ virtual void setBrushType(enumBrushType type); friend class KisBrushTest; virtual void setHasColor(bool hasColor); /** * Returns true if the brush has a bunch of pixels almost * fully transparent in the very center. If the brush is pierced, * then dulling mode may not work correctly due to empty samples. * * WARNING: this method is relatively expensive since it iterates * up to 100 pixels of the brush. */ bool isPiercedApprox() const; protected: - virtual QByteArray generateMD5() const; void resetBoundary(); void predefinedBrushToXML(const QString &type, QDomElement& e) const; private: friend class KisImagePipeBrushTest; // Initialize our boundary void generateBoundary() const; struct Private; Private* const d; }; #endif // KIS_BRUSH_ diff --git a/krita/libbrush/kis_brush_registry.h b/krita/libbrush/kis_brush_registry.h index 8e67d6f4aa3..af66cfdb312 100644 --- a/krita/libbrush/kis_brush_registry.h +++ b/krita/libbrush/kis_brush_registry.h @@ -1,52 +1,52 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_REGISTRY_H_ #define KIS_BRUSH_REGISTRY_H_ #include #include "kis_types.h" #include "KoGenericRegistry.h" -#include +#include #include "kis_brush.h" #include "kis_brush_factory.h" class QDomElement; class BRUSH_EXPORT KisBrushRegistry : public QObject, public KoGenericRegistry { Q_OBJECT public: virtual ~KisBrushRegistry(); static KisBrushRegistry* instance(); KisBrushSP getOrCreateBrush(const QDomElement& element); private: KisBrushRegistry(); KisBrushRegistry(const KisBrushRegistry&); KisBrushRegistry operator=(const KisBrushRegistry&); }; #endif // KIS_GENERATOR_REGISTRY_H_ diff --git a/krita/libbrush/kis_brush_server.h b/krita/libbrush/kis_brush_server.h index 89714e8569e..eb440e0c958 100644 --- a/krita/libbrush/kis_brush_server.h +++ b/krita/libbrush/kis_brush_server.h @@ -1,67 +1,67 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_SERVER_H #define KIS_BRUSH_SERVER_H #include #include #include #include #include -#include "krita_export.h" +#include "kritabrush_export.h" #include "kis_brush.h" class KoResource; class KoResourceLoaderThread; typedef KoResourceServer > KisBrushResourceServer; typedef KoResourceServerAdapter > KisBrushResourceServerAdapter; /** * */ class BRUSH_EXPORT KisBrushServer : public QObject { Q_OBJECT public: virtual ~KisBrushServer(); KisBrushResourceServer* brushServer(bool block = true); static KisBrushServer* instance(); public Q_SLOTS: void slotRemoveBlacklistedResources(); private: KisBrushServer(); KisBrushServer(const KisBrushServer&); KisBrushServer operator=(const KisBrushServer&); KisBrushResourceServer* m_brushServer; private: KoResourceLoaderThread *m_brushThread; }; #endif diff --git a/krita/libbrush/kis_gbr_brush.cpp b/krita/libbrush/kis_gbr_brush.cpp index 37158f90228..c502551254b 100644 --- a/krita/libbrush/kis_gbr_brush.cpp +++ b/krita/libbrush/kis_gbr_brush.cpp @@ -1,523 +1,524 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2004 Adrian Page * Copyright (c) 2005 Bart Coppens * Copyright (c) 2007 Cyrille Berger * Copyright (c) 2010 Lukáš Tvrdý * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include // htonl #include "kis_gbr_brush.h" #include "kis_brush.h" #include #include #include #include #include #include #include #include #include "kis_datamanager.h" #include "kis_paint_device.h" #include "kis_global.h" #include "kis_image.h" struct GimpBrushV1Header { quint32 header_size; /* header_size = sizeof (BrushHeader) + brush name */ quint32 version; /* brush file version # */ quint32 width; /* width of brush */ quint32 height; /* height of brush */ quint32 bytes; /* depth of brush in bytes */ }; /// All fields are in MSB on disk! struct GimpBrushHeader { quint32 header_size; /* header_size = sizeof (BrushHeader) + brush name */ quint32 version; /* brush file version # */ quint32 width; /* width of brush */ quint32 height; /* height of brush */ quint32 bytes; /* depth of brush in bytes */ /* The following are only defined in version 2 */ quint32 magic_number; /* GIMP brush magic number */ quint32 spacing; /* brush spacing as % of width & height, 0 - 1000 */ }; // Needed, or the GIMP won't open it! quint32 const GimpV2BrushMagic = ('G' << 24) + ('I' << 16) + ('M' << 8) + ('P' << 0); struct KisGbrBrush::Private { QByteArray data; bool ownData; /* seems to indicate that @ref data is owned by the brush, but in Qt4.x this is already guaranteed... so in reality it seems more to indicate whether the data is loaded from file (ownData = true) or memory (ownData = false) */ bool useColorAsMask; quint32 header_size; /* header_size = sizeof (BrushHeader) + brush name */ quint32 version; /* brush file version # */ quint32 bytes; /* depth of brush in bytes */ quint32 magic_number; /* GIMP brush magic number */ }; #define DEFAULT_SPACING 0.25 KisGbrBrush::KisGbrBrush(const QString& filename) : KisBrush(filename) , d(new Private) { d->ownData = true; d->useColorAsMask = false; setHasColor(false); setSpacing(DEFAULT_SPACING); } KisGbrBrush::KisGbrBrush(const QString& filename, const QByteArray& data, qint32 & dataPos) : KisBrush(filename) , d(new Private) { d->ownData = false; d->useColorAsMask = false; setHasColor(false); setSpacing(DEFAULT_SPACING); d->data = QByteArray::fromRawData(data.data() + dataPos, data.size() - dataPos); init(); d->data.clear(); dataPos += d->header_size + (width() * height() * d->bytes); } KisGbrBrush::KisGbrBrush(KisPaintDeviceSP image, int x, int y, int w, int h) : KisBrush() , d(new Private) { d->ownData = true; d->useColorAsMask = false; setHasColor(false); setSpacing(DEFAULT_SPACING); initFromPaintDev(image, x, y, w, h); } KisGbrBrush::KisGbrBrush(const QImage& image, const QString& name) : KisBrush() , d(new Private) { d->ownData = false; d->useColorAsMask = false; setHasColor(false); setSpacing(DEFAULT_SPACING); setBrushTipImage(image); setName(name); } KisGbrBrush::KisGbrBrush(const KisGbrBrush& rhs) : KisBrush(rhs) - , d(new Private) + , d(new Private(*rhs.d)) { setName(rhs.name()); - *d = *rhs.d; d->data = QByteArray(); setValid(rhs.valid()); } KisGbrBrush::~KisGbrBrush() { delete d; } bool KisGbrBrush::load() { QFile file(filename()); if (file.size() == 0) return false; file.open(QIODevice::ReadOnly); bool res = loadFromDevice(&file); file.close(); return res; } bool KisGbrBrush::loadFromDevice(QIODevice *dev) { if (d->ownData) { d->data = dev->readAll(); } return init(); } bool KisGbrBrush::init() { GimpBrushHeader bh; if (sizeof(GimpBrushHeader) > (uint)d->data.size()) { return false; } memcpy(&bh, d->data, sizeof(GimpBrushHeader)); bh.header_size = ntohl(bh.header_size); d->header_size = bh.header_size; bh.version = ntohl(bh.version); d->version = bh.version; bh.width = ntohl(bh.width); bh.height = ntohl(bh.height); bh.bytes = ntohl(bh.bytes); d->bytes = bh.bytes; bh.magic_number = ntohl(bh.magic_number); d->magic_number = bh.magic_number; if (bh.version == 1) { // No spacing in version 1 files so use Gimp default bh.spacing = static_cast(DEFAULT_SPACING * 100); } else { bh.spacing = ntohl(bh.spacing); if (bh.spacing > 1000) { return false; } } setSpacing(bh.spacing / 100.0); if (bh.header_size > (uint)d->data.size() || bh.header_size == 0) { return false; } QString name; if (bh.version == 1) { // Version 1 has no magic number or spacing, so the name // is at a different offset. Character encoding is undefined. const char *text = d->data.constData() + sizeof(GimpBrushV1Header); name = QString::fromLatin1(text, bh.header_size - sizeof(GimpBrushV1Header) - 1); } else { // ### Version = 3->cinepaint; may be float16 data! // Version >=2: UTF-8 encoding is used name = QString::fromUtf8(d->data.constData() + sizeof(GimpBrushHeader), bh.header_size - sizeof(GimpBrushHeader) - 1); } setName(name); if (bh.width == 0 || bh.height == 0) { return false; } QImage::Format imageFormat; if (bh.bytes == 1) { imageFormat = QImage::Format_Indexed8; } else { imageFormat = QImage::Format_ARGB32; } QImage image(QImage(bh.width, bh.height, imageFormat)); if (image.isNull()) { return false; } qint32 k = bh.header_size; if (bh.bytes == 1) { QVector table; for (int i = 0; i < 256; ++i) table.append(qRgb(i, i, i)); image.setColorTable(table); // Grayscale if (static_cast(k + bh.width * bh.height) > d->data.size()) { return false; } setHasColor(false); for (quint32 y = 0; y < bh.height; y++) { uchar *pixel = reinterpret_cast(image.scanLine(y)); for (quint32 x = 0; x < bh.width; x++, k++) { qint32 val = 255 - static_cast(d->data[k]); *pixel = val; ++pixel; } } } else if (bh.bytes == 4) { // RGBA if (static_cast(k + (bh.width * bh.height * 4)) > d->data.size()) { return false; } setHasColor(true); for (quint32 y = 0; y < bh.height; y++) { QRgb *pixel = reinterpret_cast(image.scanLine(y)); for (quint32 x = 0; x < bh.width; x++, k += 4) { *pixel = qRgba(d->data[k], d->data[k + 1], d->data[k + 2], d->data[k + 3]); ++pixel; } } } else { qWarning() << "WARNING: loading of GBR brushes with" << bh.bytes << "bytes per pixel is not supported"; return false; } setWidth(image.width()); setHeight(image.height()); if (d->ownData) { d->data.resize(0); // Save some memory, we're using enough of it as it is. } setValid(image.width() != 0 && image.height() != 0); setBrushTipImage(image); return true; } bool KisGbrBrush::initFromPaintDev(KisPaintDeviceSP image, int x, int y, int w, int h) { // Forcefully convert to RGBA8 // XXX profile and exposure? setBrushTipImage(image->convertToQImage(0, x, y, w, h, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags)); setName(image->objectName()); setHasColor(true); return true; } bool KisGbrBrush::save() { QFile file(filename()); file.open(QIODevice::WriteOnly | QIODevice::Truncate); bool ok = saveToDevice(&file); file.close(); return ok; } bool KisGbrBrush::saveToDevice(QIODevice* dev) const { GimpBrushHeader bh; QByteArray utf8Name = name().toUtf8(); // Names in v2 brushes are in UTF-8 char const* name = utf8Name.data(); int nameLength = qstrlen(name); int wrote; bh.header_size = htonl(sizeof(GimpBrushHeader) + nameLength + 1); bh.version = htonl(2); // Only RGBA8 data needed atm, no cinepaint stuff bh.width = htonl(width()); bh.height = htonl(height()); // Hardcoded, 4 bytes RGBA or 1 byte GREY if (!hasColor()) { bh.bytes = htonl(1); } else { bh.bytes = htonl(4); } bh.magic_number = htonl(GimpV2BrushMagic); bh.spacing = htonl(static_cast(spacing() * 100.0)); // Write header: first bh, then the name QByteArray bytes = QByteArray::fromRawData(reinterpret_cast(&bh), sizeof(GimpBrushHeader)); wrote = dev->write(bytes); bytes.clear(); if (wrote == -1) { return false; } wrote = dev->write(name, nameLength + 1); if (wrote == -1) { return false; } int k = 0; QImage image = brushTipImage(); if (!hasColor()) { bytes.resize(width() * height()); for (qint32 y = 0; y < height(); y++) { for (qint32 x = 0; x < width(); x++) { QRgb c = image.pixel(x, y); bytes[k++] = static_cast(255 - qRed(c)); // red == blue == green } } } else { bytes.resize(width() * height() * 4); for (qint32 y = 0; y < height(); y++) { for (qint32 x = 0; x < width(); x++) { // order for gimp brushes, v2 is: RGBA QRgb pixel = image.pixel(x, y); bytes[k++] = static_cast(qRed(pixel)); bytes[k++] = static_cast(qGreen(pixel)); bytes[k++] = static_cast(qBlue(pixel)); bytes[k++] = static_cast(qAlpha(pixel)); } } } wrote = dev->write(bytes); if (wrote == -1) { return false; } + KoResource::saveToDevice(dev); + return true; } QImage KisGbrBrush::brushTipImage() const { QImage image = KisBrush::brushTipImage(); if (hasColor() && useColorAsMask()) { for (int y = 0; y < image.height(); y++) { QRgb *pixel = reinterpret_cast(image.scanLine(y)); for (int x = 0; x < image.width(); x++) { QRgb c = pixel[x]; int a = qGray(c); pixel[x] = qRgba(a, a, a, qAlpha(c)); } } } return image; } enumBrushType KisGbrBrush::brushType() const { return !hasColor() || useColorAsMask() ? MASK : IMAGE; } void KisGbrBrush::setBrushType(enumBrushType type) { Q_UNUSED(type); qFatal("FATAL: protected member setBrushType has no meaning for KisGbrBrush"); } void KisGbrBrush::setBrushTipImage(const QImage& image) { KisBrush::setBrushTipImage(image); setValid(true); } /*QImage KisGbrBrush::outline(double pressure) { KisLayerSP layer = image(KoColorSpaceRegistry::instance()->colorSpace("RGBA",0), KisPaintInformation(pressure)); KisBoundary bounds(layer.data()); int w = maskWidth(pressure); int h = maskHeight(pressure); bounds.generateBoundary(w, h); QPixmap pix(bounds.pixmap(w, h)); QImage result; result = pix; return result; }*/ void KisGbrBrush::makeMaskImage() { if (!hasColor()) { return; } QImage brushTip = brushTipImage(); if (brushTip.width() == width() && brushTip.height() == height()) { int imageWidth = width(); int imageHeight = height(); QImage image(imageWidth, imageHeight, QImage::Format_Indexed8); QVector table; for (int i = 0; i < 256; ++i) { table.append(qRgb(i, i, i)); } image.setColorTable(table); for (int y = 0; y < imageHeight; y++) { QRgb *pixel = reinterpret_cast(brushTip.scanLine(y)); uchar * dstPixel = image.scanLine(y); for (int x = 0; x < imageWidth; x++) { QRgb c = pixel[x]; float alpha = qAlpha(c) / 255.0f; // linear interpolation with maximum gray value which is transparent in the mask //int a = (qGray(c) * alpha) + ((1.0 - alpha) * 255); // single multiplication version int a = 255 + alpha * (qGray(c) - 255); dstPixel[x] = (uchar)a; } } setBrushTipImage(image); } setHasColor(false); setUseColorAsMask(false); resetBoundary(); clearBrushPyramid(); } KisGbrBrush* KisGbrBrush::clone() const { return new KisGbrBrush(*this); } void KisGbrBrush::toXML(QDomDocument& d, QDomElement& e) const { predefinedBrushToXML("gbr_brush", e); e.setAttribute("ColorAsMask", QString::number((int)useColorAsMask())); KisBrush::toXML(d, e); } void KisGbrBrush::setUseColorAsMask(bool useColorAsMask) { /** * WARNING: There is a problem in the brush server, since it * returns not copies of brushes, but direct pointers to them. It * means that the brushes are shared among all the currently * present paintops, which might be a problem for e.g. Multihand * Brush Tool. * * Right now, all the instances of Multihand Brush Tool share the * same brush, so there is no problem in this sharing, unless we * reset the internal state of the brush on our way. */ if (useColorAsMask != d->useColorAsMask) { d->useColorAsMask = useColorAsMask; resetBoundary(); clearBrushPyramid(); } } bool KisGbrBrush::useColorAsMask() const { return d->useColorAsMask; } QString KisGbrBrush::defaultFileExtension() const { return QString(".gbr"); } diff --git a/krita/libbrush/kis_gbr_brush.h b/krita/libbrush/kis_gbr_brush.h index 667a3feec10..b8cfc1c3a21 100644 --- a/krita/libbrush/kis_gbr_brush.h +++ b/krita/libbrush/kis_gbr_brush.h @@ -1,122 +1,122 @@ /* * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * Copyright (c) 2004 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_GBR_BRUSH_ #define KIS_GBR_BRUSH_ #include #include #include "kis_brush.h" #include "kis_types.h" #include "kis_shared.h" #include "kis_paint_information.h" -#include "krita_export.h" +#include "kritabrush_export.h" class KisQImagemask; typedef KisSharedPtr KisQImagemaskSP; class QString; class QIODevice; class BRUSH_EXPORT KisGbrBrush : public KisBrush { protected: public: /// Construct brush to load filename later as brush KisGbrBrush(const QString& filename); /// Load brush from the specified data, at position dataPos, and set the filename KisGbrBrush(const QString& filename, const QByteArray & data, qint32 & dataPos); /// Load brush from the specified paint device, in the specified region KisGbrBrush(KisPaintDeviceSP image, int x, int y, int w, int h); /// Load brush as a copy from the specified QImage (handy when you need to copy a brush!) KisGbrBrush(const QImage& image, const QString& name = QString("")); virtual ~KisGbrBrush(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; /** * @return a preview of the brush */ virtual QImage brushTipImage() const; /** * If the brush image data are colorful (e.g. you created the brush from the canvas with custom brush) * and you want to paint with it as with masks, set to true. */ virtual void setUseColorAsMask(bool useColorAsMask); virtual bool useColorAsMask() const; /** * Convert the mask to inverted gray scale, so it is alpha mask. * It can be used as MASK brush type. This operates on the date of the brush, * so it destruct the original brush data */ virtual void makeMaskImage(); virtual enumBrushType brushType() const; /** * Makes a copy of this brush. */ virtual KisGbrBrush* clone() const; /** * @return default file extension for saving the brush */ virtual QString defaultFileExtension() const; protected: /** * save the content of this brush to an IO device */ friend class KisImageBrushesPipe; KisGbrBrush(const KisGbrBrush& rhs); void setBrushType(enumBrushType type); virtual void setBrushTipImage(const QImage& image); void toXML(QDomDocument& d, QDomElement& e) const; private: bool init(); bool initFromPaintDev(KisPaintDeviceSP image, int x, int y, int w, int h); struct Private; Private* const d; }; #endif // KIS_GBR_BRUSH_ diff --git a/krita/libbrush/kis_imagepipe_brush.cpp b/krita/libbrush/kis_imagepipe_brush.cpp index 9cffa379b74..6debdab1ecd 100644 --- a/krita/libbrush/kis_imagepipe_brush.cpp +++ b/krita/libbrush/kis_imagepipe_brush.cpp @@ -1,451 +1,453 @@ /* * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2005 Bart Coppens * * 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_imagepipe_brush.h" #include "kis_imagepipe_brush_p.h" #include "kis_brushes_pipe.h" class KisImageBrushesPipe : public KisBrushesPipe { /* pre and post are split because: 21:12:20 < dmitryK> boud: i guess it was somehow related to the fact that the maskWidth/maskHeight should correspond to the size of the mask returned by paintDevice() 21:13:33 < dmitryK> boud: the random stuff is called once per brush->paintDevice() call, after the device is returned to the paint op, that is "preparing the randomness for the next call" 21:14:16 < dmitryK> boud: and brushesPipe->currentBrush() always returning the same brush for any particular paintInfo. */ protected: static int selectPre(KisParasite::SelectionMode mode, int index, int rank, const KisPaintInformation& info) { qreal angle; switch (mode) { case KisParasite::Constant: case KisParasite::Incremental: case KisParasite::Random: break; case KisParasite::Pressure: index = static_cast(info.pressure() * (rank - 1) + 0.5); break; case KisParasite::Angular: // + m_d->PI_2 to be compatible with the gimp angle = info.drawingAngle() + M_PI_2; angle = normalizeAngle(angle); index = static_cast(angle / (2.0 * M_PI) * rank); break; case KisParasite::TiltX: index = qRound(info.xTilt() / 2.0 * rank) + rank / 2; break; case KisParasite::TiltY: index = qRound(info.yTilt() / 2.0 * rank) + rank / 2; break; default: warnImage << "Parasite" << mode << "is not implemented"; index = 0; } return index; } static int selectPost(KisParasite::SelectionMode mode, int index, int rank) { switch (mode) { case KisParasite::Constant: break; case KisParasite::Incremental: index = (index + 1) % rank; break; case KisParasite::Random: index = int(float(rank) * KRandom::random() / RAND_MAX); break; case KisParasite::Pressure: case KisParasite::Angular: break; case KisParasite::TiltX: case KisParasite::TiltY: break; default: warnImage << "Parasite" << mode << "is not implemented"; index = 0; } return index; } int chooseNextBrush(const KisPaintInformation& info) const { quint32 brushIndex = 0; for (int i = 0; i < m_parasite.dim; i++) { int index = selectPre(m_parasite.selection[i], m_parasite.index[i], m_parasite.rank[i], info); brushIndex += m_parasite.brushesCount[i] * index; } brushIndex %= m_brushes.size(); return brushIndex; } void updateBrushIndexes() { for (int i = 0; i < m_parasite.dim; i++) { m_parasite.index[i] = selectPost(m_parasite.selection[i], m_parasite.index[i], m_parasite.rank[i]); } } public: using KisBrushesPipe::addBrush; void setParasite(const KisPipeBrushParasite& parasite) { m_parasite = parasite; } const KisPipeBrushParasite& parasite() const { return m_parasite; } void setUseColorAsMask(bool useColorAsMask) { foreach(KisGbrBrush * brush, m_brushes) { brush->setUseColorAsMask(useColorAsMask); } } void makeMaskImage() { foreach(KisGbrBrush * brush, m_brushes) { brush->makeMaskImage(); } } bool saveToDevice(QIODevice* dev) const { foreach(KisGbrBrush * brush, m_brushes) { if (!brush->saveToDevice(dev)) { return false; } } return true; } private: KisPipeBrushParasite m_parasite; }; struct KisImagePipeBrush::Private { public: KisImageBrushesPipe brushesPipe; }; KisImagePipeBrush::KisImagePipeBrush(const QString& filename) : KisGbrBrush(filename) , m_d(new Private()) { } KisImagePipeBrush::KisImagePipeBrush(const QString& name, int w, int h, QVector< QVector > devices, QVector modes) : KisGbrBrush("") , m_d(new Private()) { Q_ASSERT(devices.count() == modes.count()); Q_ASSERT(devices.count() > 0); Q_ASSERT(devices.count() < 2); // XXX Multidimensionals not supported yet, change to MaxDim! setName(name); KisPipeBrushParasite parasite; parasite.dim = devices.count(); // XXX Change for multidim! : parasite.ncells = devices.at(0).count(); parasite.rank[0] = parasite.ncells; // ### This can masquerade some bugs, be careful here in the future parasite.selection[0] = modes.at(0); // XXX needsmovement! parasite.setBrushesCount(); m_d->brushesPipe.setParasite(parasite); for (int i = 0; i < devices.at(0).count(); i++) { m_d->brushesPipe.addBrush(new KisGbrBrush(devices.at(0).at(i), 0, 0, w, h)); } setBrushTipImage(m_d->brushesPipe.firstBrush()->brushTipImage()); } KisImagePipeBrush::KisImagePipeBrush(const KisImagePipeBrush& rhs) : KisGbrBrush(rhs), m_d(new Private(*rhs.m_d)) { } KisImagePipeBrush::~KisImagePipeBrush() { delete m_d; } bool KisImagePipeBrush::load() { QFile file(filename()); file.open(QIODevice::ReadOnly); bool res = loadFromDevice(&file); file.close(); return res; } bool KisImagePipeBrush::loadFromDevice(QIODevice *dev) { QByteArray data = dev->readAll(); return initFromData(data); } bool KisImagePipeBrush::initFromData(const QByteArray &data) { if (data.size() == 0) return false; // XXX: this doesn't correctly load the image pipe brushes yet. // XXX: This stuff is in utf-8, too. // The first line contains the name -- this means we look until we arrive at the first newline QByteArray line1; qint32 i = 0; while (data[i] != '\n' && i < data.size()) { line1.append(data[i]); i++; } setName(QString::fromUtf8(line1, line1.size())); i++; // Skip past the first newline // The second line contains the number of brushes, separated by a space from the parasite // XXX: This stuff is in utf-8, too. QByteArray line2; while (data[i] != '\n' && i < data.size()) { line2.append(data[i]); i++; } QString paramline = QString::fromUtf8(line2, line2.size()); qint32 numOfBrushes = paramline.left(paramline.indexOf(' ')).toUInt(); QString parasiteString = paramline.mid(paramline.indexOf(' ') + 1); KisPipeBrushParasite parasite = KisPipeBrushParasite(parasiteString); parasite.sanitize(); m_d->brushesPipe.setParasite(parasite); i++; // Skip past the second newline for (int brushIndex = 0; brushIndex < numOfBrushes && i < data.size(); brushIndex++) { KisGbrBrush* brush = new KisGbrBrush(name() + '_' + QString().setNum(brushIndex), data, i); m_d->brushesPipe.addBrush(brush); } if (numOfBrushes > 0) { setValid(true); setSpacing(m_d->brushesPipe.lastBrush()->spacing()); setWidth(m_d->brushesPipe.firstBrush()->width()); setHeight(m_d->brushesPipe.firstBrush()->height()); setBrushTipImage(m_d->brushesPipe.firstBrush()->brushTipImage()); } return true; } bool KisImagePipeBrush::save() { QFile file(filename()); file.open(QIODevice::WriteOnly | QIODevice::Truncate); bool ok = saveToDevice(&file); file.close(); return ok; } bool KisImagePipeBrush::saveToDevice(QIODevice* dev) const { QByteArray utf8Name = name().toUtf8(); // Names in v2 brushes are in UTF-8 char const* name = utf8Name.data(); int len = qstrlen(name); if (m_d->brushesPipe.parasite().dim != 1) { warnImage << "Save to file for pipe brushes with dim != not yet supported!"; return false; } // Save this pipe brush: first the header, and then all individual brushes consecutively // XXX: this needs some care for when we have > 1 dimension) // Gimp Pipe Brush header format: Name\n \n // The name\n if (dev->write(name, len) == -1) return false; if (!dev->putChar('\n')) return false; // Write the parasite (also writes number of brushes) if (!m_d->brushesPipe.parasite().saveToDevice(dev)) return false; if (!dev->putChar('\n')) return false; + KoResource::saveToDevice(dev); + // return m_d->brushesPipe.saveToDevice(dev); } void KisImagePipeBrush::notifyCachedDabPainted() { m_d->brushesPipe.notifyCachedDabPainted(); } void KisImagePipeBrush::generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, KisBrush::ColoringInformation* coloringInformation, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX , double subPixelY, qreal softnessFactor) const { m_d->brushesPipe.generateMaskAndApplyMaskOrCreateDab(dst, coloringInformation, scaleX, scaleY, angle, info, subPixelX, subPixelY, softnessFactor); } KisFixedPaintDeviceSP KisImagePipeBrush::paintDevice(const KoColorSpace * colorSpace, double scale, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY) const { return m_d->brushesPipe.paintDevice(colorSpace, scale, angle, info, subPixelX, subPixelY); } enumBrushType KisImagePipeBrush::brushType() const { return !hasColor() || useColorAsMask() ? PIPE_MASK : PIPE_IMAGE; } bool KisImagePipeBrush::hasColor() const { return m_d->brushesPipe.hasColor(); } void KisImagePipeBrush::makeMaskImage() { m_d->brushesPipe.makeMaskImage(); setUseColorAsMask(false); } void KisImagePipeBrush::setUseColorAsMask(bool useColorAsMask) { KisGbrBrush::setUseColorAsMask(useColorAsMask); m_d->brushesPipe.setUseColorAsMask(useColorAsMask); } const KisBoundary* KisImagePipeBrush::boundary() const { KisGbrBrush *brush = m_d->brushesPipe.firstBrush(); Q_ASSERT(brush); return brush->boundary(); } bool KisImagePipeBrush::canPaintFor(const KisPaintInformation& info) { return (!m_d->brushesPipe.parasite().needsMovement || info.drawingDistance() >= 0.5); } KisImagePipeBrush* KisImagePipeBrush::clone() const { return new KisImagePipeBrush(*this); } QString KisImagePipeBrush::defaultFileExtension() const { return QString(".gih"); } quint32 KisImagePipeBrush::brushIndex(const KisPaintInformation& info) const { return m_d->brushesPipe.brushIndex(info); } qint32 KisImagePipeBrush::maskWidth(double scale, double angle, double subPixelX, double subPixelY, const KisPaintInformation& info) const { return m_d->brushesPipe.maskWidth(scale, angle, subPixelX, subPixelY, info); } qint32 KisImagePipeBrush::maskHeight(double scale, double angle, double subPixelX, double subPixelY, const KisPaintInformation& info) const { return m_d->brushesPipe.maskHeight(scale, angle, subPixelX, subPixelY, info); } void KisImagePipeBrush::setAngle(qreal _angle) { KisGbrBrush::setAngle(_angle); m_d->brushesPipe.setAngle(_angle); } void KisImagePipeBrush::setScale(qreal _scale) { KisGbrBrush::setScale(_scale); m_d->brushesPipe.setScale(_scale); } void KisImagePipeBrush::setSpacing(double _spacing) { KisGbrBrush::setSpacing(_spacing); m_d->brushesPipe.setSpacing(_spacing); } void KisImagePipeBrush::setBrushType(enumBrushType type) { Q_UNUSED(type); qFatal("FATAL: protected member setBrushType has no meaning for KisImagePipeBrush"); // brushType() is a finction of hasColor() and useColorAsMask() } void KisImagePipeBrush::setHasColor(bool hasColor) { Q_UNUSED(hasColor); qFatal("FATAL: protected member setHasColor has no meaning for KisImagePipeBrush"); // hasColor() is a function of the underlying brushes } KisGbrBrush* KisImagePipeBrush::testingGetCurrentBrush(const KisPaintInformation& info) const { return m_d->brushesPipe.currentBrush(info); } QVector KisImagePipeBrush::testingGetBrushes() const { return m_d->brushesPipe.testingGetBrushes(); } void KisImagePipeBrush::testingSelectNextBrush(const KisPaintInformation& info) const { return m_d->brushesPipe.testingSelectNextBrush(info); } diff --git a/krita/libbrush/kis_png_brush.cpp b/krita/libbrush/kis_png_brush.cpp index 358f8da0513..87ff5bc03c1 100644 --- a/krita/libbrush/kis_png_brush.cpp +++ b/krita/libbrush/kis_png_brush.cpp @@ -1,124 +1,128 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_png_brush.h" #include #include #include #include #include -#include KisPngBrush::KisPngBrush(const QString& filename) : KisBrush(filename) { setBrushType(INVALID); setSpacing(0.25); setHasColor(false); } bool KisPngBrush::load() { QFile f(filename()); if (f.size() == 0) return false; if (!f.exists()) return false; if (!f.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&f); f.close(); return res; } bool KisPngBrush::loadFromDevice(QIODevice *dev) { // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice // fails with "libpng error: IDAT: CRC error" QByteArray data = dev->readAll(); QBuffer buf(&data); buf.open(QIODevice::ReadOnly); QImageReader reader(&buf, "PNG"); if (!reader.canRead()) { setValid(false); return false; } if (reader.textKeys().contains("brush_spacing")) { setSpacing(reader.text("brush_spacing").toDouble()); } if (reader.textKeys().contains("brush_name")) { setName(reader.text("brush_name")); } else { QFileInfo info(filename()); setName(info.baseName()); } QImage image = reader.read(); if (image.isNull()) { kWarning() << "Could not read brush" << filename() << ". Error:" << reader.errorString(); setValid(false); return false; } setBrushTipImage(image); setValid(!brushTipImage().isNull()); if (brushTipImage().isGrayscale()) { setBrushType(MASK); setHasColor(false); } else { setBrushType(IMAGE); setHasColor(true); } setWidth(brushTipImage().width()); setHeight(brushTipImage().height()); return !brushTipImage().isNull(); } bool KisPngBrush::save() { QFile f(filename()); if (!f.open(QFile::WriteOnly)) return false; bool res = saveToDevice(&f); f.close(); return res; } bool KisPngBrush::saveToDevice(QIODevice *dev) const { - return brushTipImage().save(dev, "PNG"); + if(brushTipImage().save(dev, "PNG")) { + KoResource::saveToDevice(dev); + return true; + } + + return false; } QString KisPngBrush::defaultFileExtension() const { return QString(".png"); } void KisPngBrush::toXML(QDomDocument& d, QDomElement& e) const { predefinedBrushToXML("png_brush", e); KisBrush::toXML(d, e); } diff --git a/krita/libbrush/kis_qimage_pyramid.h b/krita/libbrush/kis_qimage_pyramid.h index 18351021b1d..cfb777cbafe 100644 --- a/krita/libbrush/kis_qimage_pyramid.h +++ b/krita/libbrush/kis_qimage_pyramid.h @@ -1,74 +1,74 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_QIMAGE_PYRAMID_H #define __KIS_QIMAGE_PYRAMID_H #include #include -#include +#include class BRUSH_EXPORT KisQImagePyramid { public: KisQImagePyramid(const QImage &baseImage); ~KisQImagePyramid(); static QSize imageSize(const QSize &originalSize, qreal scale, qreal rotation, qreal subPixelX, qreal subPixelY); static QSizeF characteristicSize(const QSize &originalSize, qreal scale, qreal rotation); QImage createImage(qreal scale, qreal rotation, qreal subPixelX, qreal subPixelY); private: friend class KisBrushTest; int findNearestLevel(qreal scale, qreal *baseScale); void appendPyramidLevel(const QImage &image); static void calculateParams(qreal scale, qreal rotation, qreal subPixelX, qreal subPixelY, const QSize &originalSize, QTransform *outputTransform, QSize *outputSize); static void calculateParams(qreal scale, qreal rotation, qreal subPixelX, qreal subPixelY, const QSize &originalSize, qreal baseScale, const QSize &baseSize, QTransform *outputTransform, QSize *outputSize); private: QSize m_originalSize; qreal m_baseScale; struct PyramidLevel { PyramidLevel() {} PyramidLevel(QImage _image, QSize _size) : image(_image), size(_size) {} QImage image; QSize size; }; QVector m_levels; }; #endif /* __KIS_QIMAGE_PYRAMID_H */ diff --git a/krita/libbrush/kis_svg_brush.cpp b/krita/libbrush/kis_svg_brush.cpp index 2934a36c208..ddaee5773ae 100644 --- a/krita/libbrush/kis_svg_brush.cpp +++ b/krita/libbrush/kis_svg_brush.cpp @@ -1,113 +1,117 @@ /* * Copyright (c) 2010 Cyrille Berger * * 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_svg_brush.h" #include #include #include #include #include KisSvgBrush::KisSvgBrush(const QString& filename) : KisBrush(filename) { setBrushType(INVALID); setSpacing(0.25); setHasColor(false); } bool KisSvgBrush::load() { QFile f(filename()); if (f.size() == 0) return false; if (!f.exists()) return false; if (!f.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&f); f.close(); return res; } bool KisSvgBrush::loadFromDevice(QIODevice *dev) { m_svg = dev->readAll(); QSvgRenderer renderer(m_svg); QRect box = renderer.viewBox(); if (box.isEmpty()) return false; QImage image_(1000, (1000 * box.height()) / box.width(), QImage::Format_ARGB32); { QPainter p(&image_); p.fillRect(0, 0, image_.width(), image_.height(), Qt::white); renderer.render(&p); } QVector table; for (int i = 0; i < 256; ++i) table.push_back(qRgb(i, i, i)); image_ = image_.convertToFormat(QImage::Format_Indexed8, table); setBrushTipImage(image_); setValid(true); // Well for now, always true if (brushTipImage().isGrayscale()) { setBrushType(MASK); setHasColor(false); } else { setBrushType(IMAGE); setHasColor(true); } setWidth(brushTipImage().width()); setHeight(brushTipImage().height()); return !brushTipImage().isNull(); } bool KisSvgBrush::save() { QFile f(filename()); if (!f.open(QFile::WriteOnly)) return false; bool res = saveToDevice(&f); f.close(); return res; } bool KisSvgBrush::saveToDevice(QIODevice *dev) const { - return (dev->write(m_svg.constData(), m_svg.size()) == m_svg.size()); + if((dev->write(m_svg.constData(), m_svg.size()) == m_svg.size())) { + KoResource::saveToDevice(dev); + return true; + } + return false; } QString KisSvgBrush::defaultFileExtension() const { return QString(".svg"); } void KisSvgBrush::toXML(QDomDocument& d, QDomElement& e) const { predefinedBrushToXML("svg_brush", e); KisBrush::toXML(d, e); } diff --git a/krita/libbrush/kis_text_brush.h b/krita/libbrush/kis_text_brush.h index 965b0ef3c87..019a6d9c71c 100644 --- a/krita/libbrush/kis_text_brush.h +++ b/krita/libbrush/kis_text_brush.h @@ -1,94 +1,94 @@ /* * Copyright (c) 2004 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * 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 #include "kis_brush.h" -#include "krita_export.h" +#include "kritabrush_export.h" #include "kis_gbr_brush.h" class KisTextBrushesPipe; class BRUSH_EXPORT KisTextBrush : public KisBrush { public: KisTextBrush(); KisTextBrush(const KisTextBrush &rhs); virtual ~KisTextBrush(); void notifyCachedDabPainted(); void generateMaskAndApplyMaskOrCreateDab(KisFixedPaintDeviceSP dst, KisBrush::ColoringInformation* coloringInformation, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX = 0, double subPixelY = 0, qreal softnessFactor = DEFAULT_SOFTNESS_FACTOR) const; KisFixedPaintDeviceSP paintDevice(const KoColorSpace * colorSpace, double scale, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY) const; bool load() { return false; } virtual bool loadFromDevice(QIODevice *) { return false; } bool save() { return false; } bool saveToDevice(QIODevice* ) const { return false; } void setText(const QString& txt); QString text(void) const; QFont font(); void setFont(const QFont& font); void setPipeMode(bool pipe); bool pipeMode() const; void updateBrush(); void toXML(QDomDocument& , QDomElement&) const; quint32 brushIndex(const KisPaintInformation& info) const; qint32 maskWidth(double scale, double angle, double subPixelX, double subPixelY, const KisPaintInformation& info) const; qint32 maskHeight(double scale, double angle, double subPixelX, double subPixelY, const KisPaintInformation& info) const; void setAngle(qreal _angle); void setScale(qreal _scale); void setSpacing(double _spacing); KisBrush* clone() const; private: QFont m_font; QString m_text; private: KisTextBrushesPipe *m_brushesPipe; }; #endif diff --git a/krita/libpsd/libkispsd_export.h b/krita/libbrush/kritabrush_export.h similarity index 63% copy from krita/libpsd/libkispsd_export.h copy to krita/libbrush/kritabrush_export.h index fa028e7f943..14ec51a0055 100644 --- a/krita/libpsd/libkispsd_export.h +++ b/krita/libbrush/kritabrush_export.h @@ -1,45 +1,43 @@ -/* This file is part of the KDE project - Copyright (C) 2006 David Faure +/* + This file is part of krita + Copyright (c) 2015 Friedrich W. H. Kossebau 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. + * Boston, MA 02110-1301, USA. */ -#ifndef LIBKISPSD_EXPORT_H -#define LIBKISPSD_EXPORT_H +#ifndef KRITABRUSH_EXPORT_H +#define KRITABRUSH_EXPORT_H -/* needed for KDE_EXPORT and KDE_IMPORT macros */ #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ -#if defined _WIN32 || defined _WIN64 +#if defined(_WIN32) || defined(_WIN64) -#ifndef KRITAPSD_EXPORT -# if defined(MAKE_KRITAPSD_LIB) -/* We are building this library */ -# define KRITAPSD_EXPORT KDE_EXPORT +#ifndef BRUSH_EXPORT +# ifdef MAKE_KRITALIBBRUSH_LIB +# define BRUSH_EXPORT KDE_EXPORT # else -/* We are using this library */ -# define KRITAPSD_EXPORT KDE_IMPORT +# define BRUSH_EXPORT KDE_IMPORT # endif #endif -#else /* UNIX */ +#else // not windows -#define KRITAPSD_EXPORT KDE_EXPORT +#define BRUSH_EXPORT KDE_EXPORT -#endif +#endif /* not windows */ -#endif +#endif /* KRITABRUSH_EXPORT_H */ diff --git a/krita/libcolor/kis_color_manager.h b/krita/libcolor/kis_color_manager.h index a5ebfabd263..65c65d6e94f 100644 --- a/krita/libcolor/kis_color_manager.h +++ b/krita/libcolor/kis_color_manager.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2015 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_COLOR_MANAGER_H #define KIS_COLOR_MANAGER_H #include #include #include #include -#include "kritalibcolor_export.h" +#include "kritacolor_export.h" /** * @brief The KisColorManager class can be used as a cross-platform way to get the * display profile associated with a device. * * TODO: support other devices than monitors */ class KRITALIBCOLOR_EXPORT KisColorManager : public QObject { Q_OBJECT public: virtual ~KisColorManager(); enum DeviceType { screen, printer, camera, scanner }; /// Return the user-visible name for the given device QString deviceName(const QString &id); /// Return a list of device id's for the specified type QStringList devices(DeviceType type = screen) const; /// Return the icc profile for the given device and index (if a device has more than one profile) QByteArray displayProfile(const QString &device, int profile = 0) const; static KisColorManager *instance(); Q_SIGNALS: void changed(const QString device); public Q_SLOTS: private: explicit KisColorManager(); KisColorManager(const KisColorManager&); KisColorManager operator=(const KisColorManager&); class Private; const Private *const d; }; #endif // KIS_COLOR_MANAGER_H diff --git a/krita/libcolor/kritalibcolor_export.h b/krita/libcolor/kritacolor_export.h similarity index 95% rename from krita/libcolor/kritalibcolor_export.h rename to krita/libcolor/kritacolor_export.h index f17342938c4..ea17b8a8e2e 100644 --- a/krita/libcolor/kritalibcolor_export.h +++ b/krita/libcolor/kritacolor_export.h @@ -1,45 +1,45 @@ /* This file is part of the KDE project Copyright (C) 2006 David Faure 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 KRITALIBCOLOR_EXPORT_H -#define KRITALIBCOLOR_EXPORT_H +#ifndef KRITACOLOR_EXPORT_H +#define KRITACOLOR_EXPORT_H /* needed for KDE_EXPORT and KDE_IMPORT macros */ #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ #if defined _WIN32 || defined _WIN64 #ifndef KRITALIBCOLOR_EXPORT # if defined(MAKE_KRITACOLOR_LIB) /* We are building this library */ # define KRITALIBCOLOR_EXPORT KDE_EXPORT # else /* We are using this library */ # define KRITALIBCOLOR_EXPORT KDE_IMPORT # endif #endif #else /* UNIX */ #define KRITALIBCOLOR_EXPORT KDE_EXPORT #endif #endif diff --git a/krita/libglobal/kis_assert.h b/krita/libglobal/kis_assert.h index 533ad669826..6222e74a2df 100644 --- a/krita/libglobal/kis_assert.h +++ b/krita/libglobal/kis_assert.h @@ -1,108 +1,108 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASSERT_H #define __KIS_ASSERT_H #include -#include +#include KRITAIMAGE_EXPORT void kis_assert_exception(const char *assertion, const char *file, int line); KRITAIMAGE_EXPORT void kis_assert_recoverable(const char *assertion, const char *file, int line); KRITAIMAGE_EXPORT void kis_assert_x_exception(const char *assertion, const char *where, const char *what, const char *file, int line); /** * KIS_ASSERT family of macros allows the user to choose whether to * try to continue working in Krita or to abort an application and see * a backtrace. * * Note, the macro are present in Release mode by default! */ /** * Checks the condition and depending on the user action either aborts * the program or throws an exception, which restarts event loop. */ #define KIS_ASSERT(cond) ((!(cond)) ? kis_assert_exception(#cond,__FILE__,__LINE__) : qt_noop()) /** * Same as KIS_ASSERT, but allows to show more text to the user. * * \see KIS_ASSERT */ #define KIS_ASSERT_X(cond, where, what) ((!(cond)) ? kis_assert_x_exception(#cond,where, what,__FILE__,__LINE__) : qt_noop()) /** * This is a recoverable variant of KIS_ASSERT. It doesn't throw any * exceptions. It checks the condition, and either aborts the * application, or executes user-supplied code. The typical usecase is * the following: * * int fooBar = ...; * KIS_ASSERT_RECOVER (fooBar > 0) { * // the code which is executed in a case of emergency * } * */ #define KIS_ASSERT_RECOVER(cond) if (!(cond) && (kis_assert_recoverable(#cond,__FILE__,__LINE__), true)) /** * Equivalent of the following: * * KIS_ASSERT_RECOVER(cond) { * break; * } * */ #define KIS_ASSERT_RECOVER_BREAK(cond) KIS_ASSERT_RECOVER(cond) { break; } /** * Equivalent of the following: * * KIS_ASSERT_RECOVER(cond) { * return; * } * */ #define KIS_ASSERT_RECOVER_RETURN(cond) KIS_ASSERT_RECOVER(cond) { return; } /** * Equivalent of the following: * * KIS_ASSERT_RECOVER(cond) { * return val; * } * */ #define KIS_ASSERT_RECOVER_RETURN_VALUE(cond, val) KIS_ASSERT_RECOVER(cond) { return (val); } /** * Does nothing in case of a failure. Just continues execution. * * Equivalent of the following: * * KIS_ASSERT_RECOVER(cond) { * qt_noop(); * } * */ #define KIS_ASSERT_RECOVER_NOOP(cond) KIS_ASSERT_RECOVER(cond) { qt_noop(); } #endif /* __KIS_ASSERT_H */ diff --git a/krita/libpsd/asl/kis_asl_callback_object_catcher.h b/krita/libpsd/asl/kis_asl_callback_object_catcher.h index 3ca3407b88d..3c33faec0a7 100644 --- a/krita/libpsd/asl/kis_asl_callback_object_catcher.h +++ b/krita/libpsd/asl/kis_asl_callback_object_catcher.h @@ -1,85 +1,85 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_CALLBACK_OBJECT_CATCHER_H #define __KIS_ASL_CALLBACK_OBJECT_CATCHER_H #include "kis_asl_object_catcher.h" #include #include #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" class KoPattern; typedef boost::function ASLCallbackDouble; typedef boost::function ASLCallbackInteger; typedef boost::function ASLCallbackString; typedef boost::function ASLCallbackBoolean; typedef boost::function ASLCallbackColor; typedef boost::function ASLCallbackPoint; typedef boost::function &)> ASLCallbackCurve; typedef boost::function ASLCallbackPattern; typedef boost::function ASLCallbackPatternRef; typedef boost::function ASLCallbackGradient; typedef boost::function ASLCallbackNewStyle; class KRITAPSD_EXPORT KisAslCallbackObjectCatcher : public KisAslObjectCatcher { public: KisAslCallbackObjectCatcher(); ~KisAslCallbackObjectCatcher(); void addDouble(const QString &path, double value); void addInteger(const QString &path, int value); void addEnum(const QString &path, const QString &typeId, const QString &value); void addUnitFloat(const QString &path, const QString &unit, double value); void addText(const QString &path, const QString &value); void addBoolean(const QString &path, bool value); void addColor(const QString &path, const QColor &value); void addPoint(const QString &path, const QPointF &value); void addCurve(const QString &path, const QString &name, const QVector &points); void addPattern(const QString &path, const KoPattern *pattern); void addPatternRef(const QString &path, const QString &patternUuid, const QString &patternName); void addGradient(const QString &path, KoAbstractGradientSP gradient); void newStyleStarted(); void subscribeDouble(const QString &path, ASLCallbackDouble callback); void subscribeInteger(const QString &path, ASLCallbackInteger callback); void subscribeEnum(const QString &path, const QString &typeId, ASLCallbackString callback); void subscribeUnitFloat(const QString &path, const QString &unit, ASLCallbackDouble callback); void subscribeText(const QString &path, ASLCallbackString callback); void subscribeBoolean(const QString &path, ASLCallbackBoolean callback); void subscribeColor(const QString &path, ASLCallbackColor callback); void subscribePoint(const QString &path, ASLCallbackPoint callback); void subscribeCurve(const QString &path, ASLCallbackCurve callback); void subscribePattern(const QString &path, ASLCallbackPattern callback); void subscribePatternRef(const QString &path, ASLCallbackPatternRef callback); void subscribeGradient(const QString &path, ASLCallbackGradient callback); void subscribeNewStyleStarted(ASLCallbackNewStyle callback); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_ASL_CALLBACK_OBJECT_CATCHER_H */ diff --git a/krita/libpsd/asl/kis_asl_object_catcher.h b/krita/libpsd/asl/kis_asl_object_catcher.h index cca31657b62..a674c987d7f 100644 --- a/krita/libpsd/asl/kis_asl_object_catcher.h +++ b/krita/libpsd/asl/kis_asl_object_catcher.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_OBJECT_CATCHER_H #define __KIS_ASL_OBJECT_CATCHER_H #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QString; class QColor; class QPointF; class KoPattern; class KoAbstractGradient; template class QSharedPointer; typedef QSharedPointer KoAbstractGradientSP; class KRITAPSD_EXPORT KisAslObjectCatcher { public: KisAslObjectCatcher(); virtual ~KisAslObjectCatcher(); virtual void addDouble(const QString &path, double value); virtual void addInteger(const QString &path, int value); virtual void addEnum(const QString &path, const QString &typeId, const QString &value); virtual void addUnitFloat(const QString &path, const QString &unit, double value); virtual void addText(const QString &path, const QString &value); virtual void addBoolean(const QString &path, bool value); virtual void addColor(const QString &path, const QColor &value); virtual void addPoint(const QString &path, const QPointF &value); virtual void addCurve(const QString &path, const QString &name, const QVector &points); virtual void addPattern(const QString &path, const KoPattern *pattern); virtual void addPatternRef(const QString &path, const QString &patternUuid, const QString &patternName); virtual void addGradient(const QString &path, KoAbstractGradientSP gradient); virtual void newStyleStarted(); void setArrayMode(bool value); protected: bool m_arrayMode; }; #endif /* __KIS_ASL_OBJECT_CATCHER_H */ diff --git a/krita/libpsd/asl/kis_asl_patterns_writer.h b/krita/libpsd/asl/kis_asl_patterns_writer.h index db71a254e72..ddeda08293c 100644 --- a/krita/libpsd/asl/kis_asl_patterns_writer.h +++ b/krita/libpsd/asl/kis_asl_patterns_writer.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_PATTERNS_WRITER_H #define __KIS_ASL_PATTERNS_WRITER_H -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QDomDocument; class QIODevice; class KoPattern; class KRITAPSD_EXPORT KisAslPatternsWriter { public: KisAslPatternsWriter(const QDomDocument &doc, QIODevice *device); void writePatterns(); private: void addPattern(const KoPattern *pattern); private: const QDomDocument &m_doc; QIODevice *m_device; int m_numPatternsWritten; }; #endif /* __KIS_ASL_PATTERNS_WRITER_H */ diff --git a/krita/libpsd/asl/kis_asl_reader.h b/krita/libpsd/asl/kis_asl_reader.h index 47ddada6cd3..f1e61992041 100644 --- a/krita/libpsd/asl/kis_asl_reader.h +++ b/krita/libpsd/asl/kis_asl_reader.h @@ -1,37 +1,38 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_READER_H #define __KIS_ASL_READER_H -#include "libkispsd_export.h" +#include "kritapsd_export.h" +#include class QDomDocument; class QIODevice; class KRITAPSD_EXPORT KisAslReader { public: QDomDocument readFile(QIODevice *device); QDomDocument readLfx2PsdSection(QIODevice *device); static QDomDocument readPsdSectionPattern(QIODevice *device, qint64 bytesLeft); }; #endif /* __KIS_ASL_READER_H */ diff --git a/krita/libpsd/asl/kis_asl_writer.h b/krita/libpsd/asl/kis_asl_writer.h index 6e1fe7a4610..6a940c8f7d6 100644 --- a/krita/libpsd/asl/kis_asl_writer.h +++ b/krita/libpsd/asl/kis_asl_writer.h @@ -1,35 +1,35 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_WRITER_H #define __KIS_ASL_WRITER_H -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QDomDocument; class QIODevice; class KRITAPSD_EXPORT KisAslWriter { public: void writeFile(QIODevice *device, const QDomDocument &doc); void writePsdLfx2SectionEx(QIODevice *device, const QDomDocument &doc); }; #endif /* __KIS_ASL_WRITER_H */ diff --git a/krita/libpsd/asl/kis_asl_writer_utils.h b/krita/libpsd/asl/kis_asl_writer_utils.h index 5df43c9492d..117ea35c624 100644 --- a/krita/libpsd/asl/kis_asl_writer_utils.h +++ b/krita/libpsd/asl/kis_asl_writer_utils.h @@ -1,132 +1,132 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_WRITER_UTILS_H #define __KIS_ASL_WRITER_UTILS_H #include #include #include #include "psd_utils.h" #include "kis_debug.h" -#include "libkispsd_export.h" +#include "kritapsd_export.h" namespace KisAslWriterUtils { /** * Exception that is emitted when any write error appear. */ struct KRITAPSD_EXPORT ASLWriteException : public std::runtime_error { ASLWriteException(const QString &msg) : std::runtime_error(msg.toAscii().data()) { } }; } #define SAFE_WRITE_EX(device, varname) \ if (!psdwrite(device, varname)) { \ QString msg = QString("Failed to write \'%1\' tag!").arg(#varname); \ throw KisAslWriterUtils::ASLWriteException(msg); \ } namespace KisAslWriterUtils { KRITAPSD_EXPORT void writeRect(const QRect &rect, QIODevice *device); KRITAPSD_EXPORT void writeUnicodeString(const QString &value, QIODevice *device); KRITAPSD_EXPORT void writeVarString(const QString &value, QIODevice *device); KRITAPSD_EXPORT void writePascalString(const QString &value, QIODevice *device); KRITAPSD_EXPORT void writeFixedString(const QString &value, QIODevice *device); KRITAPSD_EXPORT QString getPatternUuidLazy(const KoPattern *pattern); /** * Align the pointer \p pos by alignment. Grow the pointer * if needed. * * \return the lowest integer not smaller than \p pos that divides by * alignment */ inline qint64 alignOffsetCeil(qint64 pos, qint64 alignment) { qint64 mask = alignment - 1; return (pos + mask) & ~mask; } template class OffsetStreamPusher { public: OffsetStreamPusher(QIODevice *device, qint64 alignOnExit = 0, qint64 externalSizeTagOffset = -1) : m_device(device), m_alignOnExit(alignOnExit), m_externalSizeTagOffset(externalSizeTagOffset) { m_chunkStartPos = m_device->pos(); if (externalSizeTagOffset < 0) { const OffsetType fakeObjectSize = OffsetType(0xdeadbeef); SAFE_WRITE_EX(m_device, fakeObjectSize); } } ~OffsetStreamPusher() { if (m_alignOnExit) { qint64 currentPos = m_device->pos(); const qint64 alignedPos = alignOffsetCeil(currentPos, m_alignOnExit); for (; currentPos < alignedPos; currentPos++) { quint8 padding = 0; SAFE_WRITE_EX(m_device, padding); } } const qint64 currentPos = m_device->pos(); qint64 writtenDataSize = 0; qint64 sizeFiledOffset = 0; if (m_externalSizeTagOffset >= 0) { writtenDataSize = currentPos - m_chunkStartPos; sizeFiledOffset = m_externalSizeTagOffset; } else { writtenDataSize = currentPos - m_chunkStartPos - sizeof(OffsetType); sizeFiledOffset = m_chunkStartPos; } m_device->seek(sizeFiledOffset); const OffsetType realObjectSize = writtenDataSize; SAFE_WRITE_EX(m_device, realObjectSize); m_device->seek(currentPos); } private: qint64 m_chunkStartPos; QIODevice *m_device; qint64 m_alignOnExit; qint64 m_externalSizeTagOffset; }; } #endif /* __KIS_ASL_WRITER_UTILS_H */ diff --git a/krita/libpsd/asl/kis_asl_xml_parser.h b/krita/libpsd/asl/kis_asl_xml_parser.h index bd01c1bcdcc..dc65fc21659 100644 --- a/krita/libpsd/asl/kis_asl_xml_parser.h +++ b/krita/libpsd/asl/kis_asl_xml_parser.h @@ -1,35 +1,35 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_XML_PARSER_H #define __KIS_ASL_XML_PARSER_H -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QDomDocument; class QIODevice; class KisAslObjectCatcher; class KRITAPSD_EXPORT KisAslXmlParser { public: void parseXML(const QDomDocument &doc, KisAslObjectCatcher &catcher); }; #endif /* __KIS_ASL_XML_PARSER_H */ diff --git a/krita/libpsd/asl/kis_asl_xml_writer.h b/krita/libpsd/asl/kis_asl_xml_writer.h index 715dbe551de..46b8746d064 100644 --- a/krita/libpsd/asl/kis_asl_xml_writer.h +++ b/krita/libpsd/asl/kis_asl_xml_writer.h @@ -1,79 +1,79 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_XML_WRITER_H #define __KIS_ASL_XML_WRITER_H #include #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QString; class QColor; class QPointF; class QDomDocument; class KoPattern; class KoStopGradient; class KoSegmentGradient; class KRITAPSD_EXPORT KisAslXmlWriter { public: KisAslXmlWriter(); ~KisAslXmlWriter(); QDomDocument document() const; void enterDescriptor(const QString &key, const QString &name, const QString &classId); void leaveDescriptor(); void enterList(const QString &key); void leaveList(); void writeDouble(const QString &key, double value); void writeInteger(const QString &key, int value); void writeEnum(const QString &key, const QString &typeId, const QString &value); void writeUnitFloat(const QString &key, const QString &unit, double value); void writeText(const QString &key, const QString &value); void writeBoolean(const QString &key, bool value); void writeColor(const QString &key, const QColor &value); void writePoint(const QString &key, const QPointF &value); void writePhasePoint(const QString &key, const QPointF &value); void writeOffsetPoint(const QString &key, const QPointF &value); void writeCurve(const QString &key, const QString &name, const QVector &points); QString writePattern(const QString &key, const KoPattern *pattern); void writePatternRef(const QString &key, const KoPattern *pattern, const QString &uuid); void writeSegmentGradient(const QString &key, const KoSegmentGradient *gradient); void writeStopGradient(const QString &key, const KoStopGradient *gradient); private: void writeGradientImpl(const QString &key, const QString &name, QVector colors, QVector transparencies, QVector positions, QVector middleOffsets); private: struct Private; const QScopedPointer m_d; }; #endif /* __KIS_ASL_XML_WRITER_H */ diff --git a/krita/libpsd/compression.h b/krita/libpsd/compression.h index f069ac22687..cd974ff39f2 100644 --- a/krita/libpsd/compression.h +++ b/krita/libpsd/compression.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2010 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 COMPRESSION_H #define COMPRESSION_H #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" class KRITAPSD_EXPORT Compression { public: enum CompressionType { Uncompressed = 0, RLE, ZIP, ZIPWithPrediction, Unknown }; static QByteArray uncompress(quint32 unpacked_len, QByteArray bytes, CompressionType compressionType); static QByteArray compress(QByteArray bytes, CompressionType compressionType); }; #endif // PSD_COMPRESSION_H diff --git a/krita/libpsd/libkispsd_export.h b/krita/libpsd/kritapsd_export.h similarity index 96% copy from krita/libpsd/libkispsd_export.h copy to krita/libpsd/kritapsd_export.h index fa028e7f943..1f44171fac4 100644 --- a/krita/libpsd/libkispsd_export.h +++ b/krita/libpsd/kritapsd_export.h @@ -1,45 +1,45 @@ /* This file is part of the KDE project Copyright (C) 2006 David Faure 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 LIBKISPSD_EXPORT_H -#define LIBKISPSD_EXPORT_H +#ifndef KRITAPSD_EXPORT_H +#define KRITAPSD_EXPORT_H /* needed for KDE_EXPORT and KDE_IMPORT macros */ #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ #if defined _WIN32 || defined _WIN64 #ifndef KRITAPSD_EXPORT # if defined(MAKE_KRITAPSD_LIB) /* We are building this library */ # define KRITAPSD_EXPORT KDE_EXPORT # else /* We are using this library */ # define KRITAPSD_EXPORT KDE_IMPORT # endif #endif #else /* UNIX */ #define KRITAPSD_EXPORT KDE_EXPORT #endif #endif diff --git a/krita/libpsd/psd.h b/krita/libpsd/psd.h index 226a9c289a2..584717baf79 100644 --- a/krita/libpsd/psd.h +++ b/krita/libpsd/psd.h @@ -1,1156 +1,1157 @@ /* * Copyright (c) 2010 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. */ /* * Constants and defines taken from gimp and psdparse */ #ifndef PSD_H #define PSD_H #include #include #include #include #include #include #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" #include "kis_debug.h" class KoPattern; const int MAX_CHANNELS = 56; typedef qint32 Fixed; /* Represents a fixed point implied decimal */ /** * Image color/depth modes */ enum psd_color_mode { Bitmap = 0, Grayscale=1, Indexed=2, RGB=3, CMYK=4, MultiChannel=7, DuoTone=8, Lab=9, Gray16, RGB48, Lab48, CMYK64, DeepMultichannel, Duotone16, UNKNOWN = 9000 }; /** * Color samplers, apparently distict from PSDColormode */ namespace psd_color_sampler { enum PSDColorSamplers { RGB, HSB, CMYK, PANTONE, // LAB FOCOLTONE, // CMYK TRUMATCH, // CMYK TOYO, // LAB LAB, GRAYSCALE, HKS, // CMYK DIC, // LAB TOTAL_INK, MONITOR_RGB, DUOTONE, OPACITY, ANPA = 3000 // LAB }; } // EFFECTS enum psd_gradient_style { psd_gradient_style_linear, // 'Lnr ' psd_gradient_style_radial, // 'Rdl ' psd_gradient_style_angle, // 'Angl' psd_gradient_style_reflected, // 'Rflc' psd_gradient_style_diamond // 'Dmnd' }; enum psd_color_stop_type { psd_color_stop_type_foreground_color, // 'FrgC' psd_color_stop_type_background_Color, // 'BckC' psd_color_stop_type_user_stop // 'UsrS' }; enum psd_technique_type { psd_technique_softer, psd_technique_precise, psd_technique_slope_limit, }; enum psd_stroke_position { psd_stroke_outside, psd_stroke_inside, psd_stroke_center }; enum psd_fill_type { psd_fill_solid_color, psd_fill_gradient, psd_fill_pattern, }; enum psd_glow_source { psd_glow_center, psd_glow_edge, }; enum psd_bevel_style { psd_bevel_outer_bevel, psd_bevel_inner_bevel, psd_bevel_emboss, psd_bevel_pillow_emboss, psd_bevel_stroke_emboss, }; enum psd_direction { psd_direction_up, psd_direction_down }; enum psd_section_type { psd_other = 0, psd_open_folder, psd_closed_folder, psd_bounding_divider }; // GRADIENT MAP // Each color stop struct psd_gradient_color_stop { qint32 location; // Location of color stop qint32 midpoint; // Midpoint of color stop QColor actual_color; psd_color_stop_type color_stop_type; }; // Each transparency stop struct psd_gradient_transparency_stop { qint32 location; // Location of transparency stop qint32 midpoint; // Midpoint of transparency stop qint8 opacity; // Opacity of transparency stop }; // Gradient settings (Photoshop 6.0) struct psd_layer_gradient_map { bool reverse; // Is gradient reverse bool dithered; // Is gradient dithered qint32 name_length; quint16 *name; // Name of the gradient: Unicode string, padded qint8 number_color_stops; // Number of color stops to follow psd_gradient_color_stop * color_stop; qint8 number_transparency_stops;// Number of transparency stops to follow psd_gradient_transparency_stop * transparency_stop; qint8 expansion_count; // Expansion count ( = 2 for Photoshop 6.0) qint8 interpolation; // Interpolation if length above is non-zero qint8 length; // Length (= 32 for Photoshop 6.0) qint8 mode; // Mode for this gradient qint32 random_number_seed; // Random number seed qint8 showing_transparency_flag;// Flag for showing transparency qint8 using_vector_color_flag;// Flag for using vector color qint32 roughness_factor; // Roughness factor QColor min_color; QColor max_color; QColor lookup_table[256]; }; struct psd_gradient_color { qint32 smoothness; qint32 name_length; quint16 * name; // Name of the gradient: Unicode string, padded qint8 number_color_stops; // Number of color stops to follow psd_gradient_color_stop * color_stop; qint8 number_transparency_stops;// Number of transparency stops to follow psd_gradient_transparency_stop *transparency_stop; }; struct psd_pattern { psd_color_mode color_mode; // The image mode of the file. quint8 height; // Point: vertical, 2 bytes and horizontal, 2 bytes quint8 width; QString name; QString uuid; qint32 version; quint8 top; // Rectangle: top, left, bottom, right quint8 left; quint8 bottom; quint8 right; qint32 max_channel; // Max channels qint32 channel_number; QVector color_table; }; struct psd_layer_effects_context { psd_layer_effects_context() : keep_original(false) { } bool keep_original; }; #define PSD_LOOKUP_TABLE_SIZE 256 // dsdw, isdw: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203 class KRITAPSD_EXPORT psd_layer_effects_shadow_base { public: psd_layer_effects_shadow_base() : m_invertsSelection(false) , m_edgeHidden(true) , m_effectEnabled(false) , m_blendMode(COMPOSITE_MULT) , m_color(Qt::black) , m_nativeColor(Qt::black) , m_opacity(75) , m_angle(120) , m_useGlobalLight(true) , m_distance(21) , m_spread(0) , m_size(21) , m_antiAliased(0) , m_noise(0) , m_knocksOut(false) , m_fillType(psd_fill_solid_color) , m_technique(psd_technique_softer) , m_range(100) , m_jitter(0) , m_gradient(0) { for(int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) { m_contourLookupTable[i] = i; } } virtual ~psd_layer_effects_shadow_base() { } QPoint calculateOffset(const psd_layer_effects_context *context) const; void setEffectEnabled(bool value) { m_effectEnabled = value; } bool effectEnabled() const { return m_effectEnabled; } QString blendMode() const { return m_blendMode; } QColor color() const { return m_color; } QColor nativeColor() const { return m_nativeColor; } qint32 opacity() const { return m_opacity; } qint32 angle() const { return m_angle; } bool useGlobalLight() const { return m_useGlobalLight; } qint32 distance() const { return m_distance; } qint32 spread() const { return m_spread; } qint32 size() const { return m_size; } const quint8* contourLookupTable() const { return m_contourLookupTable; } bool antiAliased() const { return m_antiAliased; } qint32 noise() const { return m_noise; } bool knocksOut() const { return m_knocksOut; } bool invertsSelection() const { return m_invertsSelection; } bool edgeHidden() const { return m_edgeHidden; } psd_fill_type fillType() const { return m_fillType; } psd_technique_type technique() const { return m_technique; } qint32 range() const { return m_range; } qint32 jitter() const { return m_jitter; } KoAbstractGradientSP gradient() const { return m_gradient; } public: void setBlendMode(QString value) { m_blendMode = value; } void setColor(QColor value) { m_color = value; } void setNativeColor(QColor value) { m_nativeColor = value; } void setOpacity(qint32 value) { m_opacity = value; } void setAngle(qint32 value) { m_angle = value; } void setUseGlobalLight(bool value) { m_useGlobalLight = value; } void setDistance(qint32 value) { m_distance = value; } void setSpread(qint32 value) { m_spread = value; } void setSize(qint32 value) { m_size = value; } void setContourLookupTable(const quint8* value) { memcpy(m_contourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8)); } void setAntiAliased(bool value) { m_antiAliased = value; } void setNoise(qint32 value) { m_noise = value; } void setKnocksOut(bool value) { m_knocksOut = value; } void setInvertsSelection(bool value) { m_invertsSelection = value; } void setEdgeHidden(bool value) { m_edgeHidden = value; } void setFillType(psd_fill_type value) { m_fillType = value; } void setTechnique(psd_technique_type value) { m_technique = value; } void setRange(qint32 value) { m_range = value; } void setJitter(qint32 value) { m_jitter = value; } void setGradient(KoAbstractGradientSP value) { m_gradient = value; } private: // internal bool m_invertsSelection; bool m_edgeHidden; private: bool m_effectEnabled; // Effect enabled QString m_blendMode; // already in Krita format! QColor m_color; QColor m_nativeColor; qint32 m_opacity; // Opacity as a percent (0...100) qint32 m_angle; // Angle in degrees bool m_useGlobalLight; // Use this angle in all of the layer effects qint32 m_distance; // Distance in pixels qint32 m_spread; // Intensity as a percent qint32 m_size; // Blur value in pixels quint8 m_contourLookupTable[PSD_LOOKUP_TABLE_SIZE]; bool m_antiAliased; qint32 m_noise; bool m_knocksOut; // for Outer/Inner Glow psd_fill_type m_fillType; psd_technique_type m_technique; qint32 m_range; qint32 m_jitter; KoAbstractGradientSP m_gradient; }; class KRITAPSD_EXPORT psd_layer_effects_shadow_common : public psd_layer_effects_shadow_base { public: /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setBlendMode; // using psd_layer_effects_shadow_base::setColor; // using psd_layer_effects_shadow_base::setOpacity; // using psd_layer_effects_shadow_base::setAngle; // using psd_layer_effects_shadow_base::setUseGlobalLight; // using psd_layer_effects_shadow_base::setDistance; // using psd_layer_effects_shadow_base::setSpread; // using psd_layer_effects_shadow_base::setSize; // using psd_layer_effects_shadow_base::setContourLookupTable; // using psd_layer_effects_shadow_base::setAntiAliased; // using psd_layer_effects_shadow_base::setNoise; }; class KRITAPSD_EXPORT psd_layer_effects_drop_shadow : public psd_layer_effects_shadow_common { public: /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want //using psd_layer_effects_shadow_base::setKnocksOut; }; // isdw: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_22203 class KRITAPSD_EXPORT psd_layer_effects_inner_shadow : public psd_layer_effects_shadow_common { public: psd_layer_effects_inner_shadow() { setKnocksOut(true); setInvertsSelection(true); setEdgeHidden(false); } }; class KRITAPSD_EXPORT psd_layer_effects_glow_common : public psd_layer_effects_shadow_base { public: psd_layer_effects_glow_common() { setKnocksOut(true); setDistance(0); setBlendMode(COMPOSITE_LINEAR_DODGE); setColor(Qt::white); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setBlendMode; // using psd_layer_effects_shadow_base::setColor; // using psd_layer_effects_shadow_base::setOpacity; // using psd_layer_effects_shadow_base::setSpread; // using psd_layer_effects_shadow_base::setSize; // using psd_layer_effects_shadow_base::setContourLookupTable; // using psd_layer_effects_shadow_base::setAntiAliased; // using psd_layer_effects_shadow_base::setNoise; // using psd_layer_effects_shadow_base::setFillType; // using psd_layer_effects_shadow_base::setTechnique; // using psd_layer_effects_shadow_base::setRange; // using psd_layer_effects_shadow_base::setJitter; // using psd_layer_effects_shadow_base::setGradient; }; // oglw: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_25738 class KRITAPSD_EXPORT psd_layer_effects_outer_glow : public psd_layer_effects_glow_common { }; // iglw: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_27692 class KRITAPSD_EXPORT psd_layer_effects_inner_glow : public psd_layer_effects_glow_common { public: psd_layer_effects_inner_glow() : m_source(psd_glow_edge) { setInvertsSelection(true); setEdgeHidden(false); } psd_glow_source source() const { return m_source; } void setSource(psd_glow_source value) { m_source = value; } private: psd_glow_source m_source; }; struct psd_layer_effects_satin : public psd_layer_effects_shadow_base { psd_layer_effects_satin() { setInvert(false); setUseGlobalLight(false); setDistance(8); setSize(7); setSpread(0); setKnocksOut(true); setEdgeHidden(false); setBlendMode(COMPOSITE_LINEAR_BURN); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setBlendMode; // using psd_layer_effects_shadow_base::setColor; // using psd_layer_effects_shadow_base::setOpacity; // // NOTE: no global light setting explicitly! // using psd_layer_effects_shadow_base::setAngle; // using psd_layer_effects_shadow_base::setDistance; // using psd_layer_effects_shadow_base::setSize; // using psd_layer_effects_shadow_base::setContourLookupTable; // using psd_layer_effects_shadow_base::setAntiAliased; bool invert() const { return m_invert; } void setInvert(bool value) { m_invert = value; } private: bool m_invert; }; struct psd_pattern_info { qint32 name_length; quint16 * name; quint8 identifier[256]; }; // bevl: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_31889 struct psd_layer_effects_bevel_emboss : public psd_layer_effects_shadow_base { psd_layer_effects_bevel_emboss() : m_style(psd_bevel_inner_bevel), m_technique(psd_technique_softer), m_depth(100), m_direction(psd_direction_up), m_soften(0), m_altitude(30), m_glossAntiAliased(false), m_highlightBlendMode(COMPOSITE_SCREEN), m_highlightColor(Qt::white), m_highlightOpacity(75), m_shadowBlendMode(COMPOSITE_MULT), m_shadowColor(Qt::black), m_shadowOpacity(75), m_contourEnabled(false), m_contourRange(100), m_textureEnabled(false), m_texturePattern(0), m_textureScale(100), m_textureDepth(100), m_textureInvert(false), m_textureAlignWithLayer(true), m_textureHorizontalPhase(0), m_textureVerticalPhase(0) { for(int i = 0; i < PSD_LOOKUP_TABLE_SIZE; ++i) { m_glossContourLookupTable[i] = i; } } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setSize; // using psd_layer_effects_shadow_base::setAngle; // using psd_layer_effects_shadow_base::setUseGlobalLight; // using psd_layer_effects_shadow_base::setContourLookupTable; // using psd_layer_effects_shadow_base::setAntiAliased; psd_bevel_style style() const { return m_style; } void setStyle(psd_bevel_style value) { m_style = value; } psd_technique_type technique() const { return m_technique; } void setTechnique(psd_technique_type value) { m_technique = value; } int depth() const { return m_depth; } void setDepth(int value) { m_depth = value; } psd_direction direction() const { return m_direction; } void setDirection(psd_direction value) { m_direction = value; } int soften() const { return m_soften; } void setSoften(int value) { m_soften = value; } int altitude() const { return m_altitude; } void setAltitude(int value) { m_altitude = value; } const quint8* glossContourLookupTable() const { return m_glossContourLookupTable; } void setGlossContourLookupTable(const quint8 *value) { memcpy(m_glossContourLookupTable, value, PSD_LOOKUP_TABLE_SIZE * sizeof(quint8)); } bool glossAntiAliased() const { return m_glossAntiAliased; } void setGlossAntiAliased(bool value) { m_glossAntiAliased = value; } QString highlightBlendMode() const { return m_highlightBlendMode; } void setHighlightBlendMode(QString value) { m_highlightBlendMode = value; } QColor highlightColor() const { return m_highlightColor; } void setHighlightColor(QColor value) { m_highlightColor = value; } qint32 highlightOpacity() const { return m_highlightOpacity; } void setHighlightOpacity(qint32 value) { m_highlightOpacity = value; } QString shadowBlendMode() const { return m_shadowBlendMode; } void setShadowBlendMode(QString value) { m_shadowBlendMode = value; } QColor shadowColor() const { return m_shadowColor; } void setShadowColor(QColor value) { m_shadowColor = value; } qint32 shadowOpacity() const { return m_shadowOpacity; } void setShadowOpacity(qint32 value) { m_shadowOpacity = value; } bool contourEnabled() const { return m_contourEnabled; } void setContourEnabled(bool value) { m_contourEnabled = value; } int contourRange() const { return m_contourRange; } void setContourRange(int value) { m_contourRange = value; } bool textureEnabled() const { return m_textureEnabled; } void setTextureEnabled(bool value) { m_textureEnabled = value; } KoPattern* texturePattern() const { return m_texturePattern; } void setTexturePattern(KoPattern *value) { m_texturePattern = value; } int textureScale() const { return m_textureScale; } void setTextureScale(int value) { m_textureScale = value; } int textureDepth() const { return m_textureDepth; } void setTextureDepth(int value) { m_textureDepth = value; } bool textureInvert() const { return m_textureInvert; } void setTextureInvert(bool value) { m_textureInvert = value; } bool textureAlignWithLayer() const { return m_textureAlignWithLayer; } void setTextureAlignWithLayer(bool value) { m_textureAlignWithLayer = value; } void setTexturePhase(const QPointF &phase) { m_textureHorizontalPhase = phase.x(); m_textureVerticalPhase = phase.y(); } QPointF texturePhase() const { return QPointF(m_textureHorizontalPhase, m_textureVerticalPhase); } int textureHorizontalPhase() const { return m_textureHorizontalPhase; } void setTextureHorizontalPhase(int value) { m_textureHorizontalPhase = value; } int textureVerticalPhase() const { return m_textureVerticalPhase; } void setTextureVerticalPhase(int value) { m_textureVerticalPhase = value; } private: psd_bevel_style m_style; psd_technique_type m_technique; int m_depth; psd_direction m_direction; // Up or down int m_soften; // Blur value in pixels. int m_altitude; quint8 m_glossContourLookupTable[256]; bool m_glossAntiAliased; QString m_highlightBlendMode; // already in Krita format QColor m_highlightColor; qint32 m_highlightOpacity; // Hightlight opacity as a percent QString m_shadowBlendMode; // already in Krita format QColor m_shadowColor; qint32 m_shadowOpacity; // Shadow opacity as a percent bool m_contourEnabled; int m_contourRange; bool m_textureEnabled; KoPattern *m_texturePattern; int m_textureScale; int m_textureDepth; bool m_textureInvert; bool m_textureAlignWithLayer; int m_textureHorizontalPhase; // 0..100% int m_textureVerticalPhase; // 0..100% }; struct psd_layer_effects_overlay_base : public psd_layer_effects_shadow_base { psd_layer_effects_overlay_base() : m_scale(100), m_alignWithLayer(true), m_reverse(false), m_style(psd_gradient_style_linear), m_gradientXOffset(0), m_gradientYOffset(0), m_pattern(0), m_horizontalPhase(0), m_verticalPhase(0) { setUseGlobalLight(false); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setBlendMode; // using psd_layer_effects_shadow_base::setOpacity; int scale() const { return m_scale; } bool alignWithLayer() const { return m_alignWithLayer; } bool reverse() const { return m_reverse; } psd_gradient_style style() const { return m_style; } int gradientXOffset() const { return m_gradientXOffset; } int gradientYOffset() const { return m_gradientYOffset; } KoPattern* pattern() const { return m_pattern; } int horizontalPhase() const { return m_horizontalPhase; } int verticalPhase() const { return m_verticalPhase; } // refactor that public: void setScale(int value) { m_scale = value; } void setAlignWithLayer(bool value) { m_alignWithLayer = value; } void setReverse(bool value) { m_reverse = value; } void setStyle(psd_gradient_style value) { m_style = value; } void setGradientOffset(const QPointF &pt) { m_gradientXOffset = qRound(pt.x()); m_gradientYOffset = qRound(pt.y()); } QPointF gradientOffset() const { return QPointF(m_gradientXOffset, m_gradientYOffset); } void setPattern(KoPattern *value) { m_pattern = value; } void setPatternPhase(const QPointF &phase) { m_horizontalPhase = phase.x(); m_verticalPhase = phase.y(); } QPointF patternPhase() const { return QPointF(m_horizontalPhase, m_verticalPhase); } private: // Gradient+Pattern int m_scale; bool m_alignWithLayer; // Gradient bool m_reverse; psd_gradient_style m_style; int m_gradientXOffset; // 0..100% int m_gradientYOffset; // 0..100% // Pattern KoPattern *m_pattern; int m_horizontalPhase; // 0..100% int m_verticalPhase; // 0..100% protected: /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // must be called in the derived classes' c-tor // using psd_layer_effects_shadow_base::setFillType; }; // sofi: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/PhotoshopFileFormats.htm#50577409_70055 struct psd_layer_effects_color_overlay : public psd_layer_effects_overlay_base { psd_layer_effects_color_overlay() { setFillType(psd_fill_solid_color); setColor(Qt::white); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setColor; }; struct psd_layer_effects_gradient_overlay : public psd_layer_effects_overlay_base { psd_layer_effects_gradient_overlay() { setFillType(psd_fill_gradient); setAngle(90); setReverse(false); setScale(100); setAlignWithLayer(true); setStyle(psd_gradient_style_linear); } public: /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setGradient; // using psd_layer_effects_shadow_base::setAngle; // using psd_layer_effects_overlay_base::setReverse; // using psd_layer_effects_overlay_base::setScale; // using psd_layer_effects_overlay_base::setAlignWithLayer; // using psd_layer_effects_overlay_base::setStyle; // using psd_layer_effects_overlay_base::setGradientOffset; // using psd_layer_effects_overlay_base::gradientOffset; }; struct psd_layer_effects_pattern_overlay : public psd_layer_effects_overlay_base { psd_layer_effects_pattern_overlay() { setFillType(psd_fill_pattern); setScale(100); setAlignWithLayer(true); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_overlay_base::setScale; // using psd_layer_effects_overlay_base::setAlignWithLayer; // using psd_layer_effects_overlay_base::setPattern; // using psd_layer_effects_overlay_base::setPatternPhase; // using psd_layer_effects_overlay_base::patternPhase; private: - int m_scale; + // These are unused + /*int m_scale; bool m_alignWithLayer; KoPattern *m_pattern; int m_horizontalPhase; - int m_verticalPhase; + int m_verticalPhase;*/ }; struct psd_layer_effects_stroke : public psd_layer_effects_overlay_base { psd_layer_effects_stroke() : m_position(psd_stroke_outside) { setFillType(psd_fill_solid_color); setColor(Qt::black); setAngle(90); setReverse(false); setScale(100); setAlignWithLayer(true); setStyle(psd_gradient_style_linear); setScale(100); setAlignWithLayer(true); } /// FIXME: 'using' is not supported by MSVC, so please refactor in /// some other way to ensure that the setters are not used /// in the classes we don't want // using psd_layer_effects_shadow_base::setFillType; // using psd_layer_effects_shadow_base::setSize; // using psd_layer_effects_shadow_base::setColor; // using psd_layer_effects_shadow_base::setGradient; // using psd_layer_effects_shadow_base::setAngle; // using psd_layer_effects_overlay_base::setReverse; // using psd_layer_effects_overlay_base::setScale; // using psd_layer_effects_overlay_base::setAlignWithLayer; // using psd_layer_effects_overlay_base::setStyle; // using psd_layer_effects_overlay_base::setGradientOffset; // using psd_layer_effects_overlay_base::gradientOffset; // using psd_layer_effects_overlay_base::setPattern; // using psd_layer_effects_overlay_base::setPatternPhase; // using psd_layer_effects_overlay_base::patternPhase; psd_stroke_position position() const { return m_position; } void setPosition(psd_stroke_position value) { m_position = value; } private: psd_stroke_position m_position; }; /** * Convert PsdColorMode to pigment colormodelid and colordepthid. * @see KoColorModelStandardIds * * @return a QPair containing ColorModelId and ColorDepthID */ QPair KRITAPSD_EXPORT psd_colormode_to_colormodelid(psd_color_mode colormode, quint16 channelDepth); /** * Convert the Photoshop blend mode strings to Pigment compositeop id's */ QString KRITAPSD_EXPORT psd_blendmode_to_composite_op(const QString& blendmode); QString KRITAPSD_EXPORT composite_op_to_psd_blendmode(const QString& compositeOp); #endif // PSD_H diff --git a/krita/libpsd/psd_utils.h b/krita/libpsd/psd_utils.h index 607f7722646..85c0194aedd 100644 --- a/krita/libpsd/psd_utils.h +++ b/krita/libpsd/psd_utils.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2009 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 PSD_UTILS_H #define PSD_UTILS_H #include #include -#include "libkispsd_export.h" +#include "kritapsd_export.h" class QIODevice; class QString; bool KRITAPSD_EXPORT psdwrite(QIODevice* io, quint8 v); bool KRITAPSD_EXPORT psdwrite(QIODevice* io, quint16 v); bool KRITAPSD_EXPORT psdwrite(QIODevice* io, qint16 v); bool KRITAPSD_EXPORT psdwrite(QIODevice* io, quint32 v); bool KRITAPSD_EXPORT psdwrite(QIODevice* io, const QString &s); bool KRITAPSD_EXPORT psdwrite(QIODevice* io, double v); bool KRITAPSD_EXPORT psdwrite_pascalstring(QIODevice* io, const QString &s); bool KRITAPSD_EXPORT psdwrite_pascalstring(QIODevice* io, const QString &s, int padding); bool KRITAPSD_EXPORT psdpad(QIODevice* io, quint32 padding); bool KRITAPSD_EXPORT psdread(QIODevice* io, quint8* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, quint16* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, qint16* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, quint32* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, qint32* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, quint64* v); bool KRITAPSD_EXPORT psdread(QIODevice* io, double* v); bool KRITAPSD_EXPORT psdread_pascalstring(QIODevice* io, QString& s, int padding); bool KRITAPSD_EXPORT psdread_unicodestring(QIODevice* io, QString &s); bool KRITAPSD_EXPORT psd_read_blendmode(QIODevice* io, QString &blendModeKey); #endif // PSD_UTILS_H diff --git a/krita/main.cc b/krita/main.cc index 1de8d922053..b1cebb554e8 100644 --- a/krita/main.cc +++ b/krita/main.cc @@ -1,198 +1,196 @@ /* * main.cc - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2002 Patrick Julien * * 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 */ #include #include #include #include #include #include #include #include #include #include #include #include #include -#include - #include "data/splash/splash_screen.xpm" #include "data/splash/splash_holidays.xpm" #include "ui/kis_aboutdata.h" #include "ui/kis_factory2.h" #include "ui/KisDocument.h" #include "kis_splash_screen.h" #include "KisPart.h" #if defined Q_OS_WIN #include #include #include #ifdef USE_BREAKPAD #include "kis_crash_handler.h" #endif #elif defined Q_WS_X11 #include #if QT_VERSION < 0x040800 // needed for XInitThreads() #include #endif #endif extern "C" int main(int argc, char **argv) { bool runningInKDE = !qgetenv("KDE_FULL_SESSION").isEmpty(); #ifdef Q_WS_X11 if (runningInKDE) { qputenv("QT_NO_GLIB", "1"); } #endif #ifdef USE_BREAKPAD qputenv("KDE_DEBUG", "1"); KisCrashHandler crashHandler; Q_UNUSED(crashHandler); #endif #if defined Q_OS_WIN SetProcessDPIAware(); // The n-trig wintab driver needs this to report the correct dimensions #endif int state; KAboutData *aboutData = KisFactory::aboutData(); KCmdLineArgs::init(argc, argv, aboutData); KCmdLineOptions options; options.add("print", ki18n("Only print and exit")); options.add("template", ki18n("Open a new document with a template")); options.add("dpi ", ki18n("Override display DPI")); options.add("export-pdf", ki18n("Only export to PDF and exit")); options.add("export", ki18n("Export to the given filename and exit")); options.add("export-filename ", ki18n("Filename for export/export-pdf")); options.add("profile-filename ", ki18n("Filename to write profiling information into.")); options.add("+[file(s)]", ki18n("File(s) or URL(s) to open")); KCmdLineArgs::addCmdLineOptions(options); // A per-user unique string, without /, because QLocalServer cannot use names with a / in it QString key = "Krita" + QDesktopServices::storageLocation(QDesktopServices::HomeLocation).replace("/", "_"); key = key.replace(":", "_").replace("\\","_"); #if defined Q_WS_X11 #if QT_VERSION >= 0x040800 // we need to call XInitThreads() (which this does) because of gmic (and possibly others) // do their own X11 stuff in their own threads // this call must happen before the creation of the application (see AA_X11InitThreads docs) QCoreApplication::setAttribute(Qt::AA_X11InitThreads, true); #else XInitThreads(); #endif #endif // first create the application so we can create a pixmap KisApplication app(key); // If we should clear the config, it has to be done as soon as possible after // KisApplication has been created. Otherwise the config file may have been read // and stored in a KConfig object we have no control over. app.askClearConfig(); // create factory only after application, the componentData it creates in the // constructor will need an existing QCoreApplication at least with Qt5/KF5, // to set name of application etc., as also needed to find resources KisFactory factory; Q_UNUSED(factory); // Not really, it'll self-destruct on exiting main if (app.isRunning()) { KCmdLineArgs *args = KCmdLineArgs::parsedArgs(); // only pass arguments to main instance if they are not for batch processing // any batch processing would be done in this separate instance const bool batchRun = args->isSet("print") || args->isSet("export") || args->isSet("export-pdf"); if (!batchRun) { QByteArray ba; QDataStream ds(&ba, QIODevice::WriteOnly); args->saveAppArgs(ds); ds.device()->close(); if (app.sendMessage(ba)) { return 0; } } } #if defined Q_OS_WIN KisTabletSupportWin::init(); app.setEventFilter(&KisTabletSupportWin::eventFilter); #elif defined Q_WS_X11 KisTabletSupportX11::init(); app.setEventFilter(&KisTabletSupportX11::eventFilter); #endif if (!runningInKDE) { // Icons in menus are ugly and distracting app.setAttribute(Qt::AA_DontShowIconsInMenus); } // then create the pixmap from an xpm: we cannot get the // location of our datadir before we've started our components, // so use an xpm. QDate currentDate = QDate::currentDate(); QWidget *splash = 0; if (currentDate > QDate(currentDate.year(), 12, 4) || currentDate < QDate(currentDate.year(), 1, 9)) { splash = new KisSplashScreen(aboutData->version(), QPixmap(splash_holidays_xpm)); } else { splash = new KisSplashScreen(aboutData->version(), QPixmap(splash_screen_xpm)); } app.setSplashScreen(splash); if (!app.start()) { return 1; } // Set up remote arguments. QObject::connect(&app, SIGNAL(messageReceived(QByteArray,QObject*)), &app, SLOT(remoteArguments(QByteArray,QObject*))); QObject::connect(&app, SIGNAL(fileOpenRequest(QString)), &app, SLOT(fileOpenRequested(QString))); state = app.exec(); return state; } diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-dark/dark_application-exit.svg similarity index 51% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-dark/dark_application-exit.svg index 2cca70c5c62..04f5370a7f2 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-dark/dark_application-exit.svg @@ -1,99 +1,104 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="application-exit.svg"> + id="defs3111" /> + inkscape:showpageshadow="false"> + + id="guide4114" /> + id="guide4116" /> + id="guide4118" /> + id="guide4120" /> + id="guide4122" /> + id="guide4124" /> + id="guide4126" /> - + id="guide4128" /> + id="metadata3114"> image/svg+xml + transform="translate(-534.14288,-579.07648)"> + style="opacity:1;fill:#da4453;fill-opacity:1;stroke:none" + d="M 3 3 L 3 7 L 3 19 L 4 19 L 18 19 L 19 19 L 19 18 L 19 6 L 19 3 L 4 3 L 3 3 z M 4 7 L 18 7 L 18 18 L 4 18 L 4 7 z M 8 11 L 8 13 L 14 13 L 14 11 L 8 11 z " + transform="translate(534.14288,579.07648)" + id="rect4141" /> diff --git a/krita/pics/Breeze-dark/dark_configure-shortcuts.svg b/krita/pics/Breeze-dark/dark_configure-shortcuts.svg new file mode 120000 index 00000000000..e82a8571aac --- /dev/null +++ b/krita/pics/Breeze-dark/dark_configure-shortcuts.svg @@ -0,0 +1 @@ +dark_applications-system.svg \ No newline at end of file diff --git a/krita/pics/Breeze-dark/dark_configure-toolbars.svg b/krita/pics/Breeze-dark/dark_configure-toolbars.svg new file mode 120000 index 00000000000..489d15bce0c --- /dev/null +++ b/krita/pics/Breeze-dark/dark_configure-toolbars.svg @@ -0,0 +1 @@ +dark_configure.svg \ No newline at end of file diff --git a/krita/pics/Breeze-dark/dark_dialog-cancel.svg b/krita/pics/Breeze-dark/dark_dialog-cancel.svg new file mode 100644 index 00000000000..d3833319df8 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_dialog-cancel.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-dark/dark_dialog-close.svg b/krita/pics/Breeze-dark/dark_dialog-close.svg new file mode 120000 index 00000000000..7115c2eca45 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_dialog-close.svg @@ -0,0 +1 @@ +dark_window-close.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-dark/dark_dialog-ok.svg similarity index 51% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-dark/dark_dialog-ok.svg index 2cca70c5c62..e879822657d 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-dark/dark_dialog-ok.svg @@ -1,99 +1,111 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="dialog-apply.svg"> + id="defs3383" /> + showguides="true"> + + + + id="guide4163" /> + id="guide4165" /> + id="guide4167" /> + id="guide4169" /> + id="guide4171" /> + id="guide4173" /> + id="guide4175" /> - + id="guide4177" /> + id="metadata3386"> image/svg+xml + transform="translate(-364.57143,-525.79075)"> + style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:none" + d="m 382.8643,530.79077 -10.43876,10.56644 -4.14699,-4.19772 -0.70712,0.71578 4.14699,4.1977 -0.002,0.002 0.70713,0.71577 0.002,-0.002 0.002,0.002 0.70711,-0.71577 -0.002,-0.002 10.43877,-10.56645 -0.70712,-0.71576 z" + id="rect4113" + inkscape:connector-curvature="0" /> diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-dark/dark_document-open-recent.svg similarity index 51% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-dark/dark_document-open-recent.svg index 2cca70c5c62..503ae6b3385 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-dark/dark_document-open-recent.svg @@ -1,99 +1,133 @@ + inkscape:version="0.48+devel r" + viewBox="0 0 22 22" + sodipodi:docname="document-open-recent.svg"> + id="defs4" /> + units="px"> + id="guide4085" /> + id="guide4087" /> + id="guide4089" /> + id="guide4091" /> + id="guide4093" /> + id="guide4095" /> + id="guide4097" /> + id="guide4099" /> + id="grid4101" /> + + + + + + + + + id="metadata7"> image/svg+xml diff --git a/krita/pics/Breeze-dark/dark_document-print-preview.svg b/krita/pics/Breeze-dark/dark_document-print-preview.svg new file mode 100644 index 00000000000..83e03d35ff2 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_document-print-preview.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-dark/dark_document-print.svg similarity index 50% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-dark/dark_document-print.svg index 2cca70c5c62..5130f62af79 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-dark/dark_document-print.svg @@ -1,99 +1,102 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="document-print.svg"> + id="defs3406" /> + inkscape:showpageshadow="false"> + + id="guide4123" /> + id="guide4125" /> + id="guide4127" /> + id="guide4129" /> + id="guide4131" /> + id="guide4133" /> + id="guide4135" /> - + id="guide4137" /> + id="metadata3409"> image/svg+xml - + + transform="translate(-384.57143,-482.93361)"> + style="opacity:1;fill:#4d4d4d;fill-opacity:1;stroke:none" + d="M 5 3 L 5 4 L 5 8 L 3 8 L 3 9 L 3 16 L 4 16 L 7 16 L 7 18 L 7 19 L 15 19 L 15 18 L 15 16 L 19 16 L 19 15 L 19 9 L 19 8 L 17 8 L 17 4 L 17 3 L 5 3 z M 6 4 L 16 4 L 16 8 L 15 8 L 15 7 L 7 7 L 7 8 L 6 8 L 6 4 z M 7 5 L 7 6 L 15 6 L 15 5 L 7 5 z M 4 9 L 18 9 L 18 15 L 16 15 L 16 13 L 6 13 L 6 15 L 4 15 L 4 9 z M 14 10 L 14 11 L 17 11 L 17 10 L 14 10 z M 8 16 L 14 16 L 14 18 L 8 18 L 8 16 z " + transform="translate(384.57143,482.93361)" + id="rect4145" /> diff --git a/krita/pics/Breeze-dark/dark_document-save-as.svg b/krita/pics/Breeze-dark/dark_document-save-as.svg new file mode 100644 index 00000000000..a4c9cd42d4f --- /dev/null +++ b/krita/pics/Breeze-dark/dark_document-save-as.svg @@ -0,0 +1,127 @@ + + + + + I REALLY hate this icon + + + + + + + + + + + + + + + image/svg+xml + + I REALLY hate this icon + November 20th 2014 + + + Uri Herrera + + + + + + + + English + Migh as well use Tango... for crying out loud. This damn icon has to die, but no because obviously we're still using floppies therefore it is still relevant in 2014. + + + + + + + + + + diff --git a/krita/pics/Breeze-dark/dark_help-contents.svg b/krita/pics/Breeze-dark/dark_help-contents.svg new file mode 120000 index 00000000000..a3c477c5eaa --- /dev/null +++ b/krita/pics/Breeze-dark/dark_help-contents.svg @@ -0,0 +1 @@ +dark_system-help.svg \ No newline at end of file diff --git a/krita/pics/Breeze-dark/dark_kde.svg b/krita/pics/Breeze-dark/dark_kde.svg new file mode 100644 index 00000000000..e94af0a12b6 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_kde.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-dark/dark_object-locked.svg b/krita/pics/Breeze-dark/dark_object-locked.svg new file mode 120000 index 00000000000..66dcc044416 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_object-locked.svg @@ -0,0 +1 @@ +dark_locked.svg \ No newline at end of file diff --git a/krita/pics/Breeze-dark/dark_object-unlocked.svg b/krita/pics/Breeze-dark/dark_object-unlocked.svg new file mode 120000 index 00000000000..9179f5edcb6 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_object-unlocked.svg @@ -0,0 +1 @@ +dark_unlocked.svg \ No newline at end of file diff --git a/krita/pics/Breeze-dark/dark_preferences-desktop-locale.svg b/krita/pics/Breeze-dark/dark_preferences-desktop-locale.svg new file mode 100644 index 00000000000..b42e884399a --- /dev/null +++ b/krita/pics/Breeze-dark/dark_preferences-desktop-locale.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-dark/dark_tools-report-bug.svg similarity index 59% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-dark/dark_tools-report-bug.svg index 2cca70c5c62..d60adb772e6 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-dark/dark_tools-report-bug.svg @@ -1,99 +1,100 @@ + inkscape:version="0.48+devel r" + viewBox="0 0 22 22" + sodipodi:docname="tools-report-bug.svg"> + id="defs4" /> + units="px" + inkscape:window-width="1366" + inkscape:window-height="718" + inkscape:window-x="-2" + inkscape:window-y="23" + inkscape:window-maximized="1"> + + id="guide4107" /> + id="guide4109" /> + id="guide4111" /> + id="guide4113" /> + id="guide4115" /> + id="guide4117" /> + id="guide4119" /> - + id="guide4121" /> + id="metadata7"> image/svg+xml - + + id="rect4129" /> diff --git a/krita/pics/Breeze-dark/dark_view-fullscreen.svg b/krita/pics/Breeze-dark/dark_view-fullscreen.svg new file mode 100644 index 00000000000..f1117d22c55 --- /dev/null +++ b/krita/pics/Breeze-dark/dark_view-fullscreen.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_application-exit.svg similarity index 51% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-light/light_application-exit.svg index 2cca70c5c62..04f5370a7f2 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_application-exit.svg @@ -1,99 +1,104 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="application-exit.svg"> + id="defs3111" /> + inkscape:showpageshadow="false"> + + id="guide4114" /> + id="guide4116" /> + id="guide4118" /> + id="guide4120" /> + id="guide4122" /> + id="guide4124" /> + id="guide4126" /> - + id="guide4128" /> + id="metadata3114"> image/svg+xml + transform="translate(-534.14288,-579.07648)"> + style="opacity:1;fill:#da4453;fill-opacity:1;stroke:none" + d="M 3 3 L 3 7 L 3 19 L 4 19 L 18 19 L 19 19 L 19 18 L 19 6 L 19 3 L 4 3 L 3 3 z M 4 7 L 18 7 L 18 18 L 4 18 L 4 7 z M 8 11 L 8 13 L 14 13 L 14 11 L 8 11 z " + transform="translate(534.14288,579.07648)" + id="rect4141" /> diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_applications-system.svg index 2cca70c5c62..2cbbb8e5c35 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_applications-system.svg @@ -1,99 +1,99 @@ + inkscape:version="0.91 r13725" + sodipodi:docname="light_configure-shortcuts.svg"> image/svg+xml - + diff --git a/krita/pics/Breeze-light/light_configure-shortcuts.svg b/krita/pics/Breeze-light/light_configure-shortcuts.svg new file mode 120000 index 00000000000..3a1eaf84e94 --- /dev/null +++ b/krita/pics/Breeze-light/light_configure-shortcuts.svg @@ -0,0 +1 @@ +light_applications-system.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_configure-toolbars.svg b/krita/pics/Breeze-light/light_configure-toolbars.svg new file mode 120000 index 00000000000..b0c09418e0d --- /dev/null +++ b/krita/pics/Breeze-light/light_configure-toolbars.svg @@ -0,0 +1 @@ +light_configure.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_dialog-cancel.svg b/krita/pics/Breeze-light/light_dialog-cancel.svg new file mode 100644 index 00000000000..33ea984975e --- /dev/null +++ b/krita/pics/Breeze-light/light_dialog-cancel.svg @@ -0,0 +1,134 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_dialog-close.svg b/krita/pics/Breeze-light/light_dialog-close.svg new file mode 120000 index 00000000000..5d5d36866f3 --- /dev/null +++ b/krita/pics/Breeze-light/light_dialog-close.svg @@ -0,0 +1 @@ +light_window-close.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_dialog-ok.svg similarity index 51% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-light/light_dialog-ok.svg index 2cca70c5c62..8234907b899 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_dialog-ok.svg @@ -1,99 +1,111 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="dialog-apply.svg"> + id="defs3383" /> + showguides="true"> + + + + id="guide4163" /> + id="guide4165" /> + id="guide4167" /> + id="guide4169" /> + id="guide4171" /> + id="guide4173" /> + id="guide4175" /> - + id="guide4177" /> + id="metadata3386"> image/svg+xml + transform="translate(-364.57143,-525.79075)"> + style="opacity:1;fill:#f2f2f2;fill-opacity:1;stroke:none" + d="m 382.8643,530.79077 -10.43876,10.56644 -4.14699,-4.19772 -0.70712,0.71578 4.14699,4.1977 -0.002,0.002 0.70713,0.71577 0.002,-0.002 0.002,0.002 0.70711,-0.71577 -0.002,-0.002 10.43877,-10.56645 -0.70712,-0.71576 z" + id="rect4113" + inkscape:connector-curvature="0" /> diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_document-open-recent.svg similarity index 52% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-light/light_document-open-recent.svg index 2cca70c5c62..340f98bb89b 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_document-open-recent.svg @@ -1,99 +1,133 @@ + inkscape:version="0.48+devel r" + viewBox="0 0 22 22" + sodipodi:docname="document-open-recent.svg"> + id="defs4" /> + units="px"> + id="guide4085" /> + id="guide4087" /> + id="guide4089" /> + id="guide4091" /> + id="guide4093" /> + id="guide4095" /> + id="guide4097" /> + id="guide4099" /> + id="grid4101" /> + + + + + + + + + id="metadata7"> image/svg+xml diff --git a/krita/pics/Breeze-light/light_document-print-preview.svg b/krita/pics/Breeze-light/light_document-print-preview.svg new file mode 100644 index 00000000000..c4144ee00fc --- /dev/null +++ b/krita/pics/Breeze-light/light_document-print-preview.svg @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_document-print.svg similarity index 50% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-light/light_document-print.svg index 2cca70c5c62..16018557b89 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_document-print.svg @@ -1,99 +1,102 @@ + inkscape:version="0.48+devel r" + sodipodi:docname="document-print.svg"> + id="defs3406" /> + inkscape:showpageshadow="false"> + + id="guide4123" /> + id="guide4125" /> + id="guide4127" /> + id="guide4129" /> + id="guide4131" /> + id="guide4133" /> + id="guide4135" /> - + id="guide4137" /> + id="metadata3409"> image/svg+xml - + + transform="translate(-384.57143,-482.93361)"> + style="opacity:1;fill:#f2f2f2;fill-opacity:1;stroke:none" + d="M 5 3 L 5 4 L 5 8 L 3 8 L 3 9 L 3 16 L 4 16 L 7 16 L 7 18 L 7 19 L 15 19 L 15 18 L 15 16 L 19 16 L 19 15 L 19 9 L 19 8 L 17 8 L 17 4 L 17 3 L 5 3 z M 6 4 L 16 4 L 16 8 L 15 8 L 15 7 L 7 7 L 7 8 L 6 8 L 6 4 z M 7 5 L 7 6 L 15 6 L 15 5 L 7 5 z M 4 9 L 18 9 L 18 15 L 16 15 L 16 13 L 6 13 L 6 15 L 4 15 L 4 9 z M 14 10 L 14 11 L 17 11 L 17 10 L 14 10 z M 8 16 L 14 16 L 14 18 L 8 18 L 8 16 z " + transform="translate(384.57143,482.93361)" + id="rect4145" /> diff --git a/krita/pics/Breeze-light/light_document-save-as.svg b/krita/pics/Breeze-light/light_document-save-as.svg new file mode 100644 index 00000000000..e4d9aabdc10 --- /dev/null +++ b/krita/pics/Breeze-light/light_document-save-as.svg @@ -0,0 +1,127 @@ + + + + + I REALLY hate this icon + + + + + + + + + + + + + + + image/svg+xml + + I REALLY hate this icon + November 20th 2014 + + + Uri Herrera + + + + + + + + English + Migh as well use Tango... for crying out loud. This damn icon has to die, but no because obviously we're still using floppies therefore it is still relevant in 2014. + + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_help-contents.svg b/krita/pics/Breeze-light/light_help-contents.svg new file mode 120000 index 00000000000..beacc557974 --- /dev/null +++ b/krita/pics/Breeze-light/light_help-contents.svg @@ -0,0 +1 @@ +light_system-help.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_kde.svg b/krita/pics/Breeze-light/light_kde.svg new file mode 100644 index 00000000000..9e0c4ad3000 --- /dev/null +++ b/krita/pics/Breeze-light/light_kde.svg @@ -0,0 +1,133 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_object-locked.svg b/krita/pics/Breeze-light/light_object-locked.svg new file mode 120000 index 00000000000..43dd393a4f1 --- /dev/null +++ b/krita/pics/Breeze-light/light_object-locked.svg @@ -0,0 +1 @@ +light_locked.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_object-unlocked.svg b/krita/pics/Breeze-light/light_object-unlocked.svg new file mode 120000 index 00000000000..beded13e09a --- /dev/null +++ b/krita/pics/Breeze-light/light_object-unlocked.svg @@ -0,0 +1 @@ +light_unlocked.svg \ No newline at end of file diff --git a/krita/pics/Breeze-light/light_preferences-desktop-locale.svg b/krita/pics/Breeze-light/light_preferences-desktop-locale.svg new file mode 100644 index 00000000000..b42e884399a --- /dev/null +++ b/krita/pics/Breeze-light/light_preferences-desktop-locale.svg @@ -0,0 +1,198 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + diff --git a/krita/pics/Breeze-light/light_applications-system.svg b/krita/pics/Breeze-light/light_tools-report-bug.svg similarity index 59% copy from krita/pics/Breeze-light/light_applications-system.svg copy to krita/pics/Breeze-light/light_tools-report-bug.svg index 2cca70c5c62..a5ef8ce0dd1 100644 --- a/krita/pics/Breeze-light/light_applications-system.svg +++ b/krita/pics/Breeze-light/light_tools-report-bug.svg @@ -1,99 +1,100 @@ + inkscape:version="0.48+devel r" + viewBox="0 0 22 22" + sodipodi:docname="tools-report-bug.svg"> + id="defs4" /> + units="px" + inkscape:window-width="1366" + inkscape:window-height="718" + inkscape:window-x="-2" + inkscape:window-y="23" + inkscape:window-maximized="1"> + + id="guide4107" /> + id="guide4109" /> + id="guide4111" /> + id="guide4113" /> + id="guide4115" /> + id="guide4117" /> + id="guide4119" /> - + id="guide4121" /> + id="metadata7"> image/svg+xml - + + id="rect4129" /> diff --git a/krita/pics/Breeze-light/light_view-fullscreen.svg b/krita/pics/Breeze-light/light_view-fullscreen.svg new file mode 100644 index 00000000000..8a6dc897172 --- /dev/null +++ b/krita/pics/Breeze-light/light_view-fullscreen.svg @@ -0,0 +1,118 @@ + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + + + + diff --git a/krita/pics/CMakeLists.txt b/krita/pics/CMakeLists.txt index f042a5799dc..9b6206bc498 100644 --- a/krita/pics/CMakeLists.txt +++ b/krita/pics/CMakeLists.txt @@ -1,313 +1,384 @@ install(FILES arrow-down.png arrow-right.png broken-preset.png delete.png height_icon.png height.png hi16-add_dialog.png hi16-palette_library.png icon-kritasketch-256.png landscape.png linked.png local_selection_active.png local_selection_inactive.png offset_horizontal.png offset_vertical.png -paintop_presets_disabled.png -paintop_settings_01.png -paintop_settings_02.png -paintop_settings_disabled.png portrait.png ratio_icon.png selection_add.png selection_exclude.png selection_intersect.png selection_replace.png selection_subtract.png select_pixel.png select_shape.png shade.png shear_horizontal.png shear_vertical.png sidebaricon.png tablet.png tool_screenshot.png transparency-locked.png transparency-unlocked.png passthrough-enabled.png passthrough-disabled.png layer-style-enabled.png layer-style-disabled.png unlinked.png width_icon.png width.png workspace-chooser.png onionA.png onionB.png mirrorAxis-HorizontalMove.png mirrorAxis-VerticalMove.png dark_selection-mode_ants.png dark_selection-mode_invisible.png dark_selection-mode_mask.png -dark_symmetry-horizontal.png -dark_symmetry-vertical.png dark_trim-to-image.png dark_layer-locked.png dark_layer-unlocked.png dark_novisible.png dark_visible.png dark_transparency-enabled.png dark_transparency-disabled.png light_transparency-enabled.png light_transparency-disabled.png light_layer-locked.png light_layer-unlocked.png light_novisible.png light_visible.png light_selection-mode_ants.png light_selection-mode_invisible.png light_selection-mode_mask.png -light_symmetry-vertical.png -light_symmetry-horizontal.png light_trim-to-image.png layerbox/dark_addlayer.png layerbox/dark_addtofolder.png layerbox/dark_arrowdown.png layerbox/dark_arrowupblr.png layerbox/dark_deletelayer.png layerbox/dark_duplicatelayer.png layerbox/dark_properties.png layerbox/dark_removefromfolder.png layerbox/light_addlayer.png layerbox/light_addtofolder.png layerbox/light_arrowdown.png layerbox/light_arrowupblr.png layerbox/light_deletelayer.png layerbox/light_duplicatelayer.png layerbox/light_properties.png layerbox/light_removefromfolder.png +misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg +misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg +misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg +misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg +misc-light/light_ox16-action-object-align-vertical-center-calligra.svg +misc-light/light_ox16-action-object-align-vertical-top-calligra.svg +misc-light/light_ox16-action-object-group-calligra.svg +misc-light/light_ox16-action-object-order-back-calligra.svg +misc-light/light_ox16-action-object-order-front-calligra.svg +misc-light/light_ox16-action-object-order-lower-calligra.svg +misc-light/light_ox16-action-object-order-raise-calligra.svg +misc-light/light_ox16-action-object-ungroup-calligra.svg +misc-light/light_paintop_settings_01.svg +misc-light/light_paintop_settings_02.svg +misc-light/light_stroke-cap-butt.svg +misc-light/light_stroke-cap-round.svg +misc-light/light_stroke-cap-square.svg +misc-light/light_stroke-join-bevel.svg +misc-light/light_stroke-join-miter.svg +misc-light/light_stroke-join-round.svg +misc-light/light_symmetry-horizontal.svg +misc-light/light_symmetry-vertical.svg + +misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg +misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg +misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg +misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg +misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg +misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg +misc-dark/dark_ox16-action-object-group-calligra.svg +misc-dark/dark_ox16-action-object-order-back-calligra.svg +misc-dark/dark_ox16-action-object-order-front-calligra.svg +misc-dark/dark_ox16-action-object-order-lower-calligra.svg +misc-dark/dark_ox16-action-object-order-raise-calligra.svg +misc-dark/dark_ox16-action-object-ungroup-calligra.svg +misc-dark/dark_paintop_settings_01.svg +misc-dark/dark_paintop_settings_02.svg +misc-dark/dark_stroke-cap-butt.svg +misc-dark/dark_stroke-cap-round.svg +misc-dark/dark_stroke-cap-square.svg +misc-dark/dark_stroke-join-bevel.svg +misc-dark/dark_stroke-join-miter.svg +misc-dark/dark_stroke-join-round.svg +misc-dark/dark_symmetry-horizontal.svg +misc-dark/dark_symmetry-vertical.svg + tools/16/dark_calligraphy.png tools/16/dark_draw-text.png tools/16/dark_format-fill-color.png tools/16/dark_krita_draw_path.png tools/16/dark_krita_tool_color_fill.png tools/16/dark_krita_tool_color_picker.png tools/16/dark_krita_tool_dyna.png tools/16/dark_krita_tool_ellipse.png tools/16/dark_krita_tool_freehand.png tools/16/dark_krita_tool_freehandvector.png tools/16/dark_krita_tool_gradient.png tools/16/dark_krita_tool_grid.png tools/16/dark_krita_tool_line.png tools/16/dark_krita_tool_measure.png tools/16/dark_krita_tool_move.png tools/16/dark_krita_tool_multihand.png tools/16/dark_krita_tool_polygon.png tools/16/dark_krita_tool_rectangle.png tools/16/dark_krita_tool_ruler_assistant.png tools/16/dark_krita_tool_transform.png tools/16/dark_pattern.png tools/16/dark_polyline.png tools/16/dark_select.png tools/16/dark_tool_contiguous_selection.png tools/16/dark_tool_crop.png tools/16/dark_tool_elliptical_selection.png tools/16/dark_tool_outline_selection.png tools/16/dark_tool_path_selection.png tools/16/dark_tool_perspectivegrid.png tools/16/dark_tool_polygonal_selection.png tools/16/dark_tool_rect_selection.png tools/16/dark_tool_similar_selection.png tools/16/light_calligraphy.png tools/16/light_draw-text.png tools/16/light_format-fill-color.png tools/16/light_krita_draw_path.png tools/16/light_krita_tool_color_fill.png tools/16/light_krita_tool_color_picker.png tools/16/light_krita_tool_dyna.png tools/16/light_krita_tool_ellipse.png tools/16/light_krita_tool_freehand.png tools/16/light_krita_tool_freehandvector.png tools/16/light_krita_tool_gradient.png tools/16/light_krita_tool_grid.png tools/16/light_krita_tool_line.png tools/16/light_krita_tool_measure.png tools/16/light_krita_tool_move.png tools/16/light_krita_tool_multihand.png tools/16/light_krita_tool_polygon.png tools/16/light_krita_tool_rectangle.png tools/16/light_krita_tool_ruler_assistant.png tools/16/light_krita_tool_transform.png tools/16/light_pattern.png tools/16/light_polyline.png tools/16/light_select.png tools/16/light_tool_contiguous_selection.png tools/16/light_tool_crop.png tools/16/light_tool_elliptical_selection.png tools/16/light_tool_outline_selection.png tools/16/light_tool_path_selection.png tools/16/light_tool_perspectivegrid.png tools/16/light_tool_polygon.png tools/16/light_tool_polygonal_selection.png tools/16/light_tool_rect_selection.png tools/16/light_tool_similar_selection.png tool_transform/dark_transform_icons_cage.png tool_transform/dark_transform_icons_liquify_erase.png tool_transform/dark_transform_icons_liquify_main.png tool_transform/dark_transform_icons_liquify_move.png tool_transform/dark_transform_icons_liquify_offset.png tool_transform/dark_transform_icons_liquify_resize.png tool_transform/dark_transform_icons_liquify_rotate.png tool_transform/dark_transform_icons_liquify_rotateCCW.png tool_transform/dark_transform_icons_main.png tool_transform/dark_transform_icons_perspective.png tool_transform/dark_transform_icons_warp.png tool_transform/dark_transform_icons_penPressure.png tool_transform/light_transform_icons_cage.png tool_transform/light_transform_icons_liquify_erase.png tool_transform/light_transform_icons_liquify_main.png tool_transform/light_transform_icons_liquify_move.png tool_transform/light_transform_icons_liquify_offset.png tool_transform/light_transform_icons_liquify_resize.png tool_transform/light_transform_icons_liquify_rotate.png tool_transform/light_transform_icons_liquify_rotateCCW.png tool_transform/light_transform_icons_main.png tool_transform/light_transform_icons_perspective.png tool_transform/light_transform_icons_warp.png tool_transform/light_transform_icons_penPressure.png +Breeze-dark/dark_application-exit.svg Breeze-dark/dark_application-pdf.svg Breeze-dark/dark_applications-system.svg Breeze-dark/dark_arrow-down.svg Breeze-dark/dark_arrow-left.svg Breeze-dark/dark_arrow-right.svg Breeze-dark/dark_arrow-up.svg Breeze-dark/dark_bookmarks.svg +Breeze-dark/dark_configure-shortcuts.svg +Breeze-dark/dark_configure-toolbars.svg Breeze-dark/dark_configure.svg +Breeze-dark/dark_dialog-cancel.svg +Breeze-dark/dark_dialog-close.svg +Breeze-dark/dark_dialog-ok.svg Breeze-dark/dark_dialog-warning.svg Breeze-dark/dark_document-edit.svg Breeze-dark/dark_document-export.svg Breeze-dark/dark_document-import.svg Breeze-dark/dark_document-new.svg +Breeze-dark/dark_document-open-recent.svg Breeze-dark/dark_document-open.svg +Breeze-dark/dark_document-print-preview.svg +Breeze-dark/dark_document-print.svg +Breeze-dark/dark_document-save-as.svg Breeze-dark/dark_document-save.svg Breeze-dark/dark_download.svg Breeze-dark/dark_draw-eraser.svg Breeze-dark/dark_drive-harddisk.svg Breeze-dark/dark_edit-clear.svg Breeze-dark/dark_edit-copy.svg Breeze-dark/dark_edit-cut.svg Breeze-dark/dark_edit-delete.svg Breeze-dark/dark_edit-paste.svg Breeze-dark/dark_edit-redo.svg Breeze-dark/dark_edit-undo.svg Breeze-dark/dark_folder-documents.svg Breeze-dark/dark_folder-pictures.svg Breeze-dark/dark_folder.svg Breeze-dark/dark_format-list-unordered.svg Breeze-dark/dark_go-home.svg +Breeze-dark/dark_help-contents.svg Breeze-dark/dark_im-user.svg +Breeze-dark/dark_kde.svg Breeze-dark/dark_layer-visible-off.svg Breeze-dark/dark_link.svg Breeze-dark/dark_list-add.svg Breeze-dark/dark_locked.svg Breeze-dark/dark_media-playback-start.svg Breeze-dark/dark_media-playback-stop.svg Breeze-dark/dark_media-record.svg +Breeze-dark/dark_object-locked.svg Breeze-dark/dark_object-rotate-left.svg Breeze-dark/dark_object-rotate-right.svg +Breeze-dark/dark_object-unlocked.svg Breeze-dark/dark_preferences-desktop-color.svg Breeze-dark/dark_preferences-desktop-display.svg +Breeze-dark/dark_preferences-desktop-locale.svg Breeze-dark/dark_process-stop.svg Breeze-dark/dark_select-all.svg Breeze-dark/dark_select-clear.svg Breeze-dark/dark_system-help.svg +Breeze-dark/dark_tools-report-bug.svg Breeze-dark/dark_tools-wizard.svg Breeze-dark/dark_unlocked.svg Breeze-dark/dark_view-choose.svg Breeze-dark/dark_view-filter.svg +Breeze-dark/dark_view-fullscreen.svg Breeze-dark/dark_view-grid.svg Breeze-dark/dark_view-list-details.svg Breeze-dark/dark_view-list-text.svg Breeze-dark/dark_view-preview.svg Breeze-dark/dark_view-refresh.svg Breeze-dark/dark_window-close.svg Breeze-dark/dark_window-new.svg Breeze-dark/dark_zoom-in.svg Breeze-dark/dark_zoom-original.svg Breeze-dark/dark_zoom-out.svg - +Breeze-light/light_application-exit.svg Breeze-light/light_application-pdf.svg Breeze-light/light_applications-system.svg Breeze-light/light_arrow-down.svg Breeze-light/light_arrow-left.svg Breeze-light/light_arrow-right.svg Breeze-light/light_arrow-up.svg Breeze-light/light_bookmarks.svg +Breeze-light/light_configure-shortcuts.svg +Breeze-light/light_configure-toolbars.svg Breeze-light/light_configure.svg +Breeze-light/light_dialog-cancel.svg +Breeze-light/light_dialog-close.svg +Breeze-light/light_dialog-ok.svg Breeze-light/light_dialog-warning.svg Breeze-light/light_document-edit.svg Breeze-light/light_document-export.svg Breeze-light/light_document-import.svg Breeze-light/light_document-new.svg +Breeze-light/light_document-open-recent.svg Breeze-light/light_document-open.svg +Breeze-light/light_document-print-preview.svg +Breeze-light/light_document-print.svg +Breeze-light/light_document-save-as.svg Breeze-light/light_document-save.svg Breeze-light/light_download.svg Breeze-light/light_draw-eraser.svg Breeze-light/light_drive-harddisk.svg Breeze-light/light_edit-clear.svg Breeze-light/light_edit-copy.svg Breeze-light/light_edit-cut.svg Breeze-light/light_edit-delete.svg Breeze-light/light_edit-paste.svg Breeze-light/light_edit-redo.svg Breeze-light/light_edit-undo.svg Breeze-light/light_folder-documents.svg Breeze-light/light_folder-pictures.svg Breeze-light/light_folder.svg Breeze-light/light_format-list-unordered.svg Breeze-light/light_go-home.svg +Breeze-light/light_help-contents.svg Breeze-light/light_im-user.svg +Breeze-light/light_kde.svg Breeze-light/light_layer-visible-off.svg Breeze-light/light_link.svg Breeze-light/light_list-add.svg Breeze-light/light_locked.svg Breeze-light/light_media-playback-start.svg Breeze-light/light_media-playback-stop.svg Breeze-light/light_media-record.svg +Breeze-light/light_object-locked.svg Breeze-light/light_object-rotate-left.svg Breeze-light/light_object-rotate-right.svg +Breeze-light/light_object-unlocked.svg Breeze-light/light_preferences-desktop-color.svg Breeze-light/light_preferences-desktop-display.svg +Breeze-light/light_preferences-desktop-locale.svg Breeze-light/light_process-stop.svg Breeze-light/light_select-all.svg Breeze-light/light_select-clear.svg Breeze-light/light_system-help.svg +Breeze-light/light_tools-report-bug.svg Breeze-light/light_tools-wizard.svg Breeze-light/light_unlocked.svg Breeze-light/light_view-choose.svg Breeze-light/light_view-filter.svg +Breeze-light/light_view-fullscreen.svg Breeze-light/light_view-grid.svg Breeze-light/light_view-list-details.svg Breeze-light/light_view-list-text.svg Breeze-light/light_view-preview.svg Breeze-light/light_view-refresh.svg Breeze-light/light_window-close.svg Breeze-light/light_window-new.svg Breeze-light/light_zoom-in.svg Breeze-light/light_zoom-original.svg Breeze-light/light_zoom-out.svg DESTINATION ${DATA_INSTALL_DIR}/krita/pics) add_subdirectory(app) diff --git a/krita/pics/dark_symmetry-horizontal.png b/krita/pics/dark_symmetry-horizontal.png deleted file mode 100644 index 553ff77fdef..00000000000 Binary files a/krita/pics/dark_symmetry-horizontal.png and /dev/null differ diff --git a/krita/pics/dark_symmetry-vertical.png b/krita/pics/dark_symmetry-vertical.png deleted file mode 100644 index 7524437b1c7..00000000000 Binary files a/krita/pics/dark_symmetry-vertical.png and /dev/null differ diff --git a/krita/pics/landscape.png b/krita/pics/landscape.png index 389ecacb9bb..01a517c2f37 100644 Binary files a/krita/pics/landscape.png and b/krita/pics/landscape.png differ diff --git a/krita/pics/light_symmetry-horizontal.png b/krita/pics/light_symmetry-horizontal.png deleted file mode 100644 index 4f946fd71f7..00000000000 Binary files a/krita/pics/light_symmetry-horizontal.png and /dev/null differ diff --git a/krita/pics/light_symmetry-vertical.png b/krita/pics/light_symmetry-vertical.png deleted file mode 100644 index 6e7a2b177d7..00000000000 Binary files a/krita/pics/light_symmetry-vertical.png and /dev/null differ diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg new file mode 100644 index 00000000000..b86fca58f51 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-center-calligra.svg @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg new file mode 100644 index 00000000000..be7607060e5 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-left-calligra.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg new file mode 100644 index 00000000000..0cccb03e0d7 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-horizontal-right-calligra.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg new file mode 100644 index 00000000000..7730a3cf4c7 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-bottom-calligra.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg new file mode 100644 index 00000000000..4c1dc3ca148 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-center-calligra.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg new file mode 100644 index 00000000000..adcdad9f7db --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-align-vertical-top-calligra.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-group-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-group-calligra.svg new file mode 100644 index 00000000000..5bef54f271a --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-group-calligra.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-order-back-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-order-back-calligra.svg new file mode 100644 index 00000000000..46bdc695736 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-order-back-calligra.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-order-front-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-order-front-calligra.svg new file mode 100644 index 00000000000..7b20dcf4da6 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-order-front-calligra.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-order-lower-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-order-lower-calligra.svg new file mode 100644 index 00000000000..ec9bcd2caf4 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-order-lower-calligra.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-order-raise-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-order-raise-calligra.svg new file mode 100644 index 00000000000..b446ecad1b7 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-order-raise-calligra.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_ox16-action-object-ungroup-calligra.svg b/krita/pics/misc-dark/dark_ox16-action-object-ungroup-calligra.svg new file mode 100644 index 00000000000..2dc4b19bca2 --- /dev/null +++ b/krita/pics/misc-dark/dark_ox16-action-object-ungroup-calligra.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_paintop_settings_01.svg b/krita/pics/misc-dark/dark_paintop_settings_01.svg new file mode 100644 index 00000000000..db59775aaf9 --- /dev/null +++ b/krita/pics/misc-dark/dark_paintop_settings_01.svg @@ -0,0 +1,361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_paintop_settings_02.svg b/krita/pics/misc-dark/dark_paintop_settings_02.svg new file mode 100644 index 00000000000..fc0bbde233b --- /dev/null +++ b/krita/pics/misc-dark/dark_paintop_settings_02.svg @@ -0,0 +1,280 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-cap-butt.svg b/krita/pics/misc-dark/dark_stroke-cap-butt.svg new file mode 100644 index 00000000000..fa3455115bc --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-cap-butt.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-cap-round.svg b/krita/pics/misc-dark/dark_stroke-cap-round.svg new file mode 100644 index 00000000000..31286698467 --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-cap-round.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-cap-square.svg b/krita/pics/misc-dark/dark_stroke-cap-square.svg new file mode 100644 index 00000000000..6400868b55d --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-cap-square.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-join-bevel.svg b/krita/pics/misc-dark/dark_stroke-join-bevel.svg new file mode 100644 index 00000000000..30b632e1f7e --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-join-bevel.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-join-miter.svg b/krita/pics/misc-dark/dark_stroke-join-miter.svg new file mode 100644 index 00000000000..b18d26a977f --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-join-miter.svg @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_stroke-join-round.svg b/krita/pics/misc-dark/dark_stroke-join-round.svg new file mode 100644 index 00000000000..ca25e688ac3 --- /dev/null +++ b/krita/pics/misc-dark/dark_stroke-join-round.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_symmetry-horizontal.svg b/krita/pics/misc-dark/dark_symmetry-horizontal.svg new file mode 100644 index 00000000000..bd9157fa31e --- /dev/null +++ b/krita/pics/misc-dark/dark_symmetry-horizontal.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-dark/dark_symmetry-vertical.svg b/krita/pics/misc-dark/dark_symmetry-vertical.svg new file mode 100644 index 00000000000..bf6b633f6e0 --- /dev/null +++ b/krita/pics/misc-dark/dark_symmetry-vertical.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg new file mode 100644 index 00000000000..9b0d93470d1 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-center-calligra.svg @@ -0,0 +1,174 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg new file mode 100644 index 00000000000..3371a182d08 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-left-calligra.svg @@ -0,0 +1,168 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg new file mode 100644 index 00000000000..fca09332413 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-horizontal-right-calligra.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg new file mode 100644 index 00000000000..85ef44d1438 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-vertical-bottom-calligra.svg @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-vertical-center-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-vertical-center-calligra.svg new file mode 100644 index 00000000000..e104ea30e8d --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-vertical-center-calligra.svg @@ -0,0 +1,175 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-align-vertical-top-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-align-vertical-top-calligra.svg new file mode 100644 index 00000000000..e6bb1c2f26a --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-align-vertical-top-calligra.svg @@ -0,0 +1,169 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-group-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-group-calligra.svg new file mode 100644 index 00000000000..d8a9a22ae44 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-group-calligra.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-order-back-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-order-back-calligra.svg new file mode 100644 index 00000000000..a66667d355a --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-order-back-calligra.svg @@ -0,0 +1,171 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-order-front-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-order-front-calligra.svg new file mode 100644 index 00000000000..9351ae1894a --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-order-front-calligra.svg @@ -0,0 +1,166 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-order-lower-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-order-lower-calligra.svg new file mode 100644 index 00000000000..d63051f054a --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-order-lower-calligra.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-order-raise-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-order-raise-calligra.svg new file mode 100644 index 00000000000..f506d7594ac --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-order-raise-calligra.svg @@ -0,0 +1,160 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + diff --git a/krita/pics/misc-light/light_ox16-action-object-ungroup-calligra.svg b/krita/pics/misc-light/light_ox16-action-object-ungroup-calligra.svg new file mode 100644 index 00000000000..2dcd2c6d288 --- /dev/null +++ b/krita/pics/misc-light/light_ox16-action-object-ungroup-calligra.svg @@ -0,0 +1,173 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_paintop_settings_01.svg b/krita/pics/misc-light/light_paintop_settings_01.svg new file mode 100644 index 00000000000..6225cb21d5b --- /dev/null +++ b/krita/pics/misc-light/light_paintop_settings_01.svg @@ -0,0 +1,361 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_paintop_settings_02.svg b/krita/pics/misc-light/light_paintop_settings_02.svg new file mode 100644 index 00000000000..c66e3b2fce0 --- /dev/null +++ b/krita/pics/misc-light/light_paintop_settings_02.svg @@ -0,0 +1,285 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-cap-butt.svg b/krita/pics/misc-light/light_stroke-cap-butt.svg new file mode 100644 index 00000000000..f15a9876408 --- /dev/null +++ b/krita/pics/misc-light/light_stroke-cap-butt.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-cap-round.svg b/krita/pics/misc-light/light_stroke-cap-round.svg new file mode 100644 index 00000000000..d0762322eab --- /dev/null +++ b/krita/pics/misc-light/light_stroke-cap-round.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-cap-square.svg b/krita/pics/misc-light/light_stroke-cap-square.svg new file mode 100644 index 00000000000..5c623b52710 --- /dev/null +++ b/krita/pics/misc-light/light_stroke-cap-square.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-join-bevel.svg b/krita/pics/misc-light/light_stroke-join-bevel.svg new file mode 100644 index 00000000000..e6a758a3209 --- /dev/null +++ b/krita/pics/misc-light/light_stroke-join-bevel.svg @@ -0,0 +1,191 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-join-miter.svg b/krita/pics/misc-light/light_stroke-join-miter.svg new file mode 100644 index 00000000000..c3b74c38d7f --- /dev/null +++ b/krita/pics/misc-light/light_stroke-join-miter.svg @@ -0,0 +1,209 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_stroke-join-round.svg b/krita/pics/misc-light/light_stroke-join-round.svg new file mode 100644 index 00000000000..bc13deb55cd --- /dev/null +++ b/krita/pics/misc-light/light_stroke-join-round.svg @@ -0,0 +1,208 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_symmetry-horizontal.svg b/krita/pics/misc-light/light_symmetry-horizontal.svg new file mode 100644 index 00000000000..ee4b8ed5cb0 --- /dev/null +++ b/krita/pics/misc-light/light_symmetry-horizontal.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/misc-light/light_symmetry-vertical.svg b/krita/pics/misc-light/light_symmetry-vertical.svg new file mode 100644 index 00000000000..a95032142a0 --- /dev/null +++ b/krita/pics/misc-light/light_symmetry-vertical.svg @@ -0,0 +1,231 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + Andrei Rudenko + + + + + + + + + + diff --git a/krita/pics/paintop_presets_disabled.png b/krita/pics/paintop_presets_disabled.png deleted file mode 100644 index 8262c1126d6..00000000000 Binary files a/krita/pics/paintop_presets_disabled.png and /dev/null differ diff --git a/krita/pics/paintop_settings_01.png b/krita/pics/paintop_settings_01.png deleted file mode 100644 index 13db91b88a9..00000000000 Binary files a/krita/pics/paintop_settings_01.png and /dev/null differ diff --git a/krita/pics/paintop_settings_02.png b/krita/pics/paintop_settings_02.png deleted file mode 100644 index 427e7ed69dc..00000000000 Binary files a/krita/pics/paintop_settings_02.png and /dev/null differ diff --git a/krita/pics/paintop_settings_disabled.png b/krita/pics/paintop_settings_disabled.png deleted file mode 100644 index fe6a5b4ffb1..00000000000 Binary files a/krita/pics/paintop_settings_disabled.png and /dev/null differ diff --git a/krita/pics/portrait.png b/krita/pics/portrait.png index 043711748ae..b7af3758559 100644 Binary files a/krita/pics/portrait.png and b/krita/pics/portrait.png differ diff --git a/krita/pics/svg/symmetry-horyzontal.svg b/krita/pics/svg/symmetry-horyzontal.svg deleted file mode 100644 index b36cce77f9d..00000000000 --- a/krita/pics/svg/symmetry-horyzontal.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/krita/pics/svg/symmetry-vertical.svg b/krita/pics/svg/symmetry-vertical.svg deleted file mode 100644 index 8b9cada4268..00000000000 --- a/krita/pics/svg/symmetry-vertical.svg +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - - - - - - - image/svg+xml - - - - - - - - - - diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_acs_pixel_cache_renderer.h b/krita/plugins/extensions/dockers/advancedcolorselector/kis_acs_pixel_cache_renderer.h index 8615c6dda9f..3b061e5faf5 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_acs_pixel_cache_renderer.h +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_acs_pixel_cache_renderer.h @@ -1,65 +1,68 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ACS_PIXEL_CACHE_RENDERER_H #define __KIS_ACS_PIXEL_CACHE_RENDERER_H #include "KoColorSpace.h" #include "kis_paint_device.h" #include "kis_iterator_ng.h" #include "kis_display_color_converter.h" namespace Acs { class PixelCacheRenderer { public: /** * \p Picker class must provide one method: * - KoColor Picker::colorAt(int x, int y); */ template static void render(Picker *picker, const KisDisplayColorConverter *converter, const QRect &pickRect, KisPaintDeviceSP &realPixelCache, QImage &pixelCache, QPoint &pixelCacheOffset) { const KoColorSpace *cacheColorSpace = converter->paintingColorSpace(); const int pixelSize = cacheColorSpace->pixelSize(); - realPixelCache = new KisPaintDevice(cacheColorSpace); + + if (!realPixelCache || realPixelCache->colorSpace() != cacheColorSpace) { + realPixelCache = new KisPaintDevice(cacheColorSpace); + } KoColor color; KisSequentialIterator it(realPixelCache, pickRect); do { color = picker->colorAt(it.x(), it.y()); memcpy(it.rawData(), color.data(), pixelSize); } while (it.nextPixel()); // NOTE: toQImage() function of the converter copies exactBounds() only! pixelCache = converter->toQImage(realPixelCache); pixelCacheOffset = realPixelCache->exactBounds().topLeft() - pickRect.topLeft(); - } + } }; } #endif /* __KIS_ACS_PIXEL_CACHE_RENDERER_H */ diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.cpp b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.cpp index dad502d70fb..2e88e91f346 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.cpp +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.cpp @@ -1,469 +1,475 @@ /* * Copyright (c) 2010 Adam Celarek * * 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 */ #include "kis_color_selector_base.h" #include #include #include #include #include #include #include #include #include #include #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "kis_canvas2.h" #include "kis_canvas_resource_provider.h" #include "kis_node.h" #include "KisViewManager.h" #include #include "kis_image.h" #include "kis_display_color_converter.h" class KisColorPreviewPopup : public QWidget { public: KisColorPreviewPopup(KisColorSelectorBase* parent) : QWidget(), m_parent(parent) { setWindowFlags(Qt::ToolTip); setQColor(QColor(0,0,0)); setMouseTracking(true); } void show() { updatePosition(); QWidget::show(); } void updatePosition() { QPoint parentPos = m_parent->mapToGlobal(QPoint(0,0)); QRect availRect = QApplication::desktop()->availableGeometry(this); QPoint targetPos; if ( parentPos.x() - 100 > availRect.x() ) { targetPos = QPoint(parentPos.x() - 100, parentPos.y()); } else if ( parentPos.x() + m_parent->width() + 100 < availRect.right()) { targetPos = m_parent->mapToGlobal(QPoint(m_parent->width(), 0)); } else if ( parentPos.y() - 100 > availRect.y() ) { targetPos = QPoint(parentPos.x(), parentPos.y() - 100); } else { targetPos = QPoint(parentPos.x(), parentPos.y() + m_parent->height()); } setGeometry(targetPos.x(), targetPos.y(), 100, 100); } void setQColor(const QColor& color) { m_color = color; update(); } protected: void paintEvent(QPaintEvent *e) { Q_UNUSED(e); QPainter p(this); p.fillRect(0,0, width(), width(), m_color); } private: KisColorSelectorBase* m_parent; QColor m_color; }; KisColorSelectorBase::KisColorSelectorBase(QWidget *parent) : QWidget(parent), m_canvas(0), m_popup(0), m_parent(0), m_colorUpdateAllowed(true), m_colorUpdateSelf(false), m_hideTimer(new QTimer(this)), m_popupOnMouseOver(false), m_popupOnMouseClick(true), m_colorSpace(0), m_isPopup(false), m_hideOnMouseClick(false), m_colorPreviewPopup(new KisColorPreviewPopup(this)) { m_hideTimer->setInterval(0); m_hideTimer->setSingleShot(true); connect(m_hideTimer, SIGNAL(timeout()), this, SLOT(hidePopup())); } KisColorSelectorBase::~KisColorSelectorBase() { delete m_colorPreviewPopup; } void KisColorSelectorBase::setPopupBehaviour(bool onMouseOver, bool onMouseClick) { m_popupOnMouseClick = onMouseClick; m_popupOnMouseOver = onMouseOver; if(onMouseClick) { m_popupOnMouseOver = false; } if(m_popupOnMouseOver) { setMouseTracking(true); } } void KisColorSelectorBase::setColorSpace(const KoColorSpace *colorSpace) { m_colorSpace = colorSpace; } void KisColorSelectorBase::setCanvas(KisCanvas2 *canvas) { if (m_canvas) { m_canvas->disconnectCanvasObserver(this); } m_canvas = canvas; if (m_canvas) { connect(m_canvas->resourceManager(), SIGNAL(canvasResourceChanged(int, const QVariant&)), SLOT(canvasResourceChanged(int, const QVariant&)), Qt::UniqueConnection); connect(m_canvas->displayColorConverter(), SIGNAL(displayConfigurationChanged()), SLOT(reset())); if (m_canvas->viewManager() && m_canvas->viewManager()->resourceProvider()) { setColor(Acs::currentColor(m_canvas->viewManager()->resourceProvider(), Acs::Foreground)); } } if (m_popup) { m_popup->setCanvas(canvas); } reset(); } void KisColorSelectorBase::unsetCanvas() { if (m_popup) { m_popup->unsetCanvas(); } m_canvas = 0; } void KisColorSelectorBase::mousePressEvent(QMouseEvent* event) { event->accept(); //this boolean here is to check if the colour selector is updating the resource, so it won't update itself when the resource is updated// if (m_colorUpdateSelf==false) {m_colorUpdateSelf=true;} if(!m_isPopup && m_popupOnMouseClick && event->button() == Qt::MidButton) { lazyCreatePopup(); int x = event->globalX(); int y = event->globalY(); int popupsize = m_popup->width(); x-=popupsize/2; y-=popupsize/2; QRect availRect = QApplication::desktop()->availableGeometry(this); if(xwidth()>availRect.x()+availRect.width()) x = availRect.x()+availRect.width()-m_popup->width(); if(y+m_popup->height()>availRect.y()+availRect.height()) y = availRect.y()+availRect.height()-m_popup->height(); m_popup->move(x, y); m_popup->setHidingTime(200); showPopup(DontMove); } else if (m_isPopup && event->button() == Qt::MidButton) { hide(); } else { showColorPreview(); event->ignore(); } } void KisColorSelectorBase::mouseReleaseEvent(QMouseEvent *e) { Q_UNUSED(e); if (e->button() == Qt::MidButton) { e->accept(); } else if (m_isPopup && m_hideOnMouseClick==true && !m_hideTimer->isActive()) { showColorPreview(); hide(); } } void KisColorSelectorBase::enterEvent(QEvent *e) { Q_UNUSED(e); if (m_popup && m_popup->isVisible()) { m_popup->m_hideTimer->stop(); } if (m_isPopup && m_hideTimer->isActive()) { m_hideTimer->stop(); } // do not show the popup when boxed in // the configuration dialog (m_canvas == 0) if (m_canvas && !m_isPopup && m_popupOnMouseOver && (!m_popup || m_popup->isHidden())) { lazyCreatePopup(); QRect availRect = QApplication::desktop()->availableGeometry(this); QRect forbiddenRect = QRect(parentWidget()->mapToGlobal(QPoint(0,0)), QSize(parentWidget()->width(), parentWidget()->height())); int x,y; if(forbiddenRect.y()+forbiddenRect.height()/2 > availRect.height()/2) { //popup above forbiddenRect y = forbiddenRect.y()-m_popup->height(); } else { //popup below forbiddenRect y = forbiddenRect.y()+forbiddenRect.height(); } if(forbiddenRect.x()+forbiddenRect.width()/2 < availRect.width()/2) { //left edge of popup justified with left edge of popup x = forbiddenRect.x(); } else { //the other way round x = forbiddenRect.x()+forbiddenRect.width()-m_popup->width(); } m_popup->move(x, y); m_popup->setHidingTime(200); showPopup(DontMove); } } void KisColorSelectorBase::leaveEvent(QEvent *e) { Q_UNUSED(e); if (m_colorPreviewPopup->isVisible()) { m_colorUpdateSelf=false; //this is for allowing advanced selector to listen to outside colour-change events. m_colorPreviewPopup->hide(); } if (m_popup && m_popup->isVisible()) { m_popup->m_hideTimer->start(); } if (m_isPopup && !m_hideTimer->isActive()) { m_hideTimer->start(); } } void KisColorSelectorBase::keyPressEvent(QKeyEvent *) { if (m_isPopup) { hidePopup(); } } void KisColorSelectorBase::dragEnterEvent(QDragEnterEvent *e) { if(e->mimeData()->hasColor()) e->acceptProposedAction(); if(e->mimeData()->hasText() && QColor(e->mimeData()->text()).isValid()) e->acceptProposedAction(); } void KisColorSelectorBase::dropEvent(QDropEvent *e) { QColor color; if(e->mimeData()->hasColor()) { color = qvariant_cast(e->mimeData()->colorData()); } else if(e->mimeData()->hasText()) { color.setNamedColor(e->mimeData()->text()); if(!color.isValid()) return; } KoColor kocolor(color , KoColorSpaceRegistry::instance()->rgb8()); updateColor(kocolor, Acs::Foreground, true); } void KisColorSelectorBase::updateColor(const KoColor &color, Acs::ColorRole role, bool needsExplicitColorReset) { commitColor(color, role); if (needsExplicitColorReset) { setColor(color); } } void KisColorSelectorBase::setColor(const KoColor& color) { Q_UNUSED(color); } void KisColorSelectorBase::setHidingTime(int time) { KIS_ASSERT_RECOVER_NOOP(m_isPopup); m_hideTimer->setInterval(time); } void KisColorSelectorBase::lazyCreatePopup() { if (!m_popup) { m_popup = createPopup(); Q_ASSERT(m_popup); m_popup->setWindowFlags(Qt::FramelessWindowHint|Qt::SubWindow|Qt::X11BypassWindowManagerHint); m_popup->m_parent = this; m_popup->m_isPopup=true; } m_popup->setCanvas(m_canvas); m_popup->updateSettings(); } void KisColorSelectorBase::showPopup(Move move) { // This slot may be called by some action, // so we need to be able to handle it lazyCreatePopup(); QPoint cursorPos = QCursor::pos(); if (move == MoveToMousePosition) { m_popup->move(cursorPos.x()-m_popup->width()/2, cursorPos.y()-m_popup->height()/2); QRect rc = m_popup->geometry(); if (rc.x() < 0) rc.setX(0); if (rc.y() < 0) rc.setY(0); m_popup->setGeometry(rc); } m_popup->show(); m_popup->m_colorPreviewPopup->show(); } void KisColorSelectorBase::hidePopup() { KIS_ASSERT_RECOVER_RETURN(m_isPopup); m_colorPreviewPopup->hide(); hide(); } void KisColorSelectorBase::commitColor(const KoColor& color, Acs::ColorRole role) { if (!m_canvas) return; m_colorUpdateAllowed=false; if (role == Acs::Foreground) m_canvas->resourceManager()->setForegroundColor(color); else m_canvas->resourceManager()->setBackgroundColor(color); m_colorUpdateAllowed=true; } void KisColorSelectorBase::showColorPreview() { if(m_colorPreviewPopup->isHidden()) { m_colorPreviewPopup->show(); } } void KisColorSelectorBase::updateColorPreview(const KoColor &color) { m_colorPreviewPopup->setQColor(converter()->toQColor(color)); } void KisColorSelectorBase::canvasResourceChanged(int key, const QVariant &v) { if (key == KoCanvasResourceManager::ForegroundColor || key == KoCanvasResourceManager::BackgroundColor) { KoColor realColor(v.value()); updateColorPreview(realColor); if (m_colorUpdateAllowed && !m_colorUpdateSelf) { setColor(realColor); } } } const KoColorSpace* KisColorSelectorBase::colorSpace() const { return converter()->paintingColorSpace(); } void KisColorSelectorBase::updateSettings() { if(m_popup) { m_popup->updateSettings(); } KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); int zoomSelectorOptions = (int) cfg.readEntry("zoomSelectorOptions", 0) ; if (zoomSelectorOptions == 0) { setPopupBehaviour(false, true); // middle mouse button click will open zoom selector } else if (zoomSelectorOptions == 1) { setPopupBehaviour(true, false); // move over will open the zoom selector } else { setPopupBehaviour(false, false); // do not show zoom selector } if(m_isPopup) { m_hideOnMouseClick = cfg.readEntry("hidePopupOnClickCheck", false); resize(cfg.readEntry("zoomSize", 280), cfg.readEntry("zoomSize", 280)); } reset(); } void KisColorSelectorBase::reset() { update(); } KisDisplayColorConverter* KisColorSelectorBase::converter() const { return m_canvas ? m_canvas->displayColorConverter() : KisDisplayColorConverter::dumbConverterInstance(); } + + +void KisColorSelectorBase::mouseMoveEvent(QMouseEvent *event) +{ + event->accept(); +} diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.h b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.h index e8f882749c5..062ca2804e9 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.h +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_base.h @@ -1,113 +1,114 @@ /* * Copyright (c) 2010 Adam Celarek * * 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 */ #ifndef KIS_COLOR_SELECTOR_BASE_H #define KIS_COLOR_SELECTOR_BASE_H #include #include #include #include #include "kis_acs_types.h" class KoColor; class QTimer; class KoColorSpace; class KisCanvas2; class KisColorPreviewPopup; class KisDisplayColorConverter; /// Base class for all color selectors, that should support color management and zooming. class KisColorSelectorBase : public QWidget { Q_OBJECT public: enum Move {MoveToMousePosition, DontMove}; explicit KisColorSelectorBase(QWidget *parent = 0); ~KisColorSelectorBase(); void setPopupBehaviour(bool onMouseOver, bool onMouseClick); void setColorSpace(const KoColorSpace* colorSpace); virtual void setCanvas(KisCanvas2* canvas); virtual void unsetCanvas(); const KoColorSpace* colorSpace() const; KisDisplayColorConverter* converter() const; public: void updateColor(const KoColor &color, Acs::ColorRole role, bool needsExplicitColorReset); void updateColorPreview(const KoColor &color); void showColorPreview(); virtual void setColor(const KoColor& color); public Q_SLOTS: /** * Flushes caches and redraws the selectors */ virtual void reset(); virtual void updateSettings(); virtual void showPopup(Move move=MoveToMousePosition); public: void enterEvent(QEvent *e); void leaveEvent(QEvent *e); void mousePressEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); protected: void keyPressEvent(QKeyEvent *); virtual KisColorSelectorBase* createPopup() const = 0; void dragEnterEvent(QDragEnterEvent *); void dropEvent(QDropEvent *); void setHidingTime(int time); bool isPopup() const { return m_isPopup; } + void mouseMoveEvent(QMouseEvent *event); private: void commitColor(const KoColor& koColor, Acs::ColorRole role); protected Q_SLOTS: void hidePopup(); /// if you overwrite this, keep in mind, that you should set the colour only, if m_colorUpdateAllowed is true virtual void canvasResourceChanged(int key, const QVariant& v); private: void lazyCreatePopup(); protected: QPointer m_canvas; KisColorSelectorBase* m_popup; QWidget* m_parent; bool m_colorUpdateAllowed; bool m_colorUpdateSelf; private: QTimer* m_hideTimer; bool m_popupOnMouseOver; bool m_popupOnMouseClick; mutable const KoColorSpace* m_colorSpace; bool m_isPopup; //this instance is a popup bool m_hideOnMouseClick; KisColorPreviewPopup* m_colorPreviewPopup; }; #endif diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_settings.cpp b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_settings.cpp index 01f6c17bdc4..23035daf401 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_settings.cpp +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_color_selector_settings.cpp @@ -1,607 +1,607 @@ /* * Copyright (C) 2010 Celarek Adam * * 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_color_selector_settings.h" #include "ui_wdg_color_selector_settings.h" #include #include #include #include #include #include #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColorProfile.h" #include "kis_color_selector_combo_box.h" #include "kis_color_selector.h" #include "kis_config.h" KisColorSelectorSettings::KisColorSelectorSettings(QWidget *parent) : KisPreferenceSet(parent), ui(new Ui::KisColorSelectorSettings) { ui->setupUi(this); ui->lbl_lastUsedNumRows->hide(); ui->lastUsedColorsNumRows->hide(); ui->lbl_commonColorsNumCols->hide(); ui->commonColorsNumCols->hide(); resize(minimumSize()); ui->colorSelectorConfiguration->setColorSpace(ui->colorSpace->currentColorSpace()); ui->useDifferentColorSpaceCheckbox->setChecked(false); connect(ui->useDifferentColorSpaceCheckbox, SIGNAL(clicked(bool)), this, SLOT(useDifferentColorSpaceChecked(bool))); /* color docker selector drop down */ ui->dockerColorSettingsComboBox->addItem(i18n("Advanced Color Selector")); ui->dockerColorSettingsComboBox->addItem(i18n("Color Sliders")); ui->dockerColorSettingsComboBox->setCurrentIndex(0); // start off seeing advanced color selector properties connect( ui->dockerColorSettingsComboBox, SIGNAL(currentIndexChanged(int)),this, SLOT(changedColorDocker(int))); changedColorDocker(0); /* advanced color docker options */ ui->dockerResizeOptionsComboBox->addItem(i18n("Change to a Horizontal Layout")); ui->dockerResizeOptionsComboBox->addItem(i18n("Hide Shade Selector")); ui->dockerResizeOptionsComboBox->addItem(i18n("Do Nothing")); ui->dockerResizeOptionsComboBox->setCurrentIndex(0); ui->zoomSelectorOptionComboBox->addItem(i18n("When Pressing Middle Mouse Button")); ui->zoomSelectorOptionComboBox->addItem(i18n("On Mouse Over")); ui->zoomSelectorOptionComboBox->addItem(i18n("Never")); ui->zoomSelectorOptionComboBox->setCurrentIndex(0); ui->colorSelectorTypeComboBox->addItem(i18n("HSV")); ui->colorSelectorTypeComboBox->addItem(i18n("HSL")); ui->colorSelectorTypeComboBox->addItem(i18n("HSI")); ui->colorSelectorTypeComboBox->addItem(i18n("HSY'")); ui->colorSelectorTypeComboBox->setCurrentIndex(0); connect( ui->colorSelectorTypeComboBox, SIGNAL(currentIndexChanged(int)),this, SLOT(changedACSColorSelectorType(int))); changedACSColorSelectorType(0); // initialize everything to HSV at the start ui->ACSshadeSelectorMyPaintColorModelComboBox->addItem(i18n("HSV")); ui->ACSshadeSelectorMyPaintColorModelComboBox->addItem(i18n("HSL")); ui->ACSshadeSelectorMyPaintColorModelComboBox->addItem(i18n("HSI")); ui->ACSshadeSelectorMyPaintColorModelComboBox->addItem(i18n("HSY'")); ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(0); ui->ACSShadeSelectorTypeComboBox->addItem(i18n("MyPaint")); ui->ACSShadeSelectorTypeComboBox->addItem(i18n("Minimal")); ui->ACSShadeSelectorTypeComboBox->addItem(i18n("Do Not Show")); ui->ACSShadeSelectorTypeComboBox->setCurrentIndex(0); changedACSShadeSelectorType(0); // show/hide UI elements for MyPaint settings connect( ui->ACSShadeSelectorTypeComboBox, SIGNAL(currentIndexChanged(int)),this, SLOT(changedACSShadeSelectorType(int))); ui->commonColorsAlignVertical->setChecked(true); ui->commonColorsAlignHorizontal->setChecked(true); connect( ui->commonColorsAlignHorizontal, SIGNAL(toggled(bool)), this, SLOT(changedACSColorAlignment(bool))); connect(ui->colorSpace, SIGNAL(colorSpaceChanged(const KoColorSpace*)), ui->colorSelectorConfiguration, SLOT(setColorSpace(const KoColorSpace*))); connect(this, SIGNAL(hsxchanged(int)), ui->colorSelectorConfiguration, SLOT(setList(int))); connect(ui->minimalShadeSelectorLineCount, SIGNAL(valueChanged(int)), ui->minimalShadeSelectorLineSettings, SLOT(setLineCount(int))); connect(ui->minimalShadeSelectorLineSettings, SIGNAL(lineCountChanged(int)), ui->minimalShadeSelectorLineCount, SLOT(setValue(int))); connect(ui->minimalShadeSelectorAsGradient, SIGNAL(toggled(bool)), ui->minimalShadeSelectorLineSettings, SIGNAL(setGradient(bool))); connect(ui->minimalShadeSelectorAsColorPatches, SIGNAL(toggled(bool)), ui->minimalShadeSelectorLineSettings, SIGNAL(setPatches(bool))); connect(ui->minimalShadeSelectorLineHeight, SIGNAL(valueChanged(int)), ui->minimalShadeSelectorLineSettings, SIGNAL(setLineHeight(int))); connect(ui->minimalShadeSelectorPatchesPerLine, SIGNAL(valueChanged(int)), ui->minimalShadeSelectorLineSettings, SIGNAL(setPatchCount(int))); } KisColorSelectorSettings::~KisColorSelectorSettings() { delete ui; } QString KisColorSelectorSettings::id() { return QString("advancedColorSelector"); } QString KisColorSelectorSettings::name() { return header(); } QString KisColorSelectorSettings::header() { return QString(i18n("Color Selector Settings")); } KIcon KisColorSelectorSettings::icon() { return koIcon("extended_color_selector"); } void KisColorSelectorSettings::savePreferences() const { // write cfg KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); KConfigGroup hsxcfg = KGlobal::config()->group("hsxColorSlider"); // advanced color selector cfg.writeEntry("onDockerResize", ui->dockerResizeOptionsComboBox->currentIndex()); cfg.writeEntry("zoomSelectorOptions", ui->zoomSelectorOptionComboBox->currentIndex() ); cfg.writeEntry("zoomSize", ui->popupSize->value()); bool useCustomColorSpace = ui->useDifferentColorSpaceCheckbox->isChecked(); const KoColorSpace* colorSpace = useCustomColorSpace ? ui->colorSpace->currentColorSpace() : 0; KisConfig kisconfig; kisconfig.setCustomColorSelectorColorSpace(colorSpace); //color patches cfg.writeEntry("lastUsedColorsShow", ui->lastUsedColorsShow->isChecked()); cfg.writeEntry("lastUsedColorsAlignment", ui->lastUsedColorsAlignVertical->isChecked()); cfg.writeEntry("lastUsedColorsScrolling", ui->lastUsedColorsAllowScrolling->isChecked()); cfg.writeEntry("lastUsedColorsNumCols", ui->lastUsedColorsNumCols->value()); cfg.writeEntry("lastUsedColorsNumRows", ui->lastUsedColorsNumRows->value()); cfg.writeEntry("lastUsedColorsCount", ui->lastUsedColorsPatchCount->value()); cfg.writeEntry("lastUsedColorsWidth", ui->lastUsedColorsWidth->value()); cfg.writeEntry("lastUsedColorsHeight", ui->lastUsedColorsHeight->value()); cfg.writeEntry("commonColorsShow", ui->commonColorsShow->isChecked()); cfg.writeEntry("commonColorsAlignment", ui->commonColorsAlignVertical->isChecked()); cfg.writeEntry("commonColorsScrolling", ui->commonColorsAllowScrolling->isChecked()); cfg.writeEntry("commonColorsNumCols", ui->commonColorsNumCols->value()); cfg.writeEntry("commonColorsNumRows", ui->commonColorsNumRows->value()); cfg.writeEntry("commonColorsCount", ui->commonColorsPatchCount->value()); cfg.writeEntry("commonColorsWidth", ui->commonColorsWidth->value()); cfg.writeEntry("commonColorsHeight", ui->commonColorsHeight->value()); cfg.writeEntry("commonColorsAutoUpdate", ui->commonColorsAutoUpdate->isChecked()); //shade selector int shadeSelectorTypeIndex = ui->ACSShadeSelectorTypeComboBox->currentIndex(); if(shadeSelectorTypeIndex == 0) { cfg.writeEntry("shadeSelectorType", "MyPaint"); } else if (shadeSelectorTypeIndex == 1) { cfg.writeEntry("shadeSelectorType", "Minimal"); } else { cfg.writeEntry("shadeSelectorType", "Hidden"); } cfg.writeEntry("shadeSelectorUpdateOnRightClick", ui->shadeSelectorUpdateOnRightClick->isChecked()); cfg.writeEntry("shadeSelectorUpdateOnForeground", ui->shadeSelectorUpdateOnForeground->isChecked()); cfg.writeEntry("shadeSelectorUpdateOnLeftClick", ui->shadeSelectorUpdateOnLeftClick->isChecked()); cfg.writeEntry("shadeSelectorUpdateOnBackground", ui->shadeSelectorUpdateOnBackground->isChecked()); cfg.writeEntry("hidePopupOnClickCheck", ui->hidePopupOnClickCheck->isChecked()); //mypaint model int shadeMyPaintComboBoxIndex = ui->ACSshadeSelectorMyPaintColorModelComboBox->currentIndex(); if (shadeMyPaintComboBoxIndex == 0 ) { cfg.writeEntry("shadeMyPaintType", "HSV"); } else if (shadeMyPaintComboBoxIndex == 1 ) { cfg.writeEntry("shadeMyPaintType", "HSL"); } else if (shadeMyPaintComboBoxIndex == 2 ) { cfg.writeEntry("shadeMyPaintType", "HSI"); } else { // HSY cfg.writeEntry("shadeMyPaintType", "HSY"); } cfg.writeEntry("minimalShadeSelectorAsGradient", ui->minimalShadeSelectorAsGradient->isChecked()); cfg.writeEntry("minimalShadeSelectorPatchCount", ui->minimalShadeSelectorPatchesPerLine->value()); cfg.writeEntry("minimalShadeSelectorLineConfig", ui->minimalShadeSelectorLineSettings->toString()); cfg.writeEntry("minimalShadeSelectorLineHeight", ui->minimalShadeSelectorLineHeight->value()); //color selector KisColorSelectorComboBox* cstw = dynamic_cast(ui->colorSelectorConfiguration); cfg.writeEntry("colorSelectorConfiguration", cstw->configuration().toString()); cfg.writeEntry("hsxSettingType", ui->colorSelectorTypeComboBox->currentIndex()); //luma// - cfg.writeEntry("lumaR", ui->l_lumaR->text()); - cfg.writeEntry("lumaG", ui->l_lumaG->text()); - cfg.writeEntry("lumaB", ui->l_lumaB->text()); + cfg.writeEntry("lumaR", ui->l_lumaR->value()); + cfg.writeEntry("lumaG", ui->l_lumaG->value()); + cfg.writeEntry("lumaB", ui->l_lumaB->value()); //slider// hsxcfg.writeEntry("hsvH", ui->csl_hsvH->isChecked()); hsxcfg.writeEntry("hsvS", ui->csl_hsvS->isChecked()); hsxcfg.writeEntry("hsvV", ui->csl_hsvV->isChecked()); hsxcfg.writeEntry("hslH", ui->csl_hslH->isChecked()); hsxcfg.writeEntry("hslS", ui->csl_hslS->isChecked()); hsxcfg.writeEntry("hslL", ui->csl_hslL->isChecked()); hsxcfg.writeEntry("hsiH", ui->csl_hsiH->isChecked()); hsxcfg.writeEntry("hsiS", ui->csl_hsiS->isChecked()); hsxcfg.writeEntry("hsiI", ui->csl_hsiI->isChecked()); hsxcfg.writeEntry("hsyH", ui->csl_hsyH->isChecked()); hsxcfg.writeEntry("hsyS", ui->csl_hsyS->isChecked()); hsxcfg.writeEntry("hsyY", ui->csl_hsyY->isChecked()); emit settingsChanged(); } //void KisColorSelectorSettings::changeEvent(QEvent *e) //{ // QDialog::changeEvent(e); // switch (e->type()) { // case QEvent::LanguageChange: // ui->retranslateUi(this); // break; // default: // break; // } //} void KisColorSelectorSettings::changedColorDocker(int index) { // having a situation where too many sections are visible makes the window too large. turn all off before turning more on ui->colorSliderOptions->hide(); ui->advancedColorSelectorOptions->hide(); if (index == 0) { // advanced color selector options selected ui->advancedColorSelectorOptions->show(); ui->colorSliderOptions->hide(); } else { // color slider options selected ui->advancedColorSelectorOptions->hide(); ui->colorSliderOptions->show(); } } void KisColorSelectorSettings::changedACSColorSelectorType(int index) { ui->lumaCoefficientGroupbox->setVisible(false); if (index == 0) { // HSV ui->ACSTypeDescriptionLabel->setText(i18n("Values goes from black to white, or black to the most saturated colour. Saturation, in turn, goes from the most saturated colour to white, grey or black.")); } else if (index == 1) { // HSL ui->ACSTypeDescriptionLabel->setText(i18n("Lightness goes from black to white, with middle grey being equal to the most saturated colour.")); } else if (index == 2) { // HSI ui->ACSTypeDescriptionLabel->setText(i18n("Intensity maps to the sum of rgb components")); } else { // HSY' ui->ACSTypeDescriptionLabel->setText(i18n("Luma(Y') is weighted by its coefficients which are configurable. Default values are set to 'rec 709'.")); ui->lumaCoefficientGroupbox->setVisible(true); } ui->colorSelectorConfiguration->update(); emit hsxchanged(index); } void KisColorSelectorSettings::changedACSColorAlignment(bool toggled) { // this slot is tied to the horizontal radio button's state being changed // you can infer the vertical state if (toggled) { // horizontal layout. show rows ui->lbl_commonColorsNumCols->hide(); ui->commonColorsNumCols->hide(); ui->lbl_commonColorsNumRows->show(); ui->commonColorsNumRows->show(); } else { ui->lbl_commonColorsNumCols->show(); ui->commonColorsNumCols->show(); ui->lbl_commonColorsNumRows->hide(); ui->commonColorsNumRows->hide(); } } void KisColorSelectorSettings::changedACSShadeSelectorType(int index) { if (index == 0) { // MyPaint ui->minimalShadeSelectorGroup->hide(); ui->myPaintColorModelLabel->show(); ui->ACSshadeSelectorMyPaintColorModelComboBox->show(); } else if (index == 1) { // Minimal ui->minimalShadeSelectorGroup->show(); ui->myPaintColorModelLabel->hide(); ui->ACSshadeSelectorMyPaintColorModelComboBox->hide(); }else { // do not show ui->minimalShadeSelectorGroup->hide(); ui->myPaintColorModelLabel->hide(); ui->ACSshadeSelectorMyPaintColorModelComboBox->hide(); } } void KisColorSelectorSettings::useDifferentColorSpaceChecked(bool enabled) { ui->colorSpace->setEnabled(enabled); } void KisColorSelectorSettings::loadPreferences() { //read cfg //don't forget to also add a new entry to the default preferences KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); KConfigGroup hsxcfg = KGlobal::config()->group("hsxColorSlider"); // Advanced color selector ui->dockerResizeOptionsComboBox->setCurrentIndex( (int)cfg.readEntry("onDockerResize", 0) ); ui->zoomSelectorOptionComboBox->setCurrentIndex( (int) cfg.readEntry("zoomSelectorOptions", 0) ); ui->popupSize->setValue(cfg.readEntry("zoomSize", 280)); { KisConfig kisconfig; const KoColorSpace *cs = kisconfig.customColorSelectorColorSpace(); if(cs) { ui->useDifferentColorSpaceCheckbox->setChecked(true); ui->colorSpace->setEnabled(true); ui->colorSpace->setCurrentColorSpace(cs); } else { ui->useDifferentColorSpaceCheckbox->setChecked(false); ui->colorSpace->setEnabled(false); } } //color patches ui->lastUsedColorsShow->setChecked(cfg.readEntry("lastUsedColorsShow", true)); bool a = cfg.readEntry("lastUsedColorsAlignment", true); ui->lastUsedColorsAlignVertical->setChecked(a); ui->lastUsedColorsAlignHorizontal->setChecked(!a); ui->lastUsedColorsAllowScrolling->setChecked(cfg.readEntry("lastUsedColorsScrolling", true)); ui->lastUsedColorsNumCols->setValue(cfg.readEntry("lastUsedColorsNumCols", 1)); ui->lastUsedColorsNumRows->setValue(cfg.readEntry("lastUsedColorsNumRows", 1)); ui->lastUsedColorsPatchCount->setValue(cfg.readEntry("lastUsedColorsCount", 20)); ui->lastUsedColorsWidth->setValue(cfg.readEntry("lastUsedColorsWidth", 16)); ui->lastUsedColorsHeight->setValue(cfg.readEntry("lastUsedColorsHeight", 16)); ui->commonColorsShow->setChecked(cfg.readEntry("commonColorsShow", true)); a = cfg.readEntry("commonColorsAlignment", false); ui->commonColorsAlignVertical->setChecked(a); ui->commonColorsAlignHorizontal->setChecked(!a); ui->commonColorsAllowScrolling->setChecked(cfg.readEntry("commonColorsScrolling", false)); ui->commonColorsNumCols->setValue(cfg.readEntry("commonColorsNumCols", 1)); ui->commonColorsNumRows->setValue(cfg.readEntry("commonColorsNumRows", 1)); ui->commonColorsPatchCount->setValue(cfg.readEntry("commonColorsCount", 12)); ui->commonColorsWidth->setValue(cfg.readEntry("commonColorsWidth", 16)); ui->commonColorsHeight->setValue(cfg.readEntry("commonColorsHeight", 16)); ui->commonColorsAutoUpdate->setChecked(cfg.readEntry("commonColorsAutoUpdate", false)); //shade selector QString shadeSelectorType=cfg.readEntry("shadeSelectorType", "MyPaint"); if ( shadeSelectorType == "MyPaint") { ui->ACSShadeSelectorTypeComboBox->setCurrentIndex(0); } else if (shadeSelectorType == "Minimal") { ui->ACSShadeSelectorTypeComboBox->setCurrentIndex(1); } else { // Hidden ui->ACSShadeSelectorTypeComboBox->setCurrentIndex(2); } ui->shadeSelectorUpdateOnRightClick->setChecked(cfg.readEntry("shadeSelectorUpdateOnRightClick", false)); ui->shadeSelectorUpdateOnLeftClick->setChecked(cfg.readEntry("shadeSelectorUpdateOnLeftClick", false)); ui->shadeSelectorUpdateOnForeground->setChecked(cfg.readEntry("shadeSelectorUpdateOnForeground", true)); ui->shadeSelectorUpdateOnBackground->setChecked(cfg.readEntry("shadeSelectorUpdateOnBackground", true)); ui->hidePopupOnClickCheck->setChecked(cfg.readEntry("hidePopupOnClickCheck", false)); QString shadeMyPaintType = cfg.readEntry("shadeMyPaintType", "HSV"); if (shadeMyPaintType == "HSV" ) { ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(0); } else if (shadeMyPaintType == "HSL" ) { ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(1); } else if (shadeMyPaintType == "HSI" ) { ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(2); } else { // HSY ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(3); } bool asGradient = cfg.readEntry("minimalShadeSelectorAsGradient", true); if(asGradient) ui->minimalShadeSelectorAsGradient->setChecked(true); else ui->minimalShadeSelectorAsColorPatches->setChecked(true); ui->minimalShadeSelectorPatchesPerLine->setValue(cfg.readEntry("minimalShadeSelectorPatchCount", 10)); ui->minimalShadeSelectorLineSettings->fromString(cfg.readEntry("minimalShadeSelectorLineConfig", "0|0.2|0|0|0|0|0;1|0|1|1|0|0|0;2|0|-1|1|0|0|0;")); ui->minimalShadeSelectorLineHeight->setValue(cfg.readEntry("minimalShadeSelectorLineHeight", 10)); int hsxSettingType= (int)cfg.readEntry("hsxSettingType", 0); ui->colorSelectorTypeComboBox->setCurrentIndex(hsxSettingType); //color selector KisColorSelectorComboBox* cstw = dynamic_cast(ui->colorSelectorConfiguration); cstw->setConfiguration(KisColorSelector::Configuration::fromString(cfg.readEntry("colorSelectorConfiguration", "3|0|5|0"))); // triangle selector //luma values// - ui->l_lumaR->setText(cfg.readEntry("lumaR", "0.2126")); - ui->l_lumaG->setText(cfg.readEntry("lumaG", "0.7152")); - ui->l_lumaB->setText(cfg.readEntry("lumaB", "0.0722")); + ui->l_lumaR->setValue(cfg.readEntry("lumaR", 0.2126)); + ui->l_lumaG->setValue(cfg.readEntry("lumaG", 0.7152)); + ui->l_lumaB->setValue(cfg.readEntry("lumaB", 0.0722)); //color sliders// ui->csl_hsvH->setChecked(hsxcfg.readEntry("hsvH", false)); ui->csl_hsvS->setChecked(hsxcfg.readEntry("hsvS", false)); ui->csl_hsvV->setChecked(hsxcfg.readEntry("hsvV", false)); ui->csl_hslH->setChecked(hsxcfg.readEntry("hslH", true)); ui->csl_hslS->setChecked(hsxcfg.readEntry("hslS", true)); ui->csl_hslL->setChecked(hsxcfg.readEntry("hslL", true)); ui->csl_hsiH->setChecked(hsxcfg.readEntry("hsiH", false)); ui->csl_hsiS->setChecked(hsxcfg.readEntry("hsiS", false)); ui->csl_hsiI->setChecked(hsxcfg.readEntry("hsiI", false)); ui->csl_hsyH->setChecked(hsxcfg.readEntry("hsyH", false)); ui->csl_hsyS->setChecked(hsxcfg.readEntry("hsyS", false)); ui->csl_hsyY->setChecked(hsxcfg.readEntry("hsyY", false)); } void KisColorSelectorSettings::loadDefaultPreferences() { //set defaults //if you change something, don't forget that loadPreferences should be kept in sync // advanced color selector docker ui->dockerResizeOptionsComboBox->setCurrentIndex(0); ui->zoomSelectorOptionComboBox->setCurrentIndex(0); ui->popupSize->setValue(280); ui->useDifferentColorSpaceCheckbox->setChecked(false); ui->colorSpace->setCurrentColorModel(KoID("RGBA")); ui->colorSpace->setCurrentColorDepth(KoID("U8")); ui->colorSpace->setCurrentProfile(KoColorSpaceRegistry::instance()->rgb8()->profile()->name()); //color patches ui->lastUsedColorsShow->setChecked(true); ui->lastUsedColorsAlignVertical->setChecked(true); ui->lastUsedColorsAlignHorizontal->setChecked(false); ui->lastUsedColorsAllowScrolling->setChecked(true); ui->lastUsedColorsNumCols->setValue(1); ui->lastUsedColorsNumRows->setValue(1); ui->lastUsedColorsPatchCount->setValue(20); ui->lastUsedColorsWidth->setValue(16); ui->lastUsedColorsHeight->setValue(16); ui->commonColorsShow->setChecked(true); ui->commonColorsAlignVertical->setChecked(false); ui->commonColorsAlignHorizontal->setChecked(true); ui->commonColorsAllowScrolling->setChecked(false); ui->commonColorsNumCols->setValue(1); ui->commonColorsNumRows->setValue(1); ui->commonColorsPatchCount->setValue(12); ui->commonColorsWidth->setValue(16); ui->commonColorsHeight->setValue(16); ui->commonColorsAutoUpdate->setChecked(false); //shade selector ui->ACSShadeSelectorTypeComboBox->setCurrentIndex(0); // MyPaint ui->ACSshadeSelectorMyPaintColorModelComboBox->setCurrentIndex(0); ui->shadeSelectorUpdateOnRightClick->setChecked(false); ui->shadeSelectorUpdateOnLeftClick->setChecked(false); ui->shadeSelectorUpdateOnForeground->setChecked(true); ui->shadeSelectorUpdateOnBackground->setChecked(true); bool asGradient = true; if(asGradient) ui->minimalShadeSelectorAsGradient->setChecked(true); else ui->minimalShadeSelectorAsColorPatches->setChecked(true); ui->minimalShadeSelectorPatchesPerLine->setValue(10); ui->minimalShadeSelectorLineSettings->fromString("0|0.2|0|0|0|0|0;1|0|1|1|0|0|0;2|0|-1|1|0|0|0;"); ui->minimalShadeSelectorLineHeight->setValue(10); // set advanced color selector to use HSV ui->colorSelectorTypeComboBox->setCurrentIndex(0); KisColorSelectorComboBox* cstw = dynamic_cast(ui->colorSelectorConfiguration); cstw->setConfiguration(KisColorSelector::Configuration("3|0|5|0")); // triangle selector //luma// - ui->l_lumaR->setText("0.2126"); - ui->l_lumaG->setText("0.7152"); - ui->l_lumaB->setText("0.0722"); + ui->l_lumaR->setValue(0.2126); + ui->l_lumaG->setValue(0.7152); + ui->l_lumaB->setValue(0.0722); //color sliders// ui->csl_hsvH->setChecked(false); ui->csl_hsvS->setChecked(false); ui->csl_hsvV->setChecked(false); ui->csl_hslH->setChecked(true); ui->csl_hslS->setChecked(true); ui->csl_hslL->setChecked(true); ui->csl_hsiH->setChecked(false); ui->csl_hsiS->setChecked(false); ui->csl_hsiI->setChecked(false); ui->csl_hsyH->setChecked(false); ui->csl_hsyS->setChecked(false); ui->csl_hsyY->setChecked(false); } KisColorSelectorSettingsDialog::KisColorSelectorSettingsDialog(QWidget *parent) : QDialog(parent), m_widget(new KisColorSelectorSettings(this)) { QLayout* l = new QVBoxLayout(this); l->addWidget(m_widget); m_widget->loadPreferences(); QDialogButtonBox* buttonBox = new QDialogButtonBox(QDialogButtonBox::Ok|QDialogButtonBox::Cancel|QDialogButtonBox::RestoreDefaults, Qt::Horizontal, this); l->addWidget(buttonBox); connect(buttonBox, SIGNAL(accepted()), m_widget, SLOT(savePreferences())); connect(buttonBox, SIGNAL(accepted()), this, SLOT(accept())); connect(buttonBox, SIGNAL(rejected()), this, SLOT(reject())); connect(buttonBox->button(QDialogButtonBox::RestoreDefaults), SIGNAL(clicked()), m_widget, SLOT(loadDefaultPreferences())); } diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp b/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp index ba7538fab8c..6b300755e40 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.cpp @@ -1,299 +1,304 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2008 Martin Renold * Copyright (c) 2009 Ilya Portnov * * This class is based on "lib/colorchanger.hpp" from MyPaint (mypaint.intilinux.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_my_paint_shade_selector.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "KoColor.h" #include "KoCanvasResourceManager.h" #include "kis_paint_device.h" #include "kis_painter.h" #include "kis_display_color_converter.h" inline int sqr(int x); inline qreal sqr2(qreal x); inline int signedSqr(int x); KisMyPaintShadeSelector::KisMyPaintShadeSelector(QWidget *parent) : KisColorSelectorBase(parent), m_updateTimer(new QTimer(this)) { setAcceptDrops(true); updateSettings(); setMinimumSize(80, 80); setColor(KoColor(Qt::red, colorSpace())); m_updateTimer->setInterval(1); m_updateTimer->setSingleShot(true); connect(m_updateTimer, SIGNAL(timeout()), this, SLOT(update())); } void KisMyPaintShadeSelector::paintEvent(QPaintEvent *) { // Hint to the casual reader: some of the calculation here do not // what Martin Renold originally intended. Not everything here will make sense. // It does not matter in the end, as long as the result looks good. // This selector was ported from MyPaint in 2010 - - m_realPixelCache = new KisPaintDevice(this->colorSpace()); - KisPaintDeviceSP realCircleBorder = new KisPaintDevice(this->colorSpace()); - + if (m_cachedColorSpace != colorSpace()) { + m_realPixelCache = new KisPaintDevice(colorSpace()); + m_realCircleBorder = new KisPaintDevice(colorSpace()); + m_cachedColorSpace = colorSpace(); + } + else { + m_realPixelCache->clear(); + m_realCircleBorder->clear(); + } KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); QString shadeMyPaintType=cfg.readEntry("shadeMyPaintType", "HSV"); int size = qMin(width(), height()); int s_radius = size/2.6; for (int x=0; x 0) dxs = dx - stripe_width; else dxs = dx + stripe_width; if (dy > 0) dys = dy - stripe_width; else dys = dy + stripe_width; qreal r = std::sqrt(qreal(sqr(dxs)+sqr(dys))); if (qMin(abs(dx), abs(dy)) < stripe_width) { // horizontal and vertical lines dx = (dx/qreal(width()))*255; dy = (dy/qreal(height()))*255; h = 0; // x-axis = value, y-axis = saturation v = dx*v_factor + signedSqr(dx)*v_factor2; s = - (dy*s_factor + signedSqr(dy)*s_factor2); // but not both at once if (std::abs(dx) > std::abs(dy)) { // horizontal stripe s = 0.0; } else { // vertical stripe v = 0.0; } } else if (r < s_radius+1) { // hue if (dx > 0) h = 90*sqr2(r/s_radius); else h = 360 - 90*sqr2(r/s_radius); s = 256*(atan2f(std::abs(dxs),dys)/M_PI) - 128; if (r > s_radius) { // antialiasing boarder qreal aaFactor = r-floor(r); // part after the decimal point aaFactor = 1-aaFactor; qreal fh = m_colorH + h/360.0; qreal fs = m_colorS + s/255.0; qreal fv = m_colorV + v/255.0; fh -= floor(fh); fs = qBound(qreal(0.0), fs, qreal(1.0)); fv = qBound(qreal(0.01), fv, qreal(1.0)); KoColor color; //KoColor color = converter()->fromHsvF(fh, fs, fv); if(shadeMyPaintType=="HSV"){color = converter()->fromHsvF(fh, fs, fv);} else if(shadeMyPaintType=="HSL"){color = converter()->fromHslF(fh, fs, fv);} else if(shadeMyPaintType=="HSI"){color = converter()->fromHsiF(fh, fs, fv);} else if(shadeMyPaintType=="HSY"){color = converter()->fromHsyF(fh, fs, fv, R, G, B);} else{qDebug()<<"MyPaint Color selector don't work right."; color = converter()->fromHsvF(fh, fs, fv);} //qDebug()<toQcolor(); color.setOpacity(aaFactor); - Acs::setColor(realCircleBorder, QPoint(x, y), color); + Acs::setColor(m_realCircleBorder, QPoint(x, y), color); h = 180 + 180*atan2f(dys,-dxs)/M_PI; v = 255*(r-s_radius)/(diag-s_radius) - 128; } } else { // background (hue+darkness gradient) h = 180 + 180*atan2f(dys,-dxs)/M_PI; v = 255*(r-s_radius)/(diag-s_radius) - 128; } qreal fh = m_colorH + h/360.0; qreal fs = m_colorS + s/255.0; qreal fv = m_colorV + v/255.0; fh -= floor(fh); fs = qBound(qreal(0.0), fs, qreal(1.0)); fv = qBound(qreal(0.01), fv, qreal(1.0)); KoColor color; //KoColor color = converter()->fromHsvF(fh, fs, fv); if(shadeMyPaintType=="HSV"){color = converter()->fromHsvF(fh, fs, fv);} else if(shadeMyPaintType=="HSL"){color = converter()->fromHslF(fh, fs, fv);} else if(shadeMyPaintType=="HSI"){color = converter()->fromHsiF(fh, fs, fv);} else if(shadeMyPaintType=="HSY"){color = converter()->fromHsyF(fh, fs, fv);} else{qDebug()<<"MyPaint Color selector don't work right."; color = converter()->fromHsvF(fh, fs, fv);} Acs::setColor(m_realPixelCache, QPoint(x, y), color); } } KisPainter gc(m_realPixelCache); - gc.bitBlt(QPoint(0,0), realCircleBorder, rect()); + gc.bitBlt(QPoint(0,0), m_realCircleBorder, rect()); QPainter painter(this); QImage renderedImage = converter()->toQImage(m_realPixelCache); painter.drawImage(0, 0, renderedImage); } void KisMyPaintShadeSelector::mousePressEvent(QMouseEvent* e) { e->setAccepted(false); KisColorSelectorBase::mousePressEvent(e); } void KisMyPaintShadeSelector::mouseMoveEvent(QMouseEvent *e) { if(rect().contains(e->pos())) { KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); this->updateColorPreview(color); } KisColorSelectorBase::mouseMoveEvent(e); } void KisMyPaintShadeSelector::mouseReleaseEvent(QMouseEvent *e) { e->setAccepted(false); KisColorSelectorBase::mouseReleaseEvent(e); if(!e->isAccepted()) { KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); Acs::ColorRole role = Acs::buttonToRole(e->button()); KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); bool onRightClick = cfg.readEntry("shadeSelectorUpdateOnRightClick", false); bool onLeftClick = cfg.readEntry("shadeSelectorUpdateOnLeftClick", false); bool explicitColorReset = (e->button() == Qt::LeftButton && onLeftClick) || (e->button() == Qt::RightButton && onRightClick); this->updateColor(color, role, explicitColorReset); e->accept(); } } KisColorSelectorBase* KisMyPaintShadeSelector::createPopup() const { KisColorSelectorBase* popup = new KisMyPaintShadeSelector(0); popup->setColor(m_lastRealColor); return popup; } void KisMyPaintShadeSelector::setColor(const KoColor &color) { KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); QString shadeMyPaintType=cfg.readEntry("shadeMyPaintType", "HSV"); R = cfg.readEntry("lumaR", 0.2126); G = cfg.readEntry("lumaG", 0.7152); B = cfg.readEntry("lumaB", 0.0722); if(shadeMyPaintType=="HSV"){this->converter()->getHsvF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSL"){this->converter()->getHslF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSI"){this->converter()->getHsiF(color, &m_colorH, &m_colorS, &m_colorV);} if(shadeMyPaintType=="HSY"){this->converter()->getHsyF(color, &m_colorH, &m_colorS, &m_colorV, R, G, B);} m_lastRealColor = color; this->updateColorPreview(color); m_updateTimer->start(); } void KisMyPaintShadeSelector::canvasResourceChanged(int key, const QVariant &v) { if(m_colorUpdateAllowed==false) return; KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); bool onForeground = cfg.readEntry("shadeSelectorUpdateOnForeground", false); bool onBackground = cfg.readEntry("shadeSelectorUpdateOnBackground", true); if ((key == KoCanvasResourceManager::ForegroundColor && onForeground) || (key == KoCanvasResourceManager::BackgroundColor && onBackground)) { setColor(v.value()); } } inline int sqr(int x) { return x*x; } inline qreal sqr2(qreal x) { return (x*x)/2+x/2; } inline int signedSqr(int x) { int sign = x>0?1:-1; return x*x*sign; } diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.h b/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.h index a831659334b..ebb5b906666 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.h +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_my_paint_shade_selector.h @@ -1,61 +1,64 @@ /* * Copyright (c) 2010 Adam Celarek * Copyright (c) 2008 Martin Renold * Copyright (c) 2009 Ilya Portnov * * This class is based on "lib/colorchanger.hpp" from MyPaint (mypaint.intilinux.com) * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_MY_PAINT_SHADE_SELECTOR_H #define KIS_MY_PAINT_SHADE_SELECTOR_H #include "kis_color_selector_base.h" #include #include #include +class KoColorSpace; class QTimer; class KisMyPaintShadeSelector : public KisColorSelectorBase { Q_OBJECT public: KisMyPaintShadeSelector(QWidget *parent = 0); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); public: void setColor(const KoColor &color); protected Q_SLOTS: void canvasResourceChanged(int key, const QVariant& v); protected: void paintEvent(QPaintEvent *); KisColorSelectorBase* createPopup() const; private: qreal m_colorH, m_colorS, m_colorV; qreal R, G, B; QTimer* m_updateTimer; KoColor m_lastRealColor; KisPaintDeviceSP m_realPixelCache; + KisPaintDeviceSP m_realCircleBorder; + const KoColorSpace *m_cachedColorSpace; }; #endif // KIS_MY_PAINT_SHADE_SELECTOR_H diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.cpp b/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.cpp index b8a62208983..43aaf36ebe0 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.cpp +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.cpp @@ -1,219 +1,226 @@ /* * Copyright (c) 2010 Adam Celarek * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_shade_selector_line.h" #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_color_selector_base_proxy.h" #include "kis_display_color_converter.h" #include "kis_paint_device.h" KisShadeSelectorLine::KisShadeSelectorLine(KisColorSelectorBaseProxy *parentProxy, QWidget *parent) : KisShadeSelectorLineBase(parent), m_displayHelpText(false), m_parentProxy(parentProxy) { setParam(0, 0, 0, 0, 0, 0); updateSettings(); setMouseTracking(true); } KisShadeSelectorLine::KisShadeSelectorLine(qreal hueDelta, qreal satDelta, qreal valDelta, KisColorSelectorBaseProxy *parentProxy, QWidget *parent, qreal hueShift, qreal satShift, qreal valShift) : KisShadeSelectorLineBase(parent), m_displayHelpText(false), m_parentProxy(parentProxy) { setParam(hueDelta, satDelta, valDelta, hueShift, satShift, valShift); updateSettings(); } KisShadeSelectorLine::~KisShadeSelectorLine() { } void KisShadeSelectorLine::setParam(qreal hueDelta, qreal satDelta, qreal valDelta, qreal hueShift, qreal satShift, qreal valShift) { m_hueDelta = hueDelta; m_saturationDelta = satDelta; m_valueDelta = valDelta; m_hueShift = hueShift; m_saturationShift = satShift; m_valueShift = valShift; } void KisShadeSelectorLine::setColor(const KoColor &color) { m_realColor = color; m_realColor.convertTo(m_parentProxy->colorSpace()); update(); } void KisShadeSelectorLine::updateSettings() { KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); m_gradient = cfg.readEntry("minimalShadeSelectorAsGradient", false); m_patchCount = cfg.readEntry("minimalShadeSelectorPatchCount", 10); m_lineHeight = cfg.readEntry("minimalShadeSelectorLineHeight", 20); setMaximumHeight(m_lineHeight); setMinimumHeight(m_lineHeight); } QString KisShadeSelectorLine::toString() const { return QString("%1|%2|%3|%4|%5|%6|%7").arg(m_lineNumber).arg(m_hueDelta).arg(m_saturationDelta).arg(m_valueDelta).arg(m_hueShift).arg(m_saturationShift).arg(m_valueShift); } void KisShadeSelectorLine::fromString(const QString& string) { QStringList strili = string.split('|'); m_lineNumber = strili.at(0).toInt(); m_hueDelta = strili.at(1).toDouble(); m_saturationDelta = strili.at(2).toDouble(); m_valueDelta = strili.at(3).toDouble(); if(strili.size()==4) return; // don't crash, if reading old config files. m_hueShift = strili.at(4).toDouble(); m_saturationShift = strili.at(5).toDouble(); m_valueShift = strili.at(6).toDouble(); } void KisShadeSelectorLine::paintEvent(QPaintEvent *) { - m_realPixelCache = new KisPaintDevice(m_parentProxy->colorSpace()); + + if (m_cachedColorSpace != m_parentProxy->colorSpace()) { + m_realPixelCache = new KisPaintDevice(m_parentProxy->colorSpace()); + m_cachedColorSpace = m_parentProxy->colorSpace(); + } + else { + m_realPixelCache->clear(); + } int patchCount; int patchSpacing; if(m_gradient) { patchCount = width(); patchSpacing = 0; } else { patchCount = m_patchCount; patchSpacing = 3; } qreal patchWidth = (width()-patchSpacing*patchCount)/qreal(patchCount); qreal hueStep=m_hueDelta/qreal(patchCount); qreal saturationStep=m_saturationDelta/qreal(patchCount); qreal valueStep=m_valueDelta/qreal(patchCount); qreal baseHue; qreal baseSaturation; qreal baseValue; m_parentProxy->converter()-> getHsvF(m_realColor, &baseHue, &baseSaturation, &baseValue); int z=0; for(int i=-patchCount/2; i<=patchCount/2; i++) { if(i==0 && patchCount%2==0) continue; qreal hue = baseHue + (i * hueStep) + m_hueShift; while (hue < 0.0) hue += 1.0; while (hue > 1.0) hue -= 1.0; qreal saturation = qBound(0., baseSaturation + (i * saturationStep) + m_saturationShift, 1.); qreal value = qBound(0., baseValue + (i * valueStep) + m_valueShift, 1.); QRect patchRect(z * (patchWidth + patchSpacing), 0, patchWidth, m_lineHeight); KoColor patchColor = m_parentProxy->converter()->fromHsvF(hue, saturation, value); patchColor.convertTo(m_realPixelCache->colorSpace()); m_realPixelCache->fill(patchRect, patchColor); z++; } QPainter wpainter(this); QImage renderedImage = m_parentProxy->converter()->toQImage(m_realPixelCache); wpainter.drawImage(0, 0, renderedImage); if(m_displayHelpText) { QString helpText(i18n("delta h=%1 s=%2 v=%3 shift h=%4 s=%5 v=%6", m_hueDelta, m_saturationDelta, m_valueDelta, m_hueShift, m_saturationShift, m_valueShift)); wpainter.setPen(QColor(255,255,255)); wpainter.drawText(rect(), helpText); } } void KisShadeSelectorLine::mousePressEvent(QMouseEvent* e) { if(e->button()!=Qt::LeftButton && e->button()!=Qt::RightButton) { e->setAccepted(false); return; } m_parentProxy->showColorPreview(); e->accept(); } void KisShadeSelectorLine::mouseMoveEvent(QMouseEvent *e) { KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); m_parentProxy->updateColorPreview(color); } void KisShadeSelectorLine::mouseReleaseEvent(QMouseEvent * e) { if (e->button() != Qt::LeftButton && e->button() != Qt::RightButton) { e->ignore(); return; } if (!rect().contains(e->pos())) { e->accept(); return; } KoColor color(Acs::pickColor(m_realPixelCache, e->pos())); Acs::ColorRole role = Acs::buttonToRole(e->button()); KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); bool onRightClick = cfg.readEntry("shadeSelectorUpdateOnRightClick", false); bool onLeftClick = cfg.readEntry("shadeSelectorUpdateOnLeftClick", false); bool explicitColorReset = (e->button() == Qt::LeftButton && onLeftClick) || (e->button() == Qt::RightButton && onRightClick); m_parentProxy->updateColor(color, role, explicitColorReset); e->accept(); } diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.h b/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.h index a232e6c8f1a..2f724688f4c 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.h +++ b/krita/plugins/extensions/dockers/advancedcolorselector/kis_shade_selector_line.h @@ -1,89 +1,91 @@ /* * Copyright (c) 2010 Adam Celarek * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SHADE_SELECTOR_LINE_H #define KIS_SHADE_SELECTOR_LINE_H #include #include #include "kis_types.h" class KisCanvas2; class KisShadeSelectorLineComboBox; class KisColorSelectorBaseProxy; +class KoColorSpace; class KisShadeSelectorLineBase : public QWidget { public: KisShadeSelectorLineBase(QWidget* parent) : QWidget(parent) {} void setLineNumber(int n) {m_lineNumber=n;} virtual QString toString() const = 0; virtual void fromString(const QString& string) = 0; protected: int m_lineNumber; }; class KisShadeSelectorLine : public KisShadeSelectorLineBase { Q_OBJECT public: explicit KisShadeSelectorLine(KisColorSelectorBaseProxy *parentProxy, QWidget *parent = 0); explicit KisShadeSelectorLine(qreal hueDelta, qreal satDelta, qreal valDelta, KisColorSelectorBaseProxy *parentProxy, QWidget *parent = 0, qreal hueShift = 0, qreal satShift = 0, qreal valShift = 0); ~KisShadeSelectorLine(); void setParam(qreal hue, qreal sat, qreal val, qreal hueShift, qreal satShift, qreal shiftVal); void setColor(const KoColor& color); void updateSettings(); void setCanvas(KisCanvas2* canvas); void showHelpText() {m_displayHelpText=true;} QString toString() const; void fromString(const QString& string); void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent *); void mouseMoveEvent(QMouseEvent *); void mouseReleaseEvent(QMouseEvent *); private: qreal m_hueDelta; qreal m_saturationDelta; qreal m_valueDelta; qreal m_hueShift; qreal m_saturationShift; qreal m_valueShift; KoColor m_realColor; KisPaintDeviceSP m_realPixelCache; + const KoColorSpace *m_cachedColorSpace; bool m_gradient; int m_patchCount; int m_lineHeight; bool m_displayHelpText; friend class KisShadeSelectorLineComboBox; KisColorSelectorBaseProxy* m_parentProxy; }; #endif // KIS_SHADE_SELECTOR_LINE_H diff --git a/krita/plugins/extensions/dockers/advancedcolorselector/wdg_color_selector_settings.ui b/krita/plugins/extensions/dockers/advancedcolorselector/wdg_color_selector_settings.ui index 260a81eda49..914c8dedfca 100644 --- a/krita/plugins/extensions/dockers/advancedcolorselector/wdg_color_selector_settings.ui +++ b/krita/plugins/extensions/dockers/advancedcolorselector/wdg_color_selector_settings.ui @@ -1,1545 +1,1532 @@ KisColorSelectorSettings 0 0 - 608 + 618 838 0 0 Color Selector Settings QLayout::SetDefaultConstraint Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop 6 20 Docker: 0 0 0 30 0 0 600 421 - 4 + 0 Color Selector 190 130 391 71 0 0 Luma Coefficients - - 6 - 0 0 + + 6 + 0 0 Red': - + 0 0 50 0 - - 9.90000; - - - 0.7152 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 4 0 0 Green': 0 0 Blue': - + 0 0 50 0 - - 9.9000; - - - 0.2126 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 4 - + 0 0 50 0 - - 9.90000; - - - 0.0722 - - - Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + 4 190 30 131 21 Color Model Type: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter colorSelectorConfiguration 20 20 131 121 320 30 131 27 190 70 401 61 0 0 Type Description goes here Qt::AlignLeading|Qt::AlignLeft|Qt::AlignTop true 20 240 561 141 0 0 Color Selector Uses Different Color Space than Image true false 0 0 Behavior true 180 30 291 27 180 60 291 27 30 30 151 21 When Docker Resizes: 20 60 161 21 Show Zoom Selector UI: 50 90 131 21 Zoom Selector Size: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 180 90 82 27 px 100 1000 10 260 180 120 161 26 Hide Popup on click. Shade Selector 320 20 201 21 Update Selector When: 320 40 271 22 Right clicking on shade selector 320 60 321 22 Left clicking on shade selector 320 80 281 22 this doesn't include a color change by the shade selector Foreground color changes false 320 100 311 22 this doesn't include a color change by the shade selector Background color change true 190 20 91 21 Color model: 20 150 531 171 Minimal Shade Selector 10 40 51 21 Display: 10 60 291 101 70 40 91 21 Gradient 180 40 121 22 Color Patches 320 60 196 115 10 px 8 99 16 Line Height: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 1 10 3 Line Count: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter Patches Per Line: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 190 40 91 31 10 40 161 27 10 20 41 21 Type: true 0 0 Color History 10 10 561 231 0 0 Show Color History true 20 40 221 131 Patch Options 30 30 61 27 Height: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 100 30 81 27 px 16 50 60 51 21 Width: 100 60 81 27 px 16 0 90 101 27 Max Patches: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 100 90 81 27 1 30 20 190 131 22 Allow scrolling true 270 40 251 141 Layout 10 30 - 231 + 232 80 Columns: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter lastUsedColorsNumCols 1 20 2 Vertical true Horizontal Rows: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter lastUsedColorsNumRows 1 20 3 Colors from Image true 10 10 561 241 Show Colors from the image true 270 40 271 121 Layout 10 30 - 227 + 232 75 Horizontal true Vertical Columns: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter commonColorsNumCols 1 20 2 Rows: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter commonColorsNumRows 1 20 3 20 40 211 131 Patch Options 50 30 51 27 Height: Qt::AlignLeading|Qt::AlignLeft|Qt::AlignVCenter 110 30 71 27 px 16 60 60 51 21 Width: 110 60 71 27 px 16 20 90 91 31 Max Patches: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 110 90 71 27 1 30 10 190 284 22 this can be slow on big images Update after every stroke 10 210 284 22 Allow scrolling 0 0 600 290 HSV Sliders to Show Hue Saturation Value HSL Sliders to Show Hue Saturation Lightness HSI Sliders to Show Hue Saturation Intensity HSY' Sliders to Show Hue Saturation Luma Qt::Vertical 20 40 + + KDoubleNumInput + QWidget +
knuminput.h
+
KTabWidget QTabWidget
ktabwidget.h
1
KisColorSpaceSelector QWidget
widgets/kis_color_space_selector.h
1
KisColorSelectorComboBox QComboBox
kis_color_selector_combo_box.h
KisShadeSelectorLinesSettings QComboBox
kis_shade_selector_lines_settings.h
lastUsedColorsAlignVertical toggled(bool) lbl_lastUsedNumCols setVisible(bool) 85 156 31 213 lastUsedColorsAlignVertical toggled(bool) lastUsedColorsNumCols setVisible(bool) 85 156 144 213 lastUsedColorsAlignVertical toggled(bool) lbl_lastUsedNumRows setHidden(bool) 85 156 31 241 lastUsedColorsAlignVertical toggled(bool) lastUsedColorsNumRows setHidden(bool) 85 156 144 241 lastUsedColorsAlignHorizontal toggled(bool) lbl_lastUsedNumCols setHidden(bool) 152 156 31 213 lastUsedColorsAlignHorizontal toggled(bool) lastUsedColorsNumCols setHidden(bool) 152 156 144 213 lastUsedColorsAlignHorizontal toggled(bool) lbl_lastUsedNumRows setVisible(bool) 152 156 31 241 lastUsedColorsAlignHorizontal toggled(bool) lastUsedColorsNumRows setVisible(bool) 152 156 144 241 minimalShadeSelectorAsColorPatches toggled(bool) minimalShadeSelectorPatchesPerLine setEnabled(bool) 142 280 149 308
diff --git a/krita/plugins/extensions/dockers/palettedocker/wdgpalettedock.ui b/krita/plugins/extensions/dockers/palettedocker/wdgpalettedock.ui index b9c0e7d181a..0154b44a811 100644 --- a/krita/plugins/extensions/dockers/palettedocker/wdgpalettedock.ui +++ b/krita/plugins/extensions/dockers/palettedocker/wdgpalettedock.ui @@ -1,126 +1,130 @@ WdgPaletteDock + + + 0 + 0 + 256 + 219 + + 1 - - 0 - - - 0 - - - 0 - - + 0 - + 0 16 Qt::Horizontal 40 20 Delete color ... 22 22 false Add foreground color ... 22 22 false Add color ... 22 22 false KisPopupButton QPushButton
kis_popup_button.h
+ + KoTableView + QTableView +
KoTableView.h
+
bnRemove
diff --git a/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.cpp b/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.cpp index 6afc96fe12d..5efe1704d54 100644 --- a/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.cpp +++ b/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.cpp @@ -1,143 +1,127 @@ /* * Copyright (c) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "taskset_resource.h" #include #include #include #include #include -#include #include #define TASKSET_VERSION 1 TasksetResource::TasksetResource(const QString& f) : KoResource(f) { } TasksetResource::~TasksetResource() { } bool TasksetResource::save() { if (filename().isEmpty()) return false; QFile file(filename()); file.open(QIODevice::WriteOnly); bool res = saveToDevice(&file); file.close(); return res; } bool TasksetResource::load() { QString fn = filename(); if (fn.isEmpty()) return false; QFile file(fn); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool TasksetResource::loadFromDevice(QIODevice *dev) { QDomDocument doc; if (!doc.setContent(dev)) { return false; } QDomElement element = doc.documentElement(); setName(element.attribute("name")); QDomNode node = element.firstChild(); while (!node.isNull()) { QDomElement child = node.toElement(); if (!child.isNull() && child.tagName() == "action") { m_actions.append(child.text()); } node = node.nextSibling(); } setValid(true); return true; } QString TasksetResource::defaultFileExtension() const { return QString(".kts"); } void TasksetResource::setActionList(const QStringList actions) { m_actions = actions; } QStringList TasksetResource::actionList() { return m_actions; } -QByteArray TasksetResource::generateMD5() const -{ - QByteArray ba; - QBuffer buf(&ba); - buf.open(QBuffer::WriteOnly); - saveToDevice(&buf); - buf.close(); - - if (!ba.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - return md5.result(); - } - - return ba; - -} - bool TasksetResource::saveToDevice(QIODevice *io) const { QDomDocument doc; QDomElement root = doc.createElement("Taskset"); root.setAttribute("name", name() ); root.setAttribute("version", TASKSET_VERSION); foreach(const QString& action, m_actions) { QDomElement element = doc.createElement("action"); element.appendChild(doc.createTextNode(action)); root.appendChild(element); } doc.appendChild(root); QTextStream textStream(io); doc.save(textStream, 4); + + KoResource::saveToDevice(io); + return true; } diff --git a/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.h b/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.h index 57ad287bd45..19916ea7af8 100644 --- a/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.h +++ b/krita/plugins/extensions/dockers/tasksetdocker/taskset_resource.h @@ -1,49 +1,48 @@ /* * Copyright (c) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef TASKSET_RESOURCE_H #define TASKSET_RESOURCE_H #include #include class TasksetResource : public KoResource { public: TasksetResource(const QString& filename); virtual ~TasksetResource(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; virtual QString defaultFileExtension() const; void setActionList(const QStringList actions); QStringList actionList(); -protected: - virtual QByteArray generateMD5() const; + private: QStringList m_actions; }; #endif // TASKSET_RESOURCE_H diff --git a/krita/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp b/krita/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp index ae49cd77d3e..95c2d42f4cd 100644 --- a/krita/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp +++ b/krita/plugins/extensions/resourcemanager/dlg_bundle_manager.cpp @@ -1,357 +1,356 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * 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 "dlg_bundle_manager.h" #include "ui_wdgdlgbundlemanager.h" #include "resourcemanager.h" #include "dlg_create_bundle.h" #include #include #include #include #include #include #include #include "kis_action.h" #define ICON_SIZE 48 DlgBundleManager::DlgBundleManager(KisActionManager* actionMgr, QWidget *parent) : KDialog(parent) , m_page(new QWidget()) , m_ui(new Ui::WdgDlgBundleManager) , m_currentBundle(0) { setCaption(i18n("Manage Resource Bundles")); m_ui->setupUi(m_page); setMainWidget(m_page); resize(m_page->sizeHint()); setButtons(Ok | Cancel); setDefaultButton(Ok); m_ui->listActive->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); m_ui->listActive->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(m_ui->listActive, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(itemSelected(QListWidgetItem*,QListWidgetItem*))); connect(m_ui->listActive, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(itemSelected(QListWidgetItem*))); m_ui->listInactive->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); m_ui->listInactive->setSelectionMode(QAbstractItemView::ExtendedSelection); connect(m_ui->listInactive, SIGNAL(currentItemChanged(QListWidgetItem*,QListWidgetItem*)), SLOT(itemSelected(QListWidgetItem*,QListWidgetItem*))); connect(m_ui->listInactive, SIGNAL(itemClicked(QListWidgetItem*)), SLOT(itemSelected(QListWidgetItem*))); m_ui->bnAdd->setIcon(themedIcon("arrow-right")); connect(m_ui->bnAdd, SIGNAL(clicked()), SLOT(addSelected())); m_ui->bnRemove->setIcon(themedIcon("arrow-left")); connect(m_ui->bnRemove, SIGNAL(clicked()), SLOT(removeSelected())); m_ui->listBundleContents->setHeaderLabel(i18n("Resource")); m_ui->listBundleContents->setSelectionMode(QAbstractItemView::NoSelection); m_actionManager = actionMgr; refreshListData(); - m_ui->bnEditBundle->hide(); // this bunde editor is pretty broken. we can delete this line once fixed connect(m_ui->bnEditBundle, SIGNAL(clicked()), SLOT(editBundle())); connect(m_ui->importBundleButton, SIGNAL(clicked()), SLOT(slotImportResource())); connect(m_ui->createBundleButton, SIGNAL(clicked()), SLOT(slotCreateBundle())); connect(m_ui->deleteBackupFilesButton, SIGNAL(clicked()), SLOT(slotDeleteBackupFiles())); connect(m_ui->openResourceFolderButton, SIGNAL(clicked()), SLOT(slotOpenResourceFolder())); } void DlgBundleManager::refreshListData() { KoResourceServer *bundleServer = ResourceBundleServerProvider::instance()->resourceBundleServer(); m_ui->listInactive->clear(); m_ui->listActive->clear(); foreach(const QString &f, bundleServer->blackListedFiles()) { ResourceBundle *bundle = new ResourceBundle(f); bundle->load(); if (bundle->valid()) { bundle->setInstalled(false); m_blacklistedBundles[f] = bundle; } } fillListWidget(m_blacklistedBundles.values(), m_ui->listInactive); foreach(ResourceBundle *bundle, bundleServer->resources()) { if (bundle->valid()) { m_activeBundles[bundle->filename()] = bundle; } } fillListWidget(m_activeBundles.values(), m_ui->listActive); } void DlgBundleManager::accept() { KoResourceServer *bundleServer = ResourceBundleServerProvider::instance()->resourceBundleServer(); for (int i = 0; i < m_ui->listActive->count(); ++i) { QListWidgetItem *item = m_ui->listActive->item(i); QByteArray ba = item->data(Qt::UserRole).toByteArray(); ResourceBundle *bundle = bundleServer->resourceByMD5(ba); QMessageBox bundleFeedback; bundleFeedback.setIcon(QMessageBox::Warning); QString feedback = "bundlefeedback"; if (!bundle) { // Get it from the blacklisted bundles foreach (ResourceBundle *b2, m_blacklistedBundles.values()) { if (b2->md5() == ba) { bundle = b2; break; } } } if (bundle) { if(!bundle->isInstalled()){ bundle->install(); //this removes the bundle from the blacklist and add it to the server without saving or putting it in front// if(!bundleServer->addResource(bundle, false, false)){ feedback = i18n("Couldn't add bundle to resource server"); bundleFeedback.setText(feedback); bundleFeedback.exec(); } if(!bundleServer->removeFromBlacklist(bundle)){ feedback = i18n("Couldn't remove bundle from blacklist"); bundleFeedback.setText(feedback); bundleFeedback.exec(); } } else { bundleServer->removeFromBlacklist(bundle); //let's asume that bundles who exist and are installed have to be removed from the blacklist, and if they were already this returns false, so that's not a problem. } } else{ QString feedback = i18n("Bundle doesn't exist!"); bundleFeedback.setText(feedback); bundleFeedback.exec(); } } for (int i = 0; i < m_ui->listInactive->count(); ++i) { QListWidgetItem *item = m_ui->listInactive->item(i); QByteArray ba = item->data(Qt::UserRole).toByteArray(); ResourceBundle *bundle = bundleServer->resourceByMD5(ba); if (bundle && bundle->isInstalled()) { bundle->uninstall(); bundleServer->removeResourceAndBlacklist(bundle); } } KDialog::accept(); } void DlgBundleManager::addSelected() { foreach(QListWidgetItem *item, m_ui->listActive->selectedItems()) { m_ui->listInactive->addItem(m_ui->listActive->takeItem(m_ui->listActive->row(item))); } } void DlgBundleManager::removeSelected() { foreach(QListWidgetItem *item, m_ui->listInactive->selectedItems()) { m_ui->listActive->addItem(m_ui->listInactive->takeItem(m_ui->listInactive->row(item))); } } void DlgBundleManager::itemSelected(QListWidgetItem *current, QListWidgetItem *) { if (!current) { m_ui->lblName->setText(""); m_ui->lblAuthor->setText(""); m_ui->lblEmail->setText(""); m_ui->lblLicense->setText(""); m_ui->lblWebsite->setText(""); m_ui->lblDescription->setPlainText(""); m_ui->lblCreated->setText(""); m_ui->lblUpdated->setText(""); m_ui->lblPreview->setPixmap(QPixmap::fromImage(QImage())); m_ui->listBundleContents->clear(); m_ui->bnEditBundle->setEnabled(false); m_currentBundle = 0; } else { QByteArray ba = current->data(Qt::UserRole).toByteArray(); KoResourceServer *bundleServer = ResourceBundleServerProvider::instance()->resourceBundleServer(); ResourceBundle *bundle = bundleServer->resourceByMD5(ba); if (!bundle) { // Get it from the blacklisted bundles foreach (ResourceBundle *b2, m_blacklistedBundles.values()) { if (b2->md5() == ba) { bundle = b2; break; } } } if (bundle) { m_currentBundle = bundle; m_ui->bnEditBundle->setEnabled(true); m_ui->lblName->setText(bundle->name()); m_ui->lblAuthor->setText(bundle->getMeta("author")); m_ui->lblEmail->setText(bundle->getMeta("email")); m_ui->lblLicense->setText(bundle->getMeta("license")); m_ui->lblWebsite->setText(bundle->getMeta("website")); m_ui->lblDescription->setPlainText(bundle->getMeta("description")); m_ui->lblCreated->setText(bundle->getMeta("created")); m_ui->lblUpdated->setText(bundle->getMeta("updated")); m_ui->lblPreview->setPixmap(QPixmap::fromImage(bundle->image().scaled(128, 128, Qt::KeepAspectRatio, Qt::SmoothTransformation))); m_ui->listBundleContents->clear(); foreach(const QString & resType, bundle->resourceTypes()) { QTreeWidgetItem *toplevel = new QTreeWidgetItem(); if (resType == "gradients") { toplevel->setText(0, i18n("Gradients")); } else if (resType == "patterns") { toplevel->setText(0, i18n("Patterns")); } else if (resType == "brushes") { toplevel->setText(0, i18n("Brushes")); } else if (resType == "palettes") { toplevel->setText(0, i18n("Palettes")); } else if (resType == "workspaces") { toplevel->setText(0, i18n("Workspaces")); } else if (resType == "paintoppresets") { toplevel->setText(0, i18n("Brush Presets")); } m_ui->listBundleContents->addTopLevelItem(toplevel); foreach(const KoResource *res, bundle->resources(resType)) { if (res) { QTreeWidgetItem *i = new QTreeWidgetItem(); i->setIcon(0, QIcon(QPixmap::fromImage(res->image()))); i->setText(0, res->name()); toplevel->addChild(i); } } } } else { m_currentBundle = 0; } } } void DlgBundleManager::itemSelected(QListWidgetItem *current) { itemSelected(current, 0); } void DlgBundleManager::editBundle() { if (m_currentBundle) { DlgCreateBundle dlg(m_currentBundle); if (dlg.exec() != QDialog::Accepted) { return; } } } void DlgBundleManager::fillListWidget(QList bundles, QListWidget *w) { w->setIconSize(QSize(ICON_SIZE, ICON_SIZE)); w->setSelectionMode(QAbstractItemView::MultiSelection); foreach(ResourceBundle *bundle, bundles) { QPixmap pixmap(ICON_SIZE, ICON_SIZE); if (!bundle->image().isNull()) { QImage scaled = bundle->image().scaled(ICON_SIZE, ICON_SIZE, Qt::KeepAspectRatio, Qt::SmoothTransformation); int x = (ICON_SIZE - scaled.width()) / 2; int y = (ICON_SIZE - scaled.height()) / 2; QPainter gc(&pixmap); gc.drawImage(x, y, scaled); gc.end(); } else { pixmap.fill(Qt::gray); } QListWidgetItem *item = new QListWidgetItem(pixmap, bundle->name()); item->setData(Qt::UserRole, bundle->md5()); w->addItem(item); } } void DlgBundleManager::slotImportResource() { if (m_actionManager) { KisAction *action = m_actionManager->actionByName("import_resources"); action->trigger(); refreshListData(); } } void DlgBundleManager::slotCreateBundle() { if (m_actionManager) { KisAction *action = m_actionManager->actionByName("create_bundle"); action->trigger(); } } void DlgBundleManager::slotDeleteBackupFiles() { if (m_actionManager) { KisAction *action = m_actionManager->actionByName("edit_blacklist_cleanup"); action->trigger(); } } void DlgBundleManager::slotOpenResourceFolder() { if (m_actionManager) { KisAction *action = m_actionManager->actionByName("open_resources_directory"); action->trigger(); } } diff --git a/krita/plugins/extensions/resourcemanager/resourcebundle.cpp b/krita/plugins/extensions/resourcemanager/resourcebundle.cpp index ba535d38c13..556bf40b667 100644 --- a/krita/plugins/extensions/resourcemanager/resourcebundle.cpp +++ b/krita/plugins/extensions/resourcemanager/resourcebundle.cpp @@ -1,934 +1,1005 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * 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 "resourcebundle.h" #include "resourcebundle_manifest.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include +#include #include #include #include #include #include #include #include #include "resourcemanager.h" ResourceBundle::ResourceBundle(QString const& fileName) - : KoResource(fileName) + : KoResource(fileName), + m_bundleVersion("1") { setName(QFileInfo(fileName).baseName()); QString calligraVersion(CALLIGRA_VERSION_STRING); QString version; - #ifdef CALLIGRA_GIT_SHA1_STRING QString gitVersion(CALLIGRA_GIT_SHA1_STRING); version = QString("%1 (git %2)").arg(calligraVersion).arg(gitVersion).toLatin1(); #else version = calligraVersion; #endif m_metadata["generator"] = "Krita (" + version + ")"; } ResourceBundle::~ResourceBundle() { } QString ResourceBundle::defaultFileExtension() const { return QString(".bundle"); } bool ResourceBundle::load() { if (filename().isEmpty()) return false; QScopedPointer resourceStore(KoStore::createStore(filename(), KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { qWarning() << "Could not open store on bundle" << filename(); m_installed = false; setValid(false); return false; } else { m_metadata.clear(); + bool toRecreate = false; if (resourceStore->open("META-INF/manifest.xml")) { if (!m_manifest.load(resourceStore->device())) { qWarning() << "Could not open manifest for bundle" << filename(); return false; } resourceStore->close(); foreach(ResourceBundleManifest::ResourceReference ref, m_manifest.files()) { if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Bundle is broken. File" << ref.resourcePath << "is missing"; - return false; + toRecreate = true; + } + else { + resourceStore->close(); } - resourceStore->close(); } + + + if(toRecreate) { + qWarning() << "Due to missing files and wrong entries in the manifest, " << filename() << " will be recreated."; + } + } else { qWarning() << "Could not load META-INF/manifest.xml"; return false; } + bool versionFound = false; if (resourceStore->open("meta.xml")) { KoXmlDocument doc; if (!doc.setContent(resourceStore->device())) { qWarning() << "Could not parse meta.xml for" << filename(); return false; } // First find the manifest:manifest node. KoXmlNode n = doc.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) { continue; } if (n.toElement().tagName() == "meta:meta") { break; } } if (n.isNull()) { qWarning() << "Could not find manifest node for bundle" << filename(); return false; } const KoXmlElement metaElement = n.toElement(); for (n = metaElement.firstChild(); !n.isNull(); n = n.nextSibling()) { if (n.isElement()) { KoXmlElement e = n.toElement(); if (e.tagName() == "meta:generator") { m_metadata.insert("generator", e.firstChild().toText().data()); } else if (e.tagName() == "dc:author") { m_metadata.insert("author", e.firstChild().toText().data()); } else if (e.tagName() == "dc:title") { m_metadata.insert("title", e.firstChild().toText().data()); } else if (e.tagName() == "dc:description") { m_metadata.insert("description", e.firstChild().toText().data()); } else if (e.tagName() == "meta:initial-creator") { m_metadata.insert("author", e.firstChild().toText().data()); } else if (e.tagName() == "dc:creator") { m_metadata.insert("author", e.firstChild().toText().data()); } else if (e.tagName() == "meta:creation-date") { m_metadata.insert("created", e.firstChild().toText().data()); } else if (e.tagName() == "meta:dc-date") { m_metadata.insert("updated", e.firstChild().toText().data()); } else if (e.tagName() == "meta:meta-userdefined") { if (e.attribute("meta:name") == "tag") { m_bundletags << e.attribute("meta:value"); } else { m_metadata.insert(e.attribute("meta:name"), e.attribute("meta:value")); } } + else if(e.tagName() == "meta:bundle-version") { + m_metadata.insert("bundle-version", e.firstChild().toText().data()); + versionFound = true; + } } } resourceStore->close(); } else { qWarning() << "Could not load meta.xml"; return false; } if (resourceStore->open("preview.png")) { // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice // fails with "libpng error: IDAT: CRC error" QByteArray data = resourceStore->device()->readAll(); QBuffer buffer(&data); m_thumbnail.load(&buffer, "PNG"); resourceStore->close(); } else { qWarning() << "Could not open preview.png"; } + /* + * If no version is found it's an old bundle with md5 hashes to fix, or if some manifest resource entry + * doesn't not correspond to a file the bundle is "broken", in both cases we need to recreate the bundle. + */ + if(!versionFound) { + m_metadata.insert("bundle-version", "1"); + qWarning() << filename() << " has an old version and possibly wrong resources md5, so it will be recreated."; + toRecreate = true; + } + + if(toRecreate) { + recreateBundle(resourceStore); + } + m_installed = true; setValid(true); setImage(m_thumbnail); } return true; } bool ResourceBundle::loadFromDevice(QIODevice *) { return false; } bool saveResourceToStore(KoResource *resource, KoStore *store, const QString &resType) { if (!resource) { qWarning() << "No Resource"; return false; } if (!resource->valid()) { qWarning() << "Resource is not valid"; return false; } if (!store || store->bad()) { qWarning() << "No Store or Store is Bad"; return false; } QByteArray ba; QBuffer buf; QFileInfo fi(resource->filename()); - if (fi.exists() && fi.isReadable() && !fi.isWritable()) { + if (fi.exists() && fi.isReadable()) { QFile f(resource->filename()); if (!f.open(QFile::ReadOnly)) { qWarning() << "Could not open resource" << resource->filename(); return false; } ba = f.readAll(); if (ba.size() == 0) { qWarning() << "Resource is empty" << resource->filename(); return false; } f.close(); buf.setBuffer(&ba); } else { - - if (!buf.open(QBuffer::WriteOnly)) { - qWarning() << "Could not open buffer"; - return false; - } - if (!resource->saveToDevice(&buf)) { - qWarning() << "Could not save resource to buffer"; - return false; - } - buf.close(); + qWarning() << "Could not find the resource " << resource->filename() << " or it isn't readable"; + return false; } if (!buf.open(QBuffer::ReadOnly)) { qWarning() << "Could not open buffer"; return false; } Q_ASSERT(!store->hasFile(resType + "/" + resource->shortFilename())); if (!store->open(resType + "/" + resource->shortFilename())) { qWarning() << "Could not open file in store for resource"; return false; } bool res = (store->write(buf.data()) == buf.size()); store->close(); return res; } bool ResourceBundle::save() { if (filename().isEmpty()) return false; addMeta("updated", QDate::currentDate().toString("dd/MM/yyyy")); QDir bundleDir = KGlobal::dirs()->saveLocation("data", "krita/bundles"); bundleDir.cdUp(); QScopedPointer store(KoStore::createStore(filename(), KoStore::Write, "application/x-krita-resourcebundle", KoStore::Zip)); if (!store || store->bad()) return false; foreach(const QString &resType, m_manifest.types()) { if (resType == "ko_gradients") { KoResourceServer* gradientServer = KoResourceServerProvider::instance()->gradientServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KoResource *res = gradientServer->resourceByMD5(ref.md5sum); if (!res) res = gradientServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); if (!saveResourceToStore(res, store.data(), "gradients")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } else if (resType == "ko_patterns") { KoResourceServer* patternServer = KoResourceServerProvider::instance()->patternServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KoResource *res = patternServer->resourceByMD5(ref.md5sum); if (!res) res = patternServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); if (!saveResourceToStore(res, store.data(), "patterns")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } else if (resType == "kis_brushes") { KisBrushResourceServer* brushServer = KisBrushServer::instance()->brushServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KisBrushSP brush = brushServer->resourceByMD5(ref.md5sum); if (!brush) brush = brushServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); KoResource *res = brush.data(); if (!saveResourceToStore(res, store.data(), "brushes")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } else if (resType == "ko_palettes") { KoResourceServer* paletteServer = KoResourceServerProvider::instance()->paletteServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KoResource *res = paletteServer->resourceByMD5(ref.md5sum); if (!res) res = paletteServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); if (!saveResourceToStore(res, store.data(), "palettes")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } else if (resType == "kis_workspaces") { KoResourceServer< KisWorkspaceResource >* workspaceServer = KisResourceServerProvider::instance()->workspaceServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KoResource *res = workspaceServer->resourceByMD5(ref.md5sum); if (!res) res = workspaceServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); if (!saveResourceToStore(res, store.data(), "workspaces")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } else if (resType == "kis_paintoppresets") { KisPaintOpPresetResourceServer* paintoppresetServer = KisResourceServerProvider::instance()->paintOpPresetServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { KisPaintOpPresetSP res = paintoppresetServer->resourceByMD5(ref.md5sum); if (!res) res = paintoppresetServer->resourceByFilename(QFileInfo(ref.resourcePath).fileName()); if (!saveResourceToStore(res.data(), store.data(), "paintoppresets")) { if (res) { qWarning() << "Could not save resource" << resType << res->name(); } else { qWarning() << "could not find resource for" << QFileInfo(ref.resourcePath).fileName(); } } } } } if (!m_thumbnail.isNull()) { QByteArray byteArray; QBuffer buffer(&byteArray); m_thumbnail.save(&buffer, "PNG"); if (!store->open("preview.png")) qWarning() << "Could not open preview.png"; if (store->write(byteArray) != buffer.size()) qWarning() << "Could not write preview.png"; store->close(); } - { - store->open("META-INF/manifest.xml"); - QBuffer buf; - buf.open(QBuffer::WriteOnly); - m_manifest.save(&buf); - buf.close(); - store->write(buf.data()); - store->close(); - } + saveManifest(store); + + saveMetadata(store); - { - QBuffer buf; - - store->open("meta.xml"); - buf.open(QBuffer::WriteOnly); - - KoXmlWriter metaWriter(&buf); - metaWriter.startDocument("office:document-meta"); - metaWriter.startElement("meta:meta"); - - writeMeta("meta:generator", "generator", &metaWriter); - writeMeta("dc:author", "author", &metaWriter); - writeMeta("dc:title", "filename", &metaWriter); - writeMeta("dc:description", "description", &metaWriter); - writeMeta("meta:initial-creator", "author", &metaWriter); - writeMeta("dc:creator", "author", &metaWriter); - writeMeta("meta:creation-date", "created", &metaWriter); - writeMeta("meta:dc-date", "updated", &metaWriter); - writeUserDefinedMeta("email", &metaWriter); - writeUserDefinedMeta("license", &metaWriter); - writeUserDefinedMeta("website", &metaWriter); - foreach (const QString &tag, m_bundletags) { - metaWriter.startElement("meta:meta-userdefined"); - metaWriter.addAttribute("meta:name", "tag"); - metaWriter.addAttribute("meta:value", tag); - metaWriter.endElement(); - } - - metaWriter.endElement(); // meta:meta - metaWriter.endDocument(); - - buf.close(); - store->write(buf.data()); - } - store->close(); store->finalize(); return true; } bool ResourceBundle::saveToDevice(QIODevice */*dev*/) const { return false; } bool ResourceBundle::install() { QStringList md5Mismatch; if (filename().isEmpty()) { qWarning() << "Cannot install bundle: no file name" << this; return false; } QScopedPointer resourceStore(KoStore::createStore(filename(), KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); if (!resourceStore || resourceStore->bad()) { qWarning() << "Cannot open the resource bundle: invalid zip file?"; return false; } foreach(const QString &resType, m_manifest.types()) { dbgResources << "Installing resource type" << resType; if (resType == "gradients") { KoResourceServer* gradientServer = KoResourceServerProvider::instance()->gradientServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KoAbstractGradient *res = gradientServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } if (!res->loadFromDevice(resourceStore->device())) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name(); KoAbstractGradient *res2 = gradientServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... gradientServer->addResource(res, false);//add it! if (!m_gradientsMd5Installed.contains(res->md5())) { m_gradientsMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { gradientServer->addTag(res, tag); } gradientServer->addTag(res, name()); } else { //qWarning() << "Didn't install" << res->name()<<"It already exists on the server"; } } } else if (resType == "patterns") { KoResourceServer* patternServer = KoResourceServerProvider::instance()->patternServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KoPattern *res = patternServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } if (!res->loadFromDevice(resourceStore->device())) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name(); KoPattern *res2 = patternServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... patternServer->addResource(res, false);//add it! if (!m_patternsMd5Installed.contains(res->md5())) { m_patternsMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { patternServer->addTag(res, tag); } patternServer->addTag(res, name()); } } } else if (resType == "brushes") { KisBrushResourceServer *brushServer = KisBrushServer::instance()->brushServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KisBrushSP res = brushServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } if (!res->loadFromDevice(resourceStore->device())) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name(); //find the resouce on the server KisBrushSP res2 = brushServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... brushServer->addResource(res, false);//add it! if (!m_brushesMd5Installed.contains(res->md5())) { m_brushesMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { brushServer->addTag(res.data(), tag); } brushServer->addTag(res.data(), name()); } else { //qWarning() << "Didn't install" << res->name()<<"It already exists on the server"; } } } else if (resType == "palettes") { KoResourceServer* paletteServer = KoResourceServerProvider::instance()->paletteServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KoColorSet *res = paletteServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } if (!res->loadFromDevice(resourceStore->device())) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name(); //find the resouce on the server KoColorSet *res2 = paletteServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... paletteServer->addResource(res, false);//add it! if (!m_palettesMd5Installed.contains(res->md5())) { m_palettesMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { paletteServer->addTag(res, tag); } paletteServer->addTag(res, name()); } else { //qWarning() << "Didn't install" << res->name()<<"It already exists on the server"; } } } else if (resType == "workspaces") { KoResourceServer< KisWorkspaceResource >* workspaceServer = KisResourceServerProvider::instance()->workspaceServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KisWorkspaceResource *res = workspaceServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } if (!res->loadFromDevice(resourceStore->device())) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name(); //the following tries to find the resource by name. KisWorkspaceResource *res2 = workspaceServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... workspaceServer->addResource(res, false);//add it! if (!m_workspacesMd5Installed.contains(res->md5())) { m_workspacesMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { workspaceServer->addTag(res, tag); } workspaceServer->addTag(res, name()); } else { //qWarning() << "Didn't install" << res->name()<<"It already exists on the server"; } } } else if (resType == "paintoppresets") { KisPaintOpPresetResourceServer* paintoppresetServer = KisResourceServerProvider::instance()->paintOpPresetServer(); foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files(resType)) { if (resourceStore->isOpen()) resourceStore->close(); dbgResources << "\tInstalling" << ref.resourcePath; KisPaintOpPresetSP res = paintoppresetServer->createResource(QString("bundle://%1:%2").arg(filename()).arg(ref.resourcePath)); if (!res) { qWarning() << "Could not create resource for" << ref.resourcePath; continue; } if (!resourceStore->open(ref.resourcePath)) { qWarning() << "Failed to open" << ref.resourcePath << "from bundle" << filename(); continue; } // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice // fails with "libpng error: IDAT: CRC error" QByteArray data = resourceStore->device()->readAll(); QBuffer buffer(&data); if (!res->loadFromDevice(&buffer)) { qWarning() << "Failed to load" << ref.resourcePath << "from bundle" << filename(); continue; } dbgResources << "\t\tresource:" << res->name() << "File:" << res->filename(); //the following tries to find the resource by name. KisPaintOpPresetSP res2 = paintoppresetServer->resourceByName(res->name()); if (!res2) {//if it doesn't exist... paintoppresetServer->addResource(res, false);//add it! if (!m_presetsMd5Installed.contains(res->md5())){ m_presetsMd5Installed.append(res->md5()); } if (ref.md5sum!=res->md5()) { md5Mismatch.append(res->name()); } foreach(const QString &tag, ref.tagList) { paintoppresetServer->addTag(res.data(), tag); } paintoppresetServer->addTag(res.data(), name()); } else { //qWarning() << "Didn't install" << res->name()<<"It already exists on the server"; } } } } m_installed = true; -// if(!md5Mismatch.isEmpty()){ -// QString message = i18n("The following resources had mismatching MD5 sums. They may have gotten corrupted, for example, during download."); -// QMessageBox bundleFeedback; -// bundleFeedback.setIcon(QMessageBox::Warning); -// foreach (QString name, md5Mismatch) { -// message.append("\n"); -// message.append(name); -// } -// bundleFeedback.setText(message); -// bundleFeedback.exec(); -// } + if(!md5Mismatch.isEmpty()){ + QString message = i18n("The following resources had mismatching MD5 sums. They may have gotten corrupted, for example, during download."); + QMessageBox bundleFeedback; + bundleFeedback.setIcon(QMessageBox::Warning); + foreach (QString name, md5Mismatch) { + message.append("\n"); + message.append(name); + } + bundleFeedback.setText(message); + bundleFeedback.exec(); + } return true; } bool ResourceBundle::uninstall() { m_installed = false; KoResourceServer* gradientServer = KoResourceServerProvider::instance()->gradientServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("gradients")) { foreach(const QByteArray md5, m_gradientsMd5Installed) { KoAbstractGradient *res = gradientServer->resourceByMD5(md5); if (res) { gradientServer->removeResourceFromServer(res); } } KoResourceServer* patternServer = KoResourceServerProvider::instance()->patternServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("patterns")) { foreach(const QByteArray md5, m_patternsMd5Installed) { KoPattern *res = patternServer->resourceByMD5(md5); if (res) { patternServer->removeResourceFromServer(res); } } KisBrushResourceServer *brushServer = KisBrushServer::instance()->brushServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("brushes")) { foreach(const QByteArray md5, m_brushesMd5Installed) { KisBrushSP res = brushServer->resourceByMD5(md5); if (res) { brushServer->removeResourceFromServer(res); } } KoResourceServer* paletteServer = KoResourceServerProvider::instance()->paletteServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("palettes")) { foreach(const QByteArray md5, m_palettesMd5Installed) { KoColorSet *res = paletteServer->resourceByMD5(md5); if (res) { paletteServer->removeResourceFromServer(res); } } KoResourceServer< KisWorkspaceResource >* workspaceServer = KisResourceServerProvider::instance()->workspaceServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("workspaces")) { foreach(const QByteArray md5, m_workspacesMd5Installed) { KisWorkspaceResource *res = workspaceServer->resourceByMD5(md5); if (res) { workspaceServer->removeResourceFromServer(res); } } KisPaintOpPresetResourceServer* paintoppresetServer = KisResourceServerProvider::instance()->paintOpPresetServer(); //foreach(const ResourceBundleManifest::ResourceReference &ref, m_manifest.files("paintoppresets")) { foreach(const QByteArray md5, m_presetsMd5Installed) { KisPaintOpPresetSP res = paintoppresetServer->resourceByMD5(md5); if (res) { paintoppresetServer->removeResourceFromServer(res); } } return true; } void ResourceBundle::addMeta(const QString &type, const QString &value) { m_metadata.insert(type, value); } const QString ResourceBundle::getMeta(const QString &type, const QString &defaultValue) const { if (m_metadata.contains(type)) { return m_metadata[type]; } else { return defaultValue; } } void ResourceBundle::addResource(QString fileType, QString filePath, QStringList fileTagList, const QByteArray md5sum) { m_manifest.addResource(fileType, filePath, fileTagList, md5sum); } QList ResourceBundle::getTagsList() { return QList::fromSet(m_bundletags); } bool ResourceBundle::isInstalled() { return m_installed; } QStringList ResourceBundle::resourceTypes() { return m_manifest.types(); } QList ResourceBundle::resources(const QString &resType) { QList references = m_manifest.files(resType); QList ret; foreach(const ResourceBundleManifest::ResourceReference &ref, references) { if (resType == "gradients") { KoResourceServer* gradientServer = KoResourceServerProvider::instance()->gradientServer(); KoResource *res = gradientServer->resourceByMD5(ref.md5sum); if (res) ret << res; } else if (resType == "patterns") { KoResourceServer* patternServer = KoResourceServerProvider::instance()->patternServer(); KoResource *res = patternServer->resourceByMD5(ref.md5sum); if (res) ret << res; } else if (resType == "brushes") { KisBrushResourceServer *brushServer = KisBrushServer::instance()->brushServer(); KoResource *res = brushServer->resourceByMD5(ref.md5sum).data(); if (res) ret << res; } else if (resType == "palettes") { KoResourceServer* paletteServer = KoResourceServerProvider::instance()->paletteServer(); KoResource *res = paletteServer->resourceByMD5(ref.md5sum); if (res) ret << res; } else if (resType == "workspaces") { KoResourceServer< KisWorkspaceResource >* workspaceServer = KisResourceServerProvider::instance()->workspaceServer(); KoResource *res = workspaceServer->resourceByMD5(ref.md5sum); if (res) ret << res; } else if (resType == "paintoppresets") { KisPaintOpPresetResourceServer* paintoppresetServer = KisResourceServerProvider::instance()->paintOpPresetServer(); KisPaintOpPresetSP res = paintoppresetServer->resourceByMD5(ref.md5sum); if (res) ret << res.data(); } } return ret; } void ResourceBundle::setThumbnail(QString filename) { if (QFileInfo(filename).exists()) { m_thumbnail = QImage(filename); m_thumbnail = m_thumbnail.scaled(256, 256, Qt::KeepAspectRatio, Qt::SmoothTransformation); Q_ASSERT(!m_thumbnail.isNull()); } else { m_thumbnail = QImage(256, 256, QImage::Format_ARGB32); QPainter gc(&m_thumbnail); gc.fillRect(0, 0, 256, 256, Qt::red); gc.end(); } } - -QByteArray ResourceBundle::generateMD5() const -{ - QFile f(filename()); - if (f.exists()) { - f.open(QFile::ReadOnly); - QByteArray ba = f.readAll(); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - return md5.result(); - } - return QByteArray(); -} - void ResourceBundle::writeMeta(const char *metaTag, const QString &metaKey, KoXmlWriter *writer) { if (m_metadata.contains(metaKey)) { writer->startElement(metaTag); writer->addTextNode(m_metadata[metaKey].toUtf8()); writer->endElement(); } } void ResourceBundle::writeUserDefinedMeta(const QString &metaKey, KoXmlWriter *writer) { if (m_metadata.contains(metaKey)) { writer->startElement("meta:meta-userdefined"); writer->addAttribute("meta:name", metaKey); writer->addAttribute("meta:value", m_metadata[metaKey]); writer->endElement(); } } void ResourceBundle::setInstalled(bool install) { m_installed = install; } + +void ResourceBundle::saveMetadata(QScopedPointer &store) +{ + QBuffer buf; + + store->open("meta.xml"); + buf.open(QBuffer::WriteOnly); + + KoXmlWriter metaWriter(&buf); + metaWriter.startDocument("office:document-meta"); + metaWriter.startElement("meta:meta"); + + writeMeta("meta:generator", "generator", &metaWriter); + + metaWriter.startElement("meta:bundle-version"); + metaWriter.addTextNode(m_bundleVersion.toUtf8()); + metaWriter.endElement(); + + writeMeta("dc:author", "author", &metaWriter); + writeMeta("dc:title", "filename", &metaWriter); + writeMeta("dc:description", "description", &metaWriter); + writeMeta("meta:initial-creator", "author", &metaWriter); + writeMeta("dc:creator", "author", &metaWriter); + writeMeta("meta:creation-date", "created", &metaWriter); + writeMeta("meta:dc-date", "updated", &metaWriter); + writeUserDefinedMeta("email", &metaWriter); + writeUserDefinedMeta("license", &metaWriter); + writeUserDefinedMeta("website", &metaWriter); + foreach (const QString &tag, m_bundletags) { + metaWriter.startElement("meta:meta-userdefined"); + metaWriter.addAttribute("meta:name", "tag"); + metaWriter.addAttribute("meta:value", tag); + metaWriter.endElement(); + } + + metaWriter.endElement(); // meta:meta + metaWriter.endDocument(); + + buf.close(); + store->write(buf.data()); + store->close(); +} + +void ResourceBundle::saveManifest(QScopedPointer &store) +{ + store->open("META-INF/manifest.xml"); + QBuffer buf; + buf.open(QBuffer::WriteOnly); + m_manifest.save(&buf); + buf.close(); + store->write(buf.data()); + store->close(); +} + +void ResourceBundle::recreateBundle(QScopedPointer &oldStore) +{ + // Save a copy of the unmodified bundle, so that if anything goes bad the user doesn't lose it + QFile file(filename()); + file.copy(filename() + ".old"); + + QString newStoreName = filename() + ".tmp"; + QScopedPointer store(KoStore::createStore(newStoreName, KoStore::Write, "application/x-krita-resourcebundle", KoStore::Zip)); + KoHashGenerator *generator = KoHashGeneratorProvider::instance()->getGenerator("MD5"); + ResourceBundleManifest newManifest; + + addMeta("updated", QDate::currentDate().toString("dd/MM/yyyy")); + + foreach(ResourceBundleManifest::ResourceReference ref, m_manifest.files()) { + // Wrong manifest entry found, skip it + if(!oldStore->open(ref.resourcePath)) + continue; + + store->open(ref.resourcePath); + + QByteArray data = oldStore->device()->readAll(); + oldStore->close(); + store->write(data); + store->close(); + QByteArray result = generator->generateHash(data); + newManifest.addResource(ref.fileTypeName, ref.resourcePath, ref.tagList, result); + } + + m_manifest = newManifest; + + if (!m_thumbnail.isNull()) { + QByteArray byteArray; + QBuffer buffer(&byteArray); + m_thumbnail.save(&buffer, "PNG"); + if (!store->open("preview.png")) qWarning() << "Could not open preview.png"; + if (store->write(byteArray) != buffer.size()) qWarning() << "Could not write preview.png"; + store->close(); + } + + saveManifest(store); + saveMetadata(store); + + store->finalize(); + + // Remove the current bundle and then move the tmp one to be the correct one + file.setFileName(filename()); + file.remove(); + file.setFileName(newStoreName); + file.rename(filename()); +} diff --git a/krita/plugins/extensions/resourcemanager/resourcebundle.h b/krita/plugins/extensions/resourcemanager/resourcebundle.h index 7e3c8b93849..8a9783d4bf0 100644 --- a/krita/plugins/extensions/resourcemanager/resourcebundle.h +++ b/krita/plugins/extensions/resourcemanager/resourcebundle.h @@ -1,137 +1,157 @@ /* * Copyright (c) 2014 Victor Lafon metabolic.ewilan@hotmail.fr * * 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 KORESOURCEBUNDLE_H #define KORESOURCEBUNDLE_H #include #include #include #include "KoResource.h" #include "resourcebundle_manifest.h" +class KoStore; + /** * @brief The ResourceBundle class * @details Describe the resource bundles as KoResources */ class ResourceBundle : public KoResource { public: /** * @brief ResourceBundle : Ctor * @param bundlePath the path of the bundle */ ResourceBundle(QString const& fileName); /** * @brief ~ResourceBundle : Dtor */ virtual ~ResourceBundle(); /** * @brief defaultFileExtension * @return the default file extension which should be when saving the resource */ QString defaultFileExtension() const; /** * @brief load : Load this resource. * @return true if succeed, false otherwise. */ bool load(); virtual bool loadFromDevice(QIODevice *dev); /** * @brief save : Save this resource. * @return true if succeed, false otherwise. */ bool save(); virtual bool saveToDevice(QIODevice* dev) const; /** * @brief install : Install the contents of the resource bundle. */ bool install(); /** * @brief uninstall : Uninstall the resource bundle. */ bool uninstall(); /** * @brief addMeta : Add a Metadata to the resource * @param type type of the metadata * @param value value of the metadata */ void addMeta(const QString &type, const QString &value); const QString getMeta(const QString &type, const QString &defaultValue = QString()) const; /** * @brief addFile : Add a file to the bundle * @param fileType type of the resource file * @param filePath path of the resource file */ void addResource(QString fileType, QString filePath, QStringList fileTagList, const QByteArray md5sum); QList getTagsList(); /** * @brief isInstalled * @return true if the bundle is installed, false otherwise. */ bool isInstalled(); /** * @brief setInstalled * This allows you to set installed or uninstalled upon loading. This is used with blacklists. */ void setInstalled(bool install); void setThumbnail(QString); - QStringList resourceTypes(); - QList resources(const QString &resType); + /** + * @brief saveMetadata: saves bundle metadata + * @param store bundle where to save the metadata + */ + void saveMetadata(QScopedPointer &store); -protected: + /** + * @brief saveManifest: saves bundle manifest + * @param store bundle where to save the manifest + */ + void saveManifest(QScopedPointer &store); - virtual QByteArray generateMD5() const; + /** + * @brief recreateBundle + * It recreates the bundle by copying the old bundle information to a new store + * and recalculating the md5 of each resource. + * @param oldStore the old store to be recreated. + */ + void recreateBundle(QScopedPointer &oldStore); + + + QStringList resourceTypes(); + QList resources(const QString &resType); private: void writeMeta(const char *metaTag, const QString &metaKey, KoXmlWriter *writer); void writeUserDefinedMeta(const QString &metaKey, KoXmlWriter *writer); private: QImage m_thumbnail; ResourceBundleManifest m_manifest; QMap m_metadata; QSet m_bundletags; bool m_installed; QList m_gradientsMd5Installed; QList m_patternsMd5Installed; QList m_brushesMd5Installed; QList m_palettesMd5Installed; QList m_workspacesMd5Installed; QList m_presetsMd5Installed; + QString m_bundleVersion; }; #endif // KORESOURCEBUNDLE_H diff --git a/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.cpp b/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.cpp index b47c10a7bc7..aeb730047b3 100644 --- a/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.cpp +++ b/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.cpp @@ -1,221 +1,233 @@ /* This file is part of the KDE project Copyright (C) 2014, Victor Lafon This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #include "resourcebundle_manifest.h" #include #include #include #include #include #include +#include #include #include #include #include "KoPattern.h" #include "KoAbstractGradient.h" #include "kis_brush_server.h" #include "kis_resource_server_provider.h" #include "kis_paintop_preset.h" #include "kis_workspace_resource.h" QString resourceTypeToManifestType(const QString &type) { if (type.startsWith("ko_")) { return type.mid(3); } else if (type.startsWith("kis_")) { return type.mid(4); } else { return type; } } QString manifestTypeToResourceType(const QString &type) { if (type == "patterns" || type == "gradients" || type == "palettes") { return "ko_" + type; } else { return "kis_" + type; } } ResourceBundleManifest::ResourceBundleManifest() { } ResourceBundleManifest::~ResourceBundleManifest() { } bool ResourceBundleManifest::load(QIODevice *device) { m_resources.clear(); if (!device->isOpen()) { if (!device->open(QIODevice::ReadOnly)) { return false; } } KoXmlDocument manifestDocument; QString errorMessage; int errorLine; int errorColumn; if (!manifestDocument.setContent(device, true, &errorMessage, &errorLine, &errorColumn)) { return false; } if (!errorMessage.isEmpty()) { qWarning() << "Error parsing manifest" << errorMessage << "line" << errorLine << "column" << errorColumn; return false; } // First find the manifest:manifest node. KoXmlNode n = manifestDocument.firstChild(); for (; !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) { continue; } if (n.toElement().localName() == "manifest" && n.toElement().namespaceURI() == KoXmlNS::manifest) { break; } } if (n.isNull()) { // "Could not find manifest:manifest"; return false; } // Now loop through the children of the manifest:manifest and // store all the manifest:file-entry elements. const KoXmlElement manifestElement = n.toElement(); for (n = manifestElement.firstChild(); !n.isNull(); n = n.nextSibling()) { if (!n.isElement()) continue; KoXmlElement el = n.toElement(); if (!(el.localName() == "file-entry" && el.namespaceURI() == KoXmlNS::manifest)) continue; QString fullPath = el.attributeNS(KoXmlNS::manifest, "full-path", QString()); QString mediaType = el.attributeNS(KoXmlNS::manifest, "media-type", QString("")); QString md5sum = el.attributeNS(KoXmlNS::manifest, "md5sum", QString("")); QString version = el.attributeNS(KoXmlNS::manifest, "version", QString()); QStringList tagList; KoXmlNode tagNode = n.firstChildElement().firstChildElement(); while (!tagNode.isNull()) { if (tagNode.firstChild().isText()) { tagList.append(tagNode.firstChild().toText().data()); } tagNode = tagNode.nextSibling(); } // Only if fullPath is valid, should we store this entry. // If not, we don't bother to find out exactly what is wrong, we just skip it. if (!fullPath.isNull() && !mediaType.isEmpty() && !md5sum.isEmpty()) { addResource(mediaType, fullPath, tagList, QByteArray::fromHex(md5sum.toLatin1())); } } return true; } bool ResourceBundleManifest::save(QIODevice *device) { if (!device->isOpen()) { if (!device->open(QIODevice::WriteOnly)) { return false; } } KoXmlWriter manifestWriter(device); manifestWriter.startDocument("manifest:manifest"); manifestWriter.startElement("manifest:manifest"); manifestWriter.addAttribute("xmlns:manifest", KoXmlNS::manifest); manifestWriter.addAttribute("manifest:version", "1.2"); manifestWriter.addManifestEntry("/", "application/x-krita-resourcebundle"); foreach(QString resourceType, m_resources.uniqueKeys()) { foreach(const ResourceReference &resource, m_resources[resourceType].values()) { manifestWriter.startElement("manifest:file-entry"); manifestWriter.addAttribute("manifest:media-type", resourceTypeToManifestType(resourceType)); manifestWriter.addAttribute("manifest:full-path", resourceTypeToManifestType(resourceType) + "/" + QFileInfo(resource.resourcePath).fileName()); manifestWriter.addAttribute("manifest:md5sum", QString(resource.md5sum.toHex())); if (!resource.tagList.isEmpty()) { manifestWriter.startElement("manifest:tags"); foreach(const QString tag, resource.tagList) { manifestWriter.startElement("manifest:tag"); manifestWriter.addTextNode(tag); manifestWriter.endElement(); } manifestWriter.endElement(); } manifestWriter.endElement(); } } manifestWriter.endElement(); manifestWriter.endDocument(); return true; } void ResourceBundleManifest::addResource(const QString &fileTypeName, const QString &fileName, const QStringList &fileTagList, const QByteArray &md5) { - ResourceReference ref(fileName, fileTagList, md5); + ResourceReference ref(fileName, fileTagList, fileTypeName, md5); if (!m_resources.contains(fileTypeName)) { m_resources[fileTypeName] = QMap(); } m_resources[fileTypeName].insert(fileName, ref); } QStringList ResourceBundleManifest::types() const { return m_resources.keys(); } QStringList ResourceBundleManifest::tags() const { QSet tags; foreach(const QString &type, m_resources.keys()) { foreach(const ResourceReference &ref, m_resources[type].values()) { tags += ref.tagList.toSet(); } } return QStringList::fromSet(tags); } QList ResourceBundleManifest::files(const QString &type) const { - if (!m_resources.contains(type)) { + // If no type is specified we return all the resources + if(type.isEmpty()) { + QList resources; + QList >::iterator i; + QList > values = m_resources.values(); + for(i = values.begin(); i != values.end(); ++i) { + resources.append(i->values()); + } + + return resources; + } + else if (!m_resources.contains(type)) { return QList(); } return m_resources[type].values(); } void ResourceBundleManifest::removeFile(QString fileName) { QList tags; foreach(const QString &type, m_resources.keys()) { if (m_resources[type].contains(fileName)) { m_resources[type].remove(fileName); } } } diff --git a/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.h b/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.h index e4de7a2e440..d3c6c683e39 100644 --- a/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.h +++ b/krita/plugins/extensions/resourcemanager/resourcebundle_manifest.h @@ -1,95 +1,96 @@ /* This file is part of the KDE project Copyright (C) 2014, Victor Lafon This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ #ifndef KOXMLRESOURCEBUNDLEMANIFEST_H #define KOXMLRESOURCEBUNDLEMANIFEST_H #include #include #include -#include "krita_export.h" class ResourceBundleManifest { public: struct ResourceReference { - ResourceReference(const QString &_resourcePath, const QList &_tagList, const QByteArray &_md5) { + ResourceReference(const QString &_resourcePath, const QList &_tagList, const QString &_fileTypeName, const QByteArray &_md5) { resourcePath = _resourcePath; tagList = _tagList; + fileTypeName = _fileTypeName; md5sum = _md5; } QString resourcePath; QList tagList; + QString fileTypeName; QByteArray md5sum; }; /** * @brief ResourceBundleManifest : Ctor * @param xmlName the name of the XML file to be created */ ResourceBundleManifest(); /** * @brief ~ResourceBundleManifest : Dtor */ virtual ~ResourceBundleManifest(); /** * @brief load the ResourceBundleManifest from the given device */ bool load(QIODevice *device); /** * @brief save the ResourceBundleManifest to the given device */ bool save(QIODevice *device); /** * @brief addTag : Add a file tag as a child of the fileType tag. * @param fileType the type of the file to be added * @param fileName the name of the file to be added * @param emptyFile true if the file is empty * @return the element corresponding to the created tag. */ void addResource(const QString &fileType, const QString &fileName, const QStringList &tagFileList, const QByteArray &md5); QStringList types() const; QStringList tags() const; QList files(const QString &type = QString()) const; /** * @brief removeFile : remove a file from the manifest * @param fileName : the name of the file to be removed * @return the list of resource tags to be removed from meta file. */ void removeFile(QString fileName); private: QMap > m_resources; }; #endif // KOXMLRESOURCEBUNDLEMANIFEST_H diff --git a/krita/plugins/formats/jpeg/kis_jpeg_converter.cc b/krita/plugins/formats/jpeg/kis_jpeg_converter.cc index ec00fd6d16d..4bc259ecbbd 100644 --- a/krita/plugins/formats/jpeg/kis_jpeg_converter.cc +++ b/krita/plugins/formats/jpeg/kis_jpeg_converter.cc @@ -1,743 +1,754 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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_jpeg_converter.h" #include #include #include #ifdef HAVE_LCMS2 # include #else # include #endif extern "C" { #include } #include #include #include #include #include #include #include #include #include #include #include #include #include #include +#include "KoColorModelStandardIds.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_iterator_ng.h" #include #define ICC_MARKER (JPEG_APP0 + 2) /* JPEG marker code for ICC */ #define ICC_OVERHEAD_LEN 14 /* size of non-profile data in APP2 */ #define MAX_BYTES_IN_MARKER 65533 /* maximum data len of a JPEG marker */ #define MAX_DATA_BYTES_IN_MARKER (MAX_BYTES_IN_MARKER - ICC_OVERHEAD_LEN) const char photoshopMarker[] = "Photoshop 3.0\0"; //const char photoshopBimId_[] = "8BIM"; const uint16_t photoshopIptc = 0x0404; const char xmpMarker[] = "http://ns.adobe.com/xap/1.0/\0"; const QByteArray photoshopIptc_((char*)&photoshopIptc, 2); namespace { J_COLOR_SPACE getColorTypeforColorSpace(const KoColorSpace * cs) { if (KoID(cs->id()) == KoID("GRAYA") || cs->id() == "GRAYAU16" || cs->id() == "GRAYA16") { return JCS_GRAYSCALE; } if (KoID(cs->id()) == KoID("RGBA") || KoID(cs->id()) == KoID("RGBA16")) { return JCS_RGB; } - if (KoID(cs->id()) == KoID("CMYK") || KoID(cs->id()) == KoID("CMYK16")) { + if (KoID(cs->id()) == KoID("CMYK") || KoID(cs->id()) == KoID("CMYKAU16")) { return JCS_CMYK; } - QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot export images in %1.\nWill save as RGB.", cs->name())) ; return JCS_UNKNOWN; } QString getColorSpaceModelForColorType(J_COLOR_SPACE color_type) { dbgFile << "color_type =" << color_type; if (color_type == JCS_GRAYSCALE) { return GrayAColorModelID.id(); } else if (color_type == JCS_RGB) { return RGBAColorModelID.id(); } else if (color_type == JCS_CMYK) { return CMYKAColorModelID.id(); } return ""; } } -KisJPEGConverter::KisJPEGConverter(KisDocument *doc) +KisJPEGConverter::KisJPEGConverter(KisDocument *doc, bool batchMode) { m_doc = doc; m_job = 0; m_stop = false; + m_batchMode = batchMode; } KisJPEGConverter::~KisJPEGConverter() { } KisImageBuilder_Result KisJPEGConverter::decode(const KUrl& uri) { struct jpeg_decompress_struct cinfo; struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); jpeg_create_decompress(&cinfo); Q_ASSERT(uri.isLocalFile()); // open the file QFile file(uri.toLocalFile()); if (!file.exists()) { return (KisImageBuilder_RESULT_NOT_EXIST); } if (!file.open(QIODevice::ReadOnly)) { return (KisImageBuilder_RESULT_BAD_FETCH); } KisJPEGSource::setSource(&cinfo, &file); jpeg_save_markers(&cinfo, JPEG_COM, 0xFFFF); /* Save APP0..APP15 markers */ for (int m = 0; m < 16; m++) jpeg_save_markers(&cinfo, JPEG_APP0 + m, 0xFFFF); // setup_read_icc_profile(&cinfo); // read header jpeg_read_header(&cinfo, true); // start reading jpeg_start_decompress(&cinfo); // Get the colorspace QString modelId = getColorSpaceModelForColorType(cinfo.out_color_space); if (modelId.isEmpty()) { dbgFile << "unsupported colorspace :" << cinfo.out_color_space; jpeg_destroy_decompress(&cinfo); return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE; } uchar* profile_data; uint profile_len; const KoColorProfile* profile = 0; QByteArray profile_rawdata; if (read_icc_profile(&cinfo, &profile_data, &profile_len)) { profile_rawdata.resize(profile_len); memcpy(profile_rawdata.data(), profile_data, profile_len); cmsHPROFILE hProfile = cmsOpenProfileFromMem(profile_data, profile_len); if (hProfile != (cmsHPROFILE) NULL) { profile = KoColorSpaceRegistry::instance()->createColorProfile(modelId, Integer8BitsColorDepthID.id(), profile_rawdata); Q_CHECK_PTR(profile); dbgFile <<"profile name:" << profile->name() <<" product information:" << profile->info(); if (!profile->isSuitableForOutput()) { dbgFile << "the profile is not suitable for output and therefore cannot be used in krita, we need to convert the image to a standard profile"; // TODO: in ko2 popup a selection menu to inform the user } } } // Check that the profile is used by the color space if (profile && !KoColorSpaceRegistry::instance()->colorSpaceFactory( KoColorSpaceRegistry::instance()->colorSpaceId( modelId, Integer8BitsColorDepthID.id()))->profileIsCompatible(profile)) { warnFile << "The profile " << profile->name() << " is not compatible with the color space model " << modelId; profile = 0; } // Retrieve a pointer to the colorspace const KoColorSpace* cs; if (profile && profile->isSuitableForOutput()) { dbgFile << "image has embedded profile:" << profile -> name() << ""; cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), profile); } else cs = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), ""); if (cs == 0) { dbgFile << "unknown colorspace"; jpeg_destroy_decompress(&cinfo); return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE; } // TODO fixit // Create the cmsTransform if needed KoColorTransformation* transform = 0; if (profile && !profile->isSuitableForOutput()) { transform = KoColorSpaceRegistry::instance()->colorSpace(modelId, Integer8BitsColorDepthID.id(), profile)->createColorConverter(cs, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); } // Apparently an invalid transform was created from the profile. See bug https://bugs.kde.org/show_bug.cgi?id=255451. // After 2.3: warn the user! if (transform && !transform->isValid()) { delete transform; transform = 0; } // Creating the KisImageWSP if (! m_image) { m_image = new KisImage(m_doc->createUndoStore(), cinfo.image_width, cinfo.image_height, cs, "built image"); Q_CHECK_PTR(m_image); } // Set resolution double xres = 72, yres = 72; if (cinfo.density_unit == 1) { xres = cinfo.X_density; yres = cinfo.Y_density; } else if (cinfo.density_unit == 2) { xres = cinfo.X_density * 2.54; yres = cinfo.Y_density * 2.54; } if (xres < 72) { xres = 72; } if (yres < 72) { yres = 72; } m_image->setResolution(POINT_TO_INCH(xres), POINT_TO_INCH(yres)); // It is the "invert" macro because we convert from pointer-per-inchs to points // Create layer KisPaintLayerSP layer = KisPaintLayerSP(new KisPaintLayer(m_image.data(), m_image -> nextLayerName(), quint8_MAX)); // Read data JSAMPROW row_pointer = new JSAMPLE[cinfo.image_width*cinfo.num_components]; for (; cinfo.output_scanline < cinfo.image_height;) { KisHLineIteratorSP it = layer->paintDevice()->createHLineIteratorNG(0, cinfo.output_scanline, cinfo.image_width); jpeg_read_scanlines(&cinfo, &row_pointer, 1); quint8 *src = row_pointer; switch (cinfo.out_color_space) { case JCS_GRAYSCALE: do { quint8 *d = it->rawData(); d[0] = *(src++); if (transform) transform->transform(d, d, 1); d[1] = quint8_MAX; } while (it->nextPixel()); break; case JCS_RGB: do { quint8 *d = it->rawData(); d[2] = *(src++); d[1] = *(src++); d[0] = *(src++); if (transform) transform->transform(d, d, 1); d[3] = quint8_MAX; } while (it->nextPixel()); break; case JCS_CMYK: do { quint8 *d = it->rawData(); d[0] = quint8_MAX - *(src++); d[1] = quint8_MAX - *(src++); d[2] = quint8_MAX - *(src++); d[3] = quint8_MAX - *(src++); if (transform) transform->transform(d, d, 1); d[4] = quint8_MAX; } while (it->nextPixel()); break; default: return KisImageBuilder_RESULT_UNSUPPORTED; } } m_image->addNode(KisNodeSP(layer.data()), m_image->rootLayer().data()); // Read exif information dbgFile << "Looking for exif information"; for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != NULL; marker = marker->next) { dbgFile << "Marker is" << marker->marker; if (marker->marker != (JOCTET)(JPEG_APP0 + 1) || marker->data_length < 14) { continue; /* Exif data is in an APP1 marker of at least 14 octets */ } if (GETJOCTET(marker->data[0]) != (JOCTET) 0x45 || GETJOCTET(marker->data[1]) != (JOCTET) 0x78 || GETJOCTET(marker->data[2]) != (JOCTET) 0x69 || GETJOCTET(marker->data[3]) != (JOCTET) 0x66 || GETJOCTET(marker->data[4]) != (JOCTET) 0x00 || GETJOCTET(marker->data[5]) != (JOCTET) 0x00) continue; /* no Exif header */ dbgFile << "Found exif information of length :" << marker->data_length; KisMetaData::IOBackend* exifIO = KisMetaData::IOBackendRegistry::instance()->value("exif"); Q_ASSERT(exifIO); QByteArray byteArray((const char*)marker->data + 6, marker->data_length - 6); QBuffer buf(&byteArray); exifIO->loadFrom(layer->metaData(), &buf); // Interpret orientation tag if (layer->metaData()->containsEntry("http://ns.adobe.com/tiff/1.0/", "Orientation")) { KisMetaData::Entry& entry = layer->metaData()->getEntry("http://ns.adobe.com/tiff/1.0/", "Orientation"); if (entry.value().type() == KisMetaData::Value::Variant) { switch (entry.value().asVariant().toInt()) { case 2: KisTransformWorker::mirrorY(layer->paintDevice()); break; case 3: image()->rotateImage(M_PI); break; case 4: KisTransformWorker::mirrorX(layer->paintDevice()); break; case 5: image()->rotateImage(M_PI / 2); KisTransformWorker::mirrorY(layer->paintDevice()); break; case 6: image()->rotateImage(M_PI / 2); break; case 7: image()->rotateImage(M_PI / 2); KisTransformWorker::mirrorX(layer->paintDevice()); break; case 8: image()->rotateImage(-M_PI / 2 + M_PI*2); break; default: break; } } entry.value().setVariant(1); } break; } dbgFile << "Looking for IPTC information"; for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != NULL; marker = marker->next) { dbgFile << "Marker is" << marker->marker; if (marker->marker != (JOCTET)(JPEG_APP0 + 13) || marker->data_length < 14) { continue; /* IPTC data is in an APP13 marker of at least 16 octets */ } if (memcmp(marker->data, photoshopMarker, 14) != 0) { for (int i = 0; i < 14; i++) { dbgFile << (int)(*(marker->data + i)) << "" << (int)(photoshopMarker[i]); } dbgFile << "No photoshop marker"; continue; /* No IPTC Header */ } dbgFile << "Found Photoshop information of length :" << marker->data_length; KisMetaData::IOBackend* iptcIO = KisMetaData::IOBackendRegistry::instance()->value("iptc"); Q_ASSERT(iptcIO); const Exiv2::byte *record = 0; uint32_t sizeIptc = 0; uint32_t sizeHdr = 0; // Find actual Iptc data within the APP13 segment if (!Exiv2::Photoshop::locateIptcIrb((Exiv2::byte*)(marker->data + 14), marker->data_length - 14, &record, &sizeHdr, &sizeIptc)) { if (sizeIptc) { // Decode the IPTC data QByteArray byteArray((const char*)(record + sizeHdr), sizeIptc); iptcIO->loadFrom(layer->metaData(), new QBuffer(&byteArray)); } else { dbgFile << "IPTC Not found in Photoshop marker"; } } break; } dbgFile << "Looking for XMP information"; for (jpeg_saved_marker_ptr marker = cinfo.marker_list; marker != NULL; marker = marker->next) { dbgFile << "Marker is" << marker->marker; if (marker->marker != (JOCTET)(JPEG_APP0 + 1) || marker->data_length < 31) { continue; /* XMP data is in an APP1 marker of at least 31 octets */ } if (memcmp(marker->data, xmpMarker, 29) != 0) { dbgFile << "Not XMP marker"; continue; /* No xmp Header */ } dbgFile << "Found XMP Marker of length " << marker->data_length; QByteArray byteArray((const char*)marker->data + 29, marker->data_length - 29); KisMetaData::IOBackend* xmpIO = KisMetaData::IOBackendRegistry::instance()->value("xmp"); Q_ASSERT(xmpIO); xmpIO->loadFrom(layer->metaData(), new QBuffer(&byteArray)); break; } // Dump loaded metadata layer->metaData()->debugDump(); // Check whether the metadata has resolution info, too... if (cinfo.density_unit == 0 && layer->metaData()->containsEntry("tiff:XResolution") && layer->metaData()->containsEntry("tiff:YResolution")) { double xres = layer->metaData()->getEntry("tiff:XResolution").value().asDouble(); double yres = layer->metaData()->getEntry("tiff:YResolution").value().asDouble(); if (xres != 0 && yres != 0) { m_image->setResolution(POINT_TO_INCH(xres), POINT_TO_INCH(yres)); // It is the "invert" macro because we convert from pointer-per-inchs to points } } // Finish decompression jpeg_finish_decompress(&cinfo); jpeg_destroy_decompress(&cinfo); delete [] row_pointer; return KisImageBuilder_RESULT_OK; } KisImageBuilder_Result KisJPEGConverter::buildImage(const KUrl& uri) { if (uri.isEmpty()) return KisImageBuilder_RESULT_NO_URI; if (!KIO::NetAccess::exists(uri, KIO::NetAccess::SourceSide, QApplication::activeWindow())) { return KisImageBuilder_RESULT_NOT_EXIST; } // We're not set up to handle asynchronous loading at the moment. KisImageBuilder_Result result = KisImageBuilder_RESULT_FAILURE; QString tmpFile; if (KIO::NetAccess::download(uri, tmpFile, QApplication::activeWindow())) { KUrl uriTF; uriTF.setPath(tmpFile); result = decode(uriTF); KIO::NetAccess::removeTempFile(tmpFile); } return result; } KisImageWSP KisJPEGConverter::image() { return m_image; } KisImageBuilder_Result KisJPEGConverter::buildFile(const KUrl& uri, KisPaintLayerSP layer, vKisAnnotationSP_it /*annotationsStart*/, vKisAnnotationSP_it /*annotationsEnd*/, KisJPEGOptions options, KisMetaData::Store* metaData) { if (!layer) return KisImageBuilder_RESULT_INVALID_ARG; KisImageWSP image = KisImageWSP(layer->image()); if (!image) return KisImageBuilder_RESULT_EMPTY; if (uri.isEmpty()) return KisImageBuilder_RESULT_NO_URI; if (!uri.isLocalFile()) return KisImageBuilder_RESULT_NOT_LOCAL; const KoColorSpace * cs = layer->colorSpace(); J_COLOR_SPACE color_type = getColorTypeforColorSpace(cs); + + if (!m_batchMode && cs->colorDepthId() != Integer8BitsColorDepthID) { + QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Warning: JPEG only supports 8 bits per channel. Your image uses: %1. Krita will save your image as 8 bits per channel.", cs->name())); + } + if (color_type == JCS_UNKNOWN) { + if (!m_batchMode) { + QMessageBox::information(0, i18nc("@title:window", "Krita"), i18n("Cannot export images in %1.\nWill save as RGB.", cs->name())); + } KUndo2Command *tmp = layer->paintDevice()->convertTo(KoColorSpaceRegistry::instance()->rgb8(), KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); delete tmp; + cs = KoColorSpaceRegistry::instance()->rgb8(); color_type = JCS_RGB; } if (options.forceSRGB) { const KoColorSpace* dst = KoColorSpaceRegistry::instance()->colorSpace(RGBAColorModelID.id(), layer->colorSpace()->colorDepthId().id(), "sRGB built-in - (lcms internal)"); KUndo2Command *tmp = layer->paintDevice()->convertTo(dst); delete tmp; + cs = dst; color_type = JCS_RGB; } // Open file for writing QFile file(uri.toLocalFile()); if (!file.open(QIODevice::WriteOnly)) { return (KisImageBuilder_RESULT_FAILURE); } uint height = image->height(); uint width = image->width(); // Initialize structure struct jpeg_compress_struct cinfo; jpeg_create_compress(&cinfo); // Initialize error output struct jpeg_error_mgr jerr; cinfo.err = jpeg_std_error(&jerr); // Initialize output stream KisJPEGDestination::setDestination(&cinfo, &file); cinfo.image_width = width; // image width and height, in pixels cinfo.image_height = height; cinfo.input_components = cs->colorChannelCount(); // number of color channels per pixel */ cinfo.in_color_space = color_type; // colorspace of input image // Set default compression parameters jpeg_set_defaults(&cinfo); // Customize them jpeg_set_quality(&cinfo, options.quality, options.baseLineJPEG); if (options.progressive) { jpeg_simple_progression(&cinfo); } // Optimize ? cinfo.optimize_coding = options.optimize; // Smoothing cinfo.smoothing_factor = options.smooth; // Subsampling switch (options.subsampling) { default: case 0: { cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } break; case 1: { cinfo.comp_info[0].h_samp_factor = 2; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } break; case 2: { cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 2; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } break; case 3: { cinfo.comp_info[0].h_samp_factor = 1; cinfo.comp_info[0].v_samp_factor = 1; cinfo.comp_info[1].h_samp_factor = 1; cinfo.comp_info[1].v_samp_factor = 1; cinfo.comp_info[2].h_samp_factor = 1; cinfo.comp_info[2].v_samp_factor = 1; } break; } // Save resolution cinfo.X_density = INCH_TO_POINT(image->xRes()); // It is the "invert" macro because we convert from pointer-per-inchs to points cinfo.Y_density = INCH_TO_POINT(image->yRes()); // It is the "invert" macro because we convert from pointer-per-inchs to points cinfo.density_unit = 1; cinfo.write_JFIF_header = 1; // Start compression jpeg_start_compress(&cinfo, true); // Save exif and iptc information if any available if (metaData && !metaData->empty()) { metaData->applyFilters(options.filters); // Save EXIF if (options.exif) { dbgFile << "Trying to save exif information"; KisMetaData::IOBackend* exifIO = KisMetaData::IOBackendRegistry::instance()->value("exif"); Q_ASSERT(exifIO); QBuffer buffer; exifIO->saveTo(metaData, &buffer, KisMetaData::IOBackend::JpegHeader); dbgFile << "Exif information size is" << buffer.data().size(); QByteArray data = buffer.data(); if (data.size() < MAX_DATA_BYTES_IN_MARKER) { jpeg_write_marker(&cinfo, JPEG_APP0 + 1, (const JOCTET*)data.data(), data.size()); } else { dbgFile << "EXIF information could not be saved."; // TODO: warn the user ? } } // Save IPTC if (options.iptc) { dbgFile << "Trying to save exif information"; KisMetaData::IOBackend* iptcIO = KisMetaData::IOBackendRegistry::instance()->value("iptc"); Q_ASSERT(iptcIO); QBuffer buffer; iptcIO->saveTo(metaData, &buffer, KisMetaData::IOBackend::JpegHeader); dbgFile << "IPTC information size is" << buffer.data().size(); QByteArray data = buffer.data(); if (data.size() < MAX_DATA_BYTES_IN_MARKER) { jpeg_write_marker(&cinfo, JPEG_APP0 + 13, (const JOCTET*)data.data(), data.size()); } else { dbgFile << "IPTC information could not be saved."; // TODO: warn the user ? } } // Save XMP if (options.xmp) { dbgFile << "Trying to save XMP information"; KisMetaData::IOBackend* xmpIO = KisMetaData::IOBackendRegistry::instance()->value("xmp"); Q_ASSERT(xmpIO); QBuffer buffer; xmpIO->saveTo(metaData, &buffer, KisMetaData::IOBackend::JpegHeader); dbgFile << "XMP information size is" << buffer.data().size(); QByteArray data = buffer.data(); if (data.size() < MAX_DATA_BYTES_IN_MARKER) { jpeg_write_marker(&cinfo, JPEG_APP0 + 14, (const JOCTET*)data.data(), data.size()); } else { dbgFile << "XMP information could not be saved."; // TODO: warn the user ? } } } const KoColorProfile* colorProfile = layer->colorSpace()->profile(); QByteArray colorProfileData = colorProfile->rawData(); KisPaintDeviceSP dev = new KisPaintDevice(layer->colorSpace()); KoColor c(options.transparencyFillColor, layer->colorSpace()); dev->fill(QRect(0, 0, width, height), c); KisPainter gc(dev); gc.bitBlt(QPoint(0, 0), layer->paintDevice(), QRect(0, 0, width, height)); gc.end(); write_icc_profile(& cinfo, (uchar*) colorProfileData.data(), colorProfileData.size()); // Write data information JSAMPROW row_pointer = new JSAMPLE[width*cinfo.input_components]; int color_nb_bits = 8 * layer->paintDevice()->pixelSize() / layer->paintDevice()->channelCount(); for (; cinfo.next_scanline < height;) { KisHLineConstIteratorSP it = dev->createHLineConstIteratorNG(0, cinfo.next_scanline, width); quint8 *dst = row_pointer; switch (color_type) { case JCS_GRAYSCALE: if (color_nb_bits == 16) { do { //const quint16 *d = reinterpret_cast(it->oldRawData()); const quint8 *d = it->oldRawData(); *(dst++) = cs->scaleToU8(d, 0);//d[0] / quint8_MAX; } while (it->nextPixel()); } else { do { const quint8 *d = it->oldRawData(); *(dst++) = d[0]; } while (it->nextPixel()); } break; case JCS_RGB: if (color_nb_bits == 16) { do { //const quint16 *d = reinterpret_cast(it->oldRawData()); const quint8 *d = it->oldRawData(); *(dst++) = cs->scaleToU8(d, 2); //d[2] / quint8_MAX; *(dst++) = cs->scaleToU8(d, 1); //d[1] / quint8_MAX; *(dst++) = cs->scaleToU8(d, 0); //d[0] / quint8_MAX; } while (it->nextPixel()); } else { do { const quint8 *d = it->oldRawData(); *(dst++) = d[2]; *(dst++) = d[1]; *(dst++) = d[0]; } while (it->nextPixel()); } break; case JCS_CMYK: if (color_nb_bits == 16) { do { //const quint16 *d = reinterpret_cast(it->oldRawData()); const quint8 *d = it->oldRawData(); - *(dst++) = cs->scaleToU8(d, 0);//quint8_MAX - d[0] / quint8_MAX; - *(dst++) = cs->scaleToU8(d, 1);//quint8_MAX - d[1] / quint8_MAX; - *(dst++) = cs->scaleToU8(d, 2);//quint8_MAX - d[2] / quint8_MAX; - *(dst++) = cs->scaleToU8(d, 3);//quint8_MAX - d[3] / quint8_MAX; + *(dst++) = quint8_MAX - cs->scaleToU8(d, 0);//quint8_MAX - d[0] / quint8_MAX; + *(dst++) = quint8_MAX - cs->scaleToU8(d, 1);//quint8_MAX - d[1] / quint8_MAX; + *(dst++) = quint8_MAX - cs->scaleToU8(d, 2);//quint8_MAX - d[2] / quint8_MAX; + *(dst++) = quint8_MAX - cs->scaleToU8(d, 3);//quint8_MAX - d[3] / quint8_MAX; } while (it->nextPixel()); } else { do { const quint8 *d = it->oldRawData(); *(dst++) = quint8_MAX - d[0]; *(dst++) = quint8_MAX - d[1]; *(dst++) = quint8_MAX - d[2]; *(dst++) = quint8_MAX - d[3]; } while (it->nextPixel()); } break; default: KIO::del(uri); // asynchronous, but I guess that's ok delete [] row_pointer; jpeg_destroy_compress(&cinfo); return KisImageBuilder_RESULT_UNSUPPORTED; } jpeg_write_scanlines(&cinfo, &row_pointer, 1); } // Writing is over jpeg_finish_compress(&cinfo); file.close(); delete [] row_pointer; // Free memory jpeg_destroy_compress(&cinfo); return KisImageBuilder_RESULT_OK; } void KisJPEGConverter::cancel() { m_stop = true; } #include "kis_jpeg_converter.moc" diff --git a/krita/plugins/formats/jpeg/kis_jpeg_converter.h b/krita/plugins/formats/jpeg/kis_jpeg_converter.h index d24a15220ba..256ca8786aa 100644 --- a/krita/plugins/formats/jpeg/kis_jpeg_converter.h +++ b/krita/plugins/formats/jpeg/kis_jpeg_converter.h @@ -1,107 +1,108 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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_JPEG_CONVERTER_H_ #define _KIS_JPEG_CONVERTER_H_ #include extern "C" { #include } #include #include #include "kis_types.h" #include "kis_annotation.h" class KisDocument; namespace KisMetaData { class Filter; } /** * Image import/export plugins can use these results to report about success or failure. */ enum KisImageBuilder_Result { KisImageBuilder_RESULT_FAILURE = -400, KisImageBuilder_RESULT_NOT_EXIST = -300, KisImageBuilder_RESULT_NOT_LOCAL = -200, KisImageBuilder_RESULT_BAD_FETCH = -100, KisImageBuilder_RESULT_INVALID_ARG = -50, KisImageBuilder_RESULT_OK = 0, KisImageBuilder_RESULT_PROGRESS = 1, KisImageBuilder_RESULT_EMPTY = 100, KisImageBuilder_RESULT_BUSY = 150, KisImageBuilder_RESULT_NO_URI = 200, KisImageBuilder_RESULT_UNSUPPORTED = 300, KisImageBuilder_RESULT_INTR = 400, KisImageBuilder_RESULT_PATH = 500, KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE = 600 }; struct KisJPEGOptions { int quality; bool progressive; bool optimize; int smooth; bool baseLineJPEG; int subsampling; bool exif; bool iptc; bool xmp; QList filters; QColor transparencyFillColor; bool forceSRGB; }; namespace KisMetaData { class Store; } class KisJPEGConverter : public QObject { Q_OBJECT public: - KisJPEGConverter(KisDocument *doc); + KisJPEGConverter(KisDocument *doc, bool batchMode = false); virtual ~KisJPEGConverter(); public: KisImageBuilder_Result buildImage(const KUrl& uri); KisImageBuilder_Result buildFile(const KUrl& uri, KisPaintLayerSP layer, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisJPEGOptions options, KisMetaData::Store* metaData); /** Retrieve the constructed image */ KisImageWSP image(); public Q_SLOTS: virtual void cancel(); private: KisImageBuilder_Result decode(const KUrl& uri); private: KisImageWSP m_image; KisDocument *m_doc; bool m_stop; KIO::TransferJob *m_job; + bool m_batchMode; }; #endif diff --git a/krita/plugins/formats/jpeg/kis_jpeg_export.cc b/krita/plugins/formats/jpeg/kis_jpeg_export.cc index 3c09ea7223d..173e218ea35 100644 --- a/krita/plugins/formats/jpeg/kis_jpeg_export.cc +++ b/krita/plugins/formats/jpeg/kis_jpeg_export.cc @@ -1,229 +1,229 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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_jpeg_export.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_slider_spin_box.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_jpeg_converter.h" - +#include #include "ui_kis_wdg_options_jpeg.h" class KisExternalLayer; K_PLUGIN_FACTORY(KisJPEGExportFactory, registerPlugin();) K_EXPORT_PLUGIN(KisJPEGExportFactory("calligrafilters")) KisJPEGExport::KisJPEGExport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisJPEGExport::~KisJPEGExport() { } KisImportExportFilter::ConversionStatus KisJPEGExport::convert(const QByteArray& from, const QByteArray& to) { dbgFile << "JPEG export! From:" << from << ", To:" << to << ""; if (from != "application/x-krita") return KisImportExportFilter::NotImplemented; KisDocument *input = m_chain->inputDocument(); if (!input) return KisImportExportFilter::NoDocumentCreated; KisImageWSP image = input->image(); Q_CHECK_PTR(image); KDialog* kdb = new KDialog(0); kdb->setWindowTitle(i18n("JPEG Export Options")); kdb->setButtons(KDialog::Ok | KDialog::Cancel); Ui::WdgOptionsJPEG wdgUi; QWidget* wdg = new QWidget(kdb); wdgUi.setupUi(wdg); KisMetaData::FilterRegistryModel frm; wdgUi.metaDataFilters->setModel(&frm); QString filterConfig = KisConfig().exportConfiguration("JPEG"); KisPropertiesConfiguration cfg; cfg.fromXML(filterConfig); wdgUi.progressive->setChecked(cfg.getBool("progressive", false)); wdgUi.qualityLevel->setValue(cfg.getInt("quality", 80)); wdgUi.qualityLevel->setRange(0, 100, 0); wdgUi.qualityLevel->setSuffix("%"); wdgUi.optimize->setChecked(cfg.getBool("optimize", true)); wdgUi.smoothLevel->setValue(cfg.getInt("smoothing", 0)); wdgUi.smoothLevel->setRange(0, 100, 0); wdgUi.smoothLevel->setSuffix("%"); wdgUi.baseLineJPEG->setChecked(cfg.getBool("baseline", true)); wdgUi.subsampling->setCurrentIndex(cfg.getInt("subsampling", 0)); wdgUi.exif->setChecked(cfg.getBool("exif", true)); wdgUi.iptc->setChecked(cfg.getBool("iptc", true)); wdgUi.xmp->setChecked(cfg.getBool("xmp", true)); const KoColorSpace* cs = image->projection()->colorSpace(); bool sRGB = cs->profile()->name().contains(QLatin1String("srgb"), Qt::CaseInsensitive); wdgUi.chkForceSRGB->setVisible(!sRGB); wdgUi.chkForceSRGB->setChecked(cfg.getBool("forceSRGB", false)); QStringList rgb = cfg.getString("transparencyFillcolor", "255,255,255").split(','); wdgUi.bnTransparencyFillColor->setDefaultColor(Qt::white); wdgUi.bnTransparencyFillColor->setColor(QColor(rgb[0].toInt(), rgb[1].toInt(), rgb[2].toInt())); frm.setEnabledFilters(cfg.getString("filters").split(',')); kdb->setMainWidget(wdg); QApplication::restoreOverrideCursor(); if (!m_chain->manager()->getBatchMode()) { if (kdb->exec() == QDialog::Rejected) { return KisImportExportFilter::OK; // FIXME Cancel doesn't exist :( } } else { qApp->processEvents(); // For vector layers to be updated } image->waitForDone(); KisJPEGOptions options; options.progressive = wdgUi.progressive->isChecked(); cfg.setProperty("progressive", options.progressive); options.quality = (int)wdgUi.qualityLevel->value(); cfg.setProperty("quality", options.quality); options.forceSRGB = wdgUi.chkForceSRGB->isChecked(); cfg.setProperty("forceSRGB", options.forceSRGB); // Advanced options.optimize = wdgUi.optimize->isChecked(); cfg.setProperty("optimize", options.optimize); options.smooth = (int)wdgUi.smoothLevel->value(); cfg.setProperty("smoothing", options.smooth); options.baseLineJPEG = wdgUi.baseLineJPEG->isChecked(); cfg.setProperty("baseline", options.baseLineJPEG); options.subsampling = wdgUi.subsampling->currentIndex(); cfg.setProperty("subsampling", options.subsampling); // Jpeg options.exif = wdgUi.exif->isChecked(); cfg.setProperty("exif", options.exif); options.iptc = wdgUi.iptc->isChecked(); cfg.setProperty("iptc", options.iptc); options.xmp = wdgUi.xmp->isChecked(); cfg.setProperty("xmp", options.xmp); QColor c = wdgUi.bnTransparencyFillColor->color(); options.transparencyFillColor = c; cfg.setProperty("transparencyFillcolor", QString("%1,%2,%3").arg(c.red()).arg(c.green()).arg(c.blue())); options.filters = frm.enabledFilters(); QString enabledFilters; foreach(const KisMetaData::Filter* filter, options.filters) { enabledFilters = enabledFilters + filter->id() + ','; } cfg.setProperty("filters", enabledFilters); KisConfig().setExportConfiguration("JPEG", cfg); delete kdb; // XXX: Add dialog about flattening layers here QString filename = m_chain->outputFile(); if (filename.isEmpty()) return KisImportExportFilter::FileNotFound; KUrl url; url.setPath(filename); image->refreshGraph(); image->lock(); - KisJPEGConverter kpc(input); + KisJPEGConverter kpc(input, m_chain->manager()->getBatchMode()); KisPaintDeviceSP pd = new KisPaintDevice(*image->projection()); image->unlock(); KisPaintLayerSP l = new KisPaintLayer(image, "projection", OPACITY_OPAQUE_U8, pd); vKisAnnotationSP_it beginIt = image->beginAnnotations(); vKisAnnotationSP_it endIt = image->endAnnotations(); KisImageBuilder_Result res; KisExifInfoVisitor eIV; eIV.visit(image->rootLayer().data()); KisMetaData::Store* eI = 0; if (eIV.countPaintLayer() == 1) eI = eIV.exifInfo(); if (eI) { KisMetaData::Store* copy = new KisMetaData::Store(*eI); eI = copy; } if ((res = kpc.buildFile(url, l, beginIt, endIt, options, eI)) == KisImageBuilder_RESULT_OK) { dbgFile << "success !"; delete eI; return KisImportExportFilter::OK; } delete eI; dbgFile << " Result =" << res; return KisImportExportFilter::InternalError; } #include diff --git a/krita/plugins/formats/jpeg/kis_jpeg_import.cc b/krita/plugins/formats/jpeg/kis_jpeg_import.cc index 2592179fe26..ff2e82ec21f 100644 --- a/krita/plugins/formats/jpeg/kis_jpeg_import.cc +++ b/krita/plugins/formats/jpeg/kis_jpeg_import.cc @@ -1,104 +1,105 @@ /* * Copyright (c) 2005 Cyrille Berger * * 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_jpeg_import.h" #include #include #include #include #include +#include #include "kis_jpeg_converter.h" K_PLUGIN_FACTORY(JPEGImportFactory, registerPlugin();) K_EXPORT_PLUGIN(JPEGImportFactory("calligrafilters")) KisJPEGImport::KisJPEGImport(QObject *parent, const QVariantList &) : KisImportExportFilter(parent) { } KisJPEGImport::~KisJPEGImport() { } KisImportExportFilter::ConversionStatus KisJPEGImport::convert(const QByteArray&, const QByteArray& to) { dbgFile << "Importing using JPEGImport!"; if (to != "application/x-krita") return KisImportExportFilter::BadMimeType; KisDocument * doc = m_chain->outputDocument(); if (!doc) return KisImportExportFilter::NoDocumentCreated; QString filename = m_chain->inputFile(); doc->prepareForImport(); if (!filename.isEmpty()) { KUrl url(filename); if (url.isEmpty()) return KisImportExportFilter::FileNotFound; - KisJPEGConverter ib(doc); + KisJPEGConverter ib(doc, m_chain->manager()->getBatchMode()); // if (view != 0) // view -> canvasSubject() -> progressDisplay() -> setSubject(&ib, false, true); switch (ib.buildImage(url)) { case KisImageBuilder_RESULT_UNSUPPORTED: case KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE: return KisImportExportFilter::NotImplemented; break; case KisImageBuilder_RESULT_INVALID_ARG: return KisImportExportFilter::BadMimeType; break; case KisImageBuilder_RESULT_NO_URI: case KisImageBuilder_RESULT_NOT_LOCAL: return KisImportExportFilter::FileNotFound; break; case KisImageBuilder_RESULT_BAD_FETCH: case KisImageBuilder_RESULT_EMPTY: return KisImportExportFilter::ParsingError; break; case KisImageBuilder_RESULT_FAILURE: return KisImportExportFilter::InternalError; break; case KisImageBuilder_RESULT_OK: doc->setCurrentImage(ib.image()); return KisImportExportFilter::OK; default: break; } } return KisImportExportFilter::StorageCreationError; } #include diff --git a/krita/plugins/formats/psd/CMakeLists.txt b/krita/plugins/formats/psd/CMakeLists.txt index 468dce843dd..1ffe2d3c64f 100644 --- a/krita/plugins/formats/psd/CMakeLists.txt +++ b/krita/plugins/formats/psd/CMakeLists.txt @@ -1,54 +1,56 @@ add_subdirectory(tests) macro_optional_find_package(ZLIB) macro_bool_to_01(ZLIB_FOUND HAVE_ZLIB) configure_file(config_psd.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config_psd.h) +include_directories(${ZLIB_INCLUDE_DIR}) set(LIB_PSD_SRCS psd_header.cpp psd_colormode_block.cpp psd_resource_section.cpp psd_resource_block.cpp psd_layer_section.cpp psd_layer_record.cpp psd_image_data.cpp + psd_pixel_utils.cpp psd_additional_layer_info_block.cpp ) set(kritapsdimport_PART_SRCS psd_import.cc psd_loader.cpp ${LIB_PSD_SRCS} ) kde4_add_plugin(kritapsdimport ${kritapsdimport_PART_SRCS}) if (WIN32) - target_link_libraries(kritapsdimport kritaui kritapsd ${KDE4_KIO_LIBS} ${WIN32_PLATFORM_NET_LIBS}) + target_link_libraries(kritapsdimport kritaui kritapsd ${KDE4_KIO_LIBS} ${WIN32_PLATFORM_NET_LIBS} ${ZLIB_LIBRARIES}) else () - target_link_libraries(kritapsdimport kritaui kritapsd ${KDE4_KIO_LIBS}) + target_link_libraries(kritapsdimport kritaui kritapsd ${KDE4_KIO_LIBS} ${ZLIB_LIBRARIES}) endif () install(TARGETS kritapsdimport DESTINATION ${PLUGIN_INSTALL_DIR}) ########### next target ############### set(kritapsdexport_PART_SRCS psd_export.cc psd_saver.cpp ${LIB_PSD_SRCS} ) kde4_add_plugin(kritapsdexport ${kritapsdexport_PART_SRCS}) if (WIN32) - target_link_libraries(kritapsdexport kritaui ${WIN32_PLATFORM_NET_LIBS}) + target_link_libraries(kritapsdexport kritaui ${WIN32_PLATFORM_NET_LIBS} ${ZLIB_LIBRARIES}) else () - target_link_libraries(kritapsdexport kritaui ) + target_link_libraries(kritapsdexport kritaui ${ZLIB_LIBRARIES}) endif () install(TARGETS kritapsdexport DESTINATION ${PLUGIN_INSTALL_DIR}) install( FILES krita_psd_import.desktop krita_psd_export.desktop DESTINATION ${SERVICES_INSTALL_DIR}/calligra) install( PROGRAMS krita_psd.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) diff --git a/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp b/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp index 1c08d092497..e52b543551f 100644 --- a/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp +++ b/krita/plugins/formats/psd/psd_additional_layer_info_block.cpp @@ -1,399 +1,413 @@ /* * Copyright (c) 2014 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 "psd_additional_layer_info_block.h" #include #include #include #include #include #include #include PsdAdditionalLayerInfoBlock::PsdAdditionalLayerInfoBlock(const PSDHeader& header) : m_header(header) { } +void PsdAdditionalLayerInfoBlock::setExtraLayerInfoBlockHandler(ExtraLayerInfoBlockHandler handler) +{ + m_layerInfoBlockHandler = handler; +} + bool PsdAdditionalLayerInfoBlock::read(QIODevice *io) { bool result = true; try { readImpl(io); } catch (KisAslReaderUtils::ASLParseException &e) { error = e.what(); result = false; } return result; } void PsdAdditionalLayerInfoBlock::readImpl(QIODevice* io) { using namespace KisAslReaderUtils; QStringList longBlocks; if (m_header.version > 1) { longBlocks << "LMsk" << "Lr16" << "Layr" << "Mt16" << "Mtrn" << "Alph"; } while (!io->atEnd()) { { const quint32 refSignature1 = 0x3842494D; // '8BIM' in little-endian const quint32 refSignature2 = 0x38423634; // '8B64' in little-endian if (!TRY_READ_SIGNATURE_2OPS_EX(io, refSignature1, refSignature2)) { break; } } QString key = readFixedString(io); dbgFile << "found info block with key" << key; quint64 blockSize = GARBAGE_VALUE_MARK; if (longBlocks.contains(key)) { SAFE_READ_EX(io, blockSize); } else { quint32 size32; SAFE_READ_EX(io, size32); blockSize = size32; } // offset verifier will correct the position on the exit from // current namespace, including 'continue', 'return' and // exceptions. SETUP_OFFSET_VERIFIER(infoBlockEndVerifier, io, blockSize, 0); if (keys.contains(key)) { error = "Found duplicate entry for key "; continue; } keys << key; - if (key == "SoCo") { + // TODO: Loading of 32 bit files is not supported yet + + if (key == "Lr16"/* || key == "Lr32"*/) { + if (m_layerInfoBlockHandler) { + int offset = m_header.version > 1 ? 8 : 4; + io->seek(io->pos() - offset); + m_layerInfoBlockHandler(io); + } + } + else if (key == "SoCo") { } else if (key == "GdFl") { } else if (key == "PtFl") { } else if (key == "brit") { } else if (key == "levl") { } else if (key == "curv") { } else if (key == "expA") { } else if (key == "vibA") { } else if (key == "hue") { } else if (key == "hue2") { } else if (key == "blnc") { } else if (key == "blwh") { } else if (key == "phfl") { } else if (key == "mixr") { } else if (key == "clrL") { } else if (key == "nvrt") { } else if (key == "post") { } else if (key == "thrs") { } else if (key == "grdm") { } else if (key == "selc") { } else if (key == "lrFX") { // deprecated! use lfx2 instead! } else if (key == "tySh") { } else if (key == "luni") { // get the unicode layer name unicodeLayerName = readUnicodeString(io); dbgFile << "unicodeLayerName" << unicodeLayerName; } else if (key == "lyid") { } else if (key == "lfx2") { KisAslReader reader; layerStyleXml = reader.readLfx2PsdSection(io); } else if (key == "Patt" || key == "Pat2" || key == "Pat3") { KisAslReader reader; QDomDocument pattern = reader.readPsdSectionPattern(io, blockSize); embeddedPatterns << pattern; } else if (key == "Anno") { } else if (key == "clbl") { } else if (key == "infx") { } else if (key == "knko") { } else if (key == "spf") { } else if (key == "lclr") { } else if (key == "fxrp") { } else if (key == "grdm") { } else if (key == "lsct") { quint32 dividerType = GARBAGE_VALUE_MARK; SAFE_READ_EX(io, dividerType); this->sectionDividerType = (psd_section_type)dividerType; dbgFile << "Reading \"lsct\" block:"; dbgFile << ppVar(blockSize); dbgFile << ppVar(dividerType); if (blockSize >= 12) { quint32 lsctSignature = GARBAGE_VALUE_MARK; const quint32 refSignature1 = 0x3842494D; // '8BIM' in little-endian SAFE_READ_SIGNATURE_EX(io, lsctSignature, refSignature1); this->sectionDividerBlendMode = readFixedString(io); dbgFile << ppVar(this->sectionDividerBlendMode); } // Animation if (blockSize >= 14) { /** * "I don't care * I don't care, no... !" (c) */ } } else if (key == "brst") { } else if (key == "SoCo") { } else if (key == "PtFl") { } else if (key == "GdFl") { } else if (key == "vmsk" || key == "vsms") { // If key is "vsms" then we are writing for (Photoshop CS6) and the document will have a "vscg" key } else if (key == "TySh") { } else if (key == "ffxi") { } else if (key == "lnsr") { } else if (key == "shpa") { } else if (key == "shmd") { } else if (key == "lyvr") { } else if (key == "tsly") { } else if (key == "lmgm") { } else if (key == "vmgm") { } else if (key == "plLd") { // Replaced by SoLd in CS3 } else if (key == "linkD" || key == "lnk2" || key == "lnk3") { } else if (key == "phfl") { } else if (key == "blwh") { } else if (key == "CgEd") { } else if (key == "Txt2") { } else if (key == "vibA") { } else if (key == "pths") { } else if (key == "anFX") { } else if (key == "FMsk") { } else if (key == "SoLd") { } else if (key == "vstk") { } else if (key == "vsCg") { } else if (key == "sn2P") { } else if (key == "vogk") { } else if (key == "Mtrn" || key == "Mt16" || key == "Mt32") { // There is no data associated with these keys. } else if (key == "LMsk") { } else if (key == "expA") { } else if (key == "FXid") { } else if (key == "FEid") { } } } bool PsdAdditionalLayerInfoBlock::write(QIODevice */*io*/, KisNodeSP /*node*/) { return true; } bool PsdAdditionalLayerInfoBlock::valid() { return true; } void PsdAdditionalLayerInfoBlock::writeLuniBlockEx(QIODevice* io, const QString &layerName) { KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString("luni", io); KisAslWriterUtils::OffsetStreamPusher layerNameSizeTag(io, 2); KisAslWriterUtils::writeUnicodeString(layerName, io); } void PsdAdditionalLayerInfoBlock::writeLsctBlockEx(QIODevice* io, psd_section_type sectionType, bool isPassThrough, const QString &blendModeKey) { KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString("lsct", io); KisAslWriterUtils::OffsetStreamPusher sectionTypeSizeTag(io, 2); SAFE_WRITE_EX(io, (quint32)sectionType); QString realBlendModeKey = isPassThrough ? QString("pass") : blendModeKey; KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString(realBlendModeKey, io); } void PsdAdditionalLayerInfoBlock::writeLfx2BlockEx(QIODevice* io, const QDomDocument &stylesXmlDoc) { KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString("lfx2", io); KisAslWriterUtils::OffsetStreamPusher lfx2SizeTag(io, 2); try { KisAslWriter writer; writer.writePsdLfx2SectionEx(io, stylesXmlDoc); } catch (KisAslWriterUtils::ASLWriteException &e) { qWarning() << "WARNING: Couldn't save layer style lfx2 block:" << PREPEND_METHOD(e.what()); // TODO: make this error recoverable! throw e; } } void PsdAdditionalLayerInfoBlock::writePattBlockEx(QIODevice* io, const QDomDocument &patternsXmlDoc) { KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString("Patt", io); KisAslWriterUtils::OffsetStreamPusher pattSizeTag(io, 2); try { KisAslPatternsWriter writer(patternsXmlDoc, io); writer.writePatterns(); } catch (KisAslWriterUtils::ASLWriteException &e) { qWarning() << "WARNING: Couldn't save layer style patterns block:" << PREPEND_METHOD(e.what()); // TODO: make this error recoverable! throw e; } } diff --git a/krita/plugins/formats/psd/psd_additional_layer_info_block.h b/krita/plugins/formats/psd/psd_additional_layer_info_block.h index dfa8e732bb8..72a6374545e 100644 --- a/krita/plugins/formats/psd/psd_additional_layer_info_block.h +++ b/krita/plugins/formats/psd/psd_additional_layer_info_block.h @@ -1,285 +1,295 @@ /* * Copyright (c) 2014 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 PSD_ADDITIONAL_LAYER_INFO_BLOCK_H #define PSD_ADDITIONAL_LAYER_INFO_BLOCK_H #include #include #include #include #include #include #include #include #include +#include + + #include "psd.h" #include "psd_header.h" // additional layer information // LEVELS // Level record struct psd_layer_level_record { quint16 input_floor; // (0...253) quint16 input_ceiling; // (2...255) quint16 output_floor; // 255). Matched to input floor. quint16 output_ceiling; // (0...255) float gamma; // Short integer from 10...999 representing 0.1...9.99. Applied to all image data. }; // Levels settings files are loaded and saved in the Levels dialog. struct psd_layer_levels { psd_layer_level_record record[29]; // 29 sets of level records, each level containing 5 qint8 integers // Photoshop CS (8.0) Additional information // At the end of the Version 2 file is the following information: quint16 extra_level_count; // Count of total level record structures. Subtract the legacy number of level record structures, 29, to determine how many are remaining in the file for reading. psd_layer_level_record *extra_record; // Additianol level records according to count quint8 lookup_table[3][256]; }; // CURVES // The following is the data for each curve specified by count above struct psd_layer_curves_data { quint16 channel_index; // Before each curve is a channel index. quint16 point_count; // Count of points in the curve (qint8 integer from 2...19) quint16 output_value[19]; // All coordinates have range 0 to 255 quint16 input_value[19]; }; // Curves file format struct psd_layer_curves { quint16 curve_count; // Count of curves in the file. psd_layer_curves_data * curve; quint8 lookup_table[3][256]; }; // BRIGHTNESS AND CONTRAST struct psd_layer_brightness_contrast { qint8 brightness; qint8 contrast; qint8 mean_value; // for brightness and contrast qint8 Lab_color; quint8 lookup_table[256]; }; // COLOR BALANCE struct psd_layer_color_balance { qint8 cyan_red[3]; // (-100...100). shadows, midtones, highlights qint8 magenta_green[3]; qint8 yellow_blue[3]; bool preserve_luminosity; quint8 lookup_table[3][256]; }; // HUE/SATURATION // Hue/Saturation settings files are loaded and saved in Photoshop¡¯s Hue/Saturation dialog struct psd_layer_hue_saturation { quint8 hue_or_colorization; // 0 = Use settings for hue-adjustment; 1 = Use settings for colorization. qint8 colorization_hue; // Photoshop 5.0: The actual values are stored for the new version. Hue is - 180...180, Saturation is 0...100, and Lightness is -100...100. qint8 colorization_saturation;// Photoshop 4.0: Three qint8 integers Hue, Saturation, and Lightness from ¨C100...100. qint8 colorization_lightness; // The user interface represents hue as ¨C180...180, saturation as 0...100, and Lightness as -100...1000, as the traditional HSB color wheel, with red = 0. qint8 master_hue; // Master hue, saturation and lightness values. qint8 master_saturation; qint8 master_lightness; qint8 range_values[6][4]; // For RGB and CMYK, those values apply to each of the six hextants in the HSB color wheel: those image pixels nearest to red, yellow, green, cyan, blue, or magenta. These numbers appear in the user interface from ¨C60...60, however the slider will reflect each of the possible 201 values from ¨C100...100. qint8 setting_values[6][3]; // For Lab, the first four of the six values are applied to image pixels in the four Lab color quadrants, yellow, green, blue, and magenta. The other two values are ignored ( = 0). The values appear in the user interface from ¨C90 to 90. quint8 lookup_table[6][360]; }; // SELECTIVE COLOR // Selective Color settings files are loaded and saved in Photoshop¡¯s Selective Color dialog. struct psd_layer_selective_color { quint16 correction_method; // 0 = Apply color correction in relative mode; 1 = Apply color correction in absolute mode. qint8 cyan_correction[10]; // Amount of cyan correction. Short integer from ¨C100...100. qint8 magenta_correction[10]; // Amount of magenta correction. Short integer from ¨C100...100. qint8 yellow_correction[10]; // Amount of yellow correction. Short integer from ¨C100...100. qint8 black_correction[10]; // Amount of black correction. Short integer from ¨C100...100. }; // THRESHOLD struct psd_layer_threshold { quint16 level; // (1...255) } ; // INVERT // no parameter // POSTERIZE struct psd_layer_posterize { quint16 levels; // (2...255) quint8 lookup_table[256]; }; // CHANNEL MIXER struct psd_layer_channel_mixer { bool monochrome; qint8 red_cyan[4]; // RGB or CMYK color plus constant for the mixer settings. 4 * 2 bytes of color with 2 bytes of constant. qint8 green_magenta[4]; // (-200...200) qint8 blue_yellow[4]; qint8 black[4]; qint8 constant[4]; }; // PHOTO FILTER struct psd_layer_photo_filter { qint32 x_color; // 4 bytes each for XYZ color qint32 y_color; qint32 z_color; qint32 density; // (1...100) bool preserve_luminosity; }; #include struct psd_layer_solid_color { quint32 id; QColor fill_color; }; struct psd_layer_gradient_fill { quint32 id; double angle; psd_gradient_style style; qint32 scale; bool reverse; // Is gradient reverse bool dithered; // Is gradient dithered bool align_with_layer; psd_gradient_color gradient_color; }; struct psd_layer_pattern_fill { quint32 id; psd_pattern_info pattern_info; qint32 scale; }; struct psd_layer_type_face { qint8 mark; // Mark value qint32 font_type; // Font type data qint8 font_name[256]; // Pascal string of font name qint8 font_family_name[256]; // Pascal string of font family name qint8 font_style_name[256]; // Pascal string of font style name qint8 script; // Script value qint32 number_axes_vector; // Number of design axes vector to follow qint32 * vector; // Design vector value }; struct psd_layer_type_style { qint8 mark; // Mark value qint8 face_mark; // Face mark value qint32 size; // Size value qint32 tracking; // Tracking value qint32 kerning; // Kerning value qint32 leading; // Leading value qint32 base_shift; // Base shift value bool auto_kern; // Auto kern on/off bool rotate; // Rotate up/down }; struct psd_layer_type_line { qint32 char_count; // Character count value qint8 orientation; // Orientation value qint8 alignment; // Alignment value qint8 actual_char; // Actual character as a double byte character qint8 style; // Style value }; struct psd_layer_type_tool { double transform_info[6]; // 6 * 8 double precision numbers for the transform information qint8 faces_count; // Count of faces psd_layer_type_face * face; qint8 styles_count; // Count of styles psd_layer_type_style * style; qint8 type; // Type value qint32 scaling_factor; // Scaling factor value qint32 character_count; // Character count value qint32 horz_place; // Horizontal placement qint32 vert_place; // Vertical placement qint32 select_start; // Select start value qint32 select_end; // Select end value qint8 lines_count; // Line count psd_layer_type_line * line; QColor color; bool anti_alias; // Anti alias on/off }; /** * @brief The PsdAdditionalLayerInfoBlock class implements the Additional Layer Information block * * See: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_71546 */ class PsdAdditionalLayerInfoBlock { public: PsdAdditionalLayerInfoBlock(const PSDHeader& header); + + typedef boost::function ExtraLayerInfoBlockHandler; + + void setExtraLayerInfoBlockHandler(ExtraLayerInfoBlockHandler handler); + bool read(QIODevice* io); bool write(QIODevice* io, KisNodeSP node); void writeLuniBlockEx(QIODevice* io, const QString &layerName); void writeLsctBlockEx(QIODevice* io, psd_section_type sectionType, bool isPassThrough, const QString &blendModeKey); void writeLfx2BlockEx(QIODevice* io, const QDomDocument &stylesXmlDoc); void writePattBlockEx(QIODevice* io, const QDomDocument &patternsXmlDoc); bool valid(); const PSDHeader &m_header; QString error; QStringList keys; // List of all the keys that we've seen QString unicodeLayerName; QDomDocument layerStyleXml; QVector embeddedPatterns; psd_section_type sectionDividerType; QString sectionDividerBlendMode; private: void readImpl(QIODevice* io); +private: + ExtraLayerInfoBlockHandler m_layerInfoBlockHandler; }; #endif // PSD_ADDITIONAL_LAYER_INFO_BLOCK_H diff --git a/krita/plugins/formats/psd/psd_image_data.cpp b/krita/plugins/formats/psd/psd_image_data.cpp index b904535b110..693f1433eb2 100644 --- a/krita/plugins/formats/psd/psd_image_data.cpp +++ b/krita/plugins/formats/psd/psd_image_data.cpp @@ -1,698 +1,189 @@ /* * Copyright (C) 2011 by Siddharth Sharma * * 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, see */ #include #include // htonl #include #include #include #include #include #include #include #include #include #include "psd_utils.h" #include "compression.h" #include "kis_iterator_ng.h" #include "kis_paint_device.h" +#include + +#include "psd_pixel_utils.h" + + PSDImageData::PSDImageData(PSDHeader *header) { m_header = header; } PSDImageData::~PSDImageData() { } bool PSDImageData::read(QIODevice *io, KisPaintDeviceSP dev ) { psdread(io, &m_compression); quint64 start = io->pos(); m_channelSize = m_header->channelDepth/8; m_channelDataLength = m_header->height * m_header->width * m_channelSize; dbgFile << "Reading Image Data Block: compression" << m_compression << "channelsize" << m_channelSize << "number of channels" << m_header->nChannels; switch (m_compression) { case 0: // Uncompressed for (int channel = 0; channel < m_header->nChannels; channel++) { m_channelOffsets << 0; ChannelInfo channelInfo; channelInfo.channelId = channel; channelInfo.compressionType = Compression::Uncompressed; channelInfo.channelDataStart = start; channelInfo.channelDataLength = m_header->width * m_header->height * m_channelSize; start += channelInfo.channelDataLength; m_channelInfoRecords.append(channelInfo); } - switch (m_header->colormode) { - case Bitmap: - break; - case Grayscale: - readGrayscale(io,dev); - break; - case Indexed: - break; - case RGB: - readRGB(io, dev); - break; - case CMYK: - readCMYK(io, dev); - break; - case MultiChannel: - break; - case DuoTone: - break; - case Lab: - readLAB(io, dev); - break; - case UNKNOWN: - break; - default: - break; - } - break; case 1: // RLE { - quint32 rlelength = 0; // The start of the actual channel data is _after_ the RLE rowlengths block if (m_header->version == 1) { start += m_header->nChannels * m_header->height * 2; } else if (m_header->version == 2) { start += m_header->nChannels * m_header->height * 4; } for (int channel = 0; channel < m_header->nChannels; channel++) { m_channelOffsets << 0; quint32 sumrlelength = 0; ChannelInfo channelInfo; channelInfo.channelId = channel; channelInfo.channelDataStart = start; channelInfo.compressionType = Compression::RLE; for (quint32 row = 0; row < m_header->height; row++ ) { if (m_header->version == 1) { psdread(io,(quint16*)&rlelength); } else if (m_header->version == 2) { psdread(io,&rlelength); } channelInfo.rleRowLengths.append(rlelength); sumrlelength += rlelength; } channelInfo.channelDataLength = sumrlelength; start += channelInfo.channelDataLength; m_channelInfoRecords.append(channelInfo); } - switch (m_header->colormode) { - case Bitmap: - break; - case Grayscale: - readGrayscale(io,dev); - break; - case Indexed: - break; - case RGB: - readRGB(io, dev); - break; - case CMYK: - readCMYK(io, dev); - break; - case MultiChannel: - break; - case DuoTone: - break; - case Lab: - readLAB(io, dev); - break; - case UNKNOWN: - break; - default: - break; - } - break; } case 2: // ZIP without prediction - - switch (m_header->colormode) { - case Bitmap: - break; - case Grayscale: - break; - case Indexed: - break; - case RGB: - break; - case CMYK: - break; - case MultiChannel: - break; - case DuoTone: - break; - case Lab: - break; - case UNKNOWN: - break; - default: - break; - } - break; - case 3: // ZIP with prediction - switch (m_header->colormode) { - case Bitmap: - break; - case Grayscale: - break; - case Indexed: - break; - case RGB: - break; - case CMYK: - break; - case MultiChannel: - break; - case DuoTone: - break; - case Lab: - break; - case UNKNOWN: - break; - default: - break; - } - - break; default: break; } - return true; -} - -bool PSDImageData::write(QIODevice *io, KisPaintDeviceSP dev) -{ - // XXX: make the compression settting configurable. For now, always use RLE. - psdwrite(io, (quint16)Compression::RLE); - - // now write all the channels in display order - // fill in the channel chooser, in the display order, but store the pixel index as well. - QRect rc(0, 0, m_header->width, m_header->height); - QVector tmp = dev->readPlanarBytes(0, 0, rc.width(), rc.height()); - // then reorder the planes to fit the psd model -- alpha first, then display order - QVector planes; - QList origChannels = dev->colorSpace()->channels(); - - quint8* alphaPlane = 0; - foreach(KoChannelInfo *ch, KoChannelInfo::displayOrderSorted(origChannels)) { - int channelIndex = KoChannelInfo::displayPositionToChannelIndex(ch->displayPosition(), origChannels); - //qDebug() << ppVar(ch->name()) << ppVar(ch->pos()) << ppVar(ch->displayPosition()) << ppVar(channelIndex); - if (ch->channelType() == KoChannelInfo::ALPHA) { - alphaPlane = tmp[channelIndex]; - } else { - planes.append(tmp[channelIndex]); - } - } - planes.append(alphaPlane); // alpha is last, in contrast with layers, where it's first. - // now planes are holding pointers to quint8 arrays - tmp.clear(); - - // Now fix up the cmyk channels, we need to invert them - if (m_header->colormode == CMYK || m_header->colormode == CMYK64) { - for (int i = 0; i < 4; ++i) { - if (m_header->channelDepth == 8) { - for (int j = 0; j < rc.width() * rc.height(); ++j) { - planes[i][j] = 255 - planes[i][j]; - } - } - else if (m_header->channelDepth == 16) { - quint16 val; - for (int j = 0; j < rc.width() * rc.height(); ++j) { - val = reinterpret_cast(planes[i])[j]; - val = quint16_MAX - ntohs(val); - reinterpret_cast(planes[i])[j] = val; - } - } - } - } - - quint64 channelLengthPos = io->pos(); - // write zero's for the channel lengths section - for (uint i = 0; i < dev->colorSpace()->channelCount() * rc.height(); ++i) { - psdwrite(io, (quint16)0); - } - // here the actual channel data starts - quint64 channelStartPos = io->pos(); - - for (int channelInfoIndex = 0; channelInfoIndex < planes.size(); ++channelInfoIndex) { - quint8 *plane = planes[channelInfoIndex]; - - quint32 stride = (m_header->channelDepth / 8) * rc.width(); - for (qint32 row = 0; row < rc.height(); ++row) { - - QByteArray uncompressed = QByteArray::fromRawData((const char*)plane + row * stride, stride); - if (m_header->channelDepth == 8) { - } else if (m_header->channelDepth == 16) { - quint16 *dataPtr = reinterpret_cast(uncompressed.data()); - for (int i = 0; i < rc.width(); i++) { - quint16 val = htons(*dataPtr); - *dataPtr = val; - ++dataPtr; - } - } else if (m_header->channelDepth == 32) { - quint32 *dataPtr = reinterpret_cast(uncompressed.data()); - for (int i = 0; i < rc.width(); i++) { - quint32 val = htonl(*dataPtr); - *dataPtr = val; - ++dataPtr; - } - } - QByteArray compressed = Compression::compress(uncompressed, Compression::RLE); - - io->seek(channelLengthPos); - psdwrite(io, (quint16)compressed.size()); - channelLengthPos +=2; - io->seek(channelStartPos); - - if (io->write(compressed) != compressed.size()) { - error = "Could not write image data"; - return false; - } - - channelStartPos += compressed.size(); - } - } - - qDeleteAll(planes); - planes.clear(); - - return true; -} - -bool PSDImageData::readRGB(QIODevice *io, KisPaintDeviceSP dev) { - - int channelid = 0; - - for (quint32 row = 0; row < m_header->height; row++) { - - KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width); - QVector channelBytes; - - for (int channel = 0; channel < m_header->nChannels; channel++) { - - switch (m_compression) { - case Compression::Uncompressed: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[0]); - channelBytes.append(io->read(m_header->width*m_channelSize)); - } - break; - case Compression::RLE: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[channel]); - int uncompressedLength = m_header->width * m_header->channelDepth / 8; - QByteArray compressedBytes = io->read(m_channelInfoRecords[channel].rleRowLengths[row]); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, m_channelInfoRecords[channel].compressionType); - channelBytes.append(uncompressedBytes); - m_channelOffsets[channel] += m_channelInfoRecords[channel].rleRowLengths[row]; - - } - break; - case Compression::ZIP: - break; - case Compression::ZIPWithPrediction: - break; - - default: - break; - } - - } - - if (m_channelInfoRecords[channelid].compressionType == 0){ - m_channelOffsets[channelid] += (m_header->width * m_channelSize); - } - - for (quint32 col = 0; col < m_header->width; col++) { - - if (m_channelSize == 1) { - - quint8 red = channelBytes[0].constData()[col]; - KoBgrU8Traits::setRed(it->rawData(), red); - - quint8 green = channelBytes[1].constData()[col]; - KoBgrU8Traits::setGreen(it->rawData(), green); - - quint8 blue = channelBytes[2].constData()[col]; - KoBgrU8Traits::setBlue(it->rawData(), blue); - - } - else if (m_channelSize == 2) { - - quint16 red = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoBgrU16Traits::setRed(it->rawData(), red); - - quint16 green = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoBgrU16Traits::setGreen(it->rawData(), green); - - quint16 blue = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoBgrU16Traits::setBlue(it->rawData(), blue); - - } - else if (m_channelSize == 4) { - - quint32 red = ntohl(reinterpret_cast(channelBytes.constData())[col]); - KoBgrTraits::setRed(it->rawData(), red); - - quint32 green = ntohl(reinterpret_cast(channelBytes.constData())[col]); - KoBgrTraits::setGreen(it->rawData(), green); - - quint32 blue = ntohl(reinterpret_cast(channelBytes.constData())[col]); - KoBgrTraits::setBlue(it->rawData(), blue); - - } - - dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1); - it->nextPixel(); - } - - } - - return true; -} - - -bool PSDImageData::readCMYK(QIODevice *io, KisPaintDeviceSP dev) { - - int channelid = 0; - - for (quint32 row = 0; row < m_header->height; row++) { - - KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width); - QVector channelBytes; - - for (int channel = 0; channel < m_header->nChannels; channel++) { - - - switch (m_compression) { - - case Compression::Uncompressed: - - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[0]); - channelBytes.append(io->read(m_header->width*m_channelSize)); - - } - break; - - case Compression::RLE: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[channel]); - int uncompressedLength = m_header->width * m_header->channelDepth / 8; - QByteArray compressedBytes = io->read(m_channelInfoRecords[channel].rleRowLengths[row]); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, m_channelInfoRecords[channel].compressionType); - channelBytes.append(uncompressedBytes); - m_channelOffsets[channel] += m_channelInfoRecords[channel].rleRowLengths[row]; - } - break; - - case Compression::ZIP: - break; - - case Compression::ZIPWithPrediction: - break; - - default: - break; - } - - } - - if (m_channelInfoRecords[channelid].compressionType == 0){ - m_channelOffsets[channelid] += (m_header->width * m_channelSize); - } - - for (quint32 col = 0; col < m_header->width; col++) { - - if (m_channelSize == 1) { - - quint8 *pixel = new quint8[5]; - memset(pixel, 0, 5); - dev->colorSpace()->setOpacity(pixel, OPACITY_OPAQUE_U8, 1); - - memset(pixel, 255 - channelBytes[0].constData()[col], 1); - memset(pixel + 1, 255 - channelBytes[1].constData()[col], 1); - memset(pixel + 2, 255 - channelBytes[2].constData()[col], 1); - memset(pixel + 3, 255 - channelBytes[3].constData()[col], 1); - dbgFile << "C" << pixel[0] << "M" << pixel[1] << "Y" << pixel[2] << "K" << pixel[3] << "A" << pixel[4]; - memcpy(it->rawData(), pixel, 5); - - - } - else if (m_channelSize == 2) { - - quint16 C = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoCmykTraits::setC(it->rawData(),C); - - quint16 M = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoCmykTraits::setM(it->rawData(),M); - - quint16 Y = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoCmykTraits::setY(it->rawData(),Y); - - quint16 K = ntohs(reinterpret_cast(channelBytes[3].constData())[col]); - KoCmykTraits::setK(it->rawData(),K); - - } - else if (m_channelSize == 4) { - - quint32 C = ntohl(reinterpret_cast(channelBytes[0].constData())[col]); - KoCmykTraits::setC(it->rawData(),C); - - quint32 M = ntohl(reinterpret_cast(channelBytes[1].constData())[col]); - KoCmykTraits::setM(it->rawData(),M); - - quint32 Y = ntohl(reinterpret_cast(channelBytes[2].constData())[col]); - KoCmykTraits::setY(it->rawData(),Y); - - quint32 K = ntohl(reinterpret_cast(channelBytes[3].constData())[col]); - KoCmykTraits::setK(it->rawData(),K); - - } - - dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1); - it->nextPixel(); - } - - } - - return true; - -} - -bool PSDImageData::readLAB(QIODevice *io, KisPaintDeviceSP dev) { + if (!m_channelInfoRecords.isEmpty()) { + QVector infoRecords; - int channelid = 0; - - for (quint32 row = 0; row < m_header->height; row++) { - - KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width); - QVector channelBytes; - - for (int channel = 0; channel < m_header->nChannels; channel++) { - - - switch (m_compression) { - - case Compression::Uncompressed: - - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[0]); - channelBytes.append(io->read(m_header->width*m_channelSize)); - } - break; - - case Compression::RLE: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[channel]); - int uncompressedLength = m_header->width * m_header->channelDepth / 8; - QByteArray compressedBytes = io->read(m_channelInfoRecords[channel].rleRowLengths[row]); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, m_channelInfoRecords[channel].compressionType); - channelBytes.append(uncompressedBytes); - m_channelOffsets[channel] += m_channelInfoRecords[channel].rleRowLengths[row]; - - } - break; - - case Compression::ZIP: - break; - - case Compression::ZIPWithPrediction: - break; - - default: - break; - } + QVector::iterator it = m_channelInfoRecords.begin(); + QVector::iterator end = m_channelInfoRecords.end(); + for (; it != end; ++it) { + infoRecords << &(*it); } - if (m_channelInfoRecords[channelid].compressionType == 0){ - m_channelOffsets[channelid] += (m_header->width * m_channelSize); - } - - for (quint32 col = 0; col < m_header->width; col++) { - - if (m_channelSize == 1) { - - quint8 L = channelBytes[0].constData()[col]; - KoLabTraits::setL(it->rawData(), L); - - quint8 A = channelBytes[1].constData()[col]; - KoLabTraits::setA(it->rawData(), A); - - quint8 B = channelBytes[2].constData()[col]; - KoLabTraits::setB(it->rawData(), B); - } - - else if (m_channelSize == 2) { - - quint16 L = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoLabU16Traits::setL(it->rawData(),L); + const QRect imageRect(0, 0, m_header->width, m_header->height); - quint16 A = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoLabU16Traits::setA(it->rawData(),A); - - quint16 B = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoLabU16Traits::setB(it->rawData(),B); - - } - - else if (m_channelSize == 4) { - - quint32 L = ntohl(reinterpret_cast(channelBytes[0].constData())[col]); - KoLabTraits::setL(it->rawData(),L); - - quint32 A = ntohl(reinterpret_cast(channelBytes[1].constData())[col]); - KoLabTraits::setA(it->rawData(),A); - - quint32 B = ntohl(reinterpret_cast(channelBytes[2].constData())[col]); - KoLabTraits::setB(it->rawData(),B); - - } - - dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1); - it->nextPixel(); + try { + PsdPixelUtils::readChannels(io, dev, + m_header->colormode, + m_channelSize, + imageRect, + infoRecords); + } catch (KisAslReaderUtils::ASLParseException &e) { + dev->clear(); + return true; } } return true; } -bool PSDImageData::readGrayscale(QIODevice *io, KisPaintDeviceSP dev) { - int channelid = 0; - - for (quint32 row = 0; row < m_header->height; row++) { - - KisHLineIteratorSP it = dev->createHLineIteratorNG(0, row, m_header->width); - QVector channelBytes; - - for (int channel = 0; channel < m_header->nChannels; channel++) { - - switch (m_compression) { - case Compression::Uncompressed: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[0]); - channelBytes.append(io->read(m_header->width*m_channelSize)); - } - break; - case Compression::RLE: - { - io->seek(m_channelInfoRecords[channel].channelDataStart + m_channelOffsets[channel]); - int uncompressedLength = m_header->width * m_header->channelDepth / 8; - QByteArray compressedBytes = io->read(m_channelInfoRecords[channel].rleRowLengths[row]); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, m_channelInfoRecords[channel].compressionType); - channelBytes.append(uncompressedBytes); - m_channelOffsets[channel] += m_channelInfoRecords[channel].rleRowLengths[row]; - - } - break; - case Compression::ZIP: - break; - case Compression::ZIPWithPrediction: - break; - - default: - break; - } - - } - - if (m_channelInfoRecords[channelid].compressionType == 0) { - m_channelOffsets[channelid] += (m_header->width * m_channelSize); - } - - for (quint32 col = 0; col < m_header->width; col++) { - - if (m_channelSize == 1) { - - quint8 Gray = channelBytes[0].constData()[col]; - KoGrayU8Traits::setGray(it->rawData(), Gray); +bool PSDImageData::write(QIODevice *io, KisPaintDeviceSP dev, bool hasAlpha) +{ + // XXX: make the compression settting configurable. For now, always use RLE. + psdwrite(io, (quint16)Compression::RLE); - } + // now write all the channels in display order + // fill in the channel chooser, in the display order, but store the pixel index as well. + QRect rc(0, 0, m_header->width, m_header->height); - else if (m_channelSize == 2) { + const int channelSize = m_header->channelDepth / 8; + const psd_color_mode colorMode = m_header->colormode; - quint16 Gray = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoGrayU16Traits::setGray(it->rawData(), Gray); + QVector writingInfoList; - } + bool writeAlpha = hasAlpha && + dev->colorSpace()->channelCount() != dev->colorSpace()->colorChannelCount(); - else if (m_channelSize == 4) { + const int numChannels = + writeAlpha ? + dev->colorSpace()->channelCount() : + dev->colorSpace()->colorChannelCount(); - quint32 Gray = ntohl(reinterpret_cast(channelBytes[0].constData())[col]); - KoGrayTraits::setGray(it->rawData(), Gray); + for (int i = 0; i < numChannels; i++) { + const int rleOffset = io->pos(); - } + int channelId = writeAlpha && i == numChannels - 1 ? -1 : i; - dev->colorSpace()->setOpacity(it->rawData(), OPACITY_OPAQUE_U8, 1); - it->nextPixel(); - } + writingInfoList << + PsdPixelUtils::ChannelWritingInfo(channelId, -1, rleOffset); + io->seek(io->pos() + rc.height() * sizeof(quint16)); } + PsdPixelUtils::writePixelDataCommon(io, dev, rc, + colorMode, channelSize, + false, false, writingInfoList); return true; } diff --git a/krita/plugins/formats/psd/psd_image_data.h b/krita/plugins/formats/psd/psd_image_data.h index 8d7c294e92b..61529bc1c5a 100644 --- a/krita/plugins/formats/psd/psd_image_data.h +++ b/krita/plugins/formats/psd/psd_image_data.h @@ -1,63 +1,63 @@ /* * Copyright (C) 2011 by Siddharth Sharma * * 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, see */ #ifndef PSD_IMAGE_DATA_H #define PSD_IMAGE_DATA_H #include #include #include #include #include #include #include class QIODevice; class PSDImageData { public: PSDImageData(PSDHeader *header); virtual ~PSDImageData(); bool read(QIODevice *io, KisPaintDeviceSP dev); - bool write(QIODevice *io, KisPaintDeviceSP dev); + bool write(QIODevice *io, KisPaintDeviceSP dev, bool hasAlpha); QString error; private: bool readRGB(QIODevice *io, KisPaintDeviceSP dev); bool readCMYK(QIODevice *io, KisPaintDeviceSP dev); bool readLAB(QIODevice *io, KisPaintDeviceSP dev); bool readGrayscale(QIODevice *io, KisPaintDeviceSP dev); PSDHeader *m_header; quint16 m_compression; quint64 m_channelDataLength; quint32 m_channelSize; QVector m_channelInfoRecords; QVector m_channelOffsets; // this doesn't need to be global }; #endif // PSD_IMAGE_DATA_H diff --git a/krita/plugins/formats/psd/psd_layer_record.cpp b/krita/plugins/formats/psd/psd_layer_record.cpp index ee59b22ba71..c572147ea55 100644 --- a/krita/plugins/formats/psd/psd_layer_record.cpp +++ b/krita/plugins/formats/psd/psd_layer_record.cpp @@ -1,1317 +1,791 @@ /* * Copyright (c) 2009 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 "psd_layer_record.h" #include // htonl #include #include #include #include #include #include #include "kis_iterator_ng.h" #include #include "psd_utils.h" #include "psd_header.h" #include "compression.h" #include #include #include #include #include +#include + +#include "psd_pixel_utils.h" // Just for pretty debug messages QString channelIdToChannelType(int channelId, psd_color_mode colormode) { switch(channelId) { case -3: return "Real User Supplied Layer Mask (when both a user mask and a vector mask are present"; case -2: return "User Supplied Layer Mask"; case -1: return "Transparency mask"; case 0: switch(colormode) { case Bitmap: case Indexed: return QString("bitmap or indexed: %1").arg(channelId); case Grayscale: case Gray16: return "gray"; case RGB: case RGB48: return "red"; case Lab: case Lab48: return "L"; case CMYK: case CMYK64: return "cyan"; case MultiChannel: case DeepMultichannel: return QString("multichannel channel %1").arg(channelId); case DuoTone: case Duotone16: return QString("duotone channel %1").arg(channelId); default: return QString("unknown: %1").arg(channelId); }; case 1: switch(colormode) { case Bitmap: case Indexed: return QString("WARNING bitmap or indexed: %1").arg(channelId); case Grayscale: case Gray16: return QString("WARNING: %1").arg(channelId); case RGB: case RGB48: return "green"; case Lab: case Lab48: return "a"; case CMYK: case CMYK64: return "Magenta"; case MultiChannel: case DeepMultichannel: return QString("multichannel channel %1").arg(channelId); case DuoTone: case Duotone16: return QString("duotone channel %1").arg(channelId); default: return QString("unknown: %1").arg(channelId); }; case 2: switch(colormode) { case Bitmap: case Indexed: return QString("WARNING bitmap or indexed: %1").arg(channelId); case Grayscale: case Gray16: return QString("WARNING: %1").arg(channelId); case RGB: case RGB48: return "blue"; case Lab: case Lab48: return "b"; case CMYK: case CMYK64: return "yellow"; case MultiChannel: case DeepMultichannel: return QString("multichannel channel %1").arg(channelId); case DuoTone: case Duotone16: return QString("duotone channel %1").arg(channelId); default: return QString("unknown: %1").arg(channelId); }; case 3: switch(colormode) { case Bitmap: case Indexed: return QString("WARNING bitmap or indexed: %1").arg(channelId); case Grayscale: case Gray16: return QString("WARNING: %1").arg(channelId); case RGB: case RGB48: return QString("alpha: %1").arg(channelId); case Lab: case Lab48: return QString("alpha: %1").arg(channelId); case CMYK: case CMYK64: return "Key"; case MultiChannel: case DeepMultichannel: return QString("multichannel channel %1").arg(channelId); case DuoTone: case Duotone16: return QString("duotone channel %1").arg(channelId); default: return QString("unknown: %1").arg(channelId); }; default: return QString("unknown: %1").arg(channelId); }; } PSDLayerRecord::PSDLayerRecord(const PSDHeader& header) : top(0) , left(0) , bottom(0) , right(0) , nChannels(0) , opacity(0) , clipping(0) , transparencyProtected(false) , visible(true) , irrelevant(false) , layerName("UNINITIALIZED") , infoBlocks(header) , m_transparencyMaskSizeOffset(0) , m_header(header) { } bool PSDLayerRecord::read(QIODevice* io) { dbgFile << "Going to read layer record. Pos:" << io->pos(); if (!psdread(io, &top) || !psdread(io, &left) || !psdread(io, &bottom) || !psdread(io, &right) || !psdread(io, &nChannels)) { error = "could not read layer record"; return false; } dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels; Q_ASSERT(top <= bottom); Q_ASSERT(left <= right); Q_ASSERT(nChannels > 0); switch(m_header.colormode) { case(Bitmap): case(Indexed): case(DuoTone): case(Grayscale): case(MultiChannel): if (nChannels < 1) { error = QString("Not enough channels. Got: %1").arg(nChannels); return false; } break; case(RGB): case(CMYK): case(Lab): default: if (nChannels < 3) { error = QString("Not enough channels. Got: %1").arg(nChannels); return false; } break; }; if (nChannels > MAX_CHANNELS) { error = QString("Too many channels. Got: %1").arg(nChannels); return false; } for (int i = 0; i < nChannels; ++i) { if (io->atEnd()) { error = "Could not read enough data for channels"; return false; } ChannelInfo* info = new ChannelInfo; if (!psdread(io, &info->channelId)) { error = "could not read channel id"; delete info; return false; } bool r; if (m_header.version == 1) { quint32 channelDataLength; r = psdread(io, &channelDataLength); info->channelDataLength = (quint64)channelDataLength; } else { r = psdread(io, &info->channelDataLength); } if (!r) { error = "Could not read length for channel data"; delete info; return false; } dbgFile << "\tchannel" << i << "id" << channelIdToChannelType(info->channelId, m_header.colormode) << "length" << info->channelDataLength << "start" << info->channelDataStart << "offset" << info->channelOffset << "channelInfoPosition" << info->channelInfoPosition; channelInfoRecords << info; } if (!psd_read_blendmode(io, blendModeKey)) { error = QString("Could not read blend mode key. Got: %1").arg(blendModeKey); return false; } dbgFile << "\tBlend mode" << blendModeKey << "pos" << io->pos(); if (!psdread(io, &opacity)) { error = "Could not read opacity"; return false; } dbgFile << "\tOpacity" << opacity << io->pos(); if (!psdread(io, &clipping)) { error = "Could not read clipping"; return false; } dbgFile << "\tclipping" << clipping << io->pos(); quint8 flags; if (!psdread(io, &flags)) { error = "Could not read flags"; return false; } dbgFile << "\tflags" << flags << io->pos(); transparencyProtected = flags & 1 ? true : false; dbgFile << "\ttransparency protected" << transparencyProtected; visible = flags & 2 ? false : true; dbgFile << "\tvisible" << visible; if (flags & 8) { irrelevant = flags & 16 ? true : false; } else { irrelevant = false; } dbgFile << "\tirrelevant" << irrelevant; dbgFile << "\tfiller at " << io->pos(); quint8 filler; if (!psdread(io, &filler) || filler != 0) { error = "Could not read padding"; return false; } dbgFile << "\tGoing to read extra data length" << io->pos(); quint32 extraDataLength; if (!psdread(io, &extraDataLength) || io->bytesAvailable() < extraDataLength) { error = QString("Could not read extra layer data: %1 at pos %2").arg(extraDataLength).arg(io->pos()); return false; } dbgFile << "\tExtra data length" << extraDataLength; if (extraDataLength > 0) { dbgFile << "Going to read extra data field. Bytes available: " << io->bytesAvailable() << "pos" << io->pos(); quint32 layerMaskLength = 1; // invalid... if (!psdread(io, &layerMaskLength) || io->bytesAvailable() < layerMaskLength || !(layerMaskLength == 0 || layerMaskLength == 20 || layerMaskLength == 36)) { error = QString("Could not read layer mask length: %1").arg(layerMaskLength); return false; } memset(&layerMask, 0, sizeof(LayerMaskData)); if (layerMaskLength == 20 || layerMaskLength == 36) { if (!psdread(io, &layerMask.top) || !psdread(io, &layerMask.left) || !psdread(io, &layerMask.bottom) || !psdread(io, &layerMask.right) || !psdread(io, &layerMask.defaultColor) || !psdread(io, &flags)) { error = "could not read mask record"; return false; } } if (layerMaskLength == 20) { quint16 padding; if (!psdread(io, &padding)) { error = "Could not read layer mask padding"; return false; } } if (layerMaskLength == 36 ) { if (!psdread(io, &flags) || !psdread(io, &layerMask.defaultColor) || !psdread(io, &layerMask.top) || !psdread(io, &layerMask.left) || !psdread(io, &layerMask.bottom) || !psdread(io, &layerMask.top)) { error = "could not read 'real' mask record"; return false; } } layerMask.positionedRelativeToLayer = flags & 1 ? true : false; layerMask.disabled = flags & 2 ? true : false; layerMask.invertLayerMaskWhenBlending = flags & 4 ? true : false; dbgFile << "\tRead layer mask/adjustment layer data. Length of block:" << layerMaskLength << "pos" << io->pos(); // layer blending thingies quint32 blendingDataLength; if (!psdread(io, &blendingDataLength) || io->bytesAvailable() < blendingDataLength) { error = "Could not read extra blending data."; return false; } //dbgFile << "blending block data length" << blendingDataLength << ", pos" << io->pos(); blendingRanges.data = io->read(blendingDataLength); if ((quint32)blendingRanges.data.size() != blendingDataLength) { error = QString("Got %1 bytes for the blending range block, needed %2").arg(blendingRanges.data.size(), blendingDataLength); } /* // XXX: reading this block correctly failed, I have more channel ranges than I'd expected. if (!psdread(io, &blendingRanges.blackValues[0]) || !psdread(io, &blendingRanges.blackValues[1]) || !psdread(io, &blendingRanges.whiteValues[0]) || !psdread(io, &blendingRanges.whiteValues[1]) || !psdread(io, &blendingRanges.compositeGrayBlendDestinationRange)) { error = "Could not read blending black/white values"; return false; } for (int i = 0; i < nChannels; ++i) { quint32 src; quint32 dst; if (!psdread(io, &src) || !psdread(io, &dst)) { error = QString("could not read src/dst range for channel %1").arg(i); return false; } dbgFile << "\tread range " << src << "to" << dst << "for channel" << i; blendingRanges.sourceDestinationRanges << QPair(src, dst); } */ dbgFile << "\tGoing to read layer name at" << io->pos(); quint8 layerNameLength; if (!psdread(io, &layerNameLength)) { error = "Could not read layer name length"; return false; } dbgFile << "\tlayer name length unpadded" << layerNameLength << "pos" << io->pos(); layerNameLength = ((layerNameLength + 1 + 3) & ~0x03) - 1; dbgFile << "\tlayer name length padded" << layerNameLength << "pos" << io->pos(); layerName = io->read(layerNameLength); dbgFile << "\tlayer name" << layerName << io->pos(); if (!infoBlocks.read(io)) { error = infoBlocks.error; return false; } if (infoBlocks.keys.contains("luni") && !infoBlocks.unicodeLayerName.isEmpty()) { layerName = infoBlocks.unicodeLayerName; } } return valid(); } void PSDLayerRecord::write(QIODevice* io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc) { dbgFile << "writing layer info record" << "at" << io->pos(); m_layerContentDevice = layerContentDevice; m_onlyTransparencyMask = onlyTransparencyMask; m_onlyTransparencyMaskRect = maskRect; dbgFile << "saving layer record for " << layerName << "at pos" << io->pos(); dbgFile << "\ttop" << top << "left" << left << "bottom" << bottom << "right" << right << "number of channels" << nChannels; Q_ASSERT(left <= right); Q_ASSERT(top <= bottom); Q_ASSERT(nChannels > 0); try { const QRect layerRect(left, top, right - left, bottom - top); KisAslWriterUtils::writeRect(layerRect, io); { quint16 realNumberOfChannels = nChannels + bool(m_onlyTransparencyMask); SAFE_WRITE_EX(io, realNumberOfChannels); } foreach(ChannelInfo *channel, channelInfoRecords) { SAFE_WRITE_EX(io, (quint16)channel->channelId); channel->channelInfoPosition = io->pos(); // to be filled in when we know how big channel block is const quint32 fakeChannelSize = 0; SAFE_WRITE_EX(io, fakeChannelSize); } if (m_onlyTransparencyMask) { const quint16 userSuppliedMaskChannelId = -2; SAFE_WRITE_EX(io, userSuppliedMaskChannelId); m_transparencyMaskSizeOffset = io->pos(); const quint32 fakeTransparencyMaskSize = 0; SAFE_WRITE_EX(io, fakeTransparencyMaskSize); } // blend mode dbgFile << ppVar(blendModeKey) << ppVar(io->pos()); KisAslWriterUtils::writeFixedString("8BIM", io); KisAslWriterUtils::writeFixedString(blendModeKey, io); SAFE_WRITE_EX(io, opacity); SAFE_WRITE_EX(io, clipping); // unused // visibility and protection quint8 flags = 0; if (transparencyProtected) flags |= 1; if (!visible) flags |= 2; if (irrelevant) { flags |= (1 << 3) | (1 << 4); } SAFE_WRITE_EX(io, flags); { quint8 padding = 0; SAFE_WRITE_EX(io, padding); } { // extra fields with their own length tag KisAslWriterUtils::OffsetStreamPusher extraDataSizeTag(io); if (m_onlyTransparencyMask) { { const quint32 layerMaskDataSize = 20; // support simple case only SAFE_WRITE_EX(io, layerMaskDataSize); } KisAslWriterUtils::writeRect(m_onlyTransparencyMaskRect, io); { KIS_ASSERT_RECOVER_NOOP(m_onlyTransparencyMask->paintDevice()->pixelSize() == 1); const quint8 defaultPixel = *m_onlyTransparencyMask->paintDevice()->defaultPixel(); SAFE_WRITE_EX(io, defaultPixel); } { const quint8 maskFlags = 0; // nothing serious SAFE_WRITE_EX(io, maskFlags); const quint16 padding = 0; // 2-byte padding SAFE_WRITE_EX(io, padding); } } else { const quint32 nullLayerMaskDataSize = 0; SAFE_WRITE_EX(io, nullLayerMaskDataSize); } { // blending ranges are not implemented yet const quint32 nullBlendingRangesSize = 0; SAFE_WRITE_EX(io, nullBlendingRangesSize); } // layer name: Pascal string, padded to a multiple of 4 bytes. psdwrite_pascalstring(io, layerName, 4); PsdAdditionalLayerInfoBlock additionalInfoBlock(m_header); // write 'luni' data block additionalInfoBlock.writeLuniBlockEx(io, layerName); // write 'lsct' data block if (sectionType != psd_other) { additionalInfoBlock.writeLsctBlockEx(io, sectionType, isPassThrough, blendModeKey); } // write 'lfx2' data block if (!stylesXmlDoc.isNull()) { additionalInfoBlock.writeLfx2BlockEx(io, stylesXmlDoc); } } } catch (KisAslWriterUtils::ASLWriteException &e) { throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what())); } } -void writeChannelDataRLE(QIODevice *io, const quint8 *plane, const int channelSize, const QRect &rc, const qint64 sizeFieldOffset) -{ - KisAslWriterUtils::OffsetStreamPusher channelBlockSizeExternalTag(io, 0, sizeFieldOffset); - - SAFE_WRITE_EX(io, (quint16)Compression::RLE); - - // the start of RLE sizes block - const qint64 channelRLESizePos = io->pos(); - - // write zero's for the channel lengths block - for(int i = 0; i < rc.height(); ++i) { - // XXX: choose size for PSB! - const quint16 fakeRLEBLockSize = 0; - SAFE_WRITE_EX(io, fakeRLEBLockSize); - } - - quint32 stride = channelSize * rc.width(); - for (qint32 row = 0; row < rc.height(); ++row) { - - QByteArray uncompressed = QByteArray::fromRawData((const char*)plane + row * stride, stride); - QByteArray compressed = Compression::compress(uncompressed, Compression::RLE); - - KisAslWriterUtils::OffsetStreamPusher rleExternalTag(io, 0, channelRLESizePos + row * sizeof(quint16)); - - if (io->write(compressed) != compressed.size()) { - throw KisAslWriterUtils::ASLWriteException("Failed to write image data"); - } - } -} - void PSDLayerRecord::writeTransparencyMaskPixelData(QIODevice *io) { if (m_onlyTransparencyMask) { KisPaintDeviceSP device = m_onlyTransparencyMask->paintDevice(); KIS_ASSERT_RECOVER_NOOP(device->pixelSize() == 1); QByteArray buffer(m_onlyTransparencyMaskRect.width() * m_onlyTransparencyMaskRect.height(), 0); device->readBytes((quint8*)buffer.data(), m_onlyTransparencyMaskRect); - writeChannelDataRLE(io, (quint8*)buffer.data(), 1, m_onlyTransparencyMaskRect, m_transparencyMaskSizeOffset); + PsdPixelUtils::writeChannelDataRLE(io, (quint8*)buffer.data(), 1, m_onlyTransparencyMaskRect, m_transparencyMaskSizeOffset, -1, true); } } void PSDLayerRecord::writePixelData(QIODevice *io) +{ + try { + writePixelDataImpl(io); + } catch (KisAslWriterUtils::ASLWriteException &e) { + throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what())); + } +} + +void PSDLayerRecord::writePixelDataImpl(QIODevice *io) { dbgFile << "writing pixel data for layer" << layerName << "at" << io->pos(); KisPaintDeviceSP dev = m_layerContentDevice; const QRect rc(left, top, right - left, bottom - top); if (rc.isEmpty()) { - try { - dbgFile << "Layer is empty! Writing placeholder information."; + dbgFile << "Layer is empty! Writing placeholder information."; - for (int i = 0; i < nChannels; i++) { - const ChannelInfo *channelInfo = channelInfoRecords[i]; - KisAslWriterUtils::OffsetStreamPusher channelBlockSizeExternalTag(io, 0, channelInfo->channelInfoPosition); - SAFE_WRITE_EX(io, (quint16)Compression::Uncompressed); - } - - writeTransparencyMaskPixelData(io); - - } catch (KisAslWriterUtils::ASLWriteException &e) { - throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what())); + for (int i = 0; i < nChannels; i++) { + const ChannelInfo *channelInfo = channelInfoRecords[i]; + KisAslWriterUtils::OffsetStreamPusher channelBlockSizeExternalTag(io, 0, channelInfo->channelInfoPosition); + SAFE_WRITE_EX(io, (quint16)Compression::Uncompressed); } + writeTransparencyMaskPixelData(io); + return; } // now write all the channels in display order dbgFile << "layer" << layerName; - QVector tmp = dev->readPlanarBytes(rc.x() - dev->x(), rc.y() - dev->y(), rc.width(), rc.height()); - - // then reorder the planes to fit the psd model -- alpha first, then display order - QVector planes; - QList origChannels = dev->colorSpace()->channels(); - - foreach(KoChannelInfo *ch, KoChannelInfo::displayOrderSorted(origChannels)) { - int channelIndex = KoChannelInfo::displayPositionToChannelIndex(ch->displayPosition(), origChannels); - - quint8 *holder = tmp[channelIndex]; - tmp[channelIndex] = 0; - - if (ch->channelType() == KoChannelInfo::ALPHA) { - planes.insert(0, holder); - } else { - planes.append(holder); - } - } - // now planes are holding pointers to quint8 arrays - tmp.clear(); + const int channelSize = m_header.channelDepth / 8; + const psd_color_mode colorMode = m_header.colormode; - try { - // here's where we save the total size of the channel data - for (int channelInfoIndex = 0; channelInfoIndex < nChannels; ++channelInfoIndex) { - - const ChannelInfo *channelInfo = channelInfoRecords[channelInfoIndex]; - - dbgFile << "\tWriting channel" << channelInfoIndex << "psd channel id" << channelInfo->channelId; - - // if the bitdepth > 8, place the bytes in the right order - // if cmyk, invert the pixel value - if (m_header.channelDepth == 8) { - if (channelInfo->channelId >= 0 && (m_header.colormode == CMYK || m_header.colormode == CMYK64)) { - for (int i = 0; i < rc.width() * rc.height(); ++i) { - planes[channelInfoIndex][i] = 255 - planes[channelInfoIndex][i]; - } - } - } - else if (m_header.channelDepth == 16) { - quint16 val; - for (int i = 0; i < rc.width() * rc.height(); ++i) { - val = reinterpret_cast(planes[channelInfoIndex])[i]; - val = ntohs(val); - if (channelInfo->channelId >= 0 && (m_header.colormode == CMYK || m_header.colormode == CMYK64)) { - val = quint16_MAX - val; - } - reinterpret_cast(planes[channelInfoIndex])[i] = val; - } - } - else if (m_header.channelDepth == 32) { - quint32 val; - for (int i = 0; i < rc.width() * rc.height(); ++i) { - val = reinterpret_cast(planes[channelInfoIndex])[i]; - val = ntohl(val); - if (channelInfo->channelId >= 0 && (m_header.colormode == CMYK || m_header.colormode == CMYK64)) { - val = quint16_MAX - val; - } - reinterpret_cast(planes[channelInfoIndex])[i] = val; - } - } - - dbgFile << "\t\tchannel start" << ppVar(io->pos()); - - writeChannelDataRLE(io, planes[channelInfoIndex], m_header.channelDepth / 8, rc, channelInfo->channelInfoPosition); - } - - writeTransparencyMaskPixelData(io); - - } catch (KisAslWriterUtils::ASLWriteException &e) { - qDeleteAll(planes); - planes.clear(); - - throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what())); + QVector writingInfoList; + foreach (const ChannelInfo *channelInfo, channelInfoRecords) { + writingInfoList << + PsdPixelUtils::ChannelWritingInfo(channelInfo->channelId, + channelInfo->channelInfoPosition); } - qDeleteAll(planes); - planes.clear(); + PsdPixelUtils::writePixelDataCommon(io, dev, rc, colorMode, channelSize, true, true, writingInfoList); + writeTransparencyMaskPixelData(io); } bool PSDLayerRecord::valid() { // XXX: check validity! return true; } bool PSDLayerRecord::readPixelData(QIODevice *io, KisPaintDeviceSP device) { dbgFile << "Reading pixel data for layer" << layerName << "pos" << io->pos(); - switch (m_header.colormode) { - case Bitmap: - error = "Unsupported color mode: bitmap"; - return false; // Not supported; - case Indexed: - error = "Unsupported color mode: indexed"; - return false; // Not supported; - case MultiChannel: - error = "Unsupported color mode: indexed"; - return false; // Not supported - case DuoTone: - error = "Unsupported color mode: Duotone"; - return false; // Not supported - case Grayscale: - return readGray(device, io); - case RGB: - return readRGB(device, io); - case CMYK: - return readCMYK(device, io); - case Lab: - return readLAB(device, io); - case UNKNOWN: - default: + + const int channelSize = m_header.channelDepth / 8; + const QRect layerRect = QRect(left, + top, + right - left, + bottom - top); + + try { + PsdPixelUtils::readChannels(io, device, m_header.colormode, channelSize, layerRect, channelInfoRecords); + } catch (KisAslReaderUtils::ASLParseException &e) { + device->clear(); + error = e.what(); return false; } - return false; + return true; } QRect PSDLayerRecord::channelRect(ChannelInfo *channel) const { QRect result; if (channel->channelId < -1) { result = QRect(layerMask.left, layerMask.top, layerMask.right - layerMask.left, layerMask.bottom - layerMask.top); } else { result = QRect(left, top, right - left, bottom - top); } return result; } + bool PSDLayerRecord::readMask(QIODevice *io, KisPaintDeviceSP dev, ChannelInfo *channelInfo) { KisOffsetKeeper keeper(io); KIS_ASSERT_RECOVER(channelInfo->channelId < -1) { return false; } dbgFile << "Going to read" << channelIdToChannelType(channelInfo->channelId, m_header.colormode) << "mask"; QRect maskRect = channelRect(channelInfo); if (maskRect.isEmpty()) { dbgFile << "Empty Channel"; return true; } // the device must be a pixel selection KIS_ASSERT_RECOVER(dev->pixelSize() == 1) { return false; } dev->setDefaultPixel(&layerMask.defaultColor); - int uncompressedLength = maskRect.width(); if (channelInfo->compressionType == Compression::ZIP || channelInfo->compressionType == Compression::ZIPWithPrediction) { error = "Unsupported Compression mode: zip"; return false; } KisHLineIteratorSP it = dev->createHLineIteratorNG(maskRect.left(), maskRect.top(), maskRect.width()); for (int row = maskRect.top(); row <= maskRect.bottom(); row++) { QByteArray channelBytes; io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); if (channelInfo->compressionType == Compression::Uncompressed) { channelBytes = io->read(uncompressedLength); channelInfo->channelOffset += uncompressedLength; } else if (channelInfo->compressionType == Compression::RLE) { int rleLength = channelInfo->rleRowLengths[row - maskRect.top()]; QByteArray compressedBytes = io->read(rleLength); channelBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); channelInfo->channelOffset += rleLength; } else { error = "Unsupported Compression mode: " + channelInfo->compressionType; return false; } for (int col = 0; col < maskRect.width(); col++){ *it->rawData() = channelBytes[col]; it->nextPixel(); } it->nextRow(); } // the position of the io device will be restored by // KisOffsetKeeper automagically return true; } -template -typename Traits::channels_type convertByteOrder(typename Traits::channels_type value); -// default implementation is undefined for every color space should be added manually - -template <> -inline quint8 convertByteOrder(quint8 value) { - return value; -} - -template <> -inline quint16 convertByteOrder(quint16 value) { - return ntohs(value); -} - -template <> -inline quint32 convertByteOrder(quint32 value) { - return ntohs(value); -} - - -template -void readGrayPixel(const QMap &channelBytes, - int col, quint8 *dstPtr) -{ - typedef typename Traits::Pixel Pixel; - typedef typename Traits::channels_type channels_type; - - quint32 opacity = KoColorSpaceMathsTraits::unitValue; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - } - - Pixel *pixelPtr = reinterpret_cast(dstPtr); - - channels_type gray = convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); - - pixelPtr->gray = gray; - pixelPtr->alpha = opacity; -} - -bool PSDLayerRecord::readGray(KisPaintDeviceSP dev, QIODevice *io) -{ - KisOffsetKeeper keeper(io); - - qint64 width = right - left; - - if (width <= 0) { - dbgFile << "Empty layer"; - return true; - } - - int channelSize = m_header.channelDepth / 8; - int uncompressedLength = width * channelSize; - - if (channelInfoRecords.first()->compressionType == Compression::ZIP - || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) { - - error = "Unsupported Compression mode: zip"; - return false; - } - - KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width); - for (int row = top ; row < bottom; row++) - { - QMap channelBytes; - - foreach(ChannelInfo *channelInfo, channelInfoRecords) { - // user supplied masks are ignored here - if (channelInfo->channelId < -1) continue; - - io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); - - if (channelInfo->compressionType == Compression::Uncompressed) { - channelBytes[channelInfo->channelId] = io->read(uncompressedLength); - channelInfo->channelOffset += uncompressedLength; - } - else if (channelInfo->compressionType == Compression::RLE) { - int rleLength = channelInfo->rleRowLengths[row - top]; - QByteArray compressedBytes = io->read(rleLength); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); - channelBytes.insert(channelInfo->channelId, uncompressedBytes); - channelInfo->channelOffset += rleLength; - - } - else { - error = "Unsupported Compression mode: " + channelInfo->compressionType; - return false; - } - } - - for (qint64 col = 0; col < width; col++){ - - if (channelSize == 1) { - readGrayPixel(channelBytes, col, it->rawData()); - } - - else if (channelSize == 2) { - readGrayPixel(channelBytes, col, it->rawData()); - } - else if (channelSize == 4) { - readGrayPixel(channelBytes, col, it->rawData()); - } - it->nextPixel(); - } - it->nextRow(); - } - - return true; -} - -template <> -inline quint8 convertByteOrder(quint8 value) { - return value; -} - -template <> -inline quint16 convertByteOrder(quint16 value) { - return ntohs(value); -} - -template <> -inline quint32 convertByteOrder(quint32 value) { - return ntohs(value); -} - - -template -void readRGBPixel(const QMap &channelBytes, - int col, quint8 *dstPtr) -{ - typedef typename Traits::Pixel Pixel; - typedef typename Traits::channels_type channels_type; - - quint32 opacity = KoColorSpaceMathsTraits::unitValue; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - } - - Pixel *pixelPtr = reinterpret_cast(dstPtr); - - channels_type blue = convertByteOrder(reinterpret_cast(channelBytes[2].constData())[col]); - channels_type green = convertByteOrder(reinterpret_cast(channelBytes[1].constData())[col]); - channels_type red = convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); - - pixelPtr->blue = blue; - pixelPtr->green = green; - pixelPtr->red = red; - pixelPtr->alpha = opacity; -} - -bool PSDLayerRecord::readRGB(KisPaintDeviceSP dev, QIODevice *io) -{ - KisOffsetKeeper keeper(io); - - qint64 width = right - left; - - if (width <= 0) { - dbgFile << "Empty layer"; - return true; - } - - int channelSize = m_header.channelDepth / 8; - int uncompressedLength = width * channelSize; - - if (channelInfoRecords.first()->compressionType == Compression::ZIP - || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) { - - error = "Unsupported Compression mode: zip"; - return false; - } - - KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width); - for (int row = top ; row < bottom; row++) - { - QMap channelBytes; - - foreach(ChannelInfo *channelInfo, channelInfoRecords) { - // user supplied masks are ignored here - if (channelInfo->channelId < -1) continue; - - io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); - - if (channelInfo->compressionType == Compression::Uncompressed) { - channelBytes[channelInfo->channelId] = io->read(uncompressedLength); - channelInfo->channelOffset += uncompressedLength; - } - else if (channelInfo->compressionType == Compression::RLE) { - int rleLength = channelInfo->rleRowLengths[row - top]; - QByteArray compressedBytes = io->read(rleLength); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); - channelBytes.insert(channelInfo->channelId, uncompressedBytes); - channelInfo->channelOffset += rleLength; - - } - else { - error = "Unsupported Compression mode: " + channelInfo->compressionType; - return false; - } - } - - for (qint64 col = 0; col < width; col++){ - - if (channelSize == 1) { - readRGBPixel(channelBytes, col, it->rawData()); - } - else if (channelSize == 2) { - readRGBPixel(channelBytes, col, it->rawData()); - } - else if (channelSize == 4) { - readRGBPixel(channelBytes, col, it->rawData()); - } - it->nextPixel(); - } - it->nextRow(); - } - - return true; -} - -bool PSDLayerRecord::readCMYK(KisPaintDeviceSP dev, QIODevice *io) -{ - dbgFile << "doCMYK for" << layerName << "channels:" << channelInfoRecords.size() << "compression" << channelInfoRecords.first()->compressionType; - dbgFile << "top" << top << "bottom" << bottom << "left" << left << "right" << right; - - KisOffsetKeeper keeper(io); - - quint64 width = right - left; - int channelSize = m_header.channelDepth / 8; - int uncompressedLength = width * channelSize; - - - if (channelInfoRecords.first()->compressionType == Compression::ZIP - || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) { - dbgFile << "zippedy-do-da!"; - // Zip needs to be implemented here. - return false; - } - - KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width); - for (int row = top ; row < bottom; row++) - { - - QMap channelBytes; - - foreach(ChannelInfo *channelInfo, channelInfoRecords) { - - io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); - - if (channelInfo->compressionType == Compression::Uncompressed) { - channelBytes[channelInfo->channelId] = io->read(uncompressedLength); - channelInfo->channelOffset += uncompressedLength; - } - else if (channelInfo->compressionType == Compression::RLE) { - int rleLength = channelInfo->rleRowLengths[row - top]; - QByteArray compressedBytes = io->read(rleLength); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); - channelBytes.insert(channelInfo->channelId, uncompressedBytes); - channelInfo->channelOffset += rleLength; - - } - } - - for (quint64 col = 0; col < width; col++){ - - if (channelSize == 1) { - - quint8 opacity = OPACITY_OPAQUE_U8; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - - } - quint8 *pixel = new quint8[5]; - memset(pixel, 0, 5); - dev->colorSpace()->setOpacity(pixel, opacity, 1); - - memset(pixel, 255 - channelBytes[0].constData()[col], 1); - memset(pixel + 1, 255 - channelBytes[1].constData()[col], 1); - memset(pixel + 2, 255 - channelBytes[2].constData()[col], 1); - memset(pixel + 3, 255 - channelBytes[3].constData()[col], 1); - //dbgFile << "C" << pixel[0] << "M" << pixel[1] << "Y" << pixel[2] << "K" << pixel[3] << "A" << pixel[4]; - memcpy(it->rawData(), pixel, 5); - - delete[] pixel; - } - else if (channelSize == 2) { - - quint16 opacity = quint16_MAX; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - } - - // We don't have a convenient setOpacity function :-( - memcpy(it->rawData() + KoCmykTraits::alpha_pos, &opacity, sizeof(quint16)); - - quint16 C = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoCmykTraits::setC(it->rawData(),C); - - quint16 M = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoCmykTraits::setM(it->rawData(),M); - - quint16 Y = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoCmykTraits::setY(it->rawData(),Y); - - quint16 K = ntohs(reinterpret_cast(channelBytes[3].constData())[col]); - KoCmykTraits::setK(it->rawData(),K); - - } - else if (channelSize == 4) { - - quint32 C = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoCmykTraits::setC(it->rawData(),C); - - quint32 M = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoCmykTraits::setM(it->rawData(),M); - - quint32 Y = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoCmykTraits::setY(it->rawData(),Y); - - quint32 K = ntohs(reinterpret_cast(channelBytes[3].constData())[col]); - KoCmykTraits::setK(it->rawData(),K); - } - - else { - // Unsupported channel sizes for now - return false; - } - it->nextPixel(); - } - it->nextRow(); - } - - return true; -} - -bool PSDLayerRecord::readLAB(KisPaintDeviceSP dev, QIODevice *io) -{ - KisOffsetKeeper keeper(io); - - quint64 width = right - left; - int channelSize = m_header.channelDepth / 8; - int uncompressedLength = width * channelSize; - - if (channelInfoRecords.first()->compressionType == Compression::ZIP - || channelInfoRecords.first()->compressionType == Compression::ZIPWithPrediction) { - - // Zip needs to be implemented here. - return false; - } - - KisHLineIteratorSP it = dev->createHLineIteratorNG(left, top, width); - for (int row = top ; row < bottom; row++) - { - - QMap channelBytes; - - foreach(ChannelInfo *channelInfo, channelInfoRecords) { - - io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); - - if (channelInfo->compressionType == Compression::Uncompressed) { - channelBytes[channelInfo->channelId] = io->read(uncompressedLength); - channelInfo->channelOffset += uncompressedLength; - } - else if (channelInfo->compressionType == Compression::RLE) { - int rleLength = channelInfo->rleRowLengths[row - top]; - QByteArray compressedBytes = io->read(rleLength); - QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); - channelBytes.insert(channelInfo->channelId, uncompressedBytes); - channelInfo->channelOffset += rleLength; - - } - } - - for (quint64 col = 0; col < width; col++){ - - if (channelSize == 1) { - quint8 opacity = OPACITY_OPAQUE_U8; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - } - KoLabTraits::setOpacity(it->rawData(), opacity, 1); - - quint8 L = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoLabTraits::setL(it->rawData(),L); - - quint8 A = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoLabTraits::setA(it->rawData(),A); - - quint8 B = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoLabTraits::setB(it->rawData(),B); - - - } - - else if (channelSize == 2) { - - quint16 opacity = quint16_MAX; - if (channelBytes.contains(-1)) { - opacity = channelBytes[-1].constData()[col]; - } - // We don't have a convenient setOpacity function :-( - memcpy(it->rawData() + KoLabU16Traits::alpha_pos, &opacity, sizeof(quint16)); - // KoLabTraits::setOpacity(it->rawData(), opacity, 1); - - quint16 L = ntohs(reinterpret_cast(channelBytes[0].constData())[col]); - KoLabTraits::setL(it->rawData(),L); - - quint16 A = ntohs(reinterpret_cast(channelBytes[1].constData())[col]); - KoLabTraits::setA(it->rawData(),A); - - quint16 B = ntohs(reinterpret_cast(channelBytes[2].constData())[col]); - KoLabTraits::setB(it->rawData(),B); - } - else { - // Unsupported channel sizes for now - return false; - } - - it->nextPixel(); - } - it->nextRow(); - } - - return true; -} - - QDebug operator<<(QDebug dbg, const PSDLayerRecord &layer) { #ifndef NODEBUG dbg.nospace() << "valid: " << const_cast(&layer)->valid(); dbg.nospace() << ", name: " << layer.layerName; dbg.nospace() << ", top: " << layer.top; dbg.nospace() << ", left:" << layer.left; dbg.nospace() << ", bottom: " << layer.bottom; dbg.nospace() << ", right: " << layer.right; dbg.nospace() << ", number of channels: " << layer.nChannels; dbg.nospace() << ", blendModeKey: " << layer.blendModeKey; dbg.nospace() << ", opacity: " << layer.opacity; dbg.nospace() << ", clipping: " << layer.clipping; dbg.nospace() << ", transparency protected: " << layer.transparencyProtected; dbg.nospace() << ", visible: " << layer.visible; dbg.nospace() << ", irrelevant: " << layer.irrelevant << "\n"; foreach(const ChannelInfo* channel, layer.channelInfoRecords) { dbg.space() << channel; } #endif return dbg.nospace(); } QDebug operator<<(QDebug dbg, const ChannelInfo &channel) { #ifndef NODEBUG dbg.nospace() << "\tChannel type" << channel.channelId << "size: " << channel.channelDataLength << "compression type" << channel.compressionType << "\n"; #endif return dbg.nospace(); } diff --git a/krita/plugins/formats/psd/psd_layer_record.h b/krita/plugins/formats/psd/psd_layer_record.h index a93cc63877d..3270eca5569 100644 --- a/krita/plugins/formats/psd/psd_layer_record.h +++ b/krita/plugins/formats/psd/psd_layer_record.h @@ -1,176 +1,176 @@ /* * Copyright (c) 2009 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 PSD_LAYER_RECORD_H #define PSD_LAYER_RECORD_H #include #include #include #include #include #include #include #include "psd.h" #include "psd_header.h" #include "compression.h" #include "psd_additional_layer_info_block.h" +#include + + class QIODevice; enum psd_layer_type { psd_layer_type_normal, psd_layer_type_hidden, psd_layer_type_folder, psd_layer_type_solid_color, psd_layer_type_gradient_fill, psd_layer_type_pattern_fill, psd_layer_type_levels, psd_layer_type_curves, psd_layer_type_brightness_contrast, psd_layer_type_color_balance, psd_layer_type_hue_saturation, psd_layer_type_selective_color, psd_layer_type_threshold, psd_layer_type_invert, psd_layer_type_posterize, psd_layer_type_channel_mixer, psd_layer_type_gradient_map, psd_layer_type_photo_filter, }; struct ChannelInfo { ChannelInfo() : channelId(0) , compressionType(Compression::Unknown) , channelDataStart(0) , channelDataLength(0) , channelOffset(0) , channelInfoPosition(0) {} qint16 channelId; // 0 red, 1 green, 2 blue, -1 transparency, -2 user-supplied layer mask Compression::CompressionType compressionType; quint64 channelDataStart; quint64 channelDataLength; QVector rleRowLengths; int channelOffset; // where the channel data starts int channelInfoPosition; // where the channelinfo record is saved in the file }; class PSDLayerRecord { public: PSDLayerRecord(const PSDHeader &header); ~PSDLayerRecord() { qDeleteAll(channelInfoRecords); } QRect channelRect(ChannelInfo *channel) const; bool read(QIODevice* io); bool readPixelData(QIODevice* io, KisPaintDeviceSP device); bool readMask(QIODevice* io, KisPaintDeviceSP dev, ChannelInfo *channel); void write(QIODevice* io, KisPaintDeviceSP layerContentDevice, KisNodeSP onlyTransparencyMask, const QRect &maskRect, psd_section_type sectionType, const QDomDocument &stylesXmlDoc); void writePixelData(QIODevice* io); bool valid(); QString error; qint32 top; qint32 left; qint32 bottom; qint32 right; quint16 nChannels; QVector channelInfoRecords; QString blendModeKey; bool isPassThrough; quint8 opacity; quint8 clipping; bool transparencyProtected; bool visible; bool irrelevant; struct LayerMaskData { qint32 top; qint32 left; qint32 bottom; qint32 right; quint8 defaultColor; // 0 or 255 bool positionedRelativeToLayer; bool disabled; bool invertLayerMaskWhenBlending; quint8 userMaskDensity; double userMaskFeather; quint8 vectorMaskDensity; double vectorMaskFeather; }; LayerMaskData layerMask; struct LayerBlendingRanges { QByteArray data; quint8 blackValues[2]; quint8 whiteValues[2]; quint32 compositeGrayBlendDestinationRange; QVector > sourceDestinationRanges; }; LayerBlendingRanges blendingRanges; QString layerName; // pascal, not unicode! PsdAdditionalLayerInfoBlock infoBlocks; private: void writeTransparencyMaskPixelData(QIODevice *io); -private: + void writePixelDataImpl(QIODevice *io); - bool readRGB(KisPaintDeviceSP dev ,QIODevice *io); - bool readCMYK(KisPaintDeviceSP dev ,QIODevice *io); - bool readLAB(KisPaintDeviceSP dev ,QIODevice *io); - bool readGray(KisPaintDeviceSP dev ,QIODevice *io); +private: KisPaintDeviceSP m_layerContentDevice; KisNodeSP m_onlyTransparencyMask; QRect m_onlyTransparencyMaskRect; qint64 m_transparencyMaskSizeOffset; const PSDHeader m_header; }; QDebug operator<<(QDebug dbg, const PSDLayerRecord& layer); QDebug operator<<(QDebug dbg, const ChannelInfo& layer); #endif // PSD_LAYER_RECORD_H diff --git a/krita/plugins/formats/psd/psd_layer_section.cpp b/krita/plugins/formats/psd/psd_layer_section.cpp index 758e526a30d..5a8eea03fb6 100644 --- a/krita/plugins/formats/psd/psd_layer_section.cpp +++ b/krita/plugins/formats/psd/psd_layer_section.cpp @@ -1,543 +1,564 @@ /* * Copyright (c) 2009 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 "psd_layer_section.h" +#include + #include #include #include #include #include #include #include #include "kis_dom_utils.h" #include "psd_header.h" #include "psd_utils.h" #include "compression.h" #include #include #include #include PSDLayerMaskSection::PSDLayerMaskSection(const PSDHeader& header) : globalInfoSection(header), m_header(header) { hasTransparency = false; layerMaskBlockSize = 0; nLayers = 0; } PSDLayerMaskSection::~PSDLayerMaskSection() { qDeleteAll(layers); } bool PSDLayerMaskSection::read(QIODevice* io) { bool retval = true; // be optimistic! <:-) try { retval = readImpl(io); } catch (KisAslReaderUtils::ASLParseException &e) { qWarning() << "WARNING: PSD (emb. pattern):" << e.what(); retval = false; } return retval; } -bool PSDLayerMaskSection::readImpl(QIODevice* io) +bool PSDLayerMaskSection::readLayerInfoImpl(QIODevice* io) { - dbgFile << "reading layer section. Pos:" << io->pos() << "bytes left:" << io->bytesAvailable(); - - layerMaskBlockSize = 0; - if (m_header.version == 1) { - quint32 _layerMaskBlockSize = 0; - if (!psdread(io, &_layerMaskBlockSize) || _layerMaskBlockSize > (quint64)io->bytesAvailable()) { - error = QString("Could not read layer + mask block size. Got %1. Bytes left %2") - .arg(_layerMaskBlockSize).arg(io->bytesAvailable()); - return false; - } - layerMaskBlockSize = _layerMaskBlockSize; - } - else if (m_header.version == 2) { - if (!psdread(io, &layerMaskBlockSize) || layerMaskBlockSize > (quint64)io->bytesAvailable()) { - error = QString("Could not read layer + mask block size. Got %1. Bytes left %2") - .arg(layerMaskBlockSize).arg(io->bytesAvailable()); - return false; - } - } - - quint64 start = io->pos(); - - dbgFile << "layer + mask section size" << layerMaskBlockSize; - - if (layerMaskBlockSize == 0) { - dbgFile << "No layer + mask info, so no layers, only a background layer"; - return true; - } - - KIS_ASSERT_RECOVER(m_header.version == 1) { return false; } - quint32 layerInfoSectionSize = 0; SAFE_READ_EX(io, layerInfoSectionSize); if (layerInfoSectionSize & 0x1) { qWarning() << "WARNING: layerInfoSectionSize is NOT even! Fixing..."; layerInfoSectionSize++; } - { SETUP_OFFSET_VERIFIER(layerInfoSectionTag, io, layerInfoSectionSize, 0); dbgFile << "Layer info block size" << layerInfoSectionSize; if (layerInfoSectionSize > 0 ) { if (!psdread(io, &nLayers) || nLayers == 0) { error = QString("Could not read read number of layers or no layers in image. %1").arg(nLayers); return false; } hasTransparency = nLayers < 0; // first alpha channel is the alpha channel of the projection. nLayers = qAbs(nLayers); dbgFile << "Number of layers:" << nLayers; dbgFile << "Has separate projection transparency:" << hasTransparency; for (int i = 0; i < nLayers; ++i) { dbgFile << "Going to read layer" << i << "pos" << io->pos(); dbgFile << "== Enter PSDLayerRecord"; PSDLayerRecord *layerRecord = new PSDLayerRecord(m_header); if (!layerRecord->read(io)) { error = QString("Could not load layer %1: %2").arg(i).arg(layerRecord->error); return false; } dbgFile << "== Leave PSDLayerRecord"; dbgFile << "Finished reading layer" << i << layerRecord->layerName << "blending mode" << layerRecord->blendModeKey << io->pos() << "Number of channels:" << layerRecord->channelInfoRecords.size(); layers << layerRecord; } } // get the positions for the channels belonging to each layer for (int i = 0; i < nLayers; ++i) { dbgFile << "Going to seek channel positions for layer" << i << "pos" << io->pos(); if (i > layers.size()) { error = QString("Expected layer %1, but only have %2 layers").arg(i).arg(layers.size()); return false; } PSDLayerRecord *layerRecord = layers.at(i); for (int j = 0; j < layerRecord->nChannels; ++j) { // save the current location so we can jump beyond this block later on. quint64 channelStartPos = io->pos(); dbgFile << "\tReading channel image data for channel" << j << "from pos" << io->pos(); KIS_ASSERT_RECOVER(j < layerRecord->channelInfoRecords.size()) { return false; } ChannelInfo* channelInfo = layerRecord->channelInfoRecords.at(j); quint16 compressionType; if (!psdread(io, &compressionType)) { error = "Could not read compression type for channel"; return false; } channelInfo->compressionType = (Compression::CompressionType)compressionType; dbgFile << "\t\tChannel" << j << "has compression type" << compressionType; QRect channelRect = layerRecord->channelRect(channelInfo); // read the rle row lengths; if (channelInfo->compressionType == Compression::RLE) { for(qint64 row = 0; row < channelRect.height(); ++row) { //dbgFile << "Reading the RLE bytecount position of row" << row << "at pos" << io->pos(); quint32 byteCount; if (m_header.version == 1) { quint16 _byteCount; if (!psdread(io, &_byteCount)) { error = QString("Could not read byteCount for rle-encoded channel"); return 0; } byteCount = _byteCount; } else { if (!psdread(io, &byteCount)) { error = QString("Could not read byteCount for rle-encoded channel"); return 0; } } ////dbgFile << "rle byte count" << byteCount; channelInfo->rleRowLengths << byteCount; } } // we're beyond all the length bytes, rle bytes and whatever, this is the // location of the real pixel data channelInfo->channelDataStart = io->pos(); dbgFile << "\t\tstart" << channelStartPos << "data start" << channelInfo->channelDataStart << "data length" << channelInfo->channelDataLength << "pos" << io->pos(); // make sure we are at the start of the next channel data block io->seek(channelStartPos + channelInfo->channelDataLength); // this is the length of the actual channel data bytes channelInfo->channelDataLength = channelInfo->channelDataLength - (channelInfo->channelDataStart - channelStartPos); dbgFile << "\t\tchannel record" << j << "for layer" << i << "with id" << channelInfo->channelId << "starting postion" << channelInfo->channelDataStart << "with length" << channelInfo->channelDataLength << "and has compression type" << channelInfo->compressionType; } } } + return true; +} + +bool PSDLayerMaskSection::readImpl(QIODevice* io) +{ + dbgFile << "reading layer section. Pos:" << io->pos() << "bytes left:" << io->bytesAvailable(); + + layerMaskBlockSize = 0; + if (m_header.version == 1) { + quint32 _layerMaskBlockSize = 0; + if (!psdread(io, &_layerMaskBlockSize) || _layerMaskBlockSize > (quint64)io->bytesAvailable()) { + error = QString("Could not read layer + mask block size. Got %1. Bytes left %2") + .arg(_layerMaskBlockSize).arg(io->bytesAvailable()); + return false; + } + layerMaskBlockSize = _layerMaskBlockSize; + } + else if (m_header.version == 2) { + if (!psdread(io, &layerMaskBlockSize) || layerMaskBlockSize > (quint64)io->bytesAvailable()) { + error = QString("Could not read layer + mask block size. Got %1. Bytes left %2") + .arg(layerMaskBlockSize).arg(io->bytesAvailable()); + return false; + } + } + + quint64 start = io->pos(); + + dbgFile << "layer + mask section size" << layerMaskBlockSize; + + if (layerMaskBlockSize == 0) { + dbgFile << "No layer + mask info, so no layers, only a background layer"; + return true; + } + + KIS_ASSERT_RECOVER(m_header.version == 1) { return false; } + + if (!readLayerInfoImpl(io)) { + return false; + } + quint32 globalMaskBlockLength; if (!psdread(io, &globalMaskBlockLength)) { error = "Could not read global mask info block"; return false; } if (globalMaskBlockLength > 0) { if (!psdread(io, &globalLayerMaskInfo.overlayColorSpace)) { error = "Could not read global mask info overlay colorspace"; return false; } for (int i = 0; i < 4; ++i) { if (!psdread(io, &globalLayerMaskInfo.colorComponents[i])) { error = QString("Could not read mask info visualizaion color component %1").arg(i); return false; } } if (!psdread(io, &globalLayerMaskInfo.opacity)) { error = "Could not read global mask info visualization opacity"; return false; } if (!psdread(io, &globalLayerMaskInfo.kind)) { error = "Could not read global mask info visualization type"; return false; } } - // second try to read additional sections + // global additional sections + + /** + * Newer versions of PSD have layers info block wrapped into + * 'Lr16' or 'Lr32' additional section, while the main block is + * absent. + * + * Here we pass the callback which should be used when such + * additional section is recognized. + */ + globalInfoSection.setExtraLayerInfoBlockHandler(boost::bind(&PSDLayerMaskSection::readLayerInfoImpl, this, _1)); + globalInfoSection.read(io); /* put us after this section so reading the next section will work even if we mess up */ io->seek(start + layerMaskBlockSize); return true; } struct FlattenedNode { FlattenedNode() : type(RASTER_LAYER) {} KisNodeSP node; enum Type { RASTER_LAYER, FOLDER_OPEN, FOLDER_CLOSED, SECTION_DIVIDER }; Type type; }; void flattenNodes(KisNodeSP node, QList &nodes) { KisNodeSP child = node->firstChild(); while (child) { bool isGroupLayer = child->inherits("KisGroupLayer"); bool isRasterLayer = child->inherits("KisPaintLayer") || child->inherits("KisShapeLayer"); if (isGroupLayer) { { FlattenedNode item; item.node = child; item.type = FlattenedNode::SECTION_DIVIDER; nodes << item; } flattenNodes(child, nodes); { FlattenedNode item; item.node = child; item.type = FlattenedNode::FOLDER_OPEN; nodes << item; } } else if (isRasterLayer) { FlattenedNode item; item.node = child; item.type = FlattenedNode::RASTER_LAYER; nodes << item; } child = child->nextSibling(); } } KisNodeSP findOnlyTransparencyMask(KisNodeSP node, FlattenedNode::Type type) { if (type != FlattenedNode::FOLDER_OPEN && type != FlattenedNode::FOLDER_CLOSED && type != FlattenedNode::RASTER_LAYER) { return 0; } KisLayer *layer = dynamic_cast(node.data()); QList masks = layer->effectMasks(); if (masks.size() != 1) return 0; KisEffectMaskSP onlyMask = masks.first(); return onlyMask->inherits("KisTransparencyMask") ? onlyMask : 0; } QDomDocument fetchLayerStyleXmlData(KisNodeSP node) { const KisLayer *layer = qobject_cast(node.data()); KisPSDLayerStyleSP layerStyle = layer->layerStyle(); if (!layerStyle) return QDomDocument(); KisAslLayerStyleSerializer serializer; serializer.setStyles(QVector() << layerStyle); return serializer.formPsdXmlDocument(); } inline QDomNode findNodeByKey(const QString &key, QDomNode parent) { return KisDomUtils::findElementByAttibute(parent, "node", "key", key); } void mergePatternsXMLSection(const QDomDocument &src, QDomDocument &dst) { QDomNode srcPatternsNode = findNodeByKey("Patterns", src.documentElement()); QDomNode dstPatternsNode = findNodeByKey("Patterns", dst.documentElement()); if (srcPatternsNode.isNull()) return; if (dstPatternsNode.isNull()) { dst = src; return; } KIS_ASSERT_RECOVER_RETURN(!srcPatternsNode.isNull()); KIS_ASSERT_RECOVER_RETURN(!dstPatternsNode.isNull()); QDomNode node = srcPatternsNode.firstChild(); while(!node.isNull()) { QDomNode importedNode = dst.importNode(node, true); KIS_ASSERT_RECOVER_RETURN(!importedNode.isNull()); dstPatternsNode.appendChild(importedNode); node = node.nextSibling(); } } bool PSDLayerMaskSection::write(QIODevice* io, KisNodeSP rootLayer) { bool retval = true; try { writeImpl(io, rootLayer); } catch (KisAslWriterUtils::ASLWriteException &e) { error = PREPEND_METHOD(e.what()); retval = false; } return retval; } void PSDLayerMaskSection::writeImpl(QIODevice* io, KisNodeSP rootLayer) { dbgFile << "Writing layer layer section"; // Build the whole layer structure QList nodes; flattenNodes(rootLayer, nodes); if (nodes.isEmpty()) { throw KisAslWriterUtils::ASLWriteException("Could not find paint layers to save"); } { KisAslWriterUtils::OffsetStreamPusher layerAndMaskSectionSizeTag(io, 2); QDomDocument mergedPatternsXmlDoc; { KisAslWriterUtils::OffsetStreamPusher layerInfoSizeTag(io, 4); { // number of layers (negative, because krita always has alpha) const qint16 layersSize = -nodes.size(); SAFE_WRITE_EX(io, layersSize); dbgFile << "Number of layers" << layersSize << "at" << io->pos(); } // Layer records section foreach(const FlattenedNode &item, nodes) { KisNodeSP node = item.node; PSDLayerRecord *layerRecord = new PSDLayerRecord(m_header); layers.append(layerRecord); KisNodeSP onlyTransparencyMask = findOnlyTransparencyMask(node, item.type); const QRect maskRect = onlyTransparencyMask ? onlyTransparencyMask->paintDevice()->exactBounds() : QRect(); const bool nodeVisible = node->visible(); const KoColorSpace *colorSpace = node->colorSpace(); const quint8 nodeOpacity = node->opacity(); const quint8 nodeClipping = 0; const KisPaintLayer *paintLayer = qobject_cast(node.data()); const bool alphaLocked = (paintLayer && paintLayer->alphaLocked()); const QString nodeCompositeOp = node->compositeOpId(); const KisGroupLayer *groupLayer = qobject_cast(node.data()); const bool nodeIsPassThrough = groupLayer && groupLayer->passThroughMode(); QDomDocument stylesXmlDoc = fetchLayerStyleXmlData(node); if (mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) { mergedPatternsXmlDoc = stylesXmlDoc; } else if (!mergedPatternsXmlDoc.isNull() && !stylesXmlDoc.isNull()) { mergePatternsXMLSection(stylesXmlDoc, mergedPatternsXmlDoc); } bool nodeIrrelevant = false; QString nodeName; KisPaintDeviceSP layerContentDevice; psd_section_type sectionType; if (item.type == FlattenedNode::RASTER_LAYER) { nodeIrrelevant = false; nodeName = node->name(); layerContentDevice = onlyTransparencyMask ? node->original() : node->projection(); sectionType = psd_other; } else { nodeIrrelevant = true; nodeName = item.type == FlattenedNode::SECTION_DIVIDER ? QString("") : node->name(); layerContentDevice = 0; sectionType = item.type == FlattenedNode::SECTION_DIVIDER ? psd_bounding_divider : item.type == FlattenedNode::FOLDER_OPEN ? psd_open_folder : psd_closed_folder; } // === no access to node anymore QRect layerRect; if (layerContentDevice) { QRect rc = layerContentDevice->extent(); rc = rc.normalized(); // keep to the max of photoshop's capabilities if (rc.width() > 30000) rc.setWidth(30000); if (rc.height() > 30000) rc.setHeight(30000); layerRect = rc; } layerRecord->top = layerRect.y(); layerRecord->left = layerRect.x(); layerRecord->bottom = layerRect.y() + layerRect.height(); layerRecord->right = layerRect.x() + layerRect.width(); // colors + alpha channel // note: transparency mask not included layerRecord->nChannels = colorSpace->colorChannelCount() + 1; ChannelInfo *info = new ChannelInfo; info->channelId = -1; // For the alpha channel, which we always have in Krita, and should be saved first in layerRecord->channelInfoRecords << info; // the rest is in display order: rgb, cmyk, lab... for (int i = 0; i < (int)colorSpace->colorChannelCount(); ++i) { info = new ChannelInfo; info->channelId = i; // 0 for red, 1 = green, etc layerRecord->channelInfoRecords << info; } layerRecord->blendModeKey = composite_op_to_psd_blendmode(nodeCompositeOp); layerRecord->isPassThrough = nodeIsPassThrough; layerRecord->opacity = nodeOpacity; layerRecord->clipping = nodeClipping; layerRecord->transparencyProtected = alphaLocked; layerRecord->visible = nodeVisible; layerRecord->irrelevant = nodeIrrelevant; layerRecord->layerName = nodeName; layerRecord->write(io, layerContentDevice, onlyTransparencyMask, maskRect, sectionType, stylesXmlDoc); } dbgFile << "start writing layer pixel data" << io->pos(); // Now save the pixel data foreach(PSDLayerRecord *layerRecord, layers) { layerRecord->writePixelData(io); } } { // write the global layer mask info -- which is empty const quint32 globalMaskSize = 0; SAFE_WRITE_EX(io, globalMaskSize); } { PsdAdditionalLayerInfoBlock globalInfoSection(m_header); globalInfoSection.writePattBlockEx(io, mergedPatternsXmlDoc); } } } diff --git a/krita/plugins/formats/psd/psd_layer_section.h b/krita/plugins/formats/psd/psd_layer_section.h index f599f648f6e..55db74f209d 100644 --- a/krita/plugins/formats/psd/psd_layer_section.h +++ b/krita/plugins/formats/psd/psd_layer_section.h @@ -1,71 +1,72 @@ /* * Copyright (c) 2009 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 PSD_LAYER_SECTION_H #define PSD_LAYER_SECTION_H #include class QIODevice; #include #include "psd_header.h" #include "psd_layer_record.h" class PSDLayerMaskSection { public: PSDLayerMaskSection(const PSDHeader& header); ~PSDLayerMaskSection(); bool read(QIODevice* io); bool write(QIODevice* io, KisNodeSP rootLayer); QString error; // http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_21849 quint64 layerMaskBlockSize; // Length of the layer and mask information section // layer info: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_16000 bool hasTransparency; qint16 nLayers; // If layer count is a negative number, its absolute value is the number of layers and the first alpha channel contains the transparency data for the merged result. QVector layers; // mask info: http://www.adobe.com/devnet-apps/photoshop/fileformatashtml/#50577409_17115 struct GlobalLayerMaskInfo { quint16 overlayColorSpace; // Overlay color space (undocumented). quint16 colorComponents[4]; // 4 * 2 byte color components quint16 opacity; // Opacity. 0 = transparent, 100 = opaque. quint8 kind; // Kind. 0 = Color selected--i.e. inverted; 1 = Color protected;128 = use value stored per layer. This value is preferred. The others are for backward compatibility with beta versions. }; GlobalLayerMaskInfo globalLayerMaskInfo; PsdAdditionalLayerInfoBlock globalInfoSection; private: + bool readLayerInfoImpl(QIODevice* io); bool readImpl(QIODevice* io); void writeImpl(QIODevice* io, KisNodeSP rootLayer); private: const PSDHeader m_header; }; #endif // PSD_LAYER_SECTION_H diff --git a/krita/plugins/formats/psd/psd_pixel_utils.cpp b/krita/plugins/formats/psd/psd_pixel_utils.cpp new file mode 100644 index 00000000000..60784fed4f3 --- /dev/null +++ b/krita/plugins/formats/psd/psd_pixel_utils.cpp @@ -0,0 +1,665 @@ +/* + * Copyright (c) 2015 Dmitry Kazakov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "psd_pixel_utils.h" + +#include +#include +#include + + +#include +#include +#include +#include + +#include // htonl + +#include +#include + +#include "psd_layer_record.h" +#include +#include "kis_iterator_ng.h" + +#include "config_psd.h" +#ifdef HAVE_ZLIB +#include "zlib.h" +#endif + +namespace PsdPixelUtils { + +template +typename Traits::channels_type convertByteOrder(typename Traits::channels_type value); +// default implementation is undefined for every color space should be added manually + +template <> +inline quint8 convertByteOrder(quint8 value) { + return value; +} + +template <> +inline quint16 convertByteOrder(quint16 value) { + return ntohs(value); +} + +template <> +inline quint32 convertByteOrder(quint32 value) { + return ntohs(value); +} + +template <> +inline quint8 convertByteOrder(quint8 value) { + return value; +} + +template <> +inline quint16 convertByteOrder(quint16 value) { + return ntohs(value); +} + +template <> +inline quint32 convertByteOrder(quint32 value) { + return ntohs(value); +} + +template <> +inline quint8 convertByteOrder(quint8 value) { + return value; +} + +template <> +inline quint16 convertByteOrder(quint16 value) { + return ntohs(value); +} + +template <> +inline float convertByteOrder(float value) { + return ntohs(value); +} + +template <> +inline quint8 convertByteOrder(quint8 value) { + return value; +} + +template <> +inline quint16 convertByteOrder(quint16 value) { + return ntohs(value); +} + +template <> +inline float convertByteOrder(float value) { + return ntohs(value); +} + +template +void readGrayPixel(const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + typedef typename Traits::Pixel Pixel; + typedef typename Traits::channels_type channels_type; + + const channels_type unitValue = KoColorSpaceMathsTraits::unitValue; + channels_type opacity = unitValue; + if (channelBytes.contains(-1)) { + opacity = convertByteOrder(reinterpret_cast(channelBytes[-1].constData())[col]); + } + + Pixel *pixelPtr = reinterpret_cast(dstPtr); + + channels_type gray = convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); + + pixelPtr->gray = gray; + pixelPtr->alpha = opacity; +} + +template +void readRgbPixel(const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + typedef typename Traits::Pixel Pixel; + typedef typename Traits::channels_type channels_type; + + const channels_type unitValue = KoColorSpaceMathsTraits::unitValue; + channels_type opacity = unitValue; + if (channelBytes.contains(-1)) { + opacity = convertByteOrder(reinterpret_cast(channelBytes[-1].constData())[col]); + } + + Pixel *pixelPtr = reinterpret_cast(dstPtr); + + channels_type blue = convertByteOrder(reinterpret_cast(channelBytes[2].constData())[col]); + channels_type green = convertByteOrder(reinterpret_cast(channelBytes[1].constData())[col]); + channels_type red = convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); + + pixelPtr->blue = blue; + pixelPtr->green = green; + pixelPtr->red = red; + pixelPtr->alpha = opacity; +} + +template +void readCmykPixel(const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + typedef typename Traits::Pixel Pixel; + typedef typename Traits::channels_type channels_type; + + const channels_type unitValue = KoColorSpaceMathsTraits::unitValue; + channels_type opacity = unitValue; + if (channelBytes.contains(-1)) { + opacity = convertByteOrder(reinterpret_cast(channelBytes[-1].constData())[col]); + } + + Pixel *pixelPtr = reinterpret_cast(dstPtr); + + channels_type cyan = unitValue - convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); + channels_type magenta = unitValue - convertByteOrder(reinterpret_cast(channelBytes[1].constData())[col]); + channels_type yellow = unitValue - convertByteOrder(reinterpret_cast(channelBytes[2].constData())[col]); + channels_type black = unitValue - convertByteOrder(reinterpret_cast(channelBytes[3].constData())[col]); + + pixelPtr->cyan = cyan; + pixelPtr->magenta = magenta; + pixelPtr->yellow = yellow; + pixelPtr->black = black; + pixelPtr->alpha = opacity; +} + +template +void readLabPixel(const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + typedef typename Traits::Pixel Pixel; + typedef typename Traits::channels_type channels_type; + + const channels_type unitValue = KoColorSpaceMathsTraits::unitValue; + channels_type opacity = unitValue; + if (channelBytes.contains(-1)) { + opacity = convertByteOrder(reinterpret_cast(channelBytes[-1].constData())[col]); + } + + Pixel *pixelPtr = reinterpret_cast(dstPtr); + + channels_type L = convertByteOrder(reinterpret_cast(channelBytes[0].constData())[col]); + channels_type a = convertByteOrder(reinterpret_cast(channelBytes[1].constData())[col]); + channels_type b = convertByteOrder(reinterpret_cast(channelBytes[2].constData())[col]); + + pixelPtr->L = L; + pixelPtr->a = a; + pixelPtr->b = b; + pixelPtr->alpha = opacity; +} + +void readRgbPixelCommon(int channelSize, + const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + if (channelSize == 1) { + readRgbPixel(channelBytes, col, dstPtr); + } else if (channelSize == 2) { + readRgbPixel(channelBytes, col, dstPtr); + } else if (channelSize == 4) { + readRgbPixel(channelBytes, col, dstPtr); + } +} + +void readGrayPixelCommon(int channelSize, + const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + if (channelSize == 1) { + readGrayPixel(channelBytes, col, dstPtr); + } else if (channelSize == 2) { + readGrayPixel(channelBytes, col, dstPtr); + } else if (channelSize == 4) { + readGrayPixel(channelBytes, col, dstPtr); + } +} + +void readCmykPixelCommon(int channelSize, + const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + if (channelSize == 1) { + readCmykPixel(channelBytes, col, dstPtr); + } else if (channelSize == 2) { + readCmykPixel(channelBytes, col, dstPtr); + } else if (channelSize == 4) { + readCmykPixel(channelBytes, col, dstPtr); + } +} + +void readLabPixelCommon(int channelSize, + const QMap &channelBytes, + int col, quint8 *dstPtr) +{ + if (channelSize == 1) { + readLabPixel(channelBytes, col, dstPtr); + } else if (channelSize == 2) { + readLabPixel(channelBytes, col, dstPtr); + } else if (channelSize == 4) { + readLabPixel(channelBytes, col, dstPtr); + } +} + +/**********************************************************************/ +/* Two functions copied from the abandoned PSDParse library (GPL) */ +/* See: http://www.telegraphics.com.au/svn/psdparse/trunk/psd_zip.c */ +/* Created by Patrick in 2007.02.02, libpsd@graphest.com */ +/* Modifications by Toby Thain */ +/**********************************************************************/ + +typedef bool psd_status; +typedef quint8 psd_uchar; +typedef int psd_int; +typedef quint8 Bytef; + +psd_status psd_unzip_without_prediction(psd_uchar *src_buf, psd_int src_len, + psd_uchar *dst_buf, psd_int dst_len) +{ +#ifdef HAVE_ZLIB + z_stream stream; + psd_int state; + + memset(&stream, 0, sizeof(z_stream)); + stream.data_type = Z_BINARY; + + stream.next_in = (Bytef *)src_buf; + stream.avail_in = src_len; + stream.next_out = (Bytef *)dst_buf; + stream.avail_out = dst_len; + + if(inflateInit(&stream) != Z_OK) + return 0; + + do { + state = inflate(&stream, Z_PARTIAL_FLUSH); + if(state == Z_STREAM_END) + break; + if(state == Z_DATA_ERROR || state != Z_OK) + break; + } while (stream.avail_out > 0); + + if (state != Z_STREAM_END && state != Z_OK) + return 0; + + return 1; + +#endif /* HAVE_ZLIB */ + + return 0; +} + +psd_status psd_unzip_with_prediction(psd_uchar *src_buf, psd_int src_len, + psd_uchar *dst_buf, psd_int dst_len, + psd_int row_size, psd_int color_depth) +{ + psd_status status; + int len; + psd_uchar * buf; + + status = psd_unzip_without_prediction(src_buf, src_len, dst_buf, dst_len); + if(!status) + return status; + + buf = dst_buf; + do { + len = row_size; + if (color_depth == 16) + { + while(--len) + { + buf[2] += buf[0] + ((buf[1] + buf[3]) >> 8); + buf[3] += buf[1]; + buf += 2; + } + buf += 2; + dst_len -= row_size * 2; + } + else + { + while(--len) + { + *(buf + 1) += *buf; + buf ++; + } + buf ++; + dst_len -= row_size; + } + } while(dst_len > 0); + + return 1; +} + +/**********************************************************************/ +/* End of third party block */ +/**********************************************************************/ + +QMap fetchChannelsBytes(QIODevice *io, QVector channelInfoRecords, + int row, int width, int channelSize) +{ + const int uncompressedLength = width * channelSize; + + QMap channelBytes; + + foreach(ChannelInfo *channelInfo, channelInfoRecords) { + // user supplied masks are ignored here + if (channelInfo->channelId < -1) continue; + + io->seek(channelInfo->channelDataStart + channelInfo->channelOffset); + + if (channelInfo->compressionType == Compression::Uncompressed) { + channelBytes[channelInfo->channelId] = io->read(uncompressedLength); + channelInfo->channelOffset += uncompressedLength; + } + else if (channelInfo->compressionType == Compression::RLE) { + int rleLength = channelInfo->rleRowLengths[row]; + QByteArray compressedBytes = io->read(rleLength); + QByteArray uncompressedBytes = Compression::uncompress(uncompressedLength, compressedBytes, channelInfo->compressionType); + channelBytes.insert(channelInfo->channelId, uncompressedBytes); + channelInfo->channelOffset += rleLength; + } + else { + QString error = QString("Unsupported Compression mode: %1").arg(channelInfo->compressionType); + dbgFile << "ERROR: fetchChannelsBytes:" << error; + throw KisAslReaderUtils::ASLParseException(error); + } + } + + return channelBytes; +} + +typedef boost::function&, int, quint8*)> PixelFunc; + +void readCommon(KisPaintDeviceSP dev, + QIODevice *io, + const QRect &layerRect, + QVector infoRecords, + int channelSize, + PixelFunc pixelFunc) +{ + KisOffsetKeeper keeper(io); + + if (layerRect.isEmpty()) { + dbgFile << "Empty layer!"; + return; + } + + if (infoRecords.first()->compressionType == Compression::ZIP || + infoRecords.first()->compressionType == Compression::ZIPWithPrediction) { + + const int numPixels = channelSize * layerRect.width() * layerRect.height(); + + QMap channelBytes; + + foreach (ChannelInfo *info, infoRecords) { + io->seek(info->channelDataStart); + QByteArray compressedBytes = io->read(info->channelDataLength); + QByteArray uncompressedBytes(numPixels, 0); + + bool status = false; + if (infoRecords.first()->compressionType == Compression::ZIP) { + status = psd_unzip_without_prediction((quint8*)compressedBytes.data(), compressedBytes.size(), + (quint8*)uncompressedBytes.data(), uncompressedBytes.size()); + } else { + status = psd_unzip_with_prediction((quint8*)compressedBytes.data(), compressedBytes.size(), + (quint8*)uncompressedBytes.data(), uncompressedBytes.size(), + layerRect.width(), channelSize * 8); + } + + if (!status) { + QString error = QString("Failed to unzip channel data: id = %1, compression = %2").arg(info->channelId).arg(info->compressionType); + dbgFile << "ERROR:" << error; + dbgFile << " " << ppVar(info->channelId); + dbgFile << " " << ppVar(info->channelDataStart); + dbgFile << " " << ppVar(info->channelDataLength); + dbgFile << " " << ppVar(info->compressionType); + throw KisAslReaderUtils::ASLParseException(error); + } + + channelBytes.insert(info->channelId, uncompressedBytes); + } + + KisSequentialIterator it(dev, layerRect); + int col = 0; + do { + pixelFunc(channelSize, channelBytes, col, it.rawData()); + col++; + } while(it.nextPixel()); + + } else { + KisHLineIteratorSP it = dev->createHLineIteratorNG(layerRect.left(), layerRect.top(), layerRect.width()); + for (int i = 0 ; i < layerRect.height(); i++) { + QMap channelBytes; + + channelBytes = fetchChannelsBytes(io, infoRecords, + i, layerRect.width(), channelSize); + + for (qint64 col = 0; col < layerRect.width(); col++){ + pixelFunc(channelSize, channelBytes, col, it->rawData()); + it->nextPixel(); + } + it->nextRow(); + } + } +} + +void readChannels(QIODevice *io, + KisPaintDeviceSP device, + psd_color_mode colorMode, + int channelSize, + const QRect &layerRect, + QVector infoRecords) +{ + switch (colorMode) { + case Grayscale: + readCommon(device, io, layerRect, infoRecords, channelSize, &readGrayPixelCommon); + break; + case RGB: + readCommon(device, io, layerRect, infoRecords, channelSize, &readRgbPixelCommon); + break; + case CMYK: + readCommon(device, io, layerRect, infoRecords, channelSize, &readCmykPixelCommon); + break; + case Lab: + readCommon(device, io, layerRect, infoRecords, channelSize, &readLabPixelCommon); + break; + case Bitmap: + case Indexed: + case MultiChannel: + case DuoTone: + case UNKNOWN: + default: + QString error = QString("Unsupported color mode: %1").arg(colorMode); + throw KisAslReaderUtils::ASLParseException(error); + } +} + +void writeChannelDataRLE(QIODevice *io, const quint8 *plane, const int channelSize, const QRect &rc, const qint64 sizeFieldOffset, const qint64 rleBlockOffset, const bool writeCompressionType) +{ + typedef KisAslWriterUtils::OffsetStreamPusher Pusher; + QScopedPointer channelBlockSizeExternalTag; + if (sizeFieldOffset >= 0) { + channelBlockSizeExternalTag.reset(new Pusher(io, 0, sizeFieldOffset)); + } + + if (writeCompressionType) { + SAFE_WRITE_EX(io, (quint16)Compression::RLE); + } + + const bool externalRleBlock = rleBlockOffset >= 0; + + // the start of RLE sizes block + const qint64 channelRLESizePos = externalRleBlock ? rleBlockOffset : io->pos(); + + { + QScopedPointer rleOffsetKeeper; + + if (externalRleBlock) { + rleOffsetKeeper.reset(new KisOffsetKeeper(io)); + io->seek(rleBlockOffset); + } + + // write zero's for the channel lengths block + for(int i = 0; i < rc.height(); ++i) { + // XXX: choose size for PSB! + const quint16 fakeRLEBLockSize = 0; + SAFE_WRITE_EX(io, fakeRLEBLockSize); + } + } + + quint32 stride = channelSize * rc.width(); + for (qint32 row = 0; row < rc.height(); ++row) { + + QByteArray uncompressed = QByteArray::fromRawData((const char*)plane + row * stride, stride); + QByteArray compressed = Compression::compress(uncompressed, Compression::RLE); + + KisAslWriterUtils::OffsetStreamPusher rleExternalTag(io, 0, channelRLESizePos + row * sizeof(quint16)); + + if (io->write(compressed) != compressed.size()) { + throw KisAslWriterUtils::ASLWriteException("Failed to write image data"); + } + } +} + +inline void preparePixelForWrite(quint8 *dataPlane, + int numPixels, + int channelSize, + int channelId, + psd_color_mode colorMode) +{ + // if the bitdepth > 8, place the bytes in the right order + // if cmyk, invert the pixel value + if (channelSize == 1) { + if (channelId >= 0 && (colorMode == CMYK || colorMode == CMYK64)) { + for (int i = 0; i < numPixels; ++i) { + dataPlane[i] = 255 - dataPlane[i]; + } + } + } + else if (channelSize == 2) { + quint16 val; + for (int i = 0; i < numPixels; ++i) { + quint16 *pixelPtr = reinterpret_cast(dataPlane) + i; + + val = *pixelPtr; + val = ntohs(val); + if (channelId >= 0 && (colorMode == CMYK || colorMode == CMYK64)) { + val = quint16_MAX - val; + } + *pixelPtr = val; + } + } + else if (channelSize == 4) { + quint32 val; + for (int i = 0; i < numPixels; ++i) { + quint32 *pixelPtr = reinterpret_cast(dataPlane) + i; + + val = *pixelPtr; + val = ntohl(val); + if (channelId >= 0 && (colorMode == CMYK || colorMode == CMYK64)) { + val = quint16_MAX - val; + } + *pixelPtr = val; + } + } +} + +void writePixelDataCommon(QIODevice *io, + KisPaintDeviceSP dev, + const QRect &rc, + psd_color_mode colorMode, + int channelSize, + bool alphaFirst, + const bool writeCompressionType, + QVector &writingInfoList) +{ + // Empty rects must be processed separately on a higher level! + KIS_ASSERT_RECOVER_RETURN(!rc.isEmpty()); + + QVector tmp = dev->readPlanarBytes(rc.x() - dev->x(), rc.y() - dev->y(), rc.width(), rc.height()); + const KoColorSpace *colorSpace = dev->colorSpace(); + + QVector planes; + + { // prepare 'planes' array + + quint8 *alphaPlanePtr = 0; + + QList origChannels = colorSpace->channels(); + foreach(KoChannelInfo *ch, KoChannelInfo::displayOrderSorted(origChannels)) { + int channelIndex = KoChannelInfo::displayPositionToChannelIndex(ch->displayPosition(), origChannels); + + quint8 *holder = 0; + qSwap(holder, tmp[channelIndex]); + + if (ch->channelType() == KoChannelInfo::ALPHA) { + qSwap(holder, alphaPlanePtr); + } else { + planes.append(holder); + } + } + + if (alphaPlanePtr) { + if (alphaFirst) { + planes.insert(0, alphaPlanePtr); + KIS_ASSERT_RECOVER_NOOP(writingInfoList.first().channelId == -1); + } else { + planes.append(alphaPlanePtr); + KIS_ASSERT_RECOVER_NOOP( + (writingInfoList.size() == planes.size() - 1) || + (writingInfoList.last().channelId == -1)); + } + } + + // now planes are holding pointers to quint8 arrays + tmp.clear(); + } + + KIS_ASSERT_RECOVER_RETURN(planes.size() >= writingInfoList.size()); + + const int numPixels = rc.width() * rc.height(); + + // write down the planes + + try { + for (int i = 0; i < writingInfoList.size(); i++) { + const ChannelWritingInfo &info = writingInfoList[i]; + + dbgFile << "\tWriting channel" << i << "psd channel id" << info.channelId; + + preparePixelForWrite(planes[i], numPixels, channelSize, info.channelId, colorMode); + + dbgFile << "\t\tchannel start" << ppVar(io->pos()); + + writeChannelDataRLE(io, planes[i], channelSize, rc, info.sizeFieldOffset, info.rleBlockOffset, writeCompressionType); + } + + } catch (KisAslWriterUtils::ASLWriteException &e) { + qDeleteAll(planes); + planes.clear(); + + throw KisAslWriterUtils::ASLWriteException(PREPEND_METHOD(e.what())); + } + + qDeleteAll(planes); + planes.clear(); +} + +} diff --git a/krita/plugins/formats/psd/psd_pixel_utils.h b/krita/plugins/formats/psd/psd_pixel_utils.h new file mode 100644 index 00000000000..a1c93b69bb6 --- /dev/null +++ b/krita/plugins/formats/psd/psd_pixel_utils.h @@ -0,0 +1,71 @@ +/* + * Copyright (c) 2015 Dmitry Kazakov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __PSD_PIXEL_UTILS_H +#define __PSD_PIXEL_UTILS_H + +#include +#include + +#include "psd.h" +#include "kis_types.h" + +class QIODevice; +struct ChannelInfo; +struct ChannelWritingInfo; + +namespace PsdPixelUtils +{ + + struct ChannelWritingInfo { + ChannelWritingInfo() : channelId(0), sizeFieldOffset(-1), rleBlockOffset(-1) {} + ChannelWritingInfo(qint16 _channelId, int _sizeFieldOffset) : channelId(_channelId), sizeFieldOffset(_sizeFieldOffset), rleBlockOffset(-1) {} + ChannelWritingInfo(qint16 _channelId, int _sizeFieldOffset, int _rleBlockOffset) : channelId(_channelId), sizeFieldOffset(_sizeFieldOffset), rleBlockOffset(_rleBlockOffset) {} + + qint16 channelId; + int sizeFieldOffset; + int rleBlockOffset; + }; + + void readChannels(QIODevice *io, + KisPaintDeviceSP device, + psd_color_mode colorMode, + int channelSize, + const QRect &layerRect, + QVector infoRecords); + + void writeChannelDataRLE(QIODevice *io, + const quint8 *plane, + const int channelSize, + const QRect &rc, + const qint64 sizeFieldOffset, + const qint64 rleBlockOffset, + const bool writeCompressionType); + + void writePixelDataCommon(QIODevice *io, + KisPaintDeviceSP dev, + const QRect &rc, + psd_color_mode colorMode, + int channelSize, + bool alphaFirst, + const bool writeCompressionType, + QVector &writingInfoList); + +} + +#endif /* __PSD_PIXEL_UTILS_H */ diff --git a/krita/plugins/formats/psd/psd_saver.cpp b/krita/plugins/formats/psd/psd_saver.cpp index 4c42c62b206..f9b44c091a6 100644 --- a/krita/plugins/formats/psd/psd_saver.cpp +++ b/krita/plugins/formats/psd/psd_saver.cpp @@ -1,253 +1,285 @@ /* * Copyright (c) 2009 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 "psd_saver.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "psd.h" #include "psd_header.h" #include "psd_colormode_block.h" #include "psd_utils.h" #include "psd_resource_section.h" #include "psd_layer_section.h" #include "psd_resource_block.h" #include "psd_image_data.h" QPair colormodelid_to_psd_colormode(const QString &colorSpaceId, const QString &colorDepthId) { psd_color_mode colorMode = UNKNOWN; if (colorSpaceId == RGBAColorModelID.id()) { colorMode = RGB; } else if (colorSpaceId == CMYKAColorModelID.id()) { colorMode = CMYK; } else if (colorSpaceId == GrayAColorModelID.id()) { colorMode = Grayscale; } else if (colorSpaceId == LABAColorModelID.id()) { colorMode = Lab; } quint16 depth = 0; if (colorDepthId == Integer8BitsColorDepthID.id()) { depth = 8; } else if (colorDepthId == Integer16BitsColorDepthID.id()) { depth = 16; } else if (colorDepthId == Float16BitsColorDepthID.id()) { depth = 32; } else if (colorDepthId == Float32BitsColorDepthID.id()) { depth = 32; } return QPair(colorMode, depth); } PSDSaver::PSDSaver(KisDocument *doc) { m_doc = doc; m_image = doc->image(); m_job = 0; m_stop = false; } PSDSaver::~PSDSaver() { } KisImageWSP PSDSaver::image() { return m_image; } +#include "kis_sequential_iterator.h" + + +bool checkIfHasTransparency(KisPaintDeviceSP dev) +{ + const QRect deviceBounds = dev->exactBounds(); + const QRect imageBounds = dev->defaultBounds()->bounds(); + + if (deviceBounds.isEmpty() || + (deviceBounds & imageBounds) != imageBounds) { + + return true; + } + + const KoColorSpace *cs = dev->colorSpace(); + KisSequentialConstIterator it(dev, deviceBounds); + + do { + if (cs->opacityU8(it.rawDataConst()) != OPACITY_OPAQUE_U8) { + return true; + } + } while(it.nextPixel()); + + return false; +} KisImageBuilder_Result PSDSaver::buildFile(const KUrl& uri) { if (!m_image) return KisImageBuilder_RESULT_EMPTY; if (uri.isEmpty()) return KisImageBuilder_RESULT_NO_URI; if (!uri.isLocalFile()) return KisImageBuilder_RESULT_NOT_LOCAL; // Open file for writing QFile f(uri.toLocalFile()); if (!f.open(QIODevice::WriteOnly)) { return KisImageBuilder_RESULT_NOT_LOCAL; } + const bool haveLayers = m_image->rootLayer()->childCount() > 1 || + checkIfHasTransparency(m_image->rootLayer()->firstChild()->projection()); + // HEADER PSDHeader header; header.signature = "8BPS"; header.version = 1; - header.nChannels = m_image->colorSpace()->channelCount(); + header.nChannels = haveLayers ? + m_image->colorSpace()->channelCount() : + m_image->colorSpace()->colorChannelCount(); + header.width = m_image->width(); header.height = m_image->height(); QPair colordef = colormodelid_to_psd_colormode(m_image->colorSpace()->colorModelId().id(), m_image->colorSpace()->colorDepthId().id()); if (colordef.first == UNKNOWN || colordef.second == 0 || colordef.second == 32) { return KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE; } header.colormode = colordef.first; header.channelDepth = colordef.second; dbgFile << "header" << header << f.pos(); if (!header.write(&f)) { dbgFile << "Failed to write header. Error:" << header.error << f.pos(); return KisImageBuilder_RESULT_FAILURE; } // COLORMODE BlOCK PSDColorModeBlock colorModeBlock(header.colormode); // XXX: check for annotations that contain the duotone spec KisAnnotationSP annotation = m_image->annotation("DuotoneColormodeBlock"); if (annotation) { colorModeBlock.duotoneSpecification = annotation->annotation(); } dbgFile << "colormode block" << f.pos(); if (!colorModeBlock.write(&f)) { dbgFile << "Failed to write colormode block. Error:" << colorModeBlock.error << f.pos(); return KisImageBuilder_RESULT_FAILURE; } // IMAGE RESOURCES SECTION PSDImageResourceSection resourceSection; vKisAnnotationSP_it it = m_image->beginAnnotations(); vKisAnnotationSP_it endIt = m_image->endAnnotations(); while (it != endIt) { KisAnnotationSP annotation = (*it); if (!annotation || annotation->type().isEmpty()) { dbgFile << "Warning: empty annotation"; it++; continue; } dbgFile << "Annotation:" << annotation->type() << annotation->description(); if (annotation->type().startsWith(QString("PSD Resource Block:"))) { // PSDResourceBlock *resourceBlock = dynamic_cast(annotation.data()); if (resourceBlock) { dbgFile << "Adding PSD Resource Block" << resourceBlock->identifier; resourceSection.resources[(PSDImageResourceSection::PSDResourceID)resourceBlock->identifier] = resourceBlock; } } it++; } // Add resolution block { RESN_INFO_1005 *resInfo = new RESN_INFO_1005; resInfo->hRes = INCH_TO_POINT(m_image->xRes()); resInfo->vRes = INCH_TO_POINT(m_image->yRes()); PSDResourceBlock *block = new PSDResourceBlock; block->identifier = PSDImageResourceSection::RESN_INFO; block->resource = resInfo; resourceSection.resources[PSDImageResourceSection::RESN_INFO] = block; } // Add icc block { ICC_PROFILE_1039 *profileInfo = new ICC_PROFILE_1039; profileInfo->icc = m_image->profile()->rawData(); PSDResourceBlock *block = new PSDResourceBlock; block->identifier = PSDImageResourceSection::ICC_PROFILE; block->resource = profileInfo; resourceSection.resources[PSDImageResourceSection::ICC_PROFILE] = block; } dbgFile << "resource section" << f.pos(); if (!resourceSection.write(&f)) { dbgFile << "Failed to write resource section. Error:" << resourceSection.error << f.pos(); return KisImageBuilder_RESULT_FAILURE; } // LAYER AND MASK DATA // Only save layers and masks if there is more than one layer dbgFile << "m_image->rootLayer->childCount" << m_image->rootLayer()->childCount() << f.pos(); - if (m_image->rootLayer()->childCount() > 1) { + + if (haveLayers) { PSDLayerMaskSection layerSection(header); layerSection.hasTransparency = true; if (!layerSection.write(&f, m_image->rootLayer())) { dbgFile << "failed to write layer section. Error:" << layerSection.error << f.pos(); return KisImageBuilder_RESULT_FAILURE; } } else { // else write a zero length block dbgFile << "No layers, saving empty layers/mask block" << f.pos(); psdwrite(&f, (quint32)0); } // IMAGE DATA dbgFile << "Saving composited image" << f.pos(); PSDImageData imagedata(&header); - if (!imagedata.write(&f, m_image->projection())) { + if (!imagedata.write(&f, m_image->projection(), haveLayers)) { dbgFile << "Failed to write image data. Error:" << imagedata.error; return KisImageBuilder_RESULT_FAILURE; } f.close(); return KisImageBuilder_RESULT_OK; } void PSDSaver::cancel() { m_stop = true; } #include "psd_saver.moc" diff --git a/krita/plugins/formats/psd/tests/kis_psd_test.cpp b/krita/plugins/formats/psd/tests/kis_psd_test.cpp index d22cf85ee1b..b0914eed229 100644 --- a/krita/plugins/formats/psd/tests/kis_psd_test.cpp +++ b/krita/plugins/formats/psd/tests/kis_psd_test.cpp @@ -1,253 +1,341 @@ /* * Copyright (C) 2009 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_psd_test.h" #include #include #include #include "filestest.h" #ifndef FILES_DATA_DIR #error "FILES_DATA_DIR not set. A directory with the data used for testing the importing of files in krita" #endif #include #include "kis_group_layer.h" #include "kis_psd_layer_style.h" void KisPSDTest::testFiles() { TestUtil::testFiles(QString(FILES_DATA_DIR) + "/sources", QStringList()); } void KisPSDTest::testOpening() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "testing_psd_ls.psd"); QScopedPointer doc(qobject_cast(KisPart::instance()->createDocument())); KisImportExportManager manager(doc.data()); manager.setBatchMode(true); KisImportExportFilter::ConversionStatus status; QString s = manager.importDocument(sourceFileInfo.absoluteFilePath(), QString(), status); qDebug() << s; Q_ASSERT(doc->image()); } QSharedPointer openPsdDocument(const QFileInfo &fileInfo) { QSharedPointer doc(qobject_cast(KisPart::instance()->createDocument())); KisImportExportManager manager(doc.data()); manager.setBatchMode(true); KisImportExportFilter::ConversionStatus status; QString s = manager.importDocument(fileInfo.absoluteFilePath(), QString(), status); return doc; } void KisPSDTest::testTransparencyMask() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "sources/masks.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); QImage result = doc->image()->projection()->convertToQImage(0, doc->image()->bounds()); QVERIFY(TestUtil::checkQImageExternal(result, "psd_test", "transparency_masks", "kiki_single")); doc->setBackupFile(false); doc->setOutputMimeType("image/vnd.adobe.photoshop"); QFileInfo dstFileInfo(QDir::currentPath() + QDir::separator() + "test_tmask.psd"); bool retval = doc->saveAs(KUrl(dstFileInfo.absoluteFilePath())); QVERIFY(retval); { QSharedPointer doc = openPsdDocument(dstFileInfo); QVERIFY(doc->image()); QImage result = doc->image()->projection()->convertToQImage(0, doc->image()->bounds()); QVERIFY(TestUtil::checkQImageExternal(result, "psd_test", "transparency_masks", "kiki_single")); QVERIFY(doc->image()->root()->lastChild()); QVERIFY(doc->image()->root()->lastChild()->firstChild()); QVERIFY(doc->image()->root()->lastChild()->firstChild()->inherits("KisTransparencyMask")); } } void KisPSDTest::testOpenGrayscaleMultilayered() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "sources/gray.psd"); //QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "sources/100x100gray8.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); } void KisPSDTest::testOpenGroupLayers() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "group_layers.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); KisNodeSP node = TestUtil::findNode(doc->image()->root(), "Group 1 PT"); KisGroupLayer *group = dynamic_cast(node.data()); QVERIFY(group); QVERIFY(group->passThroughMode()); } void KisPSDTest::testOpenLayerStyles() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "testing_psd_ls.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); KisLayerSP layer = dynamic_cast(doc->image()->root()->lastChild().data()); QVERIFY(layer->layerStyle()); QVERIFY(layer->layerStyle()->dropShadow()); QVERIFY(layer->layerStyle()->dropShadow()->effectEnabled()); } void KisPSDTest::testOpenLayerStylesWithPattern() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "test_ls_pattern.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); KisLayerSP layer = dynamic_cast(doc->image()->root()->lastChild().data()); QVERIFY(layer->layerStyle()); QVERIFY(layer->layerStyle()->patternOverlay()); QVERIFY(layer->layerStyle()->patternOverlay()->effectEnabled()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()->valid()); } void KisPSDTest::testOpenLayerStylesWithPatternMulti() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "test_ls_pattern_multi.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); KisLayerSP layer = dynamic_cast(doc->image()->root()->lastChild().data()); QVERIFY(layer->layerStyle()); QVERIFY(layer->layerStyle()->patternOverlay()); QVERIFY(layer->layerStyle()->patternOverlay()->effectEnabled()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()->valid()); QVERIFY(layer->layerStyle()->stroke()); QVERIFY(layer->layerStyle()->stroke()->effectEnabled()); QVERIFY(layer->layerStyle()->stroke()->pattern()); QVERIFY(layer->layerStyle()->stroke()->pattern()->valid()); } void KisPSDTest::testSaveLayerStylesWithPatternMulti() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "test_ls_pattern_multi.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); KisLayerSP layer = dynamic_cast(doc->image()->root()->lastChild().data()); QVERIFY(layer->layerStyle()); QVERIFY(layer->layerStyle()->patternOverlay()); QVERIFY(layer->layerStyle()->patternOverlay()->effectEnabled()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()->valid()); QVERIFY(layer->layerStyle()->stroke()); QVERIFY(layer->layerStyle()->stroke()->effectEnabled()); QVERIFY(layer->layerStyle()->stroke()->pattern()); QVERIFY(layer->layerStyle()->stroke()->pattern()->valid()); doc->setBackupFile(false); doc->setOutputMimeType("image/vnd.adobe.photoshop"); QFileInfo dstFileInfo(QDir::currentPath() + QDir::separator() + "test_save_styles.psd"); bool retval = doc->saveAs(KUrl(dstFileInfo.absoluteFilePath())); QVERIFY(retval); { QSharedPointer doc = openPsdDocument(dstFileInfo); QVERIFY(doc->image()); QImage result = doc->image()->projection()->convertToQImage(0, doc->image()->bounds()); //QVERIFY(TestUtil::checkQImageExternal(result, "psd_test", "transparency_masks", "kiki_single")); KisLayerSP layer = dynamic_cast(doc->image()->root()->lastChild().data()); QVERIFY(layer->layerStyle()); QVERIFY(layer->layerStyle()->patternOverlay()); QVERIFY(layer->layerStyle()->patternOverlay()->effectEnabled()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()); QVERIFY(layer->layerStyle()->patternOverlay()->pattern()->valid()); QVERIFY(layer->layerStyle()->stroke()); QVERIFY(layer->layerStyle()->stroke()->effectEnabled()); QVERIFY(layer->layerStyle()->stroke()->pattern()); QVERIFY(layer->layerStyle()->stroke()->pattern()->valid()); } } void KisPSDTest::testOpeningFromOpenCanvas() { QFileInfo sourceFileInfo(QString(FILES_DATA_DIR) + QDir::separator() + "test_krita_psd_from_opencanvas.psd"); Q_ASSERT(sourceFileInfo.exists()); QSharedPointer doc = openPsdDocument(sourceFileInfo); QVERIFY(doc->image()); QVERIFY(doc->image()->root()->firstChild()); } +void KisPSDTest::testOpeningAllFormats() +{ + QString path = TestUtil::fetchExternalDataFileName("psd_format_test_files"); + QDir dirSources(path); + + foreach(QFileInfo sourceFileInfo, dirSources.entryInfoList()) { + Q_ASSERT(sourceFileInfo.exists()); + + if (sourceFileInfo.isHidden() || sourceFileInfo.isDir()) { + continue; + } + + if (sourceFileInfo.fileName() != "ml_cmyk_16b.psd") { + //continue; + } + + //qDebug() << "Opening" << ppVar(sourceFileInfo.fileName()); + + QSharedPointer doc = openPsdDocument(sourceFileInfo); + + if (!doc->image()) { + qCritical() << "FAILED to open" << sourceFileInfo.fileName(); + continue; + } + + // just check visually if the file loads fine + KIS_DUMP_DEVICE_2(doc->image()->projection(), QRect(0,0,100,100), sourceFileInfo.fileName(), "dd"); + } +} + +void KisPSDTest::testSavingAllFormats() +{ + QString path = TestUtil::fetchExternalDataFileName("psd_format_test_files"); + QDir dirSources(path); + + foreach(QFileInfo sourceFileInfo, dirSources.entryInfoList()) { + Q_ASSERT(sourceFileInfo.exists()); + + if (sourceFileInfo.isHidden() || sourceFileInfo.isDir()) { + continue; + } + + if (sourceFileInfo.fileName() != "sl_rgb_8b.psd") { + //continue; + } + + qDebug() << "Opening" << ppVar(sourceFileInfo.fileName()); + + QSharedPointer doc = openPsdDocument(sourceFileInfo); + + if (!doc->image()) { + qCritical() << "FAILED to open" << sourceFileInfo.fileName(); + continue; + } + + QString baseName = sourceFileInfo.fileName(); + + QString originalName = QString("%1_0orig").arg(baseName); + QString resultName = QString("%1_1result").arg(baseName); + QString tempPsdName = QString("%1_3interm.psd").arg(baseName); + + QImage refImage = doc->image()->projection()->convertToQImage(0, QRect(0,0,100,100)); + + // uncomment to do a visual check + // KIS_DUMP_DEVICE_2(doc->image()->projection(), QRect(0,0,100,100), originalName, "dd"); + + doc->setBackupFile(false); + doc->setOutputMimeType("image/vnd.adobe.photoshop"); + QFileInfo dstFileInfo(QDir::currentPath() + QDir::separator() + tempPsdName); + + qDebug() << "Saving" << ppVar(dstFileInfo.fileName()); + + bool retval = doc->saveAs(KUrl(dstFileInfo.absoluteFilePath())); + QVERIFY(retval); + + { + QSharedPointer doc = openPsdDocument(dstFileInfo); + QVERIFY(doc->image()); + + // uncomment to do a visual check + //KIS_DUMP_DEVICE_2(doc->image()->projection(), QRect(0,0,100,100), resultName, "dd"); + + QImage resultImage = doc->image()->projection()->convertToQImage(0, QRect(0,0,100,100)); + QCOMPARE(resultImage, refImage); + } + } +} + QTEST_KDEMAIN(KisPSDTest, GUI) #include "kis_psd_test.moc" diff --git a/krita/plugins/formats/psd/tests/kis_psd_test.h b/krita/plugins/formats/psd/tests/kis_psd_test.h index 9f010c9439e..c29d7bd957e 100644 --- a/krita/plugins/formats/psd/tests/kis_psd_test.h +++ b/krita/plugins/formats/psd/tests/kis_psd_test.h @@ -1,43 +1,45 @@ /* * Copyright (C) 2009 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_PSD_TEST_H_ #define _KIS_PSD_TEST_H_ #include class KisPSDTest : public QObject { Q_OBJECT private Q_SLOTS: void testFiles(); void testOpening(); void testTransparencyMask(); void testOpenGrayscaleMultilayered(); void testOpenGroupLayers(); void testOpenLayerStyles(); void testOpenLayerStylesWithPattern(); void testOpenLayerStylesWithPatternMulti(); void testSaveLayerStylesWithPatternMulti(); void testOpeningFromOpenCanvas(); + void testOpeningAllFormats(); + void testSavingAllFormats(); }; #endif diff --git a/krita/plugins/formats/xcf/3rdparty/xcftools/config.h b/krita/plugins/formats/xcf/3rdparty/xcftools/config.h index 5dbf2db0fea..f5438656214 100644 --- a/krita/plugins/formats/xcf/3rdparty/xcftools/config.h +++ b/krita/plugins/formats/xcf/3rdparty/xcftools/config.h @@ -1,9 +1,13 @@ #define HAVE_NETINET_IN_H 1 #ifdef _MSC_VER -#define HAVE_INTTYPES_H 0 +# if _MSC_VER < 1800 +# define HAVE_INTTYPES_H 0 +# else +# define HAVE_INTTYPES_H 1 +# endif #else -#define HAVE_INTTYPES_H 1 +# define HAVE_INTTYPES_H 1 #endif #define PACKAGE_STRING "krita" diff --git a/krita/plugins/formats/xcf/3rdparty/xcftools/xcftools.h b/krita/plugins/formats/xcf/3rdparty/xcftools/xcftools.h index 5a1efccdbc3..614f94e2a5e 100644 --- a/krita/plugins/formats/xcf/3rdparty/xcftools/xcftools.h +++ b/krita/plugins/formats/xcf/3rdparty/xcftools/xcftools.h @@ -1,201 +1,201 @@ /* Generic functions and macros for reading XCF files * * This file was written by Henning Makholm * It is hereby in the public domain. * * In jurisdictions that do not recognise grants of copyright to the * public domain: I, the author and (presumably, in those jurisdictions) * copyright holder, hereby permit anyone to distribute and use this code, * in source code or binary form, with or without modifications. This * permission is world-wide and irrevocable. * * Of course, I will not be liable for any errors or shortcomings in the * code, since I give it away without asking any compenstations. * * If you use or distribute this code, I would appreciate receiving * credit for writing it, in whichever way you find proper and customary. */ #ifndef XCFTOOLS_H #define XCFTOOLS_H #include "config.h" #include "enums.h" #include #include #if defined(HAVE_GETTEXT) && defined(ENABLE_NLS) #include #define _(s) gettext(s) void nls_init(void); #else #define _(s) (s) #define nls_init() (void)0 #endif #define N_(s) (s) #if HAVE_INTTYPES_H # define __STDC_FORMAT_MACROS # include #else /* These legacy fall-backs will probably work on every system * that does not supply a inttypes.h ... */ typedef unsigned char uint8_t ; -typedef unsigned long int uint32_t, uintptr_t ; +typedef unsigned long int uint32_t; typedef signed char int8_t ; typedef signed long int int32_t ; # define PRIX32 "lX" # define PRIu32 "lu" # define PRIXPTR "lX" #endif #if __GNUC__ # define __ATTRIBUTE__ __attribute__ #else # define __ATTRIBUTE__(x) #endif #if HAVE_NETINET_IN_H # include #elif HAVE_ARPA_INET_H # include #elif WORDS_BIGENDIAN # define ntohl(x) (x) #else static inline uint32_t ntohl(uint32_t a) { return (a << 24) + ((a & 0xFF00) << 8) + ((a >> 8) & 0xFF00) + (a >> 24) ; } #endif #ifndef HAVE_STRCASECMP #define strcasecmp strcmp #endif /* Read a single word value from the XCF file */ /* Use + instead of | because that allows LEA instructions */ #define xcfBE(a) ( ((uint32_t)xcf_file[(a) ] << 24) + \ ((uint32_t)xcf_file[(a)+1] << 16) + \ ((uint32_t)xcf_file[(a)+2] << 8 ) + \ ((uint32_t)xcf_file[(a)+3] ) ) #define xcfLE(a) ( ((uint32_t)xcf_file[(a) ] ) + \ ((uint32_t)xcf_file[(a)+1] << 8 ) + \ ((uint32_t)xcf_file[(a)+2] << 16) + \ ((uint32_t)xcf_file[(a)+3] << 24) ) #if CAN_DO_UNALIGNED_WORDS # define xcfL(a) ntohl(*(uint32_t *)(xcf_file + (a))) #else # define xcfL(a) ((a) & 3 ? xcfBE(a) : ntohl(*(uint32_t *)(xcf_file + (a)))) #endif /* ****************************************************************** */ /* The following are exported from am OS-specific source file; * io-unix.c on unixish systems. */ void read_or_mmap_xcf(const char* filename, const char *unzipper); void free_or_close_xcf(void); /* ****************************************************************** */ /* utils.c */ extern const char *progname ; extern int verboseFlag ; void *xcfmalloc(size_t size); void xcffree(void*); void FatalGeneric(int status,const char* format,...) __ATTRIBUTE__((format(printf,2,3),noreturn)) ; void FatalUnexpected(const char* format,...) __ATTRIBUTE__((format(printf,1,2),noreturn)) ; void FatalBadXCF(const char* format,...) __ATTRIBUTE__((format(printf,1,2),noreturn)) ; void FatalUnsupportedXCF(const char* format,...) __ATTRIBUTE__((format(printf,1,2),noreturn)) ; void gpl_blurb(void) __ATTRIBUTE__((noreturn)); FILE* openout(const char*); void closeout(FILE *,const char*); struct rect { int t, b, l, r ; }; #define isSubrect(A,B) \ ((A).l >= (B).l && (A).r <= (B).r && (A).t >= (B).t && (A).b <= (B).b) #define disjointRects(A,B) \ ((A).l >= (B).r || (A).r <= (B).l || (A).t >= (B).b || (A).b <= (B).t) /* ****************************************************************** */ /* xcf-general.c */ extern uint8_t *xcf_file ; extern size_t xcf_length ; extern int use_utf8 ; void xcfCheckspace(uint32_t addr,int spaceafter, const char *format,...) __ATTRIBUTE__((format(printf,3,4))); uint32_t xcfOffset(uint32_t addr,int spaceafter); int xcfNextprop(uint32_t *master,uint32_t *body); const char* xcfString(uint32_t ptr,uint32_t *after); /* These are hardcoded in the Gimp sources: */ #define TILE_SHIFT 6 #define TILE_WIDTH (1<> TILE_SHIFT) struct tileDimensions { struct rect c ; unsigned width, height ; unsigned tilesx, tilesy ; unsigned ntiles ; }; /* computeDimensions assumes that width, height, c.l, and c.t are set */ void computeDimensions(struct tileDimensions *); struct xcfTiles { const struct _convertParams *params ; uint32_t *tileptrs ; uint32_t hierarchy ; }; struct xcfLayer { struct tileDimensions dim ; const char *name ; GimpLayerModeEffects mode ; GimpImageType type ; unsigned int opacity ; int isVisible, hasMask ; uint32_t propptr ; struct xcfTiles pixels ; struct xcfTiles mask ; int isGroup ; unsigned pathLength ; unsigned *path ; }; extern struct xcfImage { int version ; unsigned width, height ; GimpImageBaseType type ; XcfCompressionType compression ; int numLayers ; struct xcfLayer *layers ; uint32_t colormapptr ; } XCF ; void getBasicXcfInfo(void); #endif /* XCFTOOLS_H */ diff --git a/krita/plugins/formats/xcf/CMakeLists.txt b/krita/plugins/formats/xcf/CMakeLists.txt index 5d272e1f658..632eb2147a1 100644 --- a/krita/plugins/formats/xcf/CMakeLists.txt +++ b/krita/plugins/formats/xcf/CMakeLists.txt @@ -1,38 +1,37 @@ add_subdirectory(tests) set(XCFTOOLS_SOURCE_DIR "${CMAKE_CURRENT_SOURCE_DIR}/3rdparty/xcftools") include_directories( ${XCFTOOLS_SOURCE_DIR}) if (CMAKE_COMPILER_IS_GNUCXX OR CMAKE_COMPILER_IS_GNUC) add_definitions(-Wno-undef -Wno-missing-format-attribute -Wno-sign-compare) endif () set(kritaxcfimport_PART_SRCS kis_xcf_import.cpp ${XCFTOOLS_SOURCE_DIR}/xcf-general.c ${XCFTOOLS_SOURCE_DIR}/utils.c ${XCFTOOLS_SOURCE_DIR}/enums.c ${XCFTOOLS_SOURCE_DIR}/pixels.c ${XCFTOOLS_SOURCE_DIR}/scaletab.c ${XCFTOOLS_SOURCE_DIR}/table.c ${XCFTOOLS_SOURCE_DIR}/enums.c ${XCFTOOLS_SOURCE_DIR}/flatspec.c ${XCFTOOLS_SOURCE_DIR}/flatten.c - ${XCFTOOLS_SOURCE_DIR}/palette.c ) kde4_add_plugin(kritaxcfimport ${kritaxcfimport_PART_SRCS}) target_link_libraries(kritaxcfimport kritaui ${KDE4_KIO_LIBS}) if (WIN32) target_link_libraries(kritaxcfimport kritaui ${WIN32_PLATFORM_NET_LIBS}) else () install(TARGETS kritaxcfimport DESTINATION ${PLUGIN_INSTALL_DIR}) endif () ########### install files ############### install( FILES krita_xcf_import.desktop DESTINATION ${SERVICES_INSTALL_DIR}/calligra) install( PROGRAMS krita_xcf.desktop DESTINATION ${XDG_APPS_INSTALL_DIR}) diff --git a/krita/plugins/paintops/chalk/kis_chalk_paintop_settings.cpp b/krita/plugins/paintops/chalk/kis_chalk_paintop_settings.cpp index 0af2b93a048..1d00d01aac6 100644 --- a/krita/plugins/paintops/chalk/kis_chalk_paintop_settings.cpp +++ b/krita/plugins/paintops/chalk/kis_chalk_paintop_settings.cpp @@ -1,69 +1,69 @@ /* * Copyright (c) 2008 Lukáš Tvrdý * * 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_chalk_paintop_settings.h" #include #include #include KisChalkPaintOpSettings::KisChalkPaintOpSettings() { } bool KisChalkPaintOpSettings::paintIncremental() { return (enumPaintActionType)getInt("PaintOpAction", WASH) == BUILDUP; } bool KisChalkPaintOpSettings::isAirbrushing() const { return getBool(AIRBRUSH_ENABLED); } int KisChalkPaintOpSettings::rate() const { return getInt(AIRBRUSH_RATE); } QPainterPath KisChalkPaintOpSettings::brushOutline(const KisPaintInformation &info, OutlineMode mode) const { QPainterPath path; if (mode == CursorIsOutline || mode == CursorIsCircleOutline || mode == CursorTiltOutline) { qreal size = getInt(CHALK_RADIUS) * 2 + 1; path = ellipseOutline(size, size, 1.0, 0.0); QPainterPath tiltLine; QLineF tiltAngle(QPointF(0.0,0.0), QPointF(0.0,size)); - tiltAngle.setLength(qMax(size, 50.0) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); + tiltAngle.setLength(qMax(size, qreal(50.0)) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); tiltAngle.setAngle((360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0))-2.0); tiltLine.moveTo(tiltAngle.p1()); tiltLine.lineTo(tiltAngle.p2()); tiltAngle.setAngle((360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0))+2.0); tiltLine.lineTo(tiltAngle.p2()); tiltLine.lineTo(tiltAngle.p1()); if (mode == CursorTiltOutline) { path.addPath(tiltLine); } path.translate(info.pos()); } return path; } diff --git a/krita/plugins/paintops/chalk/kis_chalkop_option.h b/krita/plugins/paintops/chalk/kis_chalkop_option.h index 8a346d0aed7..d61a4d260ac 100644 --- a/krita/plugins/paintops/chalk/kis_chalkop_option.h +++ b/krita/plugins/paintops/chalk/kis_chalkop_option.h @@ -1,70 +1,69 @@ /* * Copyright (c) 2008,2010 Lukáš Tvrdý * * 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_CHALKOP_OPTION_H #define KIS_CHALKOP_OPTION_H #include -#include const QString CHALK_RADIUS = "Chalk/radius"; const QString CHALK_INK_DEPLETION = "Chalk/inkDepletion"; const QString CHALK_USE_OPACITY = "Chalk/opacity"; const QString CHALK_USE_SATURATION = "Chalk/saturation"; class KisChalkOpOptionsWidget; class KisChalkOpOption : public KisPaintOpOption { public: KisChalkOpOption(); ~KisChalkOpOption(); void setRadius(int radius) const; int radius() const; bool inkDepletion() const; bool saturation() const; bool opacity() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisChalkOpOptionsWidget * m_options; }; class ChalkProperties { public: int radius; bool inkDepletion; bool useOpacity; bool useSaturation; void readOptionSetting(const KisPropertiesConfiguration* settings) { radius = settings->getInt(CHALK_RADIUS); inkDepletion = settings->getBool(CHALK_INK_DEPLETION); useOpacity = settings->getBool(CHALK_USE_OPACITY); useSaturation = settings->getBool(CHALK_USE_SATURATION); } }; #endif diff --git a/krita/plugins/paintops/curvebrush/kis_curve_line_option.h b/krita/plugins/paintops/curvebrush/kis_curve_line_option.h index a296342ab99..6c045bf619d 100644 --- a/krita/plugins/paintops/curvebrush/kis_curve_line_option.h +++ b/krita/plugins/paintops/curvebrush/kis_curve_line_option.h @@ -1,65 +1,64 @@ /* * Copyright (c) 2011 Lukáš Tvrdý * * 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_CURVE_LINE_OPTION_H #define KIS_CURVE_LINE_OPTION_H #include -#include class KisCurveOpOptionsWidget; // new rewrite const QString CURVE_LINE_WIDTH = "Curve/lineWidth"; // same as in sketch const QString CURVE_PAINT_CONNECTION_LINE = "Curve/makeConnection"; // same as in sketch const QString CURVE_STROKE_HISTORY_SIZE = "Curve/strokeHistorySize"; const QString CURVE_SMOOTHING = "Curve/smoothing"; const QString CURVE_CURVES_OPACITY = "Curve/curvesOpacity"; class KisCurveOpOption : public KisPaintOpOption { public: KisCurveOpOption(); ~KisCurveOpOption(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisCurveOpOptionsWidget * m_options; }; class CurveProperties { public: int lineWidth; int historySize; qreal curvesOpacity; bool paintConnectionLine; bool smoothing; void readOptionSetting(const KisPropertiesConfiguration* settings) { lineWidth = settings->getInt(CURVE_LINE_WIDTH); historySize = settings->getInt(CURVE_STROKE_HISTORY_SIZE); paintConnectionLine = settings->getBool(CURVE_PAINT_CONNECTION_LINE); smoothing = settings->getBool(CURVE_SMOOTHING); curvesOpacity = settings->getDouble(CURVE_CURVES_OPACITY); } }; #endif diff --git a/krita/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h b/krita/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h index 3b1164a218d..820b2c075c9 100644 --- a/krita/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h +++ b/krita/plugins/paintops/defaultpaintops/duplicate/kis_duplicateop_option.h @@ -1,62 +1,61 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_DUPLICATEOP_OPTION_H #define KIS_DUPLICATEOP_OPTION_H #include -#include const QString DUPLICATE_HEALING = "Duplicateop/Healing"; const QString DUPLICATE_CORRECT_PERSPECTIVE = "Duplicateop/CorrectPerspective"; const QString DUPLICATE_MOVE_SOURCE_POINT = "Duplicateop/MoveSourcePoint"; const QString DUPLICATE_CLONE_FROM_PROJECTION = "Duplicateop/CloneFromProjection"; class KisDuplicateOpOptionsWidget; class KisDuplicateOpOption : public KisPaintOpOption { public: KisDuplicateOpOption(); ~KisDuplicateOpOption(); bool healing() const; void setHealing(bool healing); bool correctPerspective() const; void setPerspective(bool perspective); bool moveSourcePoint() const; void setMoveSourcePoint(bool move); bool cloneFromProjection() const; void setCloneFromProjection(bool cloneFromProjection); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); void setImage(KisImageWSP image); private: KisDuplicateOpOptionsWidget * m_optionWidget; }; #endif diff --git a/krita/plugins/paintops/deform/kis_deform_option.h b/krita/plugins/paintops/deform/kis_deform_option.h index 2e7ea13cc98..b943d16f4fb 100644 --- a/krita/plugins/paintops/deform/kis_deform_option.h +++ b/krita/plugins/paintops/deform/kis_deform_option.h @@ -1,54 +1,53 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_DEFORM_OPTION_H #define KIS_DEFORM_OPTION_H #include -#include class KisDeformOptionsWidget; const QString DEFORM_AMOUNT = "Deform/deformAmount"; const QString DEFORM_ACTION = "Deform/deformAction"; const QString DEFORM_USE_BILINEAR = "Deform/bilinear"; const QString DEFORM_USE_MOVEMENT_PAINT = "Deform/useMovementPaint"; const QString DEFORM_USE_COUNTER = "Deform/useCounter"; const QString DEFORM_USE_OLD_DATA = "Deform/useOldData"; class KisDeformOption : public KisPaintOpOption { public: KisDeformOption(); ~KisDeformOption(); double deformAmount() const; int deformAction() const; bool bilinear() const; bool useMovementPaint() const; bool useCounter() const; bool useOldData() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisDeformOptionsWidget * m_options; }; #endif diff --git a/krita/plugins/paintops/experiment/kis_experimentop_option.h b/krita/plugins/paintops/experiment/kis_experimentop_option.h index 81fa352a27a..00ff3b146ad 100644 --- a/krita/plugins/paintops/experiment/kis_experimentop_option.h +++ b/krita/plugins/paintops/experiment/kis_experimentop_option.h @@ -1,82 +1,81 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_EXPERIMENTOP_OPTION_H #define KIS_EXPERIMENTOP_OPTION_H #include -#include const QString EXPERIMENT_DISPLACEMENT_ENABLED = "Experiment/displacementEnabled"; const QString EXPERIMENT_DISPLACEMENT_VALUE = "Experiment/displacement"; const QString EXPERIMENT_SMOOTHING_ENABLED = "Experiment/smoothing"; const QString EXPERIMENT_SMOOTHING_VALUE = "Experiment/smoothingValue"; const QString EXPERIMENT_SPEED_ENABLED = "Experiment/speedEnabled"; const QString EXPERIMENT_SPEED_VALUE = "Experiment/speed"; const QString EXPERIMENT_WINDING_FILL = "Experiment/windingFill"; const QString EXPERIMENT_HARD_EDGE = "Experiment/hardEdge"; class KisExperimentOpOptionsWidget; class KisExperimentOpOption : public KisPaintOpOption { Q_OBJECT public: KisExperimentOpOption(); ~KisExperimentOpOption(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private Q_SLOTS: void enableSpeed(qreal value); void enableSmooth(qreal value); void enableDisplacement(qreal value); private: KisExperimentOpOptionsWidget * m_options; }; class ExperimentOption { public: bool isDisplacementEnabled; qreal displacement; bool isSpeedEnabled; qreal speed; bool isSmoothingEnabled; qreal smoothing; bool windingFill; bool hardEdge; void readOptionSetting(const KisPropertiesConfiguration* setting) { isDisplacementEnabled = setting->getBool(EXPERIMENT_DISPLACEMENT_ENABLED); displacement = setting->getDouble(EXPERIMENT_DISPLACEMENT_VALUE, 50.0); isSpeedEnabled = setting->getBool(EXPERIMENT_SPEED_ENABLED); speed = setting->getDouble(EXPERIMENT_SPEED_VALUE, 50.0); isSmoothingEnabled = setting->getBool(EXPERIMENT_SMOOTHING_ENABLED); smoothing = setting->getDouble(EXPERIMENT_SMOOTHING_VALUE, 20.0); windingFill = setting->getBool(EXPERIMENT_WINDING_FILL); hardEdge = setting->getBool(EXPERIMENT_HARD_EDGE); } }; #endif diff --git a/krita/plugins/paintops/gridbrush/kis_gridop_option.h b/krita/plugins/paintops/gridbrush/kis_gridop_option.h index fc3f86e210b..0a9a2e22ea6 100644 --- a/krita/plugins/paintops/gridbrush/kis_gridop_option.h +++ b/krita/plugins/paintops/gridbrush/kis_gridop_option.h @@ -1,66 +1,65 @@ /* * Copyright (c) 2009,2010 Lukáš Tvrdý (lukast.dev@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_GRIDOP_OPTION_H #define KIS_GRIDOP_OPTION_H #include -#include const QString GRID_WIDTH = "Grid/gridWidth"; const QString GRID_HEIGHT = "Grid/gridHeight"; const QString GRID_DIVISION_LEVEL = "Grid/divisionLevel"; const QString GRID_PRESSURE_DIVISION = "Grid/pressureDivision"; const QString GRID_SCALE = "Grid/scale"; const QString GRID_VERTICAL_BORDER = "Grid/verticalBorder"; const QString GRID_HORIZONTAL_BORDER = "Grid/horizontalBorder"; const QString GRID_RANDOM_BORDER = "Grid/randomBorder"; class KisGridOpOptionsWidget; class KisGridOpOption : public KisPaintOpOption { public: KisGridOpOption(); ~KisGridOpOption(); int gridWidth() const; void setWidth(int width) const; int gridHeight() const; void setHeight(int height) const; int divisionLevel() const; bool pressureDivision() const; qreal scale() const; qreal vertBorder() const; qreal horizBorder() const; bool randomBorder() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisGridOpOptionsWidget * m_options; }; #endif diff --git a/krita/plugins/paintops/hairy/kis_hairy_bristle_option.h b/krita/plugins/paintops/hairy/kis_hairy_bristle_option.h index 4af9c987e9b..d2cf404e537 100644 --- a/krita/plugins/paintops/hairy/kis_hairy_bristle_option.h +++ b/krita/plugins/paintops/hairy/kis_hairy_bristle_option.h @@ -1,58 +1,57 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_HAIRY_BRISTLE_OPTION_H #define KIS_HAIRY_BRISTLE_OPTION_H #include -#include const QString HAIRY_BRISTLE_USE_MOUSEPRESSURE = "HairyBristle/useMousePressure"; const QString HAIRY_BRISTLE_SCALE = "HairyBristle/scale"; const QString HAIRY_BRISTLE_SHEAR = "HairyBristle/shear"; const QString HAIRY_BRISTLE_RANDOM = "HairyBristle/random"; const QString HAIRY_BRISTLE_DENSITY = "HairyBristle/density"; const QString HAIRY_BRISTLE_THRESHOLD = "HairyBristle/threshold"; const QString HAIRY_BRISTLE_ANTI_ALIASING = "HairyBristle/antialias"; const QString HAIRY_BRISTLE_USE_COMPOSITING = "HairyBristle/useCompositing"; const QString HAIRY_BRISTLE_CONNECTED = "HairyBristle/isConnected"; class KisBristleOptionsWidget; class KisHairyBristleOption : public KisPaintOpOption { public: KisHairyBristleOption(); ~KisHairyBristleOption(); void setScaleFactor(qreal scale) const; bool useMousePressure() const; double scaleFactor() const; double shearFactor() const; double randomFactor() const; void writeOptionSetting(KisPropertiesConfiguration* config) const; void readOptionSetting(const KisPropertiesConfiguration* config); private: KisBristleOptionsWidget * m_options; }; #endif // KIS_HAIRY_BRISTLE_OPTION_H diff --git a/krita/plugins/paintops/hairy/kis_hairy_ink_option.h b/krita/plugins/paintops/hairy/kis_hairy_ink_option.h index 387a13a07e9..94a40ddc185 100644 --- a/krita/plugins/paintops/hairy/kis_hairy_ink_option.h +++ b/krita/plugins/paintops/hairy/kis_hairy_ink_option.h @@ -1,64 +1,63 @@ /* This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License version 2 as published by the Free Software Foundation. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_HAIRY_INK_OPTION_H #define KIS_HAIRY_INK_OPTION_H #include -#include const QString HAIRY_INK_DEPLETION_ENABLED = "HairyInk/enabled"; const QString HAIRY_INK_AMOUNT = "HairyInk/inkAmount"; const QString HAIRY_INK_USE_SATURATION = "HairyInk/useSaturation"; const QString HAIRY_INK_USE_OPACITY = "HairyInk/useOpacity"; const QString HAIRY_INK_USE_WEIGHTS = "HairyInk/useWeights"; const QString HAIRY_INK_PRESSURE_WEIGHT = "HairyInk/pressureWeights"; const QString HAIRY_INK_BRISTLE_LENGTH_WEIGHT = "HairyInk/bristleLengthWeights"; const QString HAIRY_INK_BRISTLE_INK_AMOUNT_WEIGHT = "HairyInk/bristleInkAmountWeight"; const QString HAIRY_INK_DEPLETION_WEIGHT = "HairyInk/inkDepletionWeight"; const QString HAIRY_INK_DEPLETION_CURVE = "HairyInk/inkDepletionCurve"; const QString HAIRY_INK_SOAK = "HairyInk/soak"; class KisInkOptionsWidget; class KisHairyInkOption : public KisPaintOpOption { public: KisHairyInkOption(); ~KisHairyInkOption(); int inkAmount() const; QList curve() const; bool useSaturation() const; bool useOpacity() const; bool useWeights() const; int pressureWeight() const; int bristleLengthWeight() const; int bristleInkAmountWeight() const; int inkDepletionWeight() const; int m_curveSamples; void writeOptionSetting(KisPropertiesConfiguration* config) const; void readOptionSetting(const KisPropertiesConfiguration* config); private: KisInkOptionsWidget * m_options; }; #endif // KIS_HAIRY_SHAPE_OPTION_H diff --git a/krita/plugins/paintops/hairy/kis_hairy_shape_option.h b/krita/plugins/paintops/hairy/kis_hairy_shape_option.h index 1467a00317a..3bcfaffd277 100644 --- a/krita/plugins/paintops/hairy/kis_hairy_shape_option.h +++ b/krita/plugins/paintops/hairy/kis_hairy_shape_option.h @@ -1,52 +1,51 @@ /* * Copyright (c) 2008-2010 Lukáš Tvrdý * * 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_HAIRY_SHAPE_OPTION_H #define KIS_HAIRY_SHAPE_OPTION_H #include -#include const QString HAIRY_RADIUS = "Hairy/radius"; const QString HAIRY_SIGMA = "Hairy/sigma"; const QString HAIRY_IS_DIMENSION_1D = "Hairy/isDimension1D"; class KisShapeOptionsWidget; class KisHairyShapeOption : public KisPaintOpOption { public: KisHairyShapeOption(); ~KisHairyShapeOption(); void setRadius(int radius) const; void setScaleFactor(qreal scale) const; int radius() const; double sigma() const; bool isbrushDimension1D() const; bool useMousePressure() const; void writeOptionSetting(KisPropertiesConfiguration* config) const; void readOptionSetting(const KisPropertiesConfiguration* config); private: KisShapeOptionsWidget * m_options; }; #endif // KIS_HAIRY_SHAPE_OPTION_H diff --git a/krita/plugins/paintops/hatching/kis_hatching_options.h b/krita/plugins/paintops/hatching/kis_hatching_options.h index 683b7f0d120..e072c6cf83e 100644 --- a/krita/plugins/paintops/hatching/kis_hatching_options.h +++ b/krita/plugins/paintops/hatching/kis_hatching_options.h @@ -1,43 +1,42 @@ /* * Copyright (c) 2008 Lukas Tvrdy * * 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_HATCHING_OPTIONS_H #define KIS_HATCHING_OPTIONS_H #include -#include class KisHatchingOptionsWidget; class KisHatchingOptions : public KisPaintOpOption { public: KisHatchingOptions(); ~KisHatchingOptions(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisHatchingOptionsWidget * m_options; }; #endif diff --git a/krita/plugins/paintops/hatching/kis_hatching_preferences.h b/krita/plugins/paintops/hatching/kis_hatching_preferences.h index 4fb9fb18946..9a4bd91fdfe 100644 --- a/krita/plugins/paintops/hatching/kis_hatching_preferences.h +++ b/krita/plugins/paintops/hatching/kis_hatching_preferences.h @@ -1,42 +1,41 @@ /* * Copyright (c) 2010 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_HATCHING_PREFERENCES_H #define KIS_HATCHING_PREFERENCES_H #include -#include class KisHatchingPreferencesWidget; class KisHatchingPreferences : public KisPaintOpOption { public: KisHatchingPreferences(); ~KisHatchingPreferences(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisHatchingPreferencesWidget * m_options; }; #endif diff --git a/krita/plugins/paintops/hatching/kis_hatching_pressure_crosshatching_option.h b/krita/plugins/paintops/hatching/kis_hatching_pressure_crosshatching_option.h index 905df815946..2baf7a44ca4 100644 --- a/krita/plugins/paintops/hatching/kis_hatching_pressure_crosshatching_option.h +++ b/krita/plugins/paintops/hatching/kis_hatching_pressure_crosshatching_option.h @@ -1,38 +1,37 @@ /* * Copyright (c) 2010 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_HATCHING_PRESSURE_CROSSHATCHING_OPTION_H #define KIS_HATCHING_PRESSURE_CROSSHATCHING_OPTION_H #include "kis_curve_option.h" #include -#include /** * The pressure crosshatching option defines a curve that is used to * calculate the effect of pressure (or other parameters) on * crosshatching in the hatching brush */ class KisHatchingPressureCrosshatchingOption : public KisCurveOption { public: KisHatchingPressureCrosshatchingOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/hatching/kis_hatching_pressure_separation_option.h b/krita/plugins/paintops/hatching/kis_hatching_pressure_separation_option.h index 007a973b116..bf6076e89d6 100644 --- a/krita/plugins/paintops/hatching/kis_hatching_pressure_separation_option.h +++ b/krita/plugins/paintops/hatching/kis_hatching_pressure_separation_option.h @@ -1,39 +1,38 @@ /* * Copyright (c) 2010 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_HATCHING_PRESSURE_SEPARATION_OPTION_H #define KIS_HATCHING_PRESSURE_SEPARATION_OPTION_H #include "kis_curve_option.h" #include -#include /** * The pressure separation option defines a curve that is used to * calculate the effect of pressure (or other parameters) on * separation in the hatching brush */ class KisHatchingPressureSeparationOption : public KisCurveOption { public: KisHatchingPressureSeparationOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/hatching/kis_hatching_pressure_thickness_option.h b/krita/plugins/paintops/hatching/kis_hatching_pressure_thickness_option.h index 310df0e5ed1..fea369b6f71 100644 --- a/krita/plugins/paintops/hatching/kis_hatching_pressure_thickness_option.h +++ b/krita/plugins/paintops/hatching/kis_hatching_pressure_thickness_option.h @@ -1,38 +1,37 @@ /* * Copyright (c) 2010 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_HATCHING_PRESSURE_THICKNESS_OPTION_H #define KIS_HATCHING_PRESSURE_THICKNESS_OPTION_H #include "kis_curve_option.h" #include -#include /** * The pressure thickness option defines a curve that is used to * calculate the effect of pressure (or other parameters) on * thickness in the hatching brush */ class KisHatchingPressureThicknessOption : public KisCurveOption { public: KisHatchingPressureThicknessOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/forms/wdgclipboardbrush.ui b/krita/plugins/paintops/libpaintop/forms/wdgclipboardbrush.ui index 4173e5da383..cbb9e686675 100644 --- a/krita/plugins/paintops/libpaintop/forms/wdgclipboardbrush.ui +++ b/krita/plugins/paintops/libpaintop/forms/wdgclipboardbrush.ui @@ -1,197 +1,209 @@ KisWdgClipboardBrush 0 0 454 251 5 0 0 0 0 0 0 110 110 QFrame::Box QFrame::Plain 2 0 Qt::Vertical 20 40 60 16777215 Spacing: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - Use color as mask + Create mask from color Qt::Vertical 20 40 Qt::Horizontal 40 20 - - - - 30 - 240 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + KisSpacingSelectionWidget QWidget
kis_spacing_selection_widget.h
1
- - buttonBox - accepted() - KisWdgClipboardBrush - accept() - - buttonBox - rejected() - KisWdgClipboardBrush - reject() - + buttonBox + accepted() + KisWdgClipboardBrush + accept() + + + 20 + 20 + + + 20 + 20 + + + + + buttonBox + rejected() + KisWdgClipboardBrush + reject() + + + 20 + 20 + + + 20 + 20 + + +
diff --git a/krita/plugins/paintops/libpaintop/forms/wdgcoloroptions.ui b/krita/plugins/paintops/libpaintop/forms/wdgcoloroptions.ui index 8c5b0cf154a..f9c3330dcee 100644 --- a/krita/plugins/paintops/libpaintop/forms/wdgcoloroptions.ui +++ b/krita/plugins/paintops/libpaintop/forms/wdgcoloroptions.ui @@ -1,228 +1,223 @@ WdgColorOptions 0 0 - 460 - 321 + 509 + 320 255 255 460 320 - - - - 0 - 220 - 424 - 52 - - - - - QLayout::SetMinimumSize - - - - - - 0 - 0 - - - - Color per particle - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 58 - 20 - - - - - - - - - 0 - 0 - - - - If checked, grid brush fill every particle's background with background color. The background of particle is rectangle of grid width and height and by default it is transparent. - - - Fill background - - - - - - - - 0 - 0 - - - - Sample Input layer - - - - - - - - 0 - 0 - - - - Mix with background color - - - - - - - Qt::Horizontal - - - QSizePolicy::Fixed - - - - 58 - 20 - - - - - - - - - - 1 - 1 - 110 - 23 - - - - Random HSV - - - - - false - - - - 1 - 28 - 451 - 155 - - - - - - 0 - 0 - 441 - 131 - - - + + + + + Random HSV + + + + + Hue: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + 10 + 0 + + + + Saturation: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + 10 + 0 + + + + Value: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter + + + + + 10 + 0 + + + + + + + + + + Random opacity + + + + + + + QLayout::SetMinimumSize + + + + + + 0 + 0 + + + + Color per particle + + + - + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 58 + 20 + + + - - + + + + + 0 + 0 + + + + If checked, grid brush fill every particle's background with background color. The background of particle is rectangle of grid width and height and by default it is transparent. + + + Fill background + + - - + + + + + 0 + 0 + + + + Sample Input layer + + + + + + + + 0 + 0 + + + + Mix with background color + + + + + + + Qt::Horizontal + + + QSizePolicy::Fixed + + + + 58 + 20 + + + - - - - - - 1 - 187 - 130 - 23 - - - - Random opacity - - + + + + + Qt::Vertical + + + + 20 + 114 + + + + + KisSliderSpinBox QWidget
kis_slider_spin_box.h
1
diff --git a/krita/plugins/paintops/libpaintop/forms/wdgcustombrush.ui b/krita/plugins/paintops/libpaintop/forms/wdgcustombrush.ui index 0f23c226d40..955642680b5 100644 --- a/krita/plugins/paintops/libpaintop/forms/wdgcustombrush.ui +++ b/krita/plugins/paintops/libpaintop/forms/wdgcustombrush.ui @@ -1,306 +1,318 @@ KisWdgCustomBrush 0 0 462 311 6 0 0 0 0 0 0 110 110 QFrame::Box Qt::Vertical 20 40 Spacing: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter Name: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter - Use color as mask + Create mask from color 0 110 Brush Style false 20 20 301 71 3 0 0 Style: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter 0 0 Regular Animated 0 0 Selection mode: Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter false 0 0 2 Constant Random Incremental Pressure Angular Qt::Vertical 20 40 Qt::Horizontal 40 20 - - - - 30 - 240 - 341 - 32 - - - - Qt::Horizontal - - - QDialogButtonBox::Cancel|QDialogButtonBox::Ok - - + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + KisSpacingSelectionWidget QWidget
kis_spacing_selection_widget.h
1
- - buttonBox - accepted() - KisWdgCustomBrush - accept() - - buttonBox - rejected() - KisWdgCustomBrush - reject() - - + buttonBox + accepted() + KisWdgCustomBrush + accept() + + + 20 + 20 + + + 20 + 20 + + + + + buttonBox + rejected() + KisWdgCustomBrush + reject() + + + 20 + 20 + + + 20 + 20 + + + +
diff --git a/krita/plugins/paintops/libpaintop/kis_airbrush_option.h b/krita/plugins/paintops/libpaintop/kis_airbrush_option.h index 30d7d386ac6..5584b1e6e8f 100644 --- a/krita/plugins/paintops/libpaintop/kis_airbrush_option.h +++ b/krita/plugins/paintops/libpaintop/kis_airbrush_option.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_AIRBRUSH_OPTION_H #define KIS_AIRBRUSH_OPTION_H #include -#include +#include const QString AIRBRUSH_ENABLED = "AirbrushOption/isAirbrushing"; const QString AIRBRUSH_RATE = "AirbrushOption/rate"; class KisAirbrushWidget; /** * Allows the user to activate airbrushing of the brush mask (brush is painted at the same position over and over) * Rate is set in miliseconds. */ class PAINTOP_EXPORT KisAirbrushOption : public KisPaintOpOption { public: KisAirbrushOption(bool enabled = true); ~KisAirbrushOption(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisAirbrushWidget * m_optionWidget; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_auto_brush_widget.h b/krita/plugins/paintops/libpaintop/kis_auto_brush_widget.h index a0ad8226e93..b594cbc70d8 100644 --- a/krita/plugins/paintops/libpaintop/kis_auto_brush_widget.h +++ b/krita/plugins/paintops/libpaintop/kis_auto_brush_widget.h @@ -1,85 +1,85 @@ /* * Copyright (c) 2004,2007 Cyrille Berger * * 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_AUTO_BRUSH_WIDGET_H_ #define _KIS_AUTO_BRUSH_WIDGET_H_ #include #include -#include "krita_export.h" +#include "kritapaintop_export.h" #include "ui_wdgautobrush.h" #include class PAINTOP_EXPORT KisWdgAutobrush : public QWidget, public Ui::KisWdgAutobrush { Q_OBJECT public: KisWdgAutobrush(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); setupUi(this); } }; class PAINTOP_EXPORT KisAutoBrushWidget : public KisWdgAutobrush { Q_OBJECT public: KisAutoBrushWidget(QWidget *parent, const char* name); void activate(); KisBrushSP brush(); void setBrush(KisBrushSP brush); void setBrushSize(qreal dxPixels, qreal dyPixels); QSizeF brushSize() const; private Q_SLOTS: void paramChanged(); void setStackedWidget(int); void spinBoxHorizontalChanged(qreal); void spinBoxVerticalChanged(qreal); void linkFadeToggled(bool); void spinBoxRatioChanged(qreal); void spinBoxRandomnessChanged(qreal); void spinBoxRadiusChanged(qreal); void spinBoxSpikesChanged(int); void spinBoxAngleChanged(int); void spinBoxDensityChanged(qreal); void slotSpacingChanged(); Q_SIGNALS: void sigBrushChanged(); protected: virtual void resizeEvent(QResizeEvent *); private: QImage m_brush; KisBrushSP m_autoBrush; bool m_linkFade; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option.h b/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option.h index 1cb295f0681..f17a075b645 100644 --- a/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option.h +++ b/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option.h @@ -1,55 +1,56 @@ /* This file is part of the KDE project * Copyright (c) 2008 Boudewijn Rempt * Copyright (c) 2008 Emanuele Tamponi * * 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_BIDIRECTIONAL_MIXING_OPTION_H #define KIS_BIDIRECTIONAL_MIXING_OPTION_H #include "kis_paintop_option.h" #include +#include class KisPropertiesConfiguration; class KisPainter; class QRect; /** * The bidirectional mixing option uses the painterly framework to * implement bidirectional paint mixing (that is, paint on the canvas * dirties the brush, and the brush mixes its color with that on the * canvas. * * Taken from the complex paintop */ class PAINTOP_EXPORT KisBidirectionalMixingOption { public: KisBidirectionalMixingOption(); ~KisBidirectionalMixingOption(); void apply(KisPaintDeviceSP dab, KisPaintDeviceSP device, KisPainter* painter, qint32 sx, qint32 sy, qint32 sw, qint32 sh, quint8 pressure, const QRect& dstRect); void applyFixed(KisFixedPaintDeviceSP dab, KisPaintDeviceSP device, KisPainter* painter, qint32 sx, qint32 sy, qint32 sw, qint32 sh, quint8 pressure, const QRect& dstRect); void readOptionSetting(const KisPropertiesConfiguration* setting); private: bool m_mixingEnabled; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option_widget.h b/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option_widget.h index ba6fee567ae..e56d5049a10 100644 --- a/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option_widget.h +++ b/krita/plugins/paintops/libpaintop/kis_bidirectional_mixing_option_widget.h @@ -1,56 +1,57 @@ /* This file is part of the KDE project * Copyright (c) 2008 Boudewijn Rempt * Copyright (c) 2008 Emanuele Tamponi * * 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_BIDIRECTIONAL_MIXING_OPTION_WIDGET_H #define KIS_BIDIRECTIONAL_MIXING_OPTION_WIDGET_H #include "kis_paintop_option.h" #include +#include class KisPropertiesConfiguration; class QLabel; const QString BIDIRECTIONAL_MIXING_ENABLED = "BidirectionalMixing/Enabled"; /** * The bidirectional mixing option uses the painterly framework to * implement bidirectional paint mixing (that is, paint on the canvas * dirties the brush, and the brush mixes its color with that on the * canvas. * * Taken from the complex paintop */ class PAINTOP_EXPORT KisBidirectionalMixingOptionWidget : public KisPaintOpOption { public: KisBidirectionalMixingOptionWidget(); ~KisBidirectionalMixingOptionWidget(); ///Reimplemented void writeOptionSetting(KisPropertiesConfiguration* setting) const; ///Reimplemented void readOptionSetting(const KisPropertiesConfiguration* setting); private: QLabel * m_optionWidget; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop.h b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop.h index c3663488e25..d9d6e8ba568 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop.h @@ -1,72 +1,72 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_BASED_PAINTOP_H #define KIS_BRUSH_BASED_PAINTOP_H -#include "krita_export.h" +#include "kritapaintop_export.h" #include "kis_paintop.h" #include "kis_dab_cache.h" #include "kis_brush.h" #include "kis_texture_option.h" #include "kis_precision_option.h" #include "kis_pressure_mirror_option.h" #include class KisPropertiesConfiguration; class KisPressureSpacingOption; /** * This is a base class for paintops that use a KisBrush or derived * brush to paint with. This is mainly important for the spacing * generation. */ class PAINTOP_EXPORT KisBrushBasedPaintOp : public KisPaintOp { public: KisBrushBasedPaintOp(const KisPropertiesConfiguration* settings, KisPainter* painter); ~KisBrushBasedPaintOp(); bool checkSizeTooSmall(qreal scale); KisSpacingInformation effectiveSpacing(qreal scale, qreal rotation) const; KisSpacingInformation effectiveSpacing(qreal scale, qreal rotation, const KisPressureSpacingOption &spacingOption, const KisPaintInformation &pi) const; ///Reimplemented, false if brush is 0 virtual bool canPaint() const; #ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND typedef int needs_preinitialization; static void preinitializeOpStatically(const KisPaintOpSettingsSP settings); #endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */ private: KisSpacingInformation effectiveSpacing(qreal dabWidth, qreal dabHeight, qreal extraScale, bool isotropicSpacing, qreal rotation) const; protected: // XXX: make private! KisBrushSP m_brush; KisTextureProperties m_textureProperties; KisPressureMirrorOption m_mirrorOption; KisPrecisionOption m_precisionOption; KisDabCache *m_dabCache; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.cpp b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.cpp index 5209a8771e7..872716b8d5e 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.cpp +++ b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.cpp @@ -1,58 +1,57 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_brush_based_paintop_options_widget.h" #include "kis_brush_option_widget.h" -#include "krita_export.h" KisBrushBasedPaintopOptionWidget::KisBrushBasedPaintopOptionWidget(QWidget* parent) : KisPaintOpSettingsWidget(parent) { m_brushOption = new KisBrushOptionWidget(); addPaintOpOption(m_brushOption, i18n("Brush Tip")); } KisBrushBasedPaintopOptionWidget::~KisBrushBasedPaintopOptionWidget() { } void KisBrushBasedPaintopOptionWidget::setPrecisionEnabled(bool value) { m_brushOption->setPrecisionEnabled(value); } KisBrushSP KisBrushBasedPaintopOptionWidget::brush() { return m_brushOption->brush(); } void KisBrushBasedPaintopOptionWidget::changePaintOpSize(qreal x, qreal y) { m_brushOption->setBrushSize(x, y); } QSizeF KisBrushBasedPaintopOptionWidget::paintOpSize() const { return m_brushOption->brushSize(); } bool KisBrushBasedPaintopOptionWidget::presetIsValid() { return m_brushOption->presetIsValid(); } diff --git a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.h b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.h index cece05ed253..05843a47266 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_options_widget.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_BASED_PAINTOP_OPTIONS_WIDGET_H #define KIS_BRUSH_BASED_PAINTOP_OPTIONS_WIDGET_H #include "kis_paintop_settings_widget.h" #include "kis_types.h" #include "kis_brush.h" -#include +#include class KisBrushOptionWidget; class PAINTOP_EXPORT KisBrushBasedPaintopOptionWidget : public KisPaintOpSettingsWidget { public: KisBrushBasedPaintopOptionWidget(QWidget* parent = 0); virtual ~KisBrushBasedPaintopOptionWidget(); void setPrecisionEnabled(bool value); KisBrushSP brush(); void changePaintOpSize(qreal x, qreal y); virtual QSizeF paintOpSize() const; virtual bool presetIsValid(); private: KisBrushOptionWidget * m_brushOption; }; #endif // KIS_BRUSH_BASED_PAINTOP_OPTIONS_WIDGET_H diff --git a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp index d070c042ba2..e2c5c13133a 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp +++ b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.cpp @@ -1,122 +1,122 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_brush_based_paintop_settings.h" #include #include #include "kis_brush_based_paintop_options_widget.h" #include #include "kis_brush_server.h" #include KisBrushBasedPaintOpSettings::KisBrushBasedPaintOpSettings() : KisOutlineGenerationPolicy(KisCurrentOutlineFetcher::SIZE_OPTION | KisCurrentOutlineFetcher::ROTATION_OPTION | KisCurrentOutlineFetcher::MIRROR_OPTION) { } bool KisBrushBasedPaintOpSettings::paintIncremental() { if (hasProperty("PaintOpAction")) { return (enumPaintActionType)getInt("PaintOpAction", WASH) == BUILDUP; } return true; } bool KisBrushBasedPaintOpSettings::isAirbrushing() const { return getBool(AIRBRUSH_ENABLED); } int KisBrushBasedPaintOpSettings::rate() const { return getInt(AIRBRUSH_RATE); } QPainterPath KisBrushBasedPaintOpSettings::brushOutlineImpl(const KisPaintInformation &info, OutlineMode mode, qreal additionalScale, bool forceOutline) const { QPainterPath path; if (forceOutline || mode == CursorIsOutline || mode == CursorIsCircleOutline || mode == CursorTiltOutline) { KisBrushBasedPaintopOptionWidget *widget = dynamic_cast(optionsWidget()); if (!widget) { return KisPaintOpSettings::brushOutline(info, mode); } KisBrushSP brush = widget->brush(); qreal finalScale = brush->scale() * additionalScale; QPainterPath realOutline = brush->outline(); QPainterPath tiltLine; QLineF tiltAngle(realOutline.boundingRect().center(), realOutline.boundingRect().topLeft()); - tiltAngle.setLength(qMax(finalScale, 50.0) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); + tiltAngle.setLength(qMax(finalScale, qreal(50.0)) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); tiltAngle.setAngle((360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0))-2.0); tiltLine.moveTo(tiltAngle.p1()); tiltLine.lineTo(tiltAngle.p2()); tiltAngle.setAngle((360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0))+2.0); tiltLine.lineTo(tiltAngle.p2()); tiltLine.lineTo(tiltAngle.p1()); if (mode == CursorIsCircleOutline || mode == CursorTiltOutline || (forceOutline && mode == CursorNoOutline)) { QPainterPath ellipse; ellipse.addEllipse(realOutline.boundingRect()); realOutline = ellipse; } path = outlineFetcher()->fetchOutline(info, this, realOutline, finalScale, brush->angle()); if (mode == CursorTiltOutline) { path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, finalScale, 0.0, true, realOutline.boundingRect().center().x(), realOutline.boundingRect().center().y())); } } return path; } QPainterPath KisBrushBasedPaintOpSettings::brushOutline(const KisPaintInformation &info, OutlineMode mode) const { return brushOutlineImpl(info, mode, 1.0); } bool KisBrushBasedPaintOpSettings::isValid() const { QString filename = getString("requiredBrushFile", ""); if (!filename.isEmpty()) { KisBrushSP brush = KisBrushServer::instance()->brushServer()->resourceByFilename(filename); if (!brush) { return false; } } return true; } bool KisBrushBasedPaintOpSettings::isLoadable() { return (KisBrushServer::instance()->brushServer()->resources().count() > 0); } diff --git a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h index e27b8935a57..3de03271d34 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_based_paintop_settings.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2010 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_BRUSH_BASED_PAINTOP_SETTINGS_H #define KIS_BRUSH_BASED_PAINTOP_SETTINGS_H #include -#include +#include #include class PAINTOP_EXPORT KisBrushBasedPaintOpSettings : public KisOutlineGenerationPolicy { public: KisBrushBasedPaintOpSettings(); ///Reimplemented virtual bool paintIncremental(); ///Reimplemented virtual bool isAirbrushing() const; ///Reimplemented virtual int rate() const; using KisPaintOpSettings::brushOutline; virtual QPainterPath brushOutline(const KisPaintInformation &info, OutlineMode mode) const; ///Reimplemented virtual bool isValid() const; ///Reimplemented virtual bool isLoadable(); protected: QPainterPath brushOutlineImpl(const KisPaintInformation &info, OutlineMode mode, qreal additionalScale, bool forceOutline = false) const; }; #endif // KIS_BRUSH_BASED_PAINTOP_SETTINGS_H diff --git a/krita/plugins/paintops/libpaintop/kis_brush_chooser.h b/krita/plugins/paintops/libpaintop/kis_brush_chooser.h index 1ac092e6bd8..b66b62a57dd 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_chooser.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_chooser.h @@ -1,87 +1,87 @@ /* * Copyright (c) 2004 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_BRUSH_CHOOSER_H_ #define KIS_BRUSH_CHOOSER_H_ #include -#include +#include #include class KisDoubleSliderSpinBox; class QLabel; class QCheckBox; class KisDoubleSliderSpinBox; class KisSpacingSelectionWidget; class KisCustomBrushWidget; class KisClipboardBrushWidget; class KoResourceItemChooser; class KoResource; class PAINTOP_EXPORT KisBrushChooser : public QWidget { Q_OBJECT public: KisBrushChooser(QWidget *parent = 0, const char *name = 0); virtual ~KisBrushChooser(); KisBrushSP brush() { return m_brush; }; void setBrush(KisBrushSP _brush); void setBrushSize(qreal xPixels, qreal yPixels); void setImage(KisImageWSP image); private Q_SLOTS: void slotResetBrush(); void slotSetItemSize(qreal); void slotSetItemRotation(qreal); void slotSpacingChanged(); void slotSetItemUseColorAsMask(bool); void slotActivatedBrush(KoResource *); void slotOpenStampBrush(); void slotOpenClipboardBrush(); void slotNewPredefinedBrush(KoResource *); void update(KoResource *); Q_SIGNALS: void sigBrushChanged(); private: QLabel* m_lbName; QLabel* m_lbRotation; QLabel* m_lbSize; QLabel* m_lbSpacing; KisDoubleSliderSpinBox* m_slRotation; KisDoubleSliderSpinBox* m_slSize; KisSpacingSelectionWidget* m_slSpacing; QCheckBox* m_chkColorMask; KisBrushSP m_brush; KoResourceItemChooser* m_itemChooser; KisImageWSP m_image; KisCustomBrushWidget* m_stampBrushWidget; KisClipboardBrushWidget* m_clipboardBrushWidget; }; #endif // KIS_BRUSH_CHOOSER_H_ diff --git a/krita/plugins/paintops/libpaintop/kis_brush_option.h b/krita/plugins/paintops/libpaintop/kis_brush_option.h index d6e3e0d99c6..53d2cee8f5e 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_option.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_option.h @@ -1,47 +1,48 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * Copyright (C) Sven Langkamp , (C) 2008 * * 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_BRUSH_OPTION_H_ #define KIS_BRUSH_OPTION_H_ #include "kis_brush.h" #include +#include class KisPropertiesConfiguration; class PAINTOP_EXPORT KisBrushOption { public: void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); KisBrushSP brush() const; void setBrush(KisBrushSP brush); #ifdef HAVE_THREADED_TEXT_RENDERING_WORKAROUND static bool isTextBrush(const KisPropertiesConfiguration* setting); #endif /* HAVE_THREADED_TEXT_RENDERING_WORKAROUND */ private: KisBrushSP m_brush; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_brush_option_widget.h b/krita/plugins/paintops/libpaintop/kis_brush_option_widget.h index 877c63102ba..ebfa7c3ff75 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_option_widget.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_option_widget.h @@ -1,73 +1,73 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_BRUSH_OPTION_H #define KIS_BRUSH_OPTION_H #include "kis_paintop_option.h" #include "kis_brush_option.h" -#include +#include #include "kis_brush.h" class KisBrushSelectionWidget; /** * The brush option allows the user to select a particular brush * footprint for suitable paintops */ class PAINTOP_EXPORT KisBrushOptionWidget : public KisPaintOpOption { Q_OBJECT public: KisBrushOptionWidget(); /** * @return the currently selected brush */ KisBrushSP brush() const; void setAutoBrush(bool on); void setPredefinedBrushes(bool on); void setCustomBrush(bool on); void setTextBrush(bool on); void setImage(KisImageWSP image); void setPrecisionEnabled(bool value); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); void setBrushSize(qreal dxPixels, qreal dyPixels); QSizeF brushSize() const; bool presetIsValid(); private Q_SLOTS: void brushChanged(); private: KisBrushSelectionWidget * m_brushSelectionWidget; KisBrushOption m_brushOption; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_brush_size_option.h b/krita/plugins/paintops/libpaintop/kis_brush_size_option.h index 34a83b88699..cf7de868313 100644 --- a/krita/plugins/paintops/libpaintop/kis_brush_size_option.h +++ b/krita/plugins/paintops/libpaintop/kis_brush_size_option.h @@ -1,96 +1,96 @@ /* * Copyright (c) 2009,2010 Lukáš Tvrdý * * 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_SIZE_OPTION_H_ #define KIS_SIZE_OPTION_H_ #include #include #include -#include +#include class KisBrushSizeOptionsWidget; const QString BRUSH_SHAPE = "Brush/shape"; const QString BRUSH_DIAMETER = "Brush/diameter"; const QString BRUSH_ASPECT = "Brush/aspect"; const QString BRUSH_SCALE = "Brush/scale"; const QString BRUSH_ROTATION = "Brush/rotation"; const QString BRUSH_SPACING = "Brush/spacing"; const QString BRUSH_DENSITY = "Brush/density"; const QString BRUSH_JITTER_MOVEMENT = "Brush/jitterMovement"; const QString BRUSH_JITTER_MOVEMENT_ENABLED = "Brush/jitterMovementEnabled"; class PAINTOP_EXPORT KisBrushSizeOption : public KisPaintOpOption { public: KisBrushSizeOption(); ~KisBrushSizeOption(); int diameter() const; void setDiameter(int diameter); void setSpacing(qreal spacing); qreal spacing() const; qreal brushAspect() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisBrushSizeOptionsWidget * m_options; }; class PAINTOP_EXPORT KisBrushSizeProperties { public: quint16 shape; quint16 diameter; qreal aspect; qreal scale; qreal rotation; qreal spacing; qreal density; qreal jitterMovementAmount; bool jitterEnabled; public: void readOptionSetting(const KisPropertiesConfiguration * settings) { //TODO: shape shape = 0; diameter = quint16(settings->getDouble(BRUSH_DIAMETER)); aspect = settings->getDouble(BRUSH_ASPECT); rotation = settings->getDouble(BRUSH_ROTATION) * (M_PI / 180.0); scale = settings->getDouble(BRUSH_SCALE); density = settings->getDouble(BRUSH_DENSITY) * 0.01; spacing = settings->getDouble(BRUSH_SPACING); if ((jitterEnabled = settings->getBool(BRUSH_JITTER_MOVEMENT_ENABLED))) { jitterMovementAmount = settings->getDouble(BRUSH_JITTER_MOVEMENT); } else { jitterMovementAmount = 0.0; } } }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_clipboard_brush_widget.cpp b/krita/plugins/paintops/libpaintop/kis_clipboard_brush_widget.cpp index a65a5afdfb1..1372b6e3b26 100644 --- a/krita/plugins/paintops/libpaintop/kis_clipboard_brush_widget.cpp +++ b/krita/plugins/paintops/libpaintop/kis_clipboard_brush_widget.cpp @@ -1,157 +1,157 @@ /* * Copyright (c) 2005 Bart Coppens * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2013 Somsubhra Bairi * * 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_clipboard_brush_widget.h" #include #include #include #include #include #include #include #include #include "kis_image.h" #include "kis_clipboard.h" #include "kis_paint_device.h" #include "kis_gbr_brush.h" #include "kis_brush_server.h" KisClipboardBrushWidget::KisClipboardBrushWidget(QWidget *parent, const QString &caption, KisImageWSP image) : KisWdgClipboardBrush(parent), m_image(image) { setWindowTitle(caption); preview->setScaledContents(true); preview->setFixedSize(preview->size()); preview->setStyleSheet("border: 2px solid #222; border-radius: 4px; padding: 5px; font: normal 10px;"); KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer(); m_rServerAdapter = QSharedPointer(new KisBrushResourceServerAdapter(rServer)); m_brush = 0; m_clipboard = KisClipboard::instance(); connect(m_clipboard, SIGNAL(clipChanged()), this, SLOT(slotCreateBrush())); connect(colorAsmask, SIGNAL(toggled(bool)), this, SLOT(slotUpdateUseColorAsMask(bool))); connect(buttonBox, SIGNAL(accepted()), this, SLOT(slotAddPredefined())); spacingWidget->setSpacing(true, 1.0); connect(spacingWidget, SIGNAL(sigSpacingChanged()), SLOT(slotSpacingChanged())); } KisClipboardBrushWidget::~KisClipboardBrushWidget() { } void KisClipboardBrushWidget::slotCreateBrush() { // do nothing if it's hidden otherwise it can break the active brush is something is copied if (m_clipboard->hasClip() && !isHidden()) { pd = m_clipboard->clip(QRect(0, 0, 0, 0), false); //Weird! Don't know how this works! if (pd) { QRect rc = pd->exactBounds(); m_brush = new KisGbrBrush(pd, rc.x(), rc.y(), rc.width(), rc.height()); m_brush->setSpacing(spacingWidget->spacing()); m_brush->setAutoSpacing(spacingWidget->autoSpacingActive(), spacingWidget->autoSpacingCoeff()); m_brush->setFilename(TEMPORARY_CLIPBOARD_BRUSH_FILENAME); m_brush->setName(TEMPORARY_CLIPBOARD_BRUSH_NAME); m_brush->setValid(true); preview->setPixmap(QPixmap::fromImage(m_brush->image())); } } else { preview->setText(i18n("Nothing copied\n to Clipboard")); } if(m_brush == 0) { buttonBox->button(QDialogButtonBox::Ok)->setEnabled(false); } else { buttonBox->button(QDialogButtonBox::Ok)->setEnabled(true); } } void KisClipboardBrushWidget::slotSpacingChanged() { if (m_brush) { m_brush->setSpacing(spacingWidget->spacing()); m_brush->setAutoSpacing(spacingWidget->autoSpacingActive(), spacingWidget->autoSpacingCoeff()); } } void KisClipboardBrushWidget::showEvent(QShowEvent *) { slotCreateBrush(); } void KisClipboardBrushWidget::slotUpdateUseColorAsMask(bool useColorAsMask) { if (m_brush) { static_cast(m_brush.data())->setUseColorAsMask(useColorAsMask); - preview->setPixmap(QPixmap::fromImage(m_brush->image())); + preview->setPixmap(QPixmap::fromImage(m_brush->brushTipImage())); } } void KisClipboardBrushWidget::slotAddPredefined() { if(!m_brush) return; QString dir = KGlobal::dirs()->saveLocation("data", "krita/brushes"); QString extension = ".gbr"; QString name = nameEdit->text(); QString tempFileName; QFileInfo fileInfo; fileInfo.setFile(dir + name + extension); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(dir + name + QString("%1").arg(i) + extension); i++; } tempFileName = fileInfo.filePath(); if (m_rServerAdapter) { KisGbrBrush* resource = static_cast(m_brush.data())->clone(); resource->setFilename(tempFileName); if (nameEdit->text().isEmpty()) { resource->setName(QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm")); } else { resource->setName(name); } if (colorAsmask->isChecked()) { resource->makeMaskImage(); } m_rServerAdapter->addResource(resource); emit sigNewPredefinedBrush(resource); } close(); } diff --git a/krita/plugins/paintops/libpaintop/kis_color_option.cpp b/krita/plugins/paintops/libpaintop/kis_color_option.cpp index 6e7cdaf4e38..402f407d68c 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_option.cpp +++ b/krita/plugins/paintops/libpaintop/kis_color_option.cpp @@ -1,164 +1,171 @@ /* * Copyright (c) 2009,2010 Lukáš Tvrdý (lukast.dev@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 "kis_color_option.h" #include #include "ui_wdgcoloroptions.h" class KisColorOptionsWidget: public QWidget, public Ui::WdgColorOptions { public: KisColorOptionsWidget(QWidget *parent = 0) : QWidget(parent) { setupUi(this); hueSlider->setRange(-180, 180); hueSlider->setValue(0); saturationSlider->setRange(-100, 100); saturationSlider->setValue(0); valueSlider->setRange(-100, 100); valueSlider->setValue(0); } }; KisColorOption::KisColorOption() : KisPaintOpOption(KisPaintOpOption::COLOR, false) { m_checkable = false; m_options = new KisColorOptionsWidget(); setObjectName("KisColorOption"); // ui - connect(m_options->randomHSVCHBox, SIGNAL(toggled(bool)), m_options->hsvWidget, SLOT(setEnabled(bool))); + connect(m_options->randomHSVCHBox, SIGNAL(toggled(bool)), SLOT(setEnabled(bool))); // settings connect(m_options->randomOpacityCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_options->randomHSVCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_options->hueSlider, SIGNAL(valueChanged(int)), SLOT(emitSettingChanged())); connect(m_options->saturationSlider, SIGNAL(valueChanged(int)), SLOT(emitSettingChanged())); connect(m_options->valueSlider, SIGNAL(valueChanged(int)), SLOT(emitSettingChanged())); connect(m_options->sampleInputCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_options->colorPerParticleCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_options->fillBackgroundCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_options->mixBgColorCHBox, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); setConfigurationPage(m_options); } KisColorOption::~KisColorOption() { // delete m_options; } void KisColorOption::writeOptionSetting(KisPropertiesConfiguration* setting) const { setting->setProperty(COLOROP_HUE, hue()); setting->setProperty(COLOROP_SATURATION, saturation()); setting->setProperty(COLOROP_VALUE, value()); setting->setProperty(COLOROP_USE_RANDOM_HSV, useRandomHSV()); setting->setProperty(COLOROP_USE_RANDOM_OPACITY, useRandomOpacity()); setting->setProperty(COLOROP_SAMPLE_COLOR, sampleInputColor()); setting->setProperty(COLOROP_FILL_BG, fillBackground()); setting->setProperty(COLOROP_COLOR_PER_PARTICLE, colorPerParticle()); setting->setProperty(COLOROP_MIX_BG_COLOR, mixBgColor()); } void KisColorOption::readOptionSetting(const KisPropertiesConfiguration* setting) { m_options->hueSlider->setValue(setting->getInt(COLOROP_HUE)); m_options->saturationSlider->setValue(setting->getInt(COLOROP_SATURATION)); m_options->valueSlider->setValue(setting->getInt(COLOROP_VALUE)); m_options->randomOpacityCHBox->setChecked(setting->getBool(COLOROP_USE_RANDOM_OPACITY)); m_options->randomHSVCHBox->setChecked(setting->getBool(COLOROP_USE_RANDOM_HSV)); + setEnabled(setting->getBool(COLOROP_USE_RANDOM_HSV)); m_options->sampleInputCHBox->setChecked(setting->getBool(COLOROP_SAMPLE_COLOR)); m_options->fillBackgroundCHBox->setChecked(setting->getBool(COLOROP_FILL_BG)); m_options->colorPerParticleCHBox->setChecked(setting->getBool(COLOROP_COLOR_PER_PARTICLE)); m_options->mixBgColorCHBox->setChecked(setting->getBool(COLOROP_MIX_BG_COLOR)); } +void KisColorOption::setEnabled(bool enabled) +{ + m_options->hueSlider->setEnabled(!enabled); + m_options->saturationSlider->setEnabled(!enabled); + m_options->valueSlider->setEnabled(!enabled); +} bool KisColorOption::useRandomOpacity() const { return m_options->randomOpacityCHBox->isChecked(); } bool KisColorOption::useRandomHSV() const { return m_options->randomHSVCHBox->isChecked(); } int KisColorOption::hue() const { return m_options->hueSlider->value(); } int KisColorOption::saturation() const { return m_options->saturationSlider->value(); } int KisColorOption::value() const { return m_options->valueSlider->value(); } bool KisColorOption::sampleInputColor() const { return m_options->sampleInputCHBox->isChecked(); } bool KisColorOption::colorPerParticle() const { return m_options->colorPerParticleCHBox->isChecked(); } bool KisColorOption::fillBackground() const { return m_options->fillBackgroundCHBox->isChecked(); } bool KisColorOption::mixBgColor() const { return m_options->mixBgColorCHBox->isChecked(); } void KisColorProperties::fillProperties(const KisPropertiesConfiguration* setting) { hue = setting->getInt(COLOROP_HUE); saturation = setting->getInt(COLOROP_SATURATION); value = setting->getInt(COLOROP_VALUE); useRandomOpacity = setting->getBool(COLOROP_USE_RANDOM_OPACITY); useRandomHSV = setting->getBool(COLOROP_USE_RANDOM_HSV); sampleInputColor = setting->getBool(COLOROP_SAMPLE_COLOR); fillBackground = setting->getBool(COLOROP_FILL_BG); colorPerParticle = setting->getBool(COLOROP_COLOR_PER_PARTICLE); mixBgColor = setting->getBool(COLOROP_MIX_BG_COLOR); } diff --git a/krita/plugins/paintops/libpaintop/kis_color_option.h b/krita/plugins/paintops/libpaintop/kis_color_option.h index f87edef53d0..b3b6dd807e7 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_option.h +++ b/krita/plugins/paintops/libpaintop/kis_color_option.h @@ -1,84 +1,92 @@ /* * Copyright (c) 2009,2010 Lukáš Tvrdý (lukast.dev@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_COLOR_OPTION_H #define KIS_COLOR_OPTION_H #include -#include +#include const QString COLOROP_HUE = "ColorOption/hue"; const QString COLOROP_SATURATION = "ColorOption/saturation"; const QString COLOROP_VALUE = "ColorOption/value"; const QString COLOROP_USE_RANDOM_HSV = "ColorOption/useRandomHSV"; const QString COLOROP_USE_RANDOM_OPACITY = "ColorOption/useRandomOpacity"; const QString COLOROP_SAMPLE_COLOR = "ColorOption/sampleInputColor"; const QString COLOROP_FILL_BG = "ColorOption/fillBackground"; const QString COLOROP_COLOR_PER_PARTICLE = "ColorOption/colorPerParticle"; const QString COLOROP_MIX_BG_COLOR = "ColorOption/mixBgColor"; class KisColorOptionsWidget; class PAINTOP_EXPORT KisColorOption : public KisPaintOpOption { + Q_OBJECT public: KisColorOption(); ~KisColorOption(); bool useRandomHSV() const; bool useRandomOpacity() const; bool sampleInputColor() const; bool fillBackground() const; bool colorPerParticle() const; bool mixBgColor() const; // TODO: these should be intervals like 20..180 int hue() const; int saturation() const; int value() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); + +private Q_SLOTS: + + void setEnabled(bool); + private: + + KisColorOptionsWidget * m_options; }; class PAINTOP_EXPORT KisColorProperties { public: bool useRandomHSV; bool useRandomOpacity; bool sampleInputColor; bool fillBackground; bool colorPerParticle; bool mixBgColor; int hue; int saturation; int value; public: /// fill the class members with related properties void fillProperties(const KisPropertiesConfiguration* setting); }; #endif // KIS_COLOR_OPTION_H diff --git a/krita/plugins/paintops/libpaintop/kis_color_source.h b/krita/plugins/paintops/libpaintop/kis_color_source.h index 340432256c0..8f2e90b8ef5 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_source.h +++ b/krita/plugins/paintops/libpaintop/kis_color_source.h @@ -1,150 +1,151 @@ /* * Copyright (c) 2006-2007, 2009 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_DYNAMIC_COLORING_H_ #define _KIS_DYNAMIC_COLORING_H_ #include "kis_paintop_option.h" #include #include #include +#include class KoAbstractGradient; class KoColorTransformation; /** * A color source allow to abstract how a brush is colorized, * and to apply transformation. * * The first function to call is @ref selectColor , then any of the transformation. */ class PAINTOP_EXPORT KisColorSource { public: virtual ~KisColorSource(); public: /** * This is function is called to initialize the color that will be used for the dab. * @param mix is a parameter between 0.0 and 1.0 */ virtual void selectColor(double mix) = 0; /** * Apply a color transformation on the selected color */ virtual void applyColorTransformation(const KoColorTransformation* transfo) = 0; virtual const KoColorSpace* colorSpace() const = 0; /** * Apply the color on a paint device */ virtual void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& _offset) const = 0; /** * @return true if the color is an uniform color */ virtual bool isUniformColor() const = 0; /** * @return the color if the color is uniformed */ virtual const KoColor& uniformColor() const; }; class PAINTOP_EXPORT KisUniformColorSource : public KisColorSource { public: KisUniformColorSource(); virtual ~KisUniformColorSource(); virtual void rotate(double); virtual void resize(double , double); virtual void applyColorTransformation(const KoColorTransformation* transfo); virtual const KoColorSpace* colorSpace() const; virtual void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& offset) const; virtual bool isUniformColor() const; virtual const KoColor& uniformColor() const; protected: KoColor* m_color; private: mutable KoColor* m_cachedColor; }; class PAINTOP_EXPORT KisPlainColorSource : public KisUniformColorSource { public: KisPlainColorSource(const KoColor& backGroundColor, const KoColor& foreGroundColor); virtual ~KisPlainColorSource(); virtual void selectColor(double mix); private: KoColor m_backGroundColor, m_foreGroundColor; KoColor* m_cachedBackGroundColor; }; class PAINTOP_EXPORT KisGradientColorSource : public KisUniformColorSource { public: KisGradientColorSource(const KoAbstractGradient* gradient, const KoColorSpace* workingCS); virtual ~KisGradientColorSource(); virtual void selectColor(double mix); private: const KoAbstractGradient* m_gradient; }; class PAINTOP_EXPORT KisUniformRandomColorSource : public KisUniformColorSource { public: KisUniformRandomColorSource(); virtual ~KisUniformRandomColorSource(); virtual void selectColor(double mix); }; class PAINTOP_EXPORT KisTotalRandomColorSource : public KisColorSource { public: KisTotalRandomColorSource(); virtual ~KisTotalRandomColorSource(); public: virtual void selectColor(double mix); virtual void applyColorTransformation(const KoColorTransformation* transfo); virtual const KoColorSpace* colorSpace() const; virtual void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& offset) const; virtual void rotate(double r); virtual void resize(double xs, double ys); virtual bool isUniformColor() const; private: const KoColorSpace* m_colorSpace; }; class PAINTOP_EXPORT KoPatternColorSource : public KisColorSource { public: KoPatternColorSource(KisPaintDeviceSP _pattern, int _width, int _height, bool _locked); virtual ~KoPatternColorSource(); public: virtual void selectColor(double mix); virtual void applyColorTransformation(const KoColorTransformation* transfo); virtual const KoColorSpace* colorSpace() const; virtual void colorize(KisPaintDeviceSP, const QRect& rect, const QPoint& _offset) const; virtual void rotate(double r); virtual void resize(double xs, double ys); virtual bool isUniformColor() const; private: const KisPaintDeviceSP m_device; QRect m_bounds; bool m_locked; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_color_source_option.cpp b/krita/plugins/paintops/libpaintop/kis_color_source_option.cpp index a740bc8f8d5..d50eac5dbf4 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_source_option.cpp +++ b/krita/plugins/paintops/libpaintop/kis_color_source_option.cpp @@ -1,125 +1,129 @@ /* * Copyright (c) 2011 Cyrille Berger * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_color_source_option.h" #include #include #include #include "kis_color_source.h" #include #include #include struct KisColorSourceOption::Private { Private() : type(PLAIN) {} KisColorSourceOption::Type type; static QMap type2id; static QMap id2type; static void addType(KisColorSourceOption::Type _type, KoID _id); }; QMap KisColorSourceOption::Private::type2id; QMap KisColorSourceOption::Private::id2type; void KisColorSourceOption::Private::addType(KisColorSourceOption::Type _type, KoID _id) { type2id[_type] = _id; id2type[_id.id()] = _type; } KisColorSourceOption::KisColorSourceOption() : d(new Private) { if (Private::type2id.isEmpty()) { Private::addType(PLAIN, KoID("plain", i18n("Plain color"))); Private::addType(GRADIENT, KoID("gradient", i18n("Gradient"))); Private::addType(UNIFORM_RANDOM, KoID("uniform_random", i18n("Uniform random"))); Private::addType(TOTAL_RANDOM, KoID("total_random", i18n("Total random"))); Private::addType(PATTERN, KoID("pattern", i18n("Pattern"))); Private::addType(PATTERN_LOCKED, KoID("lockedpattern", i18n("Locked pattern"))); } } KisColorSourceOption::~KisColorSourceOption() { delete d; } void KisColorSourceOption::writeOptionSetting(KisPropertiesConfiguration* setting) const { setting->setProperty("ColorSource/Type", Private::type2id.value(d->type).id()); } void KisColorSourceOption::readOptionSetting(const KisPropertiesConfiguration* setting) { QString colorSourceType = setting->getString("ColorSource/Type", "plain"); d->type = Private::id2type.value(colorSourceType, PLAIN); } KisColorSource* KisColorSourceOption::createColorSource(const KisPainter* _painter) const { switch (d->type) { case PLAIN: return new KisPlainColorSource(_painter->backgroundColor(), _painter->paintColor()); case GRADIENT: return new KisGradientColorSource(_painter->gradient(), _painter->paintColor().colorSpace()); case UNIFORM_RANDOM: return new KisUniformRandomColorSource(); case TOTAL_RANDOM: return new KisTotalRandomColorSource(); case PATTERN: { - KisPaintDevice* dev = new KisPaintDevice(_painter->paintColor().colorSpace(), _painter->pattern()->name()); - dev->convertFromQImage(_painter->pattern()->pattern(), 0); - return new KoPatternColorSource(dev, _painter->pattern()->width(), _painter->pattern()->height(), false); + if (_painter && _painter->pattern()) { + KisPaintDevice* dev = new KisPaintDevice(_painter->paintColor().colorSpace(), _painter->pattern()->name()); + dev->convertFromQImage(_painter->pattern()->pattern(), 0); + return new KoPatternColorSource(dev, _painter->pattern()->width(), _painter->pattern()->height(), false); + } } case PATTERN_LOCKED: { - KisPaintDevice* dev = new KisPaintDevice(_painter->paintColor().colorSpace(), _painter->pattern()->name()); - dev->convertFromQImage(_painter->pattern()->pattern(), 0); - return new KoPatternColorSource(dev, _painter->pattern()->width(), _painter->pattern()->height(), true); + if (_painter && _painter->pattern()) { + KisPaintDevice* dev = new KisPaintDevice(_painter->paintColor().colorSpace(), _painter->pattern()->name()); + dev->convertFromQImage(_painter->pattern()->pattern(), 0); + return new KoPatternColorSource(dev, _painter->pattern()->width(), _painter->pattern()->height(), true); + } } } - qFatal("Unknown color source"); - return 0; + // Fallback in case the patterns are messed up + return new KisPlainColorSource(_painter->backgroundColor(), _painter->paintColor()); } QString KisColorSourceOption::colorSourceTypeId() const { return Private::type2id.value(d->type).id(); } void KisColorSourceOption::setColorSourceType(Type _type) { d->type = _type; } void KisColorSourceOption::setColorSourceType(const QString& _id) { d->type = Private::id2type[_id]; } QList KisColorSourceOption::sourceIds() { return Private::type2id.values(); } diff --git a/krita/plugins/paintops/libpaintop/kis_color_source_option.h b/krita/plugins/paintops/libpaintop/kis_color_source_option.h index b689a14f44c..8ab12b8328b 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_source_option.h +++ b/krita/plugins/paintops/libpaintop/kis_color_source_option.h @@ -1,59 +1,59 @@ /* This file is part of the Calligra project * Copyright (C) 2008 Thomas Zander * * 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_COLOR_SOURCE_OPTION_H #define _KIS_COLOR_SOURCE_OPTION_H -#include +#include #include class KisColorSource; class KisPropertiesConfiguration; class KoID; class KisPainter; class PAINTOP_EXPORT KisColorSourceOption { public: enum Type { PLAIN, GRADIENT, UNIFORM_RANDOM, TOTAL_RANDOM, PATTERN, PATTERN_LOCKED }; public: KisColorSourceOption(); ~KisColorSourceOption(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); KisColorSource* createColorSource(const KisPainter* _painter) const; QString colorSourceTypeId() const; void setColorSourceType(Type _type); void setColorSourceType(const QString& _type); static QList sourceIds(); private: struct Private; Private* const d; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_color_source_option_widget.h b/krita/plugins/paintops/libpaintop/kis_color_source_option_widget.h index 3c3f07c2376..9575b660fc1 100644 --- a/krita/plugins/paintops/libpaintop/kis_color_source_option_widget.h +++ b/krita/plugins/paintops/libpaintop/kis_color_source_option_widget.h @@ -1,45 +1,46 @@ /* * Copyright (c) 2011 Cyrille Berger * * 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_COLOR_SOURCE_OPTION_WIDGET_H #define KIS_COLOR_SOURCE_OPTION_WIDGET_H #include "kis_paintop_option.h" +#include /** * The brush option allows the user to select a particular brush * footprint for suitable paintops */ class PAINTOP_EXPORT KisColorSourceOptionWidget : public KisPaintOpOption { Q_OBJECT public: KisColorSourceOptionWidget(); ~KisColorSourceOptionWidget(); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private Q_SLOTS: void sourceChanged(); private: struct Private; Private* const d; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_compositeop_option.h b/krita/plugins/paintops/libpaintop/kis_compositeop_option.h index 4c21cc67dde..27e7989f728 100644 --- a/krita/plugins/paintops/libpaintop/kis_compositeop_option.h +++ b/krita/plugins/paintops/libpaintop/kis_compositeop_option.h @@ -1,62 +1,62 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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_COMPOSITEOP_OPTION_H #define KIS_COMPOSITEOP_OPTION_H #include -#include +#include #include // const QString AIRBRUSH_ENABLED = "AirbrushOption/isAirbrushing"; // const QString AIRBRUSH_RATE = "AirbrushOption/rate"; class QLabel; class QModelIndex; class QPushButton; class KisCompositeOpListWidget; class KoID; class PAINTOP_EXPORT KisCompositeOpOption: public KisPaintOpOption { Q_OBJECT public: KisCompositeOpOption(bool createConfigWidget = false); ~KisCompositeOpOption(); virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); private Q_SLOTS: void slotCompositeOpChanged(const QModelIndex& index); void slotEraserToggled(bool toggled); private: void changeCompositeOp(const KoID& compositeOp); private: QLabel* m_label; QPushButton* m_bnEraser; KisCompositeOpListWidget* m_list; QString m_prevCompositeOpID; QString m_currCompositeOpID; bool m_createConfigWidget; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_current_outline_fetcher.h b/krita/plugins/paintops/libpaintop/kis_current_outline_fetcher.h index b9a7e17e79b..810a92720f2 100644 --- a/krita/plugins/paintops/libpaintop/kis_current_outline_fetcher.h +++ b/krita/plugins/paintops/libpaintop/kis_current_outline_fetcher.h @@ -1,65 +1,65 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CURRENT_OUTLINE_FETCHER_H #define __KIS_CURRENT_OUTLINE_FETCHER_H -#include +#include #include #include #include #include class KisPaintInformation; class KisPaintOpSettings; class PAINTOP_EXPORT KisCurrentOutlineFetcher { public: enum Option { NO_OPTION, SIZE_OPTION, ROTATION_OPTION, MIRROR_OPTION }; Q_DECLARE_FLAGS(Options, Option); public: KisCurrentOutlineFetcher(Options optionsAvailable); ~KisCurrentOutlineFetcher(); void setDirty(); QPainterPath fetchOutline(const KisPaintInformation &info, const KisPaintOpSettings *settings, const QPainterPath &originalOutline, qreal additionalScale = 1.0, qreal additionalRotation = 0.0, bool tilt = false, qreal tiltcenterx = 1.0, qreal tiltcentery = 1.0) const; private: struct Private; const QScopedPointer d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KisCurrentOutlineFetcher::Options); #endif /* __KIS_CURRENT_OUTLINE_FETCHER_H */ diff --git a/krita/plugins/paintops/libpaintop/kis_curve_label.h b/krita/plugins/paintops/libpaintop/kis_curve_label.h index 0dca8ce9bec..97168acbb80 100644 --- a/krita/plugins/paintops/libpaintop/kis_curve_label.h +++ b/krita/plugins/paintops/libpaintop/kis_curve_label.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2010 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_CURVE_LABEL_H_ #define _KIS_CURVE_LABEL_H_ -#include +#include class QString; class QImage; struct PAINTOP_EXPORT KisCurveLabel { public: KisCurveLabel(); KisCurveLabel(const QString&); KisCurveLabel(const QImage&); KisCurveLabel(const KisCurveLabel&); KisCurveLabel& operator=(const KisCurveLabel&); ~KisCurveLabel(); QString name() const; QImage icon() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_curve_option.h b/krita/plugins/paintops/libpaintop/kis_curve_option.h index 10c1bc9dac7..91519c56009 100644 --- a/krita/plugins/paintops/libpaintop/kis_curve_option.h +++ b/krita/plugins/paintops/libpaintop/kis_curve_option.h @@ -1,117 +1,117 @@ /* This file is part of the KDE project * Copyright (C) 2008 Boudewijn Rempt * Copyright (C) 2011 Silvio Heinrich * * 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_CURVE_OPTION_H #define KIS_CURVE_OPTION_H #include #include #include "kis_paintop_option.h" #include "kis_global.h" #include "kis_paintop_option.h" #include "kis_paint_information.h" -#include "krita_export.h" +#include "kritapaintop_export.h" #include "kis_dynamic_sensor.h" class KisDynamicSensor; /** * KisCurveOption is the base class for paintop options that are * defined through one or more curves. * * Note: it is NOT a KisPaintOpOption, even though the API is pretty similar! * */ class PAINTOP_EXPORT KisCurveOption { public: KisCurveOption(const QString& name, KisPaintOpOption::PaintopCategory category, bool checked, qreal value = 1.0, qreal min = 0.0, qreal max = 1.0); virtual ~KisCurveOption(); virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); const QString& name() const; KisPaintOpOption::PaintopCategory category() const; qreal minValue() const; qreal maxValue() const; qreal value() const; void resetAllSensors(); KisDynamicSensorSP sensor(DynamicSensorType sensorType, bool active) const; void replaceSensor(KisDynamicSensorSP sensor); QList sensors(); QList activeSensors() const; bool isCheckable(); bool isChecked() const; bool isCurveUsed() const; bool isSameCurveUsed() const; bool isRandom() const; void setSeparateCurveValue(bool separateCurveValue); void setChecked(bool checked); void setCurveUsed(bool useCurve); void setCurve(DynamicSensorType sensorType, bool useSameCurve, const KisCubicCurve &curve); void setValue(qreal value); /** * Uses the curves set on the sensors to compute a single * double value that can control the parameters of a brush. */ double computeValue(const KisPaintInformation& info) const; protected: void setValueRange(qreal min, qreal max); /** * Read the option using the prefix in argument */ void readNamedOptionSetting(const QString& prefix, const KisPropertiesConfiguration* setting); QString m_name; KisPaintOpOption::PaintopCategory m_category; bool m_checkable; bool m_checked; bool m_useCurve; bool m_useSameCurve; bool m_separateCurveValue; QMap m_sensorMap; QMap m_curveCache; private: qreal m_value; qreal m_minValue; qreal m_maxValue; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp b/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp index 793ed3d3fb7..65d1d96cdaa 100644 --- a/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp +++ b/krita/plugins/paintops/libpaintop/kis_custom_brush_widget.cpp @@ -1,253 +1,253 @@ /* * Copyright (c) 2005 Bart Coppens * Copyright (c) 2010 Lukáš Tvrdý * * 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_custom_brush_widget.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_image.h" #include "kis_layer.h" #include "kis_paint_device.h" #include "kis_gbr_brush.h" #include "kis_imagepipe_brush.h" #include #include "kis_brush_server.h" #include "kis_paint_layer.h" #include "kis_group_layer.h" #include #include #include "kis_iterator_ng.h" KisCustomBrushWidget::KisCustomBrushWidget(QWidget *parent, const QString& caption, KisImageWSP image) : KisWdgCustomBrush(parent) , m_image(image) { setWindowTitle(caption); preview->setScaledContents(true); preview->setFixedSize(preview->size()); preview->setStyleSheet("border: 2px solid #222; border-radius: 4px; padding: 5px; font: normal 10px;"); KisBrushResourceServer* rServer = KisBrushServer::instance()->brushServer(); m_rServerAdapter = QSharedPointer(new KisBrushResourceServerAdapter(rServer)); m_brush = 0; connect(this, SIGNAL(accepted()), SLOT(slotAddPredefined())); connect(brushStyle, SIGNAL(activated(int)), this, SLOT(slotUpdateCurrentBrush(int))); connect(colorAsMask, SIGNAL(toggled(bool)), this, SLOT(slotUpdateUseColorAsMask(bool))); spacingWidget->setSpacing(true, 1.0); connect(spacingWidget, SIGNAL(sigSpacingChanged()), SLOT(slotSpacingChanged())); } KisCustomBrushWidget::~KisCustomBrushWidget() { } KisBrushSP KisCustomBrushWidget::brush() { return m_brush; } void KisCustomBrushWidget::showEvent(QShowEvent *) { slotUpdateCurrentBrush(0); } void KisCustomBrushWidget::slotUpdateCurrentBrush(int) { if (brushStyle->currentIndex() == 0) { comboBox2->setEnabled(false); } else { comboBox2->setEnabled(true); } if (m_image) { createBrush(); if (m_brush) { - preview->setPixmap(QPixmap::fromImage(m_brush->image())); + preview->setPixmap(QPixmap::fromImage(m_brush->brushTipImage())); } } } void KisCustomBrushWidget::slotSpacingChanged() { if (m_brush) { m_brush->setSpacing(spacingWidget->spacing()); m_brush->setAutoSpacing(spacingWidget->autoSpacingActive(), spacingWidget->autoSpacingCoeff()); } } void KisCustomBrushWidget::slotUpdateUseColorAsMask(bool useColorAsMask) { if (m_brush) { static_cast(m_brush.data())->setUseColorAsMask(useColorAsMask); - preview->setPixmap(QPixmap::fromImage(m_brush->image())); + preview->setPixmap(QPixmap::fromImage(m_brush->brushTipImage())); } } void KisCustomBrushWidget::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 (brushStyle->currentIndex() == 0) { extension = ".gbr"; } else { extension = ".gih"; } QString name = nameLineEdit->text(); QString tempFileName; { QFileInfo fileInfo; fileInfo.setFile(dir + name + extension); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(dir + name + QString("%1").arg(i) + extension); i++; } tempFileName = fileInfo.filePath(); } // 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_rServerAdapter) { KisGbrBrush * resource = static_cast(m_brush.data())->clone(); resource->setFilename(tempFileName); if (nameLineEdit->text().isEmpty()) { resource->setName(QDateTime::currentDateTime().toString("yyyy-MM-ddThh:mm")); } else { resource->setName(name); } if (colorAsMask->isChecked()) { resource->makeMaskImage(); } m_rServerAdapter->addResource(resource); emit sigNewPredefinedBrush(resource); } close(); } void KisCustomBrushWidget::createBrush() { if (!m_image) return; if (brushStyle->currentIndex() == 0) { KisSelectionSP selection = m_image->globalSelection(); // create copy of the data m_image->lock(); KisPaintDeviceSP dev = new KisPaintDevice(*m_image->projection()); m_image->unlock(); if (!selection) { m_brush = new KisGbrBrush(dev, 0, 0, m_image->width(), m_image->height()); } else { // apply selection mask QRect r = selection->selectedExactRect(); dev->crop(r); KisHLineIteratorSP pixelIt = dev->createHLineIteratorNG(r.x(), r.top(), r.width()); KisHLineConstIteratorSP maskIt = selection->projection()->createHLineIteratorNG(r.x(), r.top(), r.width()); for (qint32 y = r.top(); y <= r.bottom(); ++y) { do { dev->colorSpace()->applyAlphaU8Mask(pixelIt->rawData(), maskIt->oldRawData(), 1); } while (pixelIt->nextPixel() && maskIt->nextPixel()); pixelIt->nextRow(); maskIt->nextRow(); } QRect rc = dev->exactBounds(); m_brush = new KisGbrBrush(dev, rc.x(), rc.y(), rc.width(), rc.height()); } } else { // For each layer in the current image, create a new image, and add it to the list QVector< QVector > devices; devices.push_back(QVector()); int w = m_image->width(); int h = m_image->height(); m_image->lock(); // We only loop over the rootLayer. Since we actually should have a layer selection // list, no need to elaborate on that here and now KoProperties properties; properties.setProperty("visible", true); QList layers = m_image->root()->childNodes(QStringList("KisLayer"), properties); KisNodeSP node; foreach(KisNodeSP node, layers) { devices[0].push_back(node->projection().data()); } QVector modes; switch (comboBox2->currentIndex()) { case 0: modes.push_back(KisParasite::Constant); break; case 1: modes.push_back(KisParasite::Random); break; case 2: modes.push_back(KisParasite::Incremental); break; case 3: modes.push_back(KisParasite::Pressure); break; case 4: modes.push_back(KisParasite::Angular); break; default: modes.push_back(KisParasite::Incremental); } m_brush = new KisImagePipeBrush(m_image->objectName(), w, h, devices, modes); m_image->unlock(); } static_cast(m_brush.data())->setUseColorAsMask(colorAsMask->isChecked()); m_brush->setSpacing(spacingWidget->spacing()); m_brush->setAutoSpacing(spacingWidget->autoSpacingActive(), spacingWidget->autoSpacingCoeff()); m_brush->setFilename(TEMPORARY_FILENAME); m_brush->setName(TEMPORARY_BRUSH_NAME); m_brush->setValid(true); } #include "kis_custom_brush_widget.moc" diff --git a/krita/plugins/paintops/libpaintop/kis_dab_cache.cpp b/krita/plugins/paintops/libpaintop/kis_dab_cache.cpp index 628e9a0cda7..ee31c71779a 100644 --- a/krita/plugins/paintops/libpaintop/kis_dab_cache.cpp +++ b/krita/plugins/paintops/libpaintop/kis_dab_cache.cpp @@ -1,420 +1,420 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dab_cache.h" #include #include "kis_color_source.h" #include "kis_paint_device.h" #include "kis_brush.h" #include #include #include #include #include #include #include struct PrecisionValues { qreal angle; qreal sizeFrac; qreal subPixel; qreal softnessFactor; }; const qreal eps = 1e-6; static const PrecisionValues precisionLevels[] = { {M_PI / 180, 0.05, 1, 0.01}, {M_PI / 180, 0.01, 1, 0.01}, {M_PI / 180, 0, 1, 0.01}, {M_PI / 180, 0, 0.5, 0.01}, {eps, 0, eps, eps} }; struct KisDabCache::SavedDabParameters { KoColor color; qreal angle; int width; int height; qreal subPixelX; qreal subPixelY; qreal softnessFactor; int index; MirrorProperties mirrorProperties; bool compare(const SavedDabParameters &rhs, int precisionLevel) const { const PrecisionValues &prec = precisionLevels[precisionLevel]; return color == rhs.color && qAbs(angle - rhs.angle) <= prec.angle && qAbs(width - rhs.width) <= (int)(prec.sizeFrac * width) && qAbs(height - rhs.height) <= (int)(prec.sizeFrac * height) && qAbs(subPixelX - rhs.subPixelX) <= prec.subPixel && qAbs(subPixelY - rhs.subPixelY) <= prec.subPixel && qAbs(softnessFactor - rhs.softnessFactor) <= prec.softnessFactor && index == rhs.index && mirrorProperties.horizontalMirror == rhs.mirrorProperties.horizontalMirror && mirrorProperties.verticalMirror == rhs.mirrorProperties.verticalMirror; } }; struct KisDabCache::Private { Private(KisBrushSP brush) : brush(brush), mirrorOption(0), sharpnessOption(0), textureOption(0), precisionOption(0), subPixelPrecisionDisabled(false), cachedDabParameters(new SavedDabParameters) {} KisFixedPaintDeviceSP dab; KisFixedPaintDeviceSP dabOriginal; KisBrushSP brush; KisPaintDeviceSP colorSourceDevice; KisPressureMirrorOption *mirrorOption; KisPressureSharpnessOption *sharpnessOption; KisTextureProperties *textureOption; KisPrecisionOption *precisionOption; bool subPixelPrecisionDisabled; SavedDabParameters *cachedDabParameters; }; KisDabCache::KisDabCache(KisBrushSP brush) : m_d(new Private(brush)) { } KisDabCache::~KisDabCache() { delete m_d->cachedDabParameters; delete m_d; } void KisDabCache::setMirrorPostprocessing(KisPressureMirrorOption *option) { m_d->mirrorOption = option; } void KisDabCache::setSharpnessPostprocessing(KisPressureSharpnessOption *option) { m_d->sharpnessOption = option; } void KisDabCache::setTexturePostprocessing(KisTextureProperties *option) { m_d->textureOption = option; } void KisDabCache::setPrecisionOption(KisPrecisionOption *option) { m_d->precisionOption = option; } void KisDabCache::disableSubpixelPrecision() { m_d->subPixelPrecisionDisabled = true; } inline KisDabCache::SavedDabParameters KisDabCache::getDabParameters(const KoColor& color, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY, qreal softnessFactor, MirrorProperties mirrorProperties) { SavedDabParameters params; params.color = color; params.angle = angle; params.width = m_d->brush->maskWidth(scaleX, angle, subPixelX, subPixelY, info); params.height = m_d->brush->maskHeight(scaleY, angle, subPixelX, subPixelY, info); params.subPixelX = subPixelX; params.subPixelY = subPixelY; params.softnessFactor = softnessFactor; params.index = m_d->brush->brushIndex(info); params.mirrorProperties = mirrorProperties; return params; } KisFixedPaintDeviceSP KisDabCache::fetchDab(const KoColorSpace *cs, const KisColorSource *colorSource, const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect) { return fetchDabCommon(cs, colorSource, KoColor(), cursorPoint, scaleX, scaleY, angle, info, softnessFactor, dstDabRect); } KisFixedPaintDeviceSP KisDabCache::fetchDab(const KoColorSpace *cs, const KoColor& color, const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect) { return fetchDabCommon(cs, 0, color, cursorPoint, scaleX, scaleY, angle, info, softnessFactor, dstDabRect); } bool KisDabCache::needSeparateOriginal() { - return (m_d->textureOption && m_d->textureOption->enabled) || + return (m_d->textureOption && m_d->textureOption->m_enabled) || (m_d->sharpnessOption && m_d->sharpnessOption->isChecked()); } struct KisDabCache::DabPosition { DabPosition(const QRect &_rect, const QPointF &_subPixel, qreal _realAngle) : rect(_rect), subPixel(_subPixel), realAngle(_realAngle) { } QRect rect; QPointF subPixel; qreal realAngle; }; inline QRect KisDabCache::correctDabRectWhenFetchedFromCache(const QRect &dabRect, const QSize &realDabSize) { int diffX = (realDabSize.width() - dabRect.width()) / 2; int diffY = (realDabSize.height() - dabRect.height()) / 2; return QRect(dabRect.x() - diffX, dabRect.y() - diffY, realDabSize.width() , realDabSize.height()); } inline KisFixedPaintDeviceSP KisDabCache::tryFetchFromCache(const SavedDabParameters ¶ms, const KisPaintInformation& info, QRect *dstDabRect) { int precisionLevel = m_d->precisionOption ? m_d->precisionOption->precisionLevel() - 1 : 3; if (!params.compare(*m_d->cachedDabParameters, precisionLevel)) { return 0; } if (needSeparateOriginal()) { *m_d->dab = *m_d->dabOriginal; *dstDabRect = correctDabRectWhenFetchedFromCache(*dstDabRect, m_d->dab->bounds().size()); postProcessDab(m_d->dab, dstDabRect->topLeft(), info); } else { *dstDabRect = correctDabRectWhenFetchedFromCache(*dstDabRect, m_d->dab->bounds().size()); } m_d->brush->notifyCachedDabPainted(); return m_d->dab; } qreal positiveFraction(qreal x) { qint32 unused = 0; qreal fraction = 0.0; KisPaintOp::splitCoordinate(x, &unused, &fraction); return fraction; } inline KisDabCache::DabPosition KisDabCache::calculateDabRect(const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, const MirrorProperties &mirrorProperties) { qint32 x = 0, y = 0; qreal subPixelX = 0.0, subPixelY = 0.0; if (mirrorProperties.coordinateSystemFlipped) { angle = 2 * M_PI - angle; } QPointF hotSpot = m_d->brush->hotSpot(scaleX, scaleY, angle, info); QPointF pt = cursorPoint - hotSpot; if (m_d->sharpnessOption) { m_d->sharpnessOption->apply(info, pt, x, y, subPixelX, subPixelY); } else { KisPaintOp::splitCoordinate(pt.x(), &x, &subPixelX); KisPaintOp::splitCoordinate(pt.y(), &y, &subPixelY); } if (m_d->subPixelPrecisionDisabled) { subPixelX = 0; subPixelY = 0; } int width = m_d->brush->maskWidth(scaleX, angle, subPixelX, subPixelY, info); int height = m_d->brush->maskHeight(scaleY, angle, subPixelX, subPixelY, info); if (mirrorProperties.horizontalMirror) { subPixelX = positiveFraction(-(cursorPoint.x() + hotSpot.x())); width = m_d->brush->maskWidth(scaleX, angle, subPixelX, subPixelY, info); x = qRound(cursorPoint.x() + subPixelX + hotSpot.x()) - width; } if (mirrorProperties.verticalMirror) { subPixelY = positiveFraction(-(cursorPoint.y() + hotSpot.y())); height = m_d->brush->maskHeight(scaleY, angle, subPixelX, subPixelY, info); y = qRound(cursorPoint.y() + subPixelY + hotSpot.y()) - height; } return DabPosition(QRect(x, y, width, height), QPointF(subPixelX, subPixelY), angle); } inline KisFixedPaintDeviceSP KisDabCache::fetchDabCommon(const KoColorSpace *cs, const KisColorSource *colorSource, const KoColor& color, const QPointF &cursorPoint, double scaleX, double scaleY, double initialAngle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect) { Q_ASSERT(dstDabRect); MirrorProperties mirrorProperties; if (m_d->mirrorOption) { mirrorProperties = m_d->mirrorOption->apply(info); } DabPosition position = calculateDabRect(cursorPoint, scaleX, scaleY, initialAngle, info, mirrorProperties); *dstDabRect = position.rect; bool cachingIsPossible = !colorSource || colorSource->isUniformColor(); KoColor paintColor = colorSource && colorSource->isUniformColor() ? colorSource->uniformColor() : color; SavedDabParameters newParams = getDabParameters(paintColor, scaleX, scaleY, position.realAngle, info, position.subPixel.x(), position.subPixel.y(), softnessFactor, mirrorProperties); if (!m_d->dab || !(*m_d->dab->colorSpace() == *cs)) { m_d->dab = new KisFixedPaintDevice(cs); } else if (cachingIsPossible) { KisFixedPaintDeviceSP cachedDab = tryFetchFromCache(newParams, info, dstDabRect); if (cachedDab) return cachedDab; } if (m_d->brush->brushType() == IMAGE || m_d->brush->brushType() == PIPE_IMAGE) { m_d->dab = m_d->brush->paintDevice(cs, scaleX, position.realAngle, info, position.subPixel.x(), position.subPixel.y()); } else if (cachingIsPossible) { *m_d->cachedDabParameters = newParams; m_d->brush->mask(m_d->dab, paintColor, scaleX, scaleY, position.realAngle, info, position.subPixel.x(), position.subPixel.y(), softnessFactor); } else { if (!m_d->colorSourceDevice || !(*cs == *m_d->colorSourceDevice->colorSpace())) { m_d->colorSourceDevice = new KisPaintDevice(cs); } else { m_d->colorSourceDevice->clear(); } QRect maskRect(QPoint(), position.rect.size()); colorSource->colorize(m_d->colorSourceDevice, maskRect, info.pos().toPoint()); delete m_d->colorSourceDevice->convertTo(cs); m_d->brush->mask(m_d->dab, m_d->colorSourceDevice, scaleX, scaleY, position.realAngle, info, position.subPixel.x(), position.subPixel.y(), softnessFactor); } if (!mirrorProperties.isEmpty()) { m_d->dab->mirror(mirrorProperties.horizontalMirror, mirrorProperties.verticalMirror); } if (needSeparateOriginal()) { if (!m_d->dabOriginal || !(*cs == *m_d->dabOriginal->colorSpace())) { m_d->dabOriginal = new KisFixedPaintDevice(cs); } *m_d->dabOriginal = *m_d->dab; } postProcessDab(m_d->dab, position.rect.topLeft(), info); return m_d->dab; } void KisDabCache::postProcessDab(KisFixedPaintDeviceSP dab, const QPoint &dabTopLeft, const KisPaintInformation& info) { if (m_d->sharpnessOption) { m_d->sharpnessOption->applyThreshold(dab); } if (m_d->textureOption) { m_d->textureOption->apply(dab, dabTopLeft, info); } } diff --git a/krita/plugins/paintops/libpaintop/kis_dab_cache.h b/krita/plugins/paintops/libpaintop/kis_dab_cache.h index 7036bff591f..3581831bd9a 100644 --- a/krita/plugins/paintops/libpaintop/kis_dab_cache.h +++ b/krita/plugins/paintops/libpaintop/kis_dab_cache.h @@ -1,139 +1,139 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DAB_CACHE_H #define __KIS_DAB_CACHE_H -#include "krita_export.h" +#include "kritapaintop_export.h" #include "kis_brush.h" class KisColorSource; class KisPressureSharpnessOption; class KisTextureProperties; class KisPressureMirrorOption; class KisPrecisionOption; struct MirrorProperties; /** * @brief The KisDabCache class provides caching for dabs into the brush paintop * * This class adds caching of the dabs to the paintop system of Krita. * Such cache makes the execution of the benchmarks up to 2 times faster. * Subjectively, the real painting becomes much faster, especially with * huge brushes. Artists report up to 20% speed gain while painting. * * Of course, such caching makes the painting a bit less precise: we need * to tolerate subpixel differences to allow the cache to work. Sometimes * small difference in the size of a dab can also be acceptable. That is * why I introduced levels of precision. They are graded from 1 to 5: from * the fastest and less precise to the slowest, but with the best quality. * You can see the slider in the paintop settings dialog. The ToolTip text * explains which features of the brush are sacrificed on each precision * level. * * The texturing and mirroring problems are solved. */ class PAINTOP_EXPORT KisDabCache { public: KisDabCache(KisBrushSP brush); ~KisDabCache(); void setMirrorPostprocessing(KisPressureMirrorOption *option); void setSharpnessPostprocessing(KisPressureSharpnessOption *option); void setTexturePostprocessing(KisTextureProperties *option); void setPrecisionOption(KisPrecisionOption *option); /** * Disables handling of the subPixelX and subPixelY values, this * is needed at least for the Color Smudge paint op, which reads * aligned areas from image, so additional offsets generated by * the subpixel precision should be avoided */ void disableSubpixelPrecision(); bool needSeparateOriginal(); KisFixedPaintDeviceSP fetchDab(const KoColorSpace *cs, const KisColorSource *colorSource, const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect); KisFixedPaintDeviceSP fetchDab(const KoColorSpace *cs, const KoColor& color, const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect); private: struct SavedDabParameters; struct DabPosition; private: inline SavedDabParameters getDabParameters(const KoColor& color, double scaleX, double scaleY, double angle, const KisPaintInformation& info, double subPixelX, double subPixelY, qreal softnessFactor, MirrorProperties mirrorProperties); inline KisDabCache::DabPosition calculateDabRect(const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, const MirrorProperties &mirrorProperties); inline QRect correctDabRectWhenFetchedFromCache(const QRect &dabRect, const QSize &realDabSize); inline KisFixedPaintDeviceSP tryFetchFromCache(const SavedDabParameters ¶ms, const KisPaintInformation& info, QRect *dstDabRect); inline KisFixedPaintDeviceSP fetchDabCommon(const KoColorSpace *cs, const KisColorSource *colorSource, const KoColor& color, const QPointF &cursorPoint, double scaleX, double scaleY, double angle, const KisPaintInformation& info, qreal softnessFactor, QRect *dstDabRect); void postProcessDab(KisFixedPaintDeviceSP dab, const QPoint &dabTopLeft, const KisPaintInformation& info); private: struct Private; Private * const m_d; }; #endif /* __KIS_DAB_CACHE_H */ diff --git a/krita/plugins/paintops/libpaintop/kis_dynamic_sensor.h b/krita/plugins/paintops/libpaintop/kis_dynamic_sensor.h index 41ce978b8e5..09add62a459 100644 --- a/krita/plugins/paintops/libpaintop/kis_dynamic_sensor.h +++ b/krita/plugins/paintops/libpaintop/kis_dynamic_sensor.h @@ -1,202 +1,202 @@ /* * Copyright (c) 2006 Cyrille Berger * Copyright (c) 2011 Lukáš Tvrdý * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_DYNAMIC_SENSOR_H_ #define _KIS_DYNAMIC_SENSOR_H_ -#include +#include #include #include #include #include "kis_serializable_configuration.h" #include "kis_curve_label.h" #include #include #include class QWidget; class KisPaintInformation; const KoID FuzzyId("fuzzy", ki18n("Fuzzy")); ///< generate a random number const KoID SpeedId("speed", ki18n("Speed")); ///< generate a number depending on the speed of the cursor const KoID FadeId("fade", ki18n("Fade")); ///< generate a number that increase every time you call it (e.g. per dab) const KoID DistanceId("distance", ki18n("Distance")); ///< generate a number that increase with distance const KoID TimeId("time", ki18n("Time")); ///< generate a number that increase with time const KoID DrawingAngleId("drawingangle", ki18n("Drawing angle")); ///< number depending on the angle const KoID RotationId("rotation", ki18n("Rotation")); ///< rotation coming from the device const KoID PressureId("pressure", ki18n("Pressure")); ///< number depending on the pressure const KoID PressureInId("pressurein", ki18n("PressureIn")); ///< number depending on the pressure const KoID XTiltId("xtilt", ki18n("X-Tilt")); ///< number depending on X-tilt const KoID YTiltId("ytilt", ki18n("Y-Tilt")); ///< number depending on Y-tilt /** * "TiltDirection" and "TiltElevation" parameters are written to * preset files as "ascension" and "declination" to keep backward * compatibility with older presets from the days when they were called * differently. */ const KoID TiltDirectionId("ascension", ki18n("Tilt direction")); /// < number depending on the X and Y tilt, tilt direction is 0 when stylus nib points to you and changes clockwise from -180 to +180. const KoID TiltElevationId("declination", ki18n("Tilt elevation")); /// < tilt elevation is 90 when stylus is perpendicular to tablet and 0 when it's parallel to tablet const KoID PerspectiveId("perspective", ki18n("Perspective")); ///< number depending on the distance on the perspective grid const KoID TangentialPressureId("tangentialpressure", ki18n("Tangential pressure")); ///< the wheel on an airbrush device const KoID SensorsListId("sensorslist", "SHOULD NOT APPEAR IN THE UI !"); ///< this a non user-visible sensor that can store a list of other sensors, and multiply their output class KisDynamicSensor; typedef KisSharedPtr KisDynamicSensorSP; enum DynamicSensorType { FUZZY, SPEED, FADE, DISTANCE, TIME, ANGLE, ROTATION, PRESSURE, XTILT, YTILT, TILT_DIRECTION, TILT_ELEVATATION, PERSPECTIVE, TANGENTIAL_PRESSURE, SENSORS_LIST, PRESSURE_IN, UNKNOWN = 255 }; /** * Sensors are used to extract from KisPaintInformation a single * double value which can be used to control the parameters of * a brush. */ class PAINTOP_EXPORT KisDynamicSensor : public KisSerializableConfiguration, public KisShared { public: enum ParameterSign { NegativeParameter = -1, UnSignedParameter = 0, PositiveParameter = 1 }; protected: KisDynamicSensor(DynamicSensorType type); public: virtual ~KisDynamicSensor(); /** * @return the value of this sensor for the given KisPaintInformation */ qreal parameter(const KisPaintInformation& info); /** * This function is call before beginning a stroke to reset the sensor. * Default implementation does nothing. */ virtual void reset(); /** * @param selector is a \ref QWidget that countains a signal called "parametersChanged()" */ virtual QWidget* createConfigurationWidget(QWidget* parent, QWidget* selector); /** * Creates a sensor from its identifiant. */ static KisDynamicSensorSP id2Sensor(const KoID& id); static KisDynamicSensorSP id2Sensor(const QString& s) { return id2Sensor(KoID(s)); } static DynamicSensorType id2Type(const KoID& id); static DynamicSensorType id2Type(const QString& s) { return id2Type(KoID(s)); } /** * type2Sensor creates a new sensor for the give type */ static KisDynamicSensorSP type2Sensor(DynamicSensorType sensorType); static QString minimumLabel(DynamicSensorType sensorType); static QString maximumLabel(DynamicSensorType sensorType, int max = -1); static KisDynamicSensorSP createFromXML(const QString&); static KisDynamicSensorSP createFromXML(const QDomElement&); /** * @return the list of sensors */ static QList sensorsIds(); static QList sensorsTypes(); /** * @return the identifiant of this sensor */ static QString id(DynamicSensorType sensorType); using KisSerializableConfiguration::fromXML; using KisSerializableConfiguration::toXML; virtual void toXML(QDomDocument&, QDomElement&) const; virtual void fromXML(const QDomElement&); void setCurve(const KisCubicCurve& curve); const KisCubicCurve& curve() const; void removeCurve(); bool hasCustomCurve() const; void setActive(bool active); bool isActive() const; virtual bool dependsOnCanvasRotation() const; inline DynamicSensorType sensorType() const { return m_type; } /** * @return the currently set length or -1 if not relevant */ int length() { return m_length; } protected: virtual qreal value(const KisPaintInformation& info) = 0; int m_length; private: Q_DISABLE_COPY(KisDynamicSensor) DynamicSensorType m_type; bool m_customCurve; KisCubicCurve m_curve; bool m_active; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.cpp b/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.cpp index d1bd8a01da4..f78c711d2f3 100644 --- a/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.cpp +++ b/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.cpp @@ -1,113 +1,130 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_embedded_pattern_manager.h" #include #include #include #include #include struct KisEmbeddedPatternManager::Private { static KoPattern* tryLoadEmbeddedPattern(const KisPropertiesConfiguration* setting) { KoPattern *pattern = 0; QByteArray ba = QByteArray::fromBase64(setting->getString("Texture/Pattern/Pattern").toLatin1()); QImage img; img.loadFromData(ba, "PNG"); QString name = setting->getString("Texture/Pattern/Name"); QString filename = setting->getString("Texture/Pattern/PatternFileName"); if (name.isEmpty() || name != QFileInfo(name).fileName()) { QFileInfo info(filename); name = info.baseName(); } if (!img.isNull()) { pattern = new KoPattern(img, name, KoResourceServerProvider::instance()->patternServer()->saveLocation()); } return pattern; } static KoPattern* tryFetchPatternByMd5(const QByteArray &md5) { KoResourceServer *server = KoResourceServerProvider::instance()->patternServer(); return server->resourceByMD5(md5); } -}; + static KoPattern* tryFetchPatternByName(const QString &name) { + KoResourceServer *server = KoResourceServerProvider::instance()->patternServer(); + return server->resourceByName(name); + } + + static KoPattern* tryFetchPatternByFileName(const QString &fileName) { + KoResourceServer *server = KoResourceServerProvider::instance()->patternServer(); + return server->resourceByFilename(fileName); + } +}; void KisEmbeddedPatternManager::saveEmbeddedPattern(KisPropertiesConfiguration* setting, const KoPattern *pattern) { QByteArray patternMD5 = pattern->md5(); /** * The process of saving a pattern may be quite expensive, so * we won't rewrite the pattern if has the same md5-sum and at * least some data is present */ QByteArray existingMD5 = QByteArray::fromBase64(setting->getString("Texture/Pattern/PatternMD5").toLatin1()); QString existingPatternBase64 = setting->getString("Texture/Pattern/PatternMD5").toLatin1(); - if (patternMD5 == existingMD5 && - !existingPatternBase64.isEmpty()) { - + if (patternMD5 == existingMD5 && !existingPatternBase64.isEmpty()) { return; } - setting->setProperty("Texture/Pattern/PatternMD5", patternMD5.toBase64()); + setting->setProperty("Texture/Pattern/PatternFileName", pattern->filename()); + setting->setProperty("Texture/Pattern/Name", pattern->name()); + QByteArray ba; QBuffer buffer(&ba); buffer.open(QIODevice::WriteOnly); pattern->pattern().save(&buffer, "PNG"); setting->setProperty("Texture/Pattern/Pattern", ba.toBase64()); - setting->setProperty("Texture/Pattern/PatternFileName", pattern->filename()); - setting->setProperty("Texture/Pattern/Name", pattern->name()); + } KoPattern* KisEmbeddedPatternManager::loadEmbeddedPattern(const KisPropertiesConfiguration* setting) { KoPattern *pattern = 0; QByteArray md5 = QByteArray::fromBase64(setting->getString("Texture/Pattern/PatternMD5").toLatin1()); pattern = Private::tryFetchPatternByMd5(md5); + if (pattern) return pattern; - if (!pattern) { - pattern = Private::tryLoadEmbeddedPattern(setting); - if (pattern) { - KoPattern *existingPattern = Private::tryFetchPatternByMd5(pattern->md5()); - if (existingPattern) { - delete pattern; - pattern = existingPattern; - } - else { - KoResourceServerProvider::instance()->patternServer()->addResource(pattern, true); - } + QString name = setting->getString("Texture/Pattern/Name"); + pattern = Private::tryFetchPatternByName(name); + if (pattern) return pattern; + + QString fileName = setting->getString("Texture/Pattern/PatternFileName"); + pattern = Private::tryFetchPatternByFileName(fileName); + if (pattern) return pattern; + + + pattern = Private::tryLoadEmbeddedPattern(setting); + if (pattern) { + KoPattern *existingPattern = Private::tryFetchPatternByMd5(pattern->md5()); + if (existingPattern) { + delete pattern; + pattern = existingPattern; + } + else { + KoResourceServerProvider::instance()->patternServer()->addResource(pattern, false); } } + return pattern; } diff --git a/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.h b/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.h index 366868357b1..474cc6bb052 100644 --- a/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.h +++ b/krita/plugins/paintops/libpaintop/kis_embedded_pattern_manager.h @@ -1,39 +1,39 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_EMBEDDED_PATTERN_MANAGER_H #define __KIS_EMBEDDED_PATTERN_MANAGER_H -#include +#include class KoPattern; class KoAbstractGradient; class KisPropertiesConfiguration; -class KRITAUI_EXPORT KisEmbeddedPatternManager +class PAINTOP_TEST_EXPORT KisEmbeddedPatternManager { public: static void saveEmbeddedPattern(KisPropertiesConfiguration* setting, const KoPattern *pattern); static KoPattern* loadEmbeddedPattern(const KisPropertiesConfiguration* setting); private: struct Private; }; #endif /* __KIS_EMBEDDED_PATTERN_MANAGER_H */ diff --git a/krita/plugins/paintops/libpaintop/kis_filter_option.h b/krita/plugins/paintops/libpaintop/kis_filter_option.h index 5b692bd1d74..29b292943d3 100644 --- a/krita/plugins/paintops/libpaintop/kis_filter_option.h +++ b/krita/plugins/paintops/libpaintop/kis_filter_option.h @@ -1,92 +1,92 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_FILTER_OPTION_H #define KIS_FILTER_OPTION_H #include "kis_paintop_option.h" #include -#include +#include class QGridLayout; class KoID; class KisConfigWidget; class KisFilterConfiguration; class KisFilterOptionWidget; const QString FILTER_ID = "Filter/id"; const QString FILTER_SMUDGE_MODE = "Filter/smudgeMode"; const QString FILTER_CONFIGURATION = "Filter/configuration"; /** * The filter option allows the user to select a particular filter * that can be applied by the paintop to the brush footprint or the * original paint device data. */ class PAINTOP_EXPORT KisFilterOption : public KisPaintOpOption { Q_OBJECT public: KisFilterOption(); /** * Return the currently selected filter */ const KisFilterSP filter() const; /** * Return the currently selected filter configuration */ KisFilterConfiguration* filterConfig() const; bool smudgeMode() const; /** * XXX */ void setNode(KisNodeWSP node); /** * XXX */ void setImage(KisImageWSP image); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private Q_SLOTS: void setCurrentFilter(const KoID&); void updateFilterConfigWidget(); private: QGridLayout* m_layout; KisFilterOptionWidget* m_options; const KisFilterSP m_currentFilter; KisConfigWidget* m_currentFilterConfigWidget; KisPaintDeviceSP m_paintDevice; KisImageSP m_image; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_paint_action_type_option.h b/krita/plugins/paintops/libpaintop/kis_paint_action_type_option.h index f041e1d89b4..ba69399cdba 100644 --- a/krita/plugins/paintops/libpaintop/kis_paint_action_type_option.h +++ b/krita/plugins/paintops/libpaintop/kis_paint_action_type_option.h @@ -1,58 +1,58 @@ /* * Copyright (c) 2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PAINT_ACTION_TYPE_OPTION_H #define KIS_PAINT_ACTION_TYPE_OPTION_H #include -#include +#include class KisPaintActionWidget; enum enumPaintActionType { UNSUPPORTED, BUILDUP, WASH, FRINGED // not used yet }; /** * Allows the user to choose between two types of paint action: * * incremental (going over the same spot in one stroke makes it darker) * * indirect (like photoshop and gimp) */ class PAINTOP_EXPORT KisPaintActionTypeOption : public KisPaintOpOption { public: KisPaintActionTypeOption(); ~KisPaintActionTypeOption(); enumPaintActionType paintActionType() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisPaintActionWidget * m_optionWidget; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_precision_option.h b/krita/plugins/paintops/libpaintop/kis_precision_option.h index a5439bfc147..840fb881fb6 100644 --- a/krita/plugins/paintops/libpaintop/kis_precision_option.h +++ b/krita/plugins/paintops/libpaintop/kis_precision_option.h @@ -1,56 +1,56 @@ /* * Copyright (c) 2012 Dmitry Kazakov * Copyright (c) 2014 Mohit Goyal * * 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_PRECISION_OPTION_H #define __KIS_PRECISION_OPTION_H #include -#include +#include class KisPropertiesConfiguration; const QString PRECISION_LEVEL = "KisPrecisionOption/precisionLevel"; const QString AUTO_PRECISION_ENABLED = "KisPrecisionOption/AutoPrecisionEnabled"; const QString STARTING_SIZE = "KisPrecisionOption/SizeToStartFrom"; const QString DELTA_VALUE = "KisPrecisionOption/DeltaValue"; class PAINTOP_EXPORT KisPrecisionOption { public: void writeOptionSetting(KisPropertiesConfiguration* settings) const; void readOptionSetting(const KisPropertiesConfiguration* settings); int precisionLevel() const; void setPrecisionLevel(int precisionLevel); void setAutoPrecisionEnabled(int); void setDeltaValue(double); void setSizeToStartFrom(double); bool autoPrecisionEnabled(); double deltaValue(); double sizeToStartFrom(); void setAutoPrecision(double brushSize); private: int m_precisionLevel; bool m_autoPrecisionEnabled; double m_sizeToStartFrom; double m_deltaValue; }; #endif /* __KIS_PRECISION_OPTION_H */ diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_darken_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_darken_option.h index 4c8f58a6614..24e60a98f69 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_darken_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_darken_option.h @@ -1,45 +1,45 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PRESSURE_DARKEN_OPTION_H #define KIS_PRESSURE_DARKEN_OPTION_H #include "kis_curve_option.h" #include -#include +#include #include class KisPainter; class KisColorSource; /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on the darkness of the dab */ class PAINTOP_EXPORT KisPressureDarkenOption : public KisCurveOption { public: KisPressureDarkenOption(); KoColor apply(KisPainter * painter, const KisPaintInformation& info) const; void apply(KisColorSource* colorSource, const KisPaintInformation& info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_flow_opacity_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_flow_opacity_option.h index ba6ff5c660e..2b8c3335113 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_flow_opacity_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_flow_opacity_option.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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_PRESSURE_FLOW_OPACITY_OPTION_H #define KIS_PRESSURE_FLOW_OPACITY_OPTION_H #include "kis_curve_option.h" -#include +#include #include #include class KisPaintInformation; class KisPainter; class PAINTOP_EXPORT KisFlowOpacityOption: public KisCurveOption { public: KisFlowOpacityOption(KisNodeSP currentNode); virtual ~KisFlowOpacityOption() { } virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); void setFlow(qreal flow); void setOpacity(qreal opacity); void apply(KisPainter* painter, const KisPaintInformation& info); qreal getFlow() const; qreal getStaticOpacity() const; qreal getDynamicOpacity(const KisPaintInformation& info) const; protected: qreal m_flow; int m_paintActionType; bool m_nodeHasIndirectPaintingSupport; }; #endif //KIS_PRESSURE_FLOW_OPACITY_OPTION_H diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_flow_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_flow_option.h index d06eb872f19..d630d744670 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_flow_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_flow_option.h @@ -1,41 +1,41 @@ /* This file is part of the KDE project * Copyright (C) Timothée Giet , (C) 2014 * * 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_PRESSURE_FLOW_OPTION_H #define KIS_PRESSURE_FLOW_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * The pressure flow option defines a curve that is used to * calculate the effect of pressure on the flow of the dab */ class PAINTOP_EXPORT KisPressureFlowOption : public KisCurveOption { public: KisPressureFlowOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_gradient_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_gradient_option.h index 1b969d34457..c0137367b51 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_gradient_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_gradient_option.h @@ -1,37 +1,37 @@ /* This file is part of the KDE project * Copyright (C) 2011 Silvio Heinrich * * 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_PRESSURE_GRADIENT_OPTION_H #define KIS_PRESSURE_GRADIENT_OPTION_H #include "kis_curve_option.h" #include -#include +#include class KoColor; class KoAbstractGradient; class PAINTOP_EXPORT KisPressureGradientOption: public KisCurveOption { public: KisPressureGradientOption(); void apply(KoColor& color, const KoAbstractGradient* gradient, const KisPaintInformation& info) const; }; #endif // KIS_PRESSURE_GRADIENT_OPTION_H diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_hsv_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_hsv_option.h index 0c5d29850b0..f5253eae992 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_hsv_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_hsv_option.h @@ -1,58 +1,58 @@ /* This file is part of the KDE project * Copyright (c) 2010 Cyrille Berger * * 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_PRESSURE_HSV_OPTION_H #define KIS_PRESSURE_HSV_OPTION_H #include "kis_curve_option.h" #include -#include +#include #include class KoColorTransformation; /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on one of the hsv of the dab */ class PAINTOP_EXPORT KisPressureHSVOption : public KisCurveOption { public: static KisPressureHSVOption* createHueOption(); static QString hueMinLabel(); static QString huemaxLabel(); static KisPressureHSVOption* createSaturationOption(); static QString saturationMinLabel(); static QString saturationmaxLabel(); static KisPressureHSVOption* createValueOption(); static QString valueMinLabel(); static QString valuemaxLabel(); public: KisPressureHSVOption(const QString& parameterName); void apply(KoColorTransformation* hsvTransfo, const KisPaintInformation& info) const; private: struct Private; Private* const d; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_mirror_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_mirror_option.h index 03c25382db6..836ecf22595 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_mirror_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_mirror_option.h @@ -1,76 +1,76 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_PRESSURE_MIRROR_OPTION_H #define KIS_PRESSURE_MIRROR_OPTION_H #include "kis_curve_option.h" #include -#include +#include #include struct MirrorProperties { MirrorProperties() : horizontalMirror(false), verticalMirror(false), coordinateSystemFlipped(false) {} bool horizontalMirror; bool verticalMirror; bool coordinateSystemFlipped; bool isEmpty() const { return !horizontalMirror && !verticalMirror; } }; const QString MIRROR_HORIZONTAL_ENABLED = "HorizontalMirrorEnabled"; const QString MIRROR_VERTICAL_ENABLED = "VerticalMirrorEnabled"; /** * If the sensor value is higher then 0.5, then the related mirror option is true, false otherwise */ class PAINTOP_EXPORT KisPressureMirrorOption : public KisCurveOption { public: KisPressureMirrorOption(); /** * Set the */ MirrorProperties apply(const KisPaintInformation& info) const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); void enableVerticalMirror(bool mirror); void enableHorizontalMirror(bool mirror); bool isVerticalMirrorEnabled(); bool isHorizontalMirrorEnabled(); private: bool m_enableVerticalMirror; bool m_enableHorizontalMirror; bool m_canvasAxisXMirrored; bool m_canvasAxisYMirrored; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_mix_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_mix_option.h index 1dbef61ce62..8f07a0adb0a 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_mix_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_mix_option.h @@ -1,40 +1,40 @@ /* This file is part of the KDE project * Copyright (c) 2009 Cyrille Berger * * 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_PRESSURE_MIX_OPTION_H #define KIS_PRESSURE_MIX_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on the mix of the color */ class PAINTOP_EXPORT KisPressureMixOption : public KisCurveOption { public: KisPressureMixOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_opacity_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_opacity_option.h index 3c49a32bba6..584cea2072b 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_opacity_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_opacity_option.h @@ -1,55 +1,55 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PRESSURE_OPACITY_OPTION #define KIS_PRESSURE_OPACITY_OPTION #include "kis_curve_option.h" -#include +#include class KisPainter; /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on opacity */ class PAINTOP_EXPORT KisPressureOpacityOption : public KisCurveOption { public: KisPressureOpacityOption(); /** * Set the opacity of the painter based on the pressure * and the curve (if checked) and return the old opacity * of the painter. */ quint8 apply(KisPainter* painter, const KisPaintInformation& info) const; \ quint8 getOpacityU8(const KisPaintInformation& info) { return quint8(qRound(getOpacityf(info) * 255.0)); } qreal getOpacityf(const KisPaintInformation& info); virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_rotation_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_rotation_option.h index b8cffb7cb62..0254bcd3c4f 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_rotation_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_rotation_option.h @@ -1,50 +1,50 @@ /* This file is part of the KDE project * Copyright (c) 2009 Cyrille Berger * * 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_PRESSURE_ROTATION_OPTION_H #define KIS_PRESSURE_ROTATION_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on the size of the dab */ class PAINTOP_EXPORT KisPressureRotationOption : public KisCurveOption { public: KisPressureRotationOption(); double apply(const KisPaintInformation & info) const; void readOptionSetting(const KisPropertiesConfiguration* setting); void applyFanCornersInfo(KisPaintOp *op); private: qreal m_defaultAngle; bool m_canvasAxisXMirrored; bool m_canvasAxisYMirrored; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_scatter_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_scatter_option.h index af43a5d55bd..d0f86c3334a 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_scatter_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_scatter_option.h @@ -1,58 +1,58 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_PRESSURE_SCATTER_OPTION_H #define KIS_PRESSURE_SCATTER_OPTION_H #include "kis_curve_option.h" #include -#include +#include #include const QString SCATTER_X = "Scattering/AxisX"; const QString SCATTER_Y = "Scattering/AxisY"; const QString SCATTER_AMOUNT = "Scattering/Amount"; /** * Scatters the position of the dab */ class PAINTOP_EXPORT KisPressureScatterOption : public KisCurveOption { public: KisPressureScatterOption(); QPointF apply(const KisPaintInformation& info, qreal width, qreal height) const; virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); void enableAxisY(bool enable); void enableAxisX(bool enable); bool isAxisXEnabled(); bool isAxisYEnabled(); void setScatterAmount(qreal amount); qreal scatterAmount(); private: bool m_axisX; bool m_axisY; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h index 156a157c0c2..ab6436a75d3 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_sharpness_option.h @@ -1,72 +1,72 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_PRESSURE_SHARPNESS_OPTION_H #define KIS_PRESSURE_SHARPNESS_OPTION_H #include "kis_curve_option.h" #include -#include +#include #include const QString SHARPNESS_FACTOR = "Sharpness/factor"; const QString SHARPNESS_THRESHOLD = "Sharpness/threshold"; /** * This option is responsible to mimic pencil effect from former Pixel Pencil brush engine.auto */ class PAINTOP_EXPORT KisPressureSharpnessOption : public KisCurveOption { public: KisPressureSharpnessOption(); /** * First part of the sharpness is the coordinates: in pen mode they are integers without fractions */ void apply(const KisPaintInformation &info, const QPointF &pt, qint32 &x, qint32 &y, qreal &xFraction, qreal &yFraction) const; /** * Apply threshold specified by user */ void applyThreshold(KisFixedPaintDeviceSP dab); void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); /// threshold has 100 levels (like opacity) void setThreshold(qint32 threshold) { m_threshold = qBound(0, threshold, 100); } qint32 threshold() { return m_threshold; } void setSharpnessFactor(qreal factor) { KisCurveOption::setValue(factor); } qreal sharpnessFactor() { return KisCurveOption::value(); } private: qint32 m_threshold; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_size_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_size_option.h index e43057ed9ae..627c29d547f 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_size_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_size_option.h @@ -1,40 +1,40 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PRESSURE_SIZE_OPTION_H #define KIS_PRESSURE_SIZE_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * The pressure opacity option defines a curve that is used to * calculate the effect of pressure on the size of the dab */ class PAINTOP_EXPORT KisPressureSizeOption : public KisCurveOption { public: KisPressureSizeOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_softness_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_softness_option.h index 05e76ad25e6..c54eac57d5c 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_softness_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_softness_option.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_PRESSURE_SOFTNESS_OPTION_H #define KIS_PRESSURE_SOFTNESS_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * This option is responsible to deliver values suitable for softness * They are in range 0.0..1.0 */ class PAINTOP_EXPORT KisPressureSoftnessOption : public KisCurveOption { public: KisPressureSoftnessOption(); double apply(const KisPaintInformation & info) const; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_spacing_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_spacing_option.h index c82b9f9c5d7..5fe7b226b78 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_spacing_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_spacing_option.h @@ -1,47 +1,47 @@ /* This file is part of the KDE project * Copyright (c) 2011 Cyrille Berger * * 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_PRESSURE_SPACING_OPTION_H #define KIS_PRESSURE_SPACING_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * The pressure spacing option defines a curve that is used to * calculate the effect of pressure on the spacing of the dab */ class PAINTOP_EXPORT KisPressureSpacingOption : public KisCurveOption { public: KisPressureSpacingOption(); double apply(const KisPaintInformation & info) const; void setIsotropicSpacing(bool isotropic); bool isotropicSpacing() const; void readOptionSetting(const KisPropertiesConfiguration* setting); void writeOptionSetting(KisPropertiesConfiguration* setting) const; private: bool m_isotropicSpacing; }; #endif diff --git a/krita/plugins/paintops/libpaintop/kis_pressure_texture_strength_option.h b/krita/plugins/paintops/libpaintop/kis_pressure_texture_strength_option.h index 4f81a51fa0c..e6effdb4fe3 100644 --- a/krita/plugins/paintops/libpaintop/kis_pressure_texture_strength_option.h +++ b/krita/plugins/paintops/libpaintop/kis_pressure_texture_strength_option.h @@ -1,41 +1,41 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_PRESSURE_TEXTURE_STRENGTH_OPTION_H #define __KIS_PRESSURE_TEXTURE_STRENGTH_OPTION_H #include "kis_curve_option.h" #include -#include +#include /** * This curve defines how deep the ink (or a pointer) of a brush * penetrates the surface of the canvas, that is how strong we * press on the paper */ class PAINTOP_EXPORT KisPressureTextureStrengthOption : public KisCurveOption { public: KisPressureTextureStrengthOption(); double apply(const KisPaintInformation & info) const; void readOptionSetting(const KisPropertiesConfiguration* setting); void writeOptionSetting(KisPropertiesConfiguration* setting) const; }; #endif /* __KIS_PRESSURE_TEXTURE_STRENGTH_OPTION_H */ diff --git a/krita/plugins/paintops/libpaintop/kis_texture_option.cpp b/krita/plugins/paintops/libpaintop/kis_texture_option.cpp index c92af80c5c5..b0e7b03b6ef 100644 --- a/krita/plugins/paintops/libpaintop/kis_texture_option.cpp +++ b/krita/plugins/paintops/libpaintop/kis_texture_option.cpp @@ -1,400 +1,398 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2012 * Copyright (C) Mohit Goyal , (C) 2014 * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_texture_option.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_embedded_pattern_manager.h" #include "kis_algebra_2d.h" #include class KisTextureOptionWidget : public QWidget { public: KisTextureOptionWidget(QWidget *parent = 0) : QWidget(parent) { QFormLayout *formLayout = new QFormLayout(this); formLayout->setMargin(0); chooser = new KisPatternChooser(this); chooser->setGrayscalePreview(true); chooser->setMaximumHeight(250); chooser->setCurrentItem(0, 0); formLayout->addRow(chooser); scaleSlider = new KisMultipliersDoubleSliderSpinBox(this); scaleSlider->setRange(0.0, 2.0, 2); scaleSlider->setValue(1.0); scaleSlider->addMultiplier(0.1); scaleSlider->addMultiplier(2); scaleSlider->addMultiplier(10); formLayout->addRow(i18n("Scale:"), scaleSlider); QBoxLayout *offsetLayoutX = new QBoxLayout(QBoxLayout::LeftToRight); offsetSliderX = new KisSliderSpinBox(this); offsetSliderX->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); randomOffsetX = new QCheckBox(i18n("Random Offset"),this); offsetLayoutX->addWidget(offsetSliderX,1,0); offsetLayoutX->addWidget(randomOffsetX,0,0); formLayout->addRow(i18n("Horizontal Offset:"), offsetLayoutX); QBoxLayout *offsetLayoutY = new QBoxLayout(QBoxLayout::LeftToRight); offsetSliderY = new KisSliderSpinBox(this); offsetSliderY->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); randomOffsetY = new QCheckBox(i18n("Random Offset"),this); offsetLayoutY->addWidget(offsetSliderY,1,0); offsetLayoutY->addWidget(randomOffsetY,0,0); formLayout->addRow(i18n("Vertical Offset:"), offsetLayoutY); cmbTexturingMode = new QComboBox(this); cmbTexturingMode->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QStringList texturingModes; texturingModes << i18n("Multiply") << i18n("Subtract"); cmbTexturingMode->addItems(texturingModes); formLayout->addRow(i18n("Texturing Mode:"), cmbTexturingMode); cmbTexturingMode->setCurrentIndex(KisTextureProperties::SUBTRACT); cmbCutoffPolicy = new QComboBox(this); cmbCutoffPolicy->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); QStringList cutOffPolicies; cutOffPolicies << i18n("Cut Off Disabled") << i18n("Cut Off Brush") << i18n("Cut Off Pattern"); cmbCutoffPolicy->addItems(cutOffPolicies); formLayout->addRow(i18n("Cutoff Policy:"), cmbCutoffPolicy); cutoffSlider = new KisGradientSlider(this); cutoffSlider->setMinimumSize(256, 30); cutoffSlider->enableGamma(false); cutoffSlider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed); cutoffSlider->setToolTip(i18n("When pattern texture values are outside the range specified" " by the slider, the cut-off policy will be applied.")); formLayout->addRow(i18n("Cutoff:"), cutoffSlider); chkInvert = new QCheckBox(this); chkInvert->setChecked(false); formLayout->addRow(i18n("Invert Pattern:"), chkInvert); setLayout(formLayout); } KisPatternChooser *chooser; KisMultipliersDoubleSliderSpinBox *scaleSlider; KisSliderSpinBox *offsetSliderX; QCheckBox *randomOffsetX; KisSliderSpinBox *offsetSliderY; QCheckBox *randomOffsetY; QComboBox *cmbTexturingMode; KisGradientSlider *cutoffSlider; QComboBox *cmbCutoffPolicy; QCheckBox *chkInvert; }; KisTextureOption::KisTextureOption(QObject *) : KisPaintOpOption(KisPaintOpOption::TEXTURE, true) { setObjectName("KisTextureOption"); setChecked(false); m_optionWidget = new KisTextureOptionWidget; m_optionWidget->hide(); setConfigurationPage(m_optionWidget); connect(m_optionWidget->chooser, SIGNAL(resourceSelected(KoResource*)), SLOT(resetGUI(KoResource*))); connect(m_optionWidget->chooser, SIGNAL(resourceSelected(KoResource*)), SLOT(emitSettingChanged())); connect(m_optionWidget->scaleSlider, SIGNAL(valueChanged(qreal)), SLOT(emitSettingChanged())); connect(m_optionWidget->offsetSliderX, SIGNAL(valueChanged(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->randomOffsetX, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_optionWidget->randomOffsetY, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); connect(m_optionWidget->offsetSliderY, SIGNAL(valueChanged(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->cmbTexturingMode, SIGNAL(currentIndexChanged(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->cmbCutoffPolicy, SIGNAL(currentIndexChanged(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->cutoffSlider, SIGNAL(sigModifiedBlack(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->cutoffSlider, SIGNAL(sigModifiedWhite(int)), SLOT(emitSettingChanged())); connect(m_optionWidget->chkInvert, SIGNAL(toggled(bool)), SLOT(emitSettingChanged())); resetGUI(m_optionWidget->chooser->currentResource()); } KisTextureOption::~KisTextureOption() { delete m_optionWidget; } void KisTextureOption::writeOptionSetting(KisPropertiesConfiguration* setting) const { m_optionWidget->chooser->blockSignals(true); // Checking if (!m_optionWidget->chooser->currentResource()) return; KoPattern *pattern = static_cast(m_optionWidget->chooser->currentResource()); m_optionWidget->chooser->blockSignals(false); // Checking if (!pattern) return; setting->setProperty("Texture/Pattern/Enabled", isChecked()); if (!isChecked()) { return; } qreal scale = m_optionWidget->scaleSlider->value(); int offsetX = m_optionWidget->offsetSliderX->value(); if (m_optionWidget ->randomOffsetX->isChecked()) { m_optionWidget -> offsetSliderX ->setEnabled(false); m_optionWidget -> offsetSliderX ->blockSignals(true); m_optionWidget -> offsetSliderX ->setValue(offsetX); m_optionWidget -> offsetSliderX ->blockSignals(false); srand(time(0)); } else { m_optionWidget -> offsetSliderX ->setEnabled(true); } int offsetY = m_optionWidget->offsetSliderY->value(); if (m_optionWidget ->randomOffsetY->isChecked()) { m_optionWidget -> offsetSliderY ->setEnabled(false); m_optionWidget -> offsetSliderY ->blockSignals(true); m_optionWidget -> offsetSliderY ->setValue(offsetY); m_optionWidget -> offsetSliderY ->blockSignals(false); srand(time(0)); } else { m_optionWidget -> offsetSliderY ->setEnabled(true); } int texturingMode = m_optionWidget->cmbTexturingMode->currentIndex(); bool invert = (m_optionWidget->chkInvert->checkState() == Qt::Checked); setting->setProperty("Texture/Pattern/Scale", scale); setting->setProperty("Texture/Pattern/OffsetX", offsetX); setting->setProperty("Texture/Pattern/OffsetY", offsetY); setting->setProperty("Texture/Pattern/TexturingMode", texturingMode); setting->setProperty("Texture/Pattern/CutoffLeft", m_optionWidget->cutoffSlider->black()); setting->setProperty("Texture/Pattern/CutoffRight", m_optionWidget->cutoffSlider->white()); setting->setProperty("Texture/Pattern/CutoffPolicy", m_optionWidget->cmbCutoffPolicy->currentIndex()); setting->setProperty("Texture/Pattern/Invert", invert); setting->setProperty("Texture/Pattern/MaximumOffsetX",m_optionWidget -> offsetSliderX ->maximum()); setting->setProperty("Texture/Pattern/MaximumOffsetY",m_optionWidget -> offsetSliderY ->maximum()); setting->setProperty("Texture/Pattern/isRandomOffsetX",m_optionWidget ->randomOffsetX ->isChecked()); setting->setProperty("Texture/Pattern/isRandomOffsetY",m_optionWidget ->randomOffsetY ->isChecked()); KisEmbeddedPatternManager::saveEmbeddedPattern(setting, pattern); } - - void KisTextureOption::readOptionSetting(const KisPropertiesConfiguration* setting) { setChecked(setting->getBool("Texture/Pattern/Enabled")); if (!isChecked()) { return; } KoPattern *pattern = KisEmbeddedPatternManager::loadEmbeddedPattern(setting); if (!pattern) { pattern = static_cast(m_optionWidget->chooser->currentResource()); } m_optionWidget->chooser->setCurrentPattern(pattern); m_optionWidget->scaleSlider->setValue(setting->getDouble("Texture/Pattern/Scale", 1.0)); m_optionWidget->offsetSliderX->setValue(setting->getInt("Texture/Pattern/OffsetX")); m_optionWidget->offsetSliderY->setValue(setting->getInt("Texture/Pattern/OffsetY")); m_optionWidget->cmbTexturingMode->setCurrentIndex(setting->getInt("Texture/Pattern/TexturingMode", KisTextureProperties::MULTIPLY)); m_optionWidget->cmbCutoffPolicy->setCurrentIndex(setting->getInt("Texture/Pattern/CutoffPolicy")); m_optionWidget->cutoffSlider->slotModifyBlack(setting->getInt("Texture/Pattern/CutoffLeft", 0)); m_optionWidget->cutoffSlider->slotModifyWhite(setting->getInt("Texture/Pattern/CutoffRight", 255)); m_optionWidget->chkInvert->setChecked(setting->getBool("Texture/Pattern/Invert")); } void KisTextureOption::resetGUI(KoResource* res) { KoPattern *pattern = static_cast(res); if (!pattern) return; m_optionWidget->offsetSliderX->setRange(0, pattern->pattern().width() / 2); m_optionWidget->offsetSliderY->setRange(0, pattern->pattern().height() / 2); } void KisTextureProperties::recalculateMask() { - if (!pattern) return; + if (!m_pattern) return; m_mask = 0; - QImage mask = pattern->pattern(); + QImage mask = m_pattern->pattern(); if (mask.format() != QImage::Format_RGB32 || mask.format() != QImage::Format_ARGB32) { mask = mask.convertToFormat(QImage::Format_ARGB32); } - if (!qFuzzyCompare(scale, 0.0)) { + if (!qFuzzyCompare(m_scale, 0.0)) { QTransform tf; - tf.scale(scale, scale); + tf.scale(m_scale, m_scale); QRect rc = KisAlgebra2D::ensureRectNotSmaller(tf.mapRect(mask.rect()), QSize(2,2)); mask = mask.scaled(rc.size(), Qt::KeepAspectRatio, Qt::SmoothTransformation); } #if QT_VERSION >= 0x040700 const QRgb* pixel = reinterpret_cast(mask.constBits()); #else const QRgb* pixel = reinterpret_cast(mask.bits()); #endif int width = mask.width(); int height = mask.height(); const KoColorSpace *cs = KoColorSpaceRegistry::instance()->alpha8(); m_mask = new KisPaintDevice(cs); KisHLineIteratorSP iter = m_mask->createHLineIteratorNG(0, 0, width); for (int row = 0; row < height; ++row) { for (int col = 0; col < width; ++col) { const QRgb currentPixel = pixel[row * width + col]; const int red = qRed(currentPixel); const int green = qGreen(currentPixel); const int blue = qBlue(currentPixel); float alpha = qAlpha(currentPixel) / 255.0; const int grayValue = (red * 11 + green * 16 + blue * 5) / 32; float maskValue = (grayValue / 255.0) * alpha + (1 - alpha); - if (invert) { + if (m_invert) { maskValue = 1 - maskValue; } - if (cutoffPolicy == 1 && (maskValue < (cutoffLeft / 255.0) || maskValue > (cutoffRight / 255.0))) { + if (m_cutoffPolicy == 1 && (maskValue < (m_cutoffLeft / 255.0) || maskValue > (m_cutoffRight / 255.0))) { // mask out the dab if it's outside the pattern's cuttoff points maskValue = OPACITY_TRANSPARENT_F; } - else if (cutoffPolicy == 2 && (maskValue < (cutoffLeft / 255.0) || maskValue > (cutoffRight / 255.0))) { + else if (m_cutoffPolicy == 2 && (maskValue < (m_cutoffLeft / 255.0) || maskValue > (m_cutoffRight / 255.0))) { maskValue = OPACITY_OPAQUE_F; } cs->setOpacity(iter->rawData(), maskValue, 1); iter->nextPixel(); } iter->nextRow(); } m_maskBounds = QRect(0, 0, width, height); } void KisTextureProperties::fillProperties(const KisPropertiesConfiguration *setting) { if (!setting->hasProperty("Texture/Pattern/PatternMD5")) { - enabled = false; + m_enabled = false; return; } - pattern = KisEmbeddedPatternManager::loadEmbeddedPattern(setting); + m_pattern = KisEmbeddedPatternManager::loadEmbeddedPattern(setting); - if (!pattern) { + if (!m_pattern) { qWarning() << "WARNING: Couldn't load the pattern for a stroke"; - enabled = false; + m_enabled = false; return; } - enabled = setting->getBool("Texture/Pattern/Enabled", false); - scale = setting->getDouble("Texture/Pattern/Scale", 1.0); - offsetX = setting->getInt("Texture/Pattern/OffsetX"); - offsetY = setting->getInt("Texture/Pattern/OffsetY"); - texturingMode = (TexturingMode) setting->getInt("Texture/Pattern/TexturingMode", MULTIPLY); - invert = setting->getBool("Texture/Pattern/Invert"); - cutoffLeft = setting->getInt("Texture/Pattern/CutoffLeft", 0); - cutoffRight = setting->getInt("Texture/Pattern/CutoffRight", 255); - cutoffPolicy = setting->getInt("Texture/Pattern/CutoffPolicy", 0); + m_enabled = setting->getBool("Texture/Pattern/Enabled", false); + m_scale = setting->getDouble("Texture/Pattern/Scale", 1.0); + m_offsetX = setting->getInt("Texture/Pattern/OffsetX"); + m_offsetY = setting->getInt("Texture/Pattern/OffsetY"); + m_texturingMode = (TexturingMode) setting->getInt("Texture/Pattern/TexturingMode", MULTIPLY); + m_invert = setting->getBool("Texture/Pattern/Invert"); + m_cutoffLeft = setting->getInt("Texture/Pattern/CutoffLeft", 0); + m_cutoffRight = setting->getInt("Texture/Pattern/CutoffRight", 255); + m_cutoffPolicy = setting->getInt("Texture/Pattern/CutoffPolicy", 0); m_strengthOption.readOptionSetting(setting); m_strengthOption.resetAllSensors(); recalculateMask(); } void KisTextureProperties::apply(KisFixedPaintDeviceSP dab, const QPoint &offset, const KisPaintInformation & info) { - if (!enabled) return; + if (!m_enabled) return; KisPaintDeviceSP fillDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); QRect rect = dab->bounds(); - int x = offset.x() % m_maskBounds.width() - offsetX; - int y = offset.y() % m_maskBounds.height() - offsetY; + int x = offset.x() % m_maskBounds.width() - m_offsetX; + int y = offset.y() % m_maskBounds.height() - m_offsetY; KisFillPainter fillPainter(fillDevice); fillPainter.fillRect(x - 1, y - 1, rect.width() + 2, rect.height() + 2, m_mask, m_maskBounds); fillPainter.end(); qreal pressure = m_strengthOption.apply(info); quint8 *dabData = dab->data(); KisHLineIteratorSP iter = fillDevice->createHLineIteratorNG(x, y, rect.width()); for (int row = 0; row < rect.height(); ++row) { for (int col = 0; col < rect.width(); ++col) { - if (texturingMode == MULTIPLY) { + if (m_texturingMode == MULTIPLY) { dab->colorSpace()->multiplyAlpha(dabData, quint8(*iter->oldRawData() * pressure), 1); } else { int pressureOffset = (1.0 - pressure) * 255; qint16 maskA = *iter->oldRawData() + pressureOffset; quint8 dabA = dab->colorSpace()->opacityU8(dabData); dabA = qMax(0, (qint16)dabA - maskA); dab->colorSpace()->setOpacity(dabData, dabA, 1); } iter->nextPixel(); dabData += dab->pixelSize(); } iter->nextRow(); } } diff --git a/krita/plugins/paintops/libpaintop/kis_texture_option.h b/krita/plugins/paintops/libpaintop/kis_texture_option.h index 54e77ebbe86..f755e0e386c 100644 --- a/krita/plugins/paintops/libpaintop/kis_texture_option.h +++ b/krita/plugins/paintops/libpaintop/kis_texture_option.h @@ -1,101 +1,101 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2012 * * 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_TEXTURE_OPTION_H #define KIS_TEXTURE_OPTION_H -#include +#include #include #include #include "kis_paintop_option.h" #include "kis_pressure_texture_strength_option.h" #include class KisTextureOptionWidget; class KoPattern; class KoResource; class KisPropertiesConfiguration; class PAINTOP_EXPORT KisTextureOption : public KisPaintOpOption { Q_OBJECT public: explicit KisTextureOption(QObject *parent = 0); virtual ~KisTextureOption(); public Q_SLOTS: virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const; virtual void readOptionSetting(const KisPropertiesConfiguration* setting); private Q_SLOTS: void resetGUI(KoResource*); /// called when a new pattern is selected private: KisTextureOptionWidget *m_optionWidget; }; class PAINTOP_EXPORT KisTextureProperties { public: KisTextureProperties() - : pattern(0) + : m_pattern(0) {} enum TexturingMode { MULTIPLY, SUBTRACT }; - bool enabled; + bool m_enabled; /** * @brief apply combine the texture map with the dab * @param dab the colored, final representation of the dab, after mirroring and everything. * @param offset the position of the dab on the image. used to calculate the position of the mask pattern */ void apply(KisFixedPaintDeviceSP dab, const QPoint& offset, const KisPaintInformation & info); void fillProperties(const KisPropertiesConfiguration *setting); private: - qreal scale; - int offsetX; - int offsetY; - TexturingMode texturingMode; - bool invert; - KoPattern *pattern; - int cutoffLeft; - int cutoffRight; - int cutoffPolicy; + qreal m_scale; + int m_offsetX; + int m_offsetY; + TexturingMode m_texturingMode; + bool m_invert; + KoPattern *m_pattern; + int m_cutoffLeft; + int m_cutoffRight; + int m_cutoffPolicy; private: KisPressureTextureStrengthOption m_strengthOption; QRect m_maskBounds; // this can be different from the extent if we mask out too many pixels in a big mask! KisPaintDeviceSP m_mask; void recalculateMask(); }; #endif // KIS_TEXTURE_OPTION_H diff --git a/krita/image/krita_export.h b/krita/plugins/paintops/libpaintop/kritapaintop_export.h similarity index 52% copy from krita/image/krita_export.h copy to krita/plugins/paintops/libpaintop/kritapaintop_export.h index 586d01fc6b2..b9cb6cfd6fc 100644 --- a/krita/image/krita_export.h +++ b/krita/plugins/paintops/libpaintop/kritapaintop_export.h @@ -1,99 +1,58 @@ /* This file is part of krita - Copyright (c) 2008 Boudewijn Rempt - Copyright (c) 2008 Thomas Zander + Copyright (c) 2015 Friedrich W. H. Kossebau 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 KRITA_EXPORT_H -#define KRITA_EXPORT_H +#ifndef KRITAPAINTOP_EXPORT_H +#define KRITAPAINTOP_EXPORT_H #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ #if defined(_WIN32) || defined(_WIN64) -#ifndef KRITASKETCH_EXPORT -# ifdef MAKE_KRITASKETCHLIB_LIB -# define KRITASKETCH_EXPORT KDE_EXPORT -# else -# define KRITASKETCH_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef KRITAUI_EXPORT -# ifdef MAKE_KRITAUI_LIB -# define KRITAUI_EXPORT KDE_EXPORT -# else -# define KRITAUI_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef KRITAIMAGE_EXPORT -# ifdef MAKE_KRITAIMAGE_LIB -# define KRITAIMAGE_EXPORT KDE_EXPORT -# else -# define KRITAIMAGE_EXPORT KDE_IMPORT -# endif -#endif - #ifndef PAINTOP_EXPORT # ifdef MAKE_KRITALIBPAINTOP_LIB # define PAINTOP_EXPORT KDE_EXPORT # else # define PAINTOP_EXPORT KDE_IMPORT # endif #endif -#ifndef BRUSH_EXPORT -# ifdef MAKE_KRITALIBBRUSH_LIB -# define BRUSH_EXPORT KDE_EXPORT -# else -# define BRUSH_EXPORT KDE_IMPORT -# endif -#endif - #else // not windows -#define KRITASKETCH_EXPORT KDE_EXPORT -#define KRITAUI_EXPORT KDE_EXPORT -#define KRITAIMAGE_EXPORT KDE_EXPORT #define PAINTOP_EXPORT KDE_EXPORT -#define BRUSH_EXPORT KDE_EXPORT #endif /* not windows */ /* Now the same for Krita*_TEST_EXPORT, if compiling with unit tests enabled */ #ifdef COMPILING_TESTS # if defined _WIN32 || defined _WIN64 -# if defined(MAKE_KRITAUI_LIB) || defined(MAKE_KRITAIMAGE_LIB) -# define KRITAIMAGE_TEST_EXPORT KDE_EXPORT -# define KRITAUI_TEST_EXPORT KDE_EXPORT +# if defined(MAKE_KRITALIBPAINTOP_LIB) +# define PAINTOP_TEST_EXPORT KDE_EXPORT # else -# define KRITAIMAGE_TEST_EXPORT KDE_IMPORT -# define KRITAUI_TEST_EXPORT KDE_IMPORT +# define PAINTOP_TEST_EXPORT KDE_IMPORT # endif # else /* not windows */ -# define KRITAIMAGE_TEST_EXPORT KDE_EXPORT -# define KRITAUI_TEST_EXPORT KDE_EXPORT +# define PAINTOP_TEST_EXPORT KDE_EXPORT # endif #else /* not compiling tests */ -# define KRITAIMAGE_TEST_EXPORT -# define KRITAUI_TEST_EXPORT +# define PAINTOP_TEST_EXPORT #endif -#endif /* KRITA_EXPORT_H */ +#endif /* KRITAPAINTOP_EXPORT_H */ diff --git a/krita/plugins/paintops/particle/kis_particleop_option.h b/krita/plugins/paintops/particle/kis_particleop_option.h index 3ff25adbf3c..931322838d1 100644 --- a/krita/plugins/paintops/particle/kis_particleop_option.h +++ b/krita/plugins/paintops/particle/kis_particleop_option.h @@ -1,53 +1,52 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_PARTICLEOP_OPTION_H #define KIS_PARTICLEOP_OPTION_H #include -#include const QString PARTICLE_COUNT = "Particle/count"; const QString PARTICLE_GRAVITY = "Particle/gravity"; const QString PARTICLE_WEIGHT = "Particle/weight"; const QString PARTICLE_ITERATIONS = "Particle/iterations"; const QString PARTICLE_SCALE_X = "Particle/scaleX"; const QString PARTICLE_SCALE_Y = "Particle/scaleY"; class KisParticleOpOptionsWidget; class KisParticleOpOption : public KisPaintOpOption { public: KisParticleOpOption(); ~KisParticleOpOption(); int particleCount() const; qreal weight() const; qreal gravity() const; int iterations() const; QPointF scale() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisParticleOpOptionsWidget * m_options; }; #endif diff --git a/krita/plugins/paintops/sketch/kis_sketch_paintop_settings.cpp b/krita/plugins/paintops/sketch/kis_sketch_paintop_settings.cpp index 1baf2bae46a..92a390a9422 100644 --- a/krita/plugins/paintops/sketch/kis_sketch_paintop_settings.cpp +++ b/krita/plugins/paintops/sketch/kis_sketch_paintop_settings.cpp @@ -1,85 +1,85 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_sketch_paintop_settings.h" #include #include #include #include "kis_current_outline_fetcher.h" KisSketchPaintOpSettings::KisSketchPaintOpSettings() { } bool KisSketchPaintOpSettings::paintIncremental() { return (enumPaintActionType)getInt("PaintOpAction", WASH) == BUILDUP; } bool KisSketchPaintOpSettings::isAirbrushing() const { return getBool(AIRBRUSH_ENABLED); } int KisSketchPaintOpSettings::rate() const { return getInt(AIRBRUSH_RATE); } QPainterPath KisSketchPaintOpSettings::brushOutline(const KisPaintInformation &info, OutlineMode mode) const { bool isSimpleMode = getBool(SKETCH_USE_SIMPLE_MODE); if (!isSimpleMode) { return KisBrushBasedPaintOpSettings::brushOutline(info, mode); } KisBrushBasedPaintopOptionWidget *widget = dynamic_cast(optionsWidget()); QPainterPath path; if (widget && (mode == CursorIsOutline || mode == CursorIsCircleOutline || mode == CursorTiltOutline)) { KisBrushSP brush = widget->brush(); // just circle supported qreal diameter = qMax(brush->width(), brush->height()); path = ellipseOutline(diameter, diameter, 1.0, 0.0/*brush->scale(), brush->angle()*/); QPainterPath tiltLine; QLineF tiltAngle(path.boundingRect().center(), path.boundingRect().topLeft()); - tiltAngle.setLength(qMax(diameter, 50.0) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); + tiltAngle.setLength(qMax(diameter, qreal(50.0)) * (1 - info.tiltElevation(info, 60.0, 60.0, true))); tiltAngle.setAngle((360.0 - fmod(KisPaintInformation::tiltDirection(info, true) * 360.0 + 270.0, 360.0))-3.0); tiltLine.moveTo(tiltAngle.p1()); tiltLine.lineTo(tiltAngle.p2()); qDebug()<fetchOutline(info, this, path); if (mode == CursorTiltOutline) { QPainterPath realOutline = brush->outline(); path.addPath(outlineFetcher()->fetchOutline(info, this, tiltLine, 1.0, 0.0, true, path.boundingRect().center().x(), path.boundingRect().center().y())); } } return path; } diff --git a/krita/plugins/paintops/sketch/kis_sketchop_option.h b/krita/plugins/paintops/sketch/kis_sketchop_option.h index 8062401100d..26ac14cd4b2 100644 --- a/krita/plugins/paintops/sketch/kis_sketchop_option.h +++ b/krita/plugins/paintops/sketch/kis_sketchop_option.h @@ -1,84 +1,83 @@ /* * Copyright (c) 2010 Lukáš Tvrdý * * 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_SKETCHOP_OPTION_H #define KIS_SKETCHOP_OPTION_H #include -#include const QString SKETCH_PROBABILITY = "Sketch/probability"; const QString SKETCH_DISTANCE_DENSITY = "Sketch/distanceDensity"; const QString SKETCH_OFFSET = "Sketch/offset"; const QString SKETCH_USE_SIMPLE_MODE = "Sketch/simpleMode"; const QString SKETCH_MAKE_CONNECTION = "Sketch/makeConnection"; const QString SKETCH_MAGNETIFY = "Sketch/magnetify"; const QString SKETCH_LINE_WIDTH = "Sketch/lineWidth"; const QString SKETCH_RANDOM_RGB = "Sketch/randomRGB"; const QString SKETCH_RANDOM_OPACITY = "Sketch/randomOpacity"; const QString SKETCH_DISTANCE_OPACITY = "Sketch/distanceOpacity"; class KisSketchOpOptionsWidget; class KisSketchOpOption : public KisPaintOpOption { public: KisSketchOpOption(); ~KisSketchOpOption(); void setThreshold(int radius) const; int threshold() const; void writeOptionSetting(KisPropertiesConfiguration* settings) const; void readOptionSetting(const KisPropertiesConfiguration* settings); private: KisSketchOpOptionsWidget * m_options; }; class SketchProperties { public: qreal offset; // perc qreal probability; // perc bool simpleMode; bool makeConnection; bool magnetify; bool randomRGB; bool randomOpacity; bool distanceOpacity; bool distanceDensity; int lineWidth; // px void readOptionSetting(const KisPropertiesConfiguration* settings) { probability = settings->getDouble(SKETCH_PROBABILITY); offset = settings->getDouble(SKETCH_OFFSET) * 0.01; lineWidth = settings->getInt(SKETCH_LINE_WIDTH); simpleMode = settings->getBool(SKETCH_USE_SIMPLE_MODE); makeConnection = settings->getBool(SKETCH_MAKE_CONNECTION); magnetify = settings->getBool(SKETCH_MAGNETIFY); randomRGB = settings->getBool(SKETCH_RANDOM_RGB); randomOpacity = settings->getBool(SKETCH_RANDOM_OPACITY); distanceDensity = settings->getBool(SKETCH_DISTANCE_DENSITY); distanceOpacity = settings->getBool(SKETCH_DISTANCE_OPACITY); } }; #endif diff --git a/krita/plugins/paintops/spray/kis_sprayop_option.h b/krita/plugins/paintops/spray/kis_sprayop_option.h index 53eaa65b971..6ec3a9d2a23 100644 --- a/krita/plugins/paintops/spray/kis_sprayop_option.h +++ b/krita/plugins/paintops/spray/kis_sprayop_option.h @@ -1,90 +1,89 @@ /* * Copyright (c) 2008,2009,2010 Lukáš Tvrdý * * 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_SPRAYOP_OPTION_H #define KIS_SPRAYOP_OPTION_H #include -#include const QString SPRAY_DIAMETER = "Spray/diameter"; const QString SPRAY_ASPECT = "Spray/aspect"; const QString SPRAY_COVERAGE = "Spray/coverage"; const QString SPRAY_SCALE = "Spray/scale"; const QString SPRAY_ROTATION = "Spray/rotation"; const QString SPRAY_PARTICLE_COUNT = "Spray/particleCount"; const QString SPRAY_JITTER_MOVE_AMOUNT = "Spray/jitterMoveAmount"; const QString SPRAY_JITTER_MOVEMENT = "Spray/jitterMovement"; const QString SPRAY_SPACING = "Spray/spacing"; const QString SPRAY_GAUSS_DISTRIBUTION = "Spray/gaussianDistribution"; const QString SPRAY_USE_DENSITY = "Spray/useDensity"; class KisSprayOpOptionsWidget; class KisSprayOpOption : public KisPaintOpOption { public: KisSprayOpOption(); ~KisSprayOpOption(); void setDiameter(int diameter) const; int diameter() const; qreal brushAspect() const; void writeOptionSetting(KisPropertiesConfiguration* setting) const; void readOptionSetting(const KisPropertiesConfiguration* setting); private: KisSprayOpOptionsWidget * m_options; }; class KisSprayProperties { public: quint16 diameter; quint16 radius; quint16 particleCount; qreal aspect; qreal coverage; qreal amount; qreal spacing; qreal scale; qreal brushRotation; bool jitterMovement; bool useDensity; bool gaussian; public: void loadSettings(const KisPropertiesConfiguration* settings) { diameter = settings->getInt(SPRAY_DIAMETER); radius = qRound(0.5 * diameter); aspect = settings->getDouble(SPRAY_ASPECT); particleCount = settings->getDouble(SPRAY_PARTICLE_COUNT); coverage = (settings->getDouble(SPRAY_COVERAGE) / 100.0); amount = settings->getDouble(SPRAY_JITTER_MOVE_AMOUNT); spacing = settings->getDouble(SPRAY_SPACING); scale = settings->getDouble(SPRAY_SCALE); brushRotation = settings->getDouble(SPRAY_ROTATION); jitterMovement = settings->getBool(SPRAY_JITTER_MOVEMENT); useDensity = settings->getBool(SPRAY_USE_DENSITY); gaussian = settings->getBool(SPRAY_GAUSS_DISTRIBUTION); } }; #endif diff --git a/krita/libpsd/libkispsd_export.h b/krita/plugins/tools/defaulttools/kritadefaulttools_export.h similarity index 55% copy from krita/libpsd/libkispsd_export.h copy to krita/plugins/tools/defaulttools/kritadefaulttools_export.h index fa028e7f943..2b11de71e7a 100644 --- a/krita/libpsd/libkispsd_export.h +++ b/krita/plugins/tools/defaulttools/kritadefaulttools_export.h @@ -1,45 +1,40 @@ -/* This file is part of the KDE project - Copyright (C) 2006 David Faure +/* + This file is part of krita + Copyright (c) 2015 Friedrich W. H. Kossebau 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. + * Boston, MA 02110-1301, USA. */ -#ifndef LIBKISPSD_EXPORT_H -#define LIBKISPSD_EXPORT_H +#ifndef KRITADEFAULTTOOLS_EXPORT_H +#define KRITADEFAULTTOOLS_EXPORT_H -/* needed for KDE_EXPORT and KDE_IMPORT macros */ #include -/* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ -#if defined _WIN32 || defined _WIN64 - -#ifndef KRITAPSD_EXPORT -# if defined(MAKE_KRITAPSD_LIB) -/* We are building this library */ -# define KRITAPSD_EXPORT KDE_EXPORT -# else -/* We are using this library */ -# define KRITAPSD_EXPORT KDE_IMPORT -# endif -#endif - -#else /* UNIX */ - -#define KRITAPSD_EXPORT KDE_EXPORT - +#ifdef COMPILING_TESTS +# if defined _WIN32 || defined _WIN64 +# if defined(MAKE_KRITADEFAULTTOOLS_LIB) +# define KRITADEFAULTTOOLS_TEST_EXPORT KDE_EXPORT +# else +# define KRITADEFAULTTOOLS_TEST_EXPORT KDE_IMPORT +# endif +# else /* not windows */ +# define KRITADEFAULTTOOLS_TEST_EXPORT KDE_EXPORT +# endif +#else /* not compiling tests */ +# define KRITADEFAULTTOOLS_TEST_EXPORT #endif -#endif +#endif /* KRITADEFAULTTOOLS_EXPORT_H */ diff --git a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h index 0fd9d45f530..e962a6a6372 100644 --- a/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h +++ b/krita/plugins/tools/defaulttools/strokes/move_stroke_strategy.h @@ -1,72 +1,73 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __MOVE_STROKE_STRATEGY_H #define __MOVE_STROKE_STRATEGY_H #include "kis_stroke_strategy_undo_command_based.h" #include "kis_types.h" +#include "kritadefaulttools_export.h" class KisUpdatesFacade; class KisPostExecutionUndoAdapter; -class KDE_EXPORT MoveStrokeStrategy : public KisStrokeStrategyUndoCommandBased +class KRITADEFAULTTOOLS_TEST_EXPORT MoveStrokeStrategy : public KisStrokeStrategyUndoCommandBased { public: - class KDE_EXPORT Data : public KisStrokeJobData { + class KRITADEFAULTTOOLS_TEST_EXPORT Data : public KisStrokeJobData { public: Data(QPoint _offset) : KisStrokeJobData(SEQUENTIAL, EXCLUSIVE), offset(_offset) { } QPoint offset; }; public: MoveStrokeStrategy(KisNodeSP node, KisUpdatesFacade *updatesFacade, KisPostExecutionUndoAdapter *undoAdapter); /** * You can use deferred initialization of the node pointer * To use it you need to pass NULL to the constructor, and * set the node with setNode layer. * NOTE: once set, you cannot change the node anymore, * you'll get an assert */ void setNode(KisNodeSP node); void finishStrokeCallback(); void cancelStrokeCallback(); void doStrokeCallback(KisStrokeJobData *data); private: void moveAndUpdate(QPoint offset); QRect moveNode(KisNodeSP node, QPoint offset); void addMoveCommands(KisNodeSP node, KUndo2Command *parent); private: KisNodeSP m_node; KisUpdatesFacade *m_updatesFacade; QPoint m_finalOffset; QRect m_dirtyRect; }; #endif /* __MOVE_STROKE_STRATEGY_H */ diff --git a/krita/plugins/tools/tool_polygon/kis_tool_polygon.h b/krita/plugins/tools/tool_polygon/kis_tool_polygon.h index 790831467f3..5a8e75aaeb8 100644 --- a/krita/plugins/tools/tool_polygon/kis_tool_polygon.h +++ b/krita/plugins/tools/tool_polygon/kis_tool_polygon.h @@ -1,68 +1,68 @@ /* * kis_tool_polygon.h - part of Krita * * Copyright (c) 2004 Michael Thaler * * 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_POLYGON_H_ #define KIS_TOOL_POLYGON_H_ #include "kis_tool_shape.h" #include "flake/kis_node_shape.h" #include #include class KoCanvasBase; class KisToolPolygon : public KisToolPolylineBase { Q_OBJECT public: KisToolPolygon(KoCanvasBase *canvas); virtual ~KisToolPolygon(); protected: virtual void finishPolyline(const QVector& points); protected Q_SLOTS: virtual void resetCursorStyle(); }; #include "KoToolFactoryBase.h" class KisToolPolygonFactory : public KoToolFactoryBase { public: KisToolPolygonFactory(const QStringList&) : KoToolFactoryBase("KisToolPolygon") { setToolTip(i18n("Polygon Tool. Shift-mouseclick ends the polygon.")); setToolType(TOOL_TYPE_SHAPE); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); - setIconName(koIconNameCStr("tool_polygon")); + setIconName(koIconNameCStr("krita_tool_polygon")); setPriority(4); } virtual ~KisToolPolygonFactory() {} virtual KoToolBase * createTool(KoCanvasBase *canvas) { return new KisToolPolygon(canvas); } }; #endif //__KIS_TOOL_POLYGON_H__ diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform.cc b/krita/plugins/tools/tool_transform2/kis_tool_transform.cc index df42df8a580..8bff9d84e3d 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform.cc +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform.cc @@ -1,1145 +1,1160 @@ /* * kis_tool_transform.cc -- part of Krita * * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2005 C. Boemann * Copyright (c) 2010 Marc Pegon * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_tool_transform.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "widgets/kis_progress_widget.h" #include "kis_transform_utils.h" #include "kis_warp_transform_strategy.h" #include "kis_cage_transform_strategy.h" #include "kis_liquify_transform_strategy.h" #include "kis_free_transform_strategy.h" #include "kis_perspective_transform_strategy.h" #include "kis_transform_mask.h" #include "kis_transform_mask_adapter.h" #include "strokes/transform_stroke_strategy.h" KisToolTransform::KisToolTransform(KoCanvasBase * canvas) : KisTool(canvas, KisCursor::rotateCursor()) , m_workRecursively(true) , m_changesTracker(&m_transaction) , m_warpStrategy( new KisWarpTransformStrategy( dynamic_cast(canvas)->coordinatesConverter(), m_currentArgs, m_transaction)) , m_cageStrategy( new KisCageTransformStrategy( dynamic_cast(canvas)->coordinatesConverter(), m_currentArgs, m_transaction)) , m_liquifyStrategy( new KisLiquifyTransformStrategy( dynamic_cast(canvas)->coordinatesConverter(), m_currentArgs, m_transaction)) , m_freeStrategy( new KisFreeTransformStrategy( dynamic_cast(canvas)->coordinatesConverter(), m_currentArgs, m_transaction)) , m_perspectiveStrategy( new KisPerspectiveTransformStrategy( dynamic_cast(canvas)->coordinatesConverter(), m_currentArgs, m_transaction)) { m_canvas = dynamic_cast(canvas); Q_ASSERT(m_canvas); setObjectName("tool_transform"); useCursor(KisCursor::selectCursor()); m_optionsWidget = 0; connect(m_warpStrategy.data(), SIGNAL(requestCanvasUpdate()), SLOT(canvasUpdateRequested())); connect(m_cageStrategy.data(), SIGNAL(requestCanvasUpdate()), SLOT(canvasUpdateRequested())); connect(m_liquifyStrategy.data(), SIGNAL(requestCanvasUpdate()), SLOT(canvasUpdateRequested())); connect(m_liquifyStrategy.data(), SIGNAL(requestCursorOutlineUpdate(const QPointF&)), SLOT(cursorOutlineUpdateRequested(const QPointF&))); connect(m_liquifyStrategy.data(), SIGNAL(requestUpdateOptionWidget()), SLOT(updateOptionWidget())); connect(m_freeStrategy.data(), SIGNAL(requestCanvasUpdate()), SLOT(canvasUpdateRequested())); connect(m_freeStrategy.data(), SIGNAL(requestResetRotationCenterButtons()), SLOT(resetRotationCenterButtonsRequested())); connect(m_freeStrategy.data(), SIGNAL(requestShowImageTooBig(bool)), SLOT(imageTooBigRequested(bool))); connect(m_perspectiveStrategy.data(), SIGNAL(requestCanvasUpdate()), SLOT(canvasUpdateRequested())); connect(m_perspectiveStrategy.data(), SIGNAL(requestShowImageTooBig(bool)), SLOT(imageTooBigRequested(bool))); connect(&m_changesTracker, SIGNAL(sigConfigChanged()), this, SLOT(slotTrackerChangedConfig())); } KisToolTransform::~KisToolTransform() { cancelStroke(); } void KisToolTransform::outlineChanged() { emit freeTransformChanged(); m_canvas->updateCanvas(); } void KisToolTransform::canvasUpdateRequested() { m_canvas->updateCanvas(); } void KisToolTransform::resetCursorStyle() { KisTool::resetCursorStyle(); overrideCursorIfNotEditable(); } void KisToolTransform::resetRotationCenterButtonsRequested() { if (!m_optionsWidget) return; m_optionsWidget->resetRotationCenterButtons(); } void KisToolTransform::imageTooBigRequested(bool value) { if (!m_optionsWidget) return; m_optionsWidget->setTooBigLabelVisible(value); } KisTransformStrategyBase* KisToolTransform::currentStrategy() const { if (m_currentArgs.mode() == ToolTransformArgs::FREE_TRANSFORM) { return m_freeStrategy.data(); } else if (m_currentArgs.mode() == ToolTransformArgs::WARP) { return m_warpStrategy.data(); } else if (m_currentArgs.mode() == ToolTransformArgs::CAGE) { return m_cageStrategy.data(); } else if (m_currentArgs.mode() == ToolTransformArgs::LIQUIFY) { return m_liquifyStrategy.data(); } else /* if (m_currentArgs.mode() == ToolTransformArgs::PERSPECTIVE_4POINT) */ { return m_perspectiveStrategy.data(); } } void KisToolTransform::paint(QPainter& gc, const KoViewConverter &converter) { Q_UNUSED(converter); if (!m_strokeData.strokeId()) return; QRectF newRefRect = KisTransformUtils::imageToFlake(m_canvas->coordinatesConverter(), QRectF(0.0,0.0,1.0,1.0)); if (m_refRect != newRefRect) { m_refRect = newRefRect; currentStrategy()->externalConfigChanged(); } gc.save(); if (m_optionsWidget && m_optionsWidget->showDecorations()) { gc.setOpacity(0.3); gc.fillPath(m_selectionPath, Qt::black); } gc.restore(); currentStrategy()->paint(gc); if (!m_cursorOutline.isEmpty()) { QPainterPath mappedOutline = KisTransformUtils::imageToFlakeTransform( m_canvas->coordinatesConverter()).map(m_cursorOutline); paintToolOutline(&gc, mappedOutline); } } void KisToolTransform::setFunctionalCursor() { if (overrideCursorIfNotEditable()) { return; } if (!m_strokeData.strokeId()) { useCursor(KisCursor::pointingHandCursor()); } else { useCursor(currentStrategy()->getCurrentCursor()); } } void KisToolTransform::cursorOutlineUpdateRequested(const QPointF &imagePos) { QRect canvasUpdateRect; if (!m_cursorOutline.isEmpty()) { canvasUpdateRect = m_canvas->coordinatesConverter()-> imageToDocument(m_cursorOutline.boundingRect()).toAlignedRect(); } m_cursorOutline = currentStrategy()-> getCursorOutline().translated(imagePos); if (!m_cursorOutline.isEmpty()) { canvasUpdateRect |= m_canvas->coordinatesConverter()-> imageToDocument(m_cursorOutline.boundingRect()).toAlignedRect(); } if (!canvasUpdateRect.isEmpty()) { // grow rect a bit to follow interpolation fuzziness canvasUpdateRect = kisGrowRect(canvasUpdateRect, 2); m_canvas->updateCanvas(canvasUpdateRect); } } void KisToolTransform::beginActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action) { if (!nodeEditable()) { event->ignore(); return; } if (!m_strokeData.strokeId()) { startStroke(m_currentArgs.mode()); } else { bool result = false; if (usePrimaryAction) { result = currentStrategy()->beginPrimaryAction(event); } else { result = currentStrategy()->beginAlternateAction(event, action); } if (result) { setMode(KisTool::PAINT_MODE); } } m_actuallyMoveWhileSelected = false; outlineChanged(); } void KisToolTransform::continueActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action) { if (mode() != KisTool::PAINT_MODE) return; m_actuallyMoveWhileSelected = true; if (usePrimaryAction) { currentStrategy()->continuePrimaryAction(event); } else { currentStrategy()->continueAlternateAction(event, action); } updateOptionWidget(); outlineChanged(); } void KisToolTransform::endActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action) { if (mode() != KisTool::PAINT_MODE) return; setMode(KisTool::HOVER_MODE); if (m_actuallyMoveWhileSelected || currentStrategy()->acceptsClicks()) { bool result = false; if (usePrimaryAction) { result = currentStrategy()->endPrimaryAction(event); } else { result = currentStrategy()->endAlternateAction(event, action); } if (result) { commitChanges(); } outlineChanged(); } updateOptionWidget(); updateApplyResetAvailability(); } void KisToolTransform::beginPrimaryAction(KoPointerEvent *event) { beginActionImpl(event, true, KisTool::NONE); } void KisToolTransform::continuePrimaryAction(KoPointerEvent *event) { continueActionImpl(event, true, KisTool::NONE); } void KisToolTransform::endPrimaryAction(KoPointerEvent *event) { endActionImpl(event, true, KisTool::NONE); } void KisToolTransform::activateAlternateAction(AlternateAction action) { currentStrategy()->activateAlternateAction(action); } void KisToolTransform::deactivateAlternateAction(AlternateAction action) { currentStrategy()->deactivateAlternateAction(action); } void KisToolTransform::beginAlternateAction(KoPointerEvent *event, AlternateAction action) { beginActionImpl(event, false, action); } void KisToolTransform::continueAlternateAction(KoPointerEvent *event, AlternateAction action) { continueActionImpl(event, false, action); } void KisToolTransform::endAlternateAction(KoPointerEvent *event, AlternateAction action) { endActionImpl(event, false, action); } void KisToolTransform::mousePressEvent(KoPointerEvent *event) { KisTool::mousePressEvent(event); } void KisToolTransform::mouseMoveEvent(KoPointerEvent *event) { QPointF mousePos = m_canvas->coordinatesConverter()->documentToImage(event->point); cursorOutlineUpdateRequested(mousePos); if (!MOVE_CONDITION(event, KisTool::PAINT_MODE)) { currentStrategy()->hoverActionCommon(event); setFunctionalCursor(); KisTool::mouseMoveEvent(event); return; } } void KisToolTransform::mouseReleaseEvent(KoPointerEvent *event) { KisTool::mouseReleaseEvent(event); } void KisToolTransform::touchEvent( QTouchEvent* event ) { //Count all moving touch points int touchCount = 0; foreach( QTouchEvent::TouchPoint tp, event->touchPoints() ) { if( tp.state() == Qt::TouchPointMoved ) { touchCount++; } } //Use the touch point count to determine the gesture switch( touchCount ) { case 1: { //Panning QTouchEvent::TouchPoint tp = event->touchPoints().at( 0 ); QPointF diff = tp.screenPos() - tp.lastScreenPos(); m_currentArgs.setTransformedCenter( m_currentArgs.transformedCenter() + diff ); outlineChanged(); break; } case 2: { //Scaling QTouchEvent::TouchPoint tp1 = event->touchPoints().at( 0 ); QTouchEvent::TouchPoint tp2 = event->touchPoints().at( 1 ); float lastZoom = (tp1.lastScreenPos() - tp2.lastScreenPos()).manhattanLength(); float newZoom = (tp1.screenPos() - tp2.screenPos()).manhattanLength(); float diff = (newZoom - lastZoom) / 100; m_currentArgs.setScaleX( m_currentArgs.scaleX() + diff ); m_currentArgs.setScaleY( m_currentArgs.scaleY() + diff ); outlineChanged(); break; } case 3: { //Rotation /* TODO: implement touch-based rotation. Vector2f center; foreach( const QTouchEvent::TouchPoint &tp, event->touchPoints() ) { if( tp.state() == Qt::TouchPointMoved ) { center += Vector2f( tp.screenPos().x(), tp.screenPos().y() ); } } center /= touchCount; QTouchEvent::TouchPoint tp = event->touchPoints().at(0); Vector2f oldPosition = (Vector2f( tp.lastScreenPos().x(), tp.lastScreenPos().y() ) - center).normalized(); Vector2f newPosition = (Vector2f( tp.screenPos().x(), tp.screenPos().y() ) - center).normalized(); float oldAngle = qAcos( oldPosition.dot( Vector2f( 0.0f, 0.0f ) ) ); float newAngle = qAcos( newPosition.dot( Vector2f( 0.0f, 0.0f ) ) ); float diff = newAngle - oldAngle; m_currentArgs.setAZ( m_currentArgs.aZ() + diff ); outlineChanged(); */ break; } } } void KisToolTransform::applyTransform() { slotApplyTransform(); } KisToolTransform::TransformToolMode KisToolTransform::transformMode() const { TransformToolMode mode = FreeTransformMode; switch (m_currentArgs.mode()) { case ToolTransformArgs::FREE_TRANSFORM: mode = FreeTransformMode; break; case ToolTransformArgs::WARP: mode = WarpTransformMode; break; case ToolTransformArgs::CAGE: mode = CageTransformMode; break; case ToolTransformArgs::LIQUIFY: mode = LiquifyTransformMode; break; case ToolTransformArgs::PERSPECTIVE_4POINT: mode = PerspectiveTransformMode; break; default: KIS_ASSERT_RECOVER_NOOP(0 && "unexpected transform mode"); } return mode; } double KisToolTransform::translateX() const { return m_currentArgs.transformedCenter().x(); } double KisToolTransform::translateY() const { return m_currentArgs.transformedCenter().y(); } double KisToolTransform::rotateX() const { return m_currentArgs.aX(); } double KisToolTransform::rotateY() const { return m_currentArgs.aY(); } double KisToolTransform::rotateZ() const { return m_currentArgs.aZ(); } double KisToolTransform::scaleX() const { return m_currentArgs.scaleX(); } double KisToolTransform::scaleY() const { return m_currentArgs.scaleY(); } double KisToolTransform::shearX() const { return m_currentArgs.shearX(); } double KisToolTransform::shearY() const { return m_currentArgs.shearY(); } KisToolTransform::WarpType KisToolTransform::warpType() const { switch(m_currentArgs.warpType()) { case KisWarpTransformWorker::AFFINE_TRANSFORM: return AffineWarpType; case KisWarpTransformWorker::RIGID_TRANSFORM: return RigidWarpType; case KisWarpTransformWorker::SIMILITUDE_TRANSFORM: return SimilitudeWarpType; default: return RigidWarpType; } } double KisToolTransform::warpFlexibility() const { return m_currentArgs.alpha(); } int KisToolTransform::warpPointDensity() const { return m_currentArgs.numPoints(); } void KisToolTransform::setTransformMode(KisToolTransform::TransformToolMode newMode) { ToolTransformArgs::TransformMode mode = ToolTransformArgs::FREE_TRANSFORM; switch (newMode) { case FreeTransformMode: mode = ToolTransformArgs::FREE_TRANSFORM; break; case WarpTransformMode: mode = ToolTransformArgs::WARP; break; case CageTransformMode: mode = ToolTransformArgs::CAGE; break; case LiquifyTransformMode: mode = ToolTransformArgs::LIQUIFY; break; case PerspectiveTransformMode: mode = ToolTransformArgs::PERSPECTIVE_4POINT; break; default: KIS_ASSERT_RECOVER_NOOP(0 && "unexpected transform mode"); } if( mode != m_currentArgs.mode() ) { if( newMode == FreeTransformMode ) { m_optionsWidget->slotSetFreeTransformModeButtonClicked( true ); } else if( newMode == WarpTransformMode ) { m_optionsWidget->slotSetWarpModeButtonClicked( true ); } else if( newMode == CageTransformMode ) { m_optionsWidget->slotSetCageModeButtonClicked( true ); } else if( newMode == LiquifyTransformMode ) { m_optionsWidget->slotSetLiquifyModeButtonClicked( true ); } else if( newMode == PerspectiveTransformMode ) { m_optionsWidget->slotSetPerspectiveModeButtonClicked( true ); } emit transformModeChanged(); } } void KisToolTransform::setRotateX( double rotation ) { m_currentArgs.setAX( normalizeAngle(rotation) ); } void KisToolTransform::setRotateY( double rotation ) { m_currentArgs.setAY( normalizeAngle(rotation) ); } void KisToolTransform::setRotateZ( double rotation ) { m_currentArgs.setAZ( normalizeAngle(rotation) ); } void KisToolTransform::setWarpType( KisToolTransform::WarpType type ) { switch( type ) { case RigidWarpType: m_currentArgs.setWarpType(KisWarpTransformWorker::RIGID_TRANSFORM); break; case AffineWarpType: m_currentArgs.setWarpType(KisWarpTransformWorker::AFFINE_TRANSFORM); break; case SimilitudeWarpType: m_currentArgs.setWarpType(KisWarpTransformWorker::SIMILITUDE_TRANSFORM); break; default: break; } } void KisToolTransform::setWarpFlexibility( double flexibility ) { m_currentArgs.setAlpha( flexibility ); } void KisToolTransform::setWarpPointDensity( int density ) { m_optionsWidget->slotSetWarpDensity(density); } bool KisToolTransform::tryInitTransformModeFromNode(KisNodeSP node) { bool result = false; if (KisTransformMaskSP mask = dynamic_cast(node.data())) { KisTransformMaskParamsInterfaceSP savedParams = mask->transformParams(); KisTransformMaskAdapter *adapter = dynamic_cast(savedParams.data()); if (adapter) { m_currentArgs = adapter->savedArgs(); initGuiAfterTransformMode(); result = true; } } return result; } bool KisToolTransform::tryFetchArgsFromCommandAndUndo(ToolTransformArgs *args, ToolTransformArgs::TransformMode mode, KisNodeSP currentNode) { bool result = false; const KUndo2Command *lastCommand = image()->undoAdapter()->presentCommand(); KisNodeSP oldRootNode; if (lastCommand && TransformStrokeStrategy::fetchArgsFromCommand(lastCommand, args, &oldRootNode) && args->mode() == mode && oldRootNode == currentNode) { args->saveContinuedState(); image()->undoAdapter()->undoLastCommand(); // FIXME: can we make it async? image()->waitForDone(); result = true; } return result; } void KisToolTransform::initTransformMode(ToolTransformArgs::TransformMode mode) { // NOTE: we are requesting an old value of m_currentArgs variable // here, which is global, don't forget about this on higher // levels. QString filterId = m_currentArgs.filterId(); m_currentArgs = ToolTransformArgs(); m_currentArgs.setOriginalCenter(m_transaction.originalCenterGeometric()); m_currentArgs.setTransformedCenter(m_transaction.originalCenterGeometric()); if (mode == ToolTransformArgs::FREE_TRANSFORM) { m_currentArgs.setMode(ToolTransformArgs::FREE_TRANSFORM); } else if (mode == ToolTransformArgs::WARP) { m_currentArgs.setMode(ToolTransformArgs::WARP); m_optionsWidget->setDefaultWarpPoints(); m_currentArgs.setEditingTransformPoints(false); } else if (mode == ToolTransformArgs::CAGE) { m_currentArgs.setMode(ToolTransformArgs::CAGE); m_currentArgs.setEditingTransformPoints(true); } else if (mode == ToolTransformArgs::LIQUIFY) { m_currentArgs.setMode(ToolTransformArgs::LIQUIFY); const QRect srcRect = m_transaction.originalRect().toAlignedRect(); if (!srcRect.isEmpty()) { m_currentArgs.initLiquifyTransformMode(m_transaction.originalRect().toAlignedRect()); } } else if (mode == ToolTransformArgs::PERSPECTIVE_4POINT) { m_currentArgs.setMode(ToolTransformArgs::PERSPECTIVE_4POINT); } initGuiAfterTransformMode(); } void KisToolTransform::initGuiAfterTransformMode() { currentStrategy()->externalConfigChanged(); outlineChanged(); updateOptionWidget(); updateApplyResetAvailability(); } void KisToolTransform::updateSelectionPath() { m_selectionPath = QPainterPath(); KisResourcesSnapshotSP resources = new KisResourcesSnapshot(image(), currentNode(), 0, this->canvas()->resourceManager()); QPainterPath selectionOutline; KisSelectionSP selection = resources->activeSelection(); if (selection && selection->outlineCacheValid()) { selectionOutline = selection->outlineCache(); } else { selectionOutline.addRect(m_selectedPortionCache->exactBounds()); } const KisCoordinatesConverter *converter = m_canvas->coordinatesConverter(); QTransform i2f = converter->imageToDocumentTransform() * converter->documentToFlakeTransform(); m_selectionPath = i2f.map(selectionOutline); } void KisToolTransform::initThumbnailImage(KisPaintDeviceSP previewDevice) { QImage origImg; m_selectedPortionCache = previewDevice; QTransform thumbToImageTransform; const int maxSize = 2000; QRect srcRect(m_transaction.originalRect().toAlignedRect()); int x, y, w, h; srcRect.getRect(&x, &y, &w, &h); if (w > maxSize || h > maxSize) { qreal scale = qreal(maxSize) / (w > h ? w : h); QTransform scaleTransform = QTransform::fromScale(scale, scale); QRect thumbRect = scaleTransform.mapRect(m_transaction.originalRect()).toAlignedRect(); origImg = m_selectedPortionCache-> createThumbnail(thumbRect.width(), thumbRect.height(), srcRect, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); thumbToImageTransform = scaleTransform.inverted(); } else { origImg = m_selectedPortionCache->convertToQImage(0, x, y, w, h, KoColorConversionTransformation::InternalRenderingIntent, KoColorConversionTransformation::InternalConversionFlags); thumbToImageTransform = QTransform(); } // init both strokes since the thumbnail is initialized only once // during the stroke m_freeStrategy->setThumbnailImage(origImg, thumbToImageTransform); m_perspectiveStrategy->setThumbnailImage(origImg, thumbToImageTransform); m_warpStrategy->setThumbnailImage(origImg, thumbToImageTransform); m_cageStrategy->setThumbnailImage(origImg, thumbToImageTransform); m_liquifyStrategy->setThumbnailImage(origImg, thumbToImageTransform); } void KisToolTransform::activate(ToolActivation toolActivation, const QSet &shapes) { KisTool::activate(toolActivation, shapes); if (currentNode()) { m_transaction = TransformTransactionProperties(QRectF(), &m_currentArgs, currentNode()); } startStroke(ToolTransformArgs::FREE_TRANSFORM); } void KisToolTransform::deactivate() { endStroke(); m_canvas->updateCanvas(); KisTool::deactivate(); } void KisToolTransform::requestUndoDuringStroke() { if (!m_strokeData.strokeId()) return; m_changesTracker.requestUndo(); } void KisToolTransform::requestStrokeEnd() { endStroke(); } void KisToolTransform::requestStrokeCancellation() { cancelStroke(); } void KisToolTransform::startStroke(ToolTransformArgs::TransformMode mode) { Q_ASSERT(!m_strokeData.strokeId()); KisPaintDeviceSP dev; KisResourcesSnapshotSP resources = new KisResourcesSnapshot(image(), currentNode(), 0, this->canvas()->resourceManager()); KisNodeSP currentNode = resources->currentNode(); if (!currentNode || !currentNode->isEditable()) { return; } /** * FIXME: The transform tool is not completely asynchronous, it * needs the content of the layer for creation of the stroke * strategy. It means that we cannot start a new stroke until the * previous one is finished. Ideally, we should create the * m_selectedPortionCache and m_selectionPath somewhere in the * stroke and pass it to the tool somehow. But currently, we will * just disable starting a new stroke asynchronously */ if (image()->tryBarrierLock()) { image()->unlock(); } else { return; } ToolTransformArgs fetchedArgs; bool fetchedFromCommand = tryFetchArgsFromCommandAndUndo(&fetchedArgs, mode, currentNode); if (m_optionsWidget) { m_workRecursively = m_optionsWidget->workRecursively() || !currentNode->paintDevice(); } TransformStrokeStrategy *strategy = new TransformStrokeStrategy(currentNode, resources->activeSelection(), image()->postExecutionUndoAdapter()); KisPaintDeviceSP previewDevice = strategy->previewDevice(); KisSelectionSP selection = strategy->realSelection(); QRect srcRect = selection ? selection->selectedExactRect() : previewDevice->exactBounds(); if (!selection && resources->activeSelection()) { KisCanvas2 *kisCanvas = dynamic_cast(canvas()); kisCanvas->viewManager()-> showFloatingMessage( i18nc("floating message in transformation tool", "Selections are not used when editing transform masks "), QIcon(), 4000, KisFloatingMessage::Low); } if (srcRect.isEmpty()) { delete strategy; KisCanvas2 *kisCanvas = dynamic_cast(canvas()); kisCanvas->viewManager()-> showFloatingMessage( i18nc("floating message in transformation tool", "Cannot transform empty layer "), QIcon(), 1000, KisFloatingMessage::Medium); return; } m_transaction = TransformTransactionProperties(srcRect, &m_currentArgs, currentNode); initThumbnailImage(previewDevice); updateSelectionPath(); if (fetchedFromCommand) { m_currentArgs = fetchedArgs; initGuiAfterTransformMode(); } else if (!tryInitTransformModeFromNode(currentNode)) { initTransformMode(mode); } m_strokeData = StrokeData(image()->startStroke(strategy)); - clearDevices(m_transaction.rootNode(), m_workRecursively); + + bool haveInvisibleNodes = clearDevices(m_transaction.rootNode(), m_workRecursively); + if (haveInvisibleNodes) { + KisCanvas2 *kisCanvas = dynamic_cast(canvas()); + kisCanvas->viewManager()-> + showFloatingMessage( + i18nc("floating message in transformation tool", + "Invisible sublayers will also be transformed. Lock layers if you do not want them to be transformed "), + QIcon(), 4000, KisFloatingMessage::Low); + } + Q_ASSERT(m_changesTracker.isEmpty()); commitChanges(); } void KisToolTransform::endStroke() { if (!m_strokeData.strokeId()) return; if (!m_currentArgs.isIdentity()) { transformDevices(m_transaction.rootNode(), m_workRecursively); image()->addJob(m_strokeData.strokeId(), new TransformStrokeStrategy::TransformData( TransformStrokeStrategy::TransformData::SELECTION, m_currentArgs, m_transaction.rootNode())); image()->endStroke(m_strokeData.strokeId()); } else { image()->cancelStroke(m_strokeData.strokeId()); } m_strokeData.clear(); m_changesTracker.reset(); } void KisToolTransform::cancelStroke() { if (!m_strokeData.strokeId()) return; if (m_currentArgs.continuedTransform()) { m_currentArgs.restoreContinuedState(); endStroke(); } else { image()->cancelStroke(m_strokeData.strokeId()); m_strokeData.clear(); m_changesTracker.reset(); } } void KisToolTransform::commitChanges() { if (!m_strokeData.strokeId()) return; m_changesTracker.commitConfig(m_currentArgs); } void KisToolTransform::slotTrackerChangedConfig() { slotUiChangedConfig(); updateOptionWidget(); } -void KisToolTransform::clearDevices(KisNodeSP node, bool recursive) +bool KisToolTransform::clearDevices(KisNodeSP node, bool recursive) { - if (!node->isEditable()) return; + bool haveInvisibleNodes = false; + if (!node->isEditable(false)) return haveInvisibleNodes; + + haveInvisibleNodes = !node->visible(false); if (recursive) { // simple tail-recursive iteration KisNodeSP prevNode = node->lastChild(); while(prevNode) { - clearDevices(prevNode, recursive); + haveInvisibleNodes |= clearDevices(prevNode, recursive); prevNode = prevNode->prevSibling(); } } image()->addJob(m_strokeData.strokeId(), new TransformStrokeStrategy::ClearSelectionData(node)); /** * It might happen that the editablity state of the node would * change during the stroke, so we need to save the set of * applicable nodes right in the beginning of the processing */ m_strokeData.addClearedNode(node); + + return haveInvisibleNodes; } void KisToolTransform::transformDevices(KisNodeSP node, bool recursive) { if (!node->isEditable()) return; KIS_ASSERT_RECOVER_RETURN(recursive || (m_strokeData.clearedNodes().size() == 1 && KisNodeSP(m_strokeData.clearedNodes().first()) == node)); foreach (KisNodeSP currentNode, m_strokeData.clearedNodes()) { KIS_ASSERT_RECOVER_RETURN(currentNode); image()->addJob(m_strokeData.strokeId(), new TransformStrokeStrategy::TransformData( TransformStrokeStrategy::TransformData::PAINT_DEVICE, m_currentArgs, currentNode)); } } QWidget* KisToolTransform::createOptionWidget() { m_optionsWidget = new KisToolTransformConfigWidget(&m_transaction, m_canvas, m_workRecursively, 0); Q_CHECK_PTR(m_optionsWidget); m_optionsWidget->setObjectName(toolId() + " option widget"); // See https://bugs.kde.org/show_bug.cgi?id=316896 QWidget *specialSpacer = new QWidget(m_optionsWidget); specialSpacer->setObjectName("SpecialSpacer"); specialSpacer->setFixedSize(0, 0); m_optionsWidget->layout()->addWidget(specialSpacer); connect(m_optionsWidget, SIGNAL(sigConfigChanged()), this, SLOT(slotUiChangedConfig())); connect(m_optionsWidget, SIGNAL(sigApplyTransform()), this, SLOT(slotApplyTransform())); connect(m_optionsWidget, SIGNAL(sigResetTransform()), this, SLOT(slotResetTransform())); connect(m_optionsWidget, SIGNAL(sigRestartTransform()), this, SLOT(slotRestartTransform())); connect(m_optionsWidget, SIGNAL(sigEditingFinished()), this, SLOT(slotEditingFinished())); updateOptionWidget(); return m_optionsWidget; } void KisToolTransform::updateOptionWidget() { if (!m_optionsWidget) return; if (!currentNode()) { m_optionsWidget->setEnabled(false); return; } else { m_optionsWidget->setEnabled(true); m_optionsWidget->updateConfig(m_currentArgs); } } void KisToolTransform::updateApplyResetAvailability() { if (m_optionsWidget) { m_optionsWidget->setApplyResetDisabled(m_currentArgs.isIdentity()); } } void KisToolTransform::slotUiChangedConfig() { if (mode() == KisTool::PAINT_MODE) return; currentStrategy()->externalConfigChanged(); if (m_currentArgs.mode() == ToolTransformArgs::LIQUIFY) { m_currentArgs.saveLiquifyTransformMode(); } outlineChanged(); updateApplyResetAvailability(); } void KisToolTransform::slotApplyTransform() { QApplication::setOverrideCursor(KisCursor::waitCursor()); endStroke(); QApplication::restoreOverrideCursor(); } void KisToolTransform::slotResetTransform() { if (m_currentArgs.continuedTransform()) { ToolTransformArgs::TransformMode savedMode = m_currentArgs.mode(); if (m_currentArgs.continuedTransform()->mode() == savedMode) { m_currentArgs.restoreContinuedState(); initGuiAfterTransformMode(); slotEditingFinished(); } else { cancelStroke(); image()->waitForDone(); startStroke(savedMode); KIS_ASSERT_RECOVER_NOOP(!m_currentArgs.continuedTransform()); } } else { initTransformMode(m_currentArgs.mode()); slotEditingFinished(); } } void KisToolTransform::slotRestartTransform() { if (!m_strokeData.strokeId()) return; ToolTransformArgs savedArgs(m_currentArgs); cancelStroke(); image()->waitForDone(); startStroke(savedArgs.mode()); } void KisToolTransform::slotEditingFinished() { commitChanges(); } void KisToolTransform::setShearY(double shear) { m_optionsWidget->slotSetShearY(shear); } void KisToolTransform::setShearX(double shear) { m_optionsWidget->slotSetShearX(shear); } void KisToolTransform::setScaleY(double scale) { m_optionsWidget->slotSetScaleY(scale); } void KisToolTransform::setScaleX(double scale) { m_optionsWidget->slotSetScaleX(scale); } void KisToolTransform::setTranslateY(double translation) { m_optionsWidget->slotSetTranslateY(translation); } void KisToolTransform::setTranslateX(double translation) { m_optionsWidget->slotSetTranslateX(translation); } #include "kis_tool_transform.moc" diff --git a/krita/plugins/tools/tool_transform2/kis_tool_transform.h b/krita/plugins/tools/tool_transform2/kis_tool_transform.h index 567437b2669..165c2305f23 100644 --- a/krita/plugins/tools/tool_transform2/kis_tool_transform.h +++ b/krita/plugins/tools/tool_transform2/kis_tool_transform.h @@ -1,326 +1,326 @@ /* * kis_tool_transform.h - part of Krita * * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2005 C. Boemann * Copyright (c) 2010 Marc Pegon * * 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_TRANSFORM_H_ #define KIS_TOOL_TRANSFORM_H_ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "tool_transform_args.h" #include "tool_transform_changes_tracker.h" #include "kis_tool_transform_config_widget.h" #include "transform_transaction_properties.h" class KisCanvas2; class QTouchEvent; class KisTransformStrategyBase; class KisWarpTransformStrategy; class KisCageTransformStrategy; class KisLiquifyTransformStrategy; class KisFreeTransformStrategy; class KisPerspectiveTransformStrategy; /** * Transform tool * The tool offers two different modes : Free Transform and Warp * - Free Transform mode allows the user to translate, scale, shear, rotate * and apply a perspective transformation to a selection or the whole * canvas. * - Warp mode allows the user to warp the selection of the canvas * by grabbing and moving control points placed on the image. * The user can either work with default control points, like a grid * whose density can be modified, or place the control points manually. * The modifications made on the selected pixels are applied only when * the user clicks the Apply button : the semi-transparent image displayed * until the user click that button is only a preview. */ class KisToolTransform : public KisTool { Q_OBJECT Q_PROPERTY(TransformToolMode transformMode READ transformMode WRITE setTransformMode NOTIFY transformModeChanged) Q_PROPERTY(double translateX READ translateX WRITE setTranslateX NOTIFY freeTransformChanged) Q_PROPERTY(double translateY READ translateY WRITE setTranslateY NOTIFY freeTransformChanged) Q_PROPERTY(double rotateX READ rotateX WRITE setRotateX NOTIFY freeTransformChanged) Q_PROPERTY(double rotateY READ rotateY WRITE setRotateY NOTIFY freeTransformChanged) Q_PROPERTY(double rotateZ READ rotateZ WRITE setRotateZ NOTIFY freeTransformChanged) Q_PROPERTY(double scaleX READ scaleX WRITE setScaleX NOTIFY freeTransformChanged) Q_PROPERTY(double scaleY READ scaleY WRITE setScaleY NOTIFY freeTransformChanged) Q_PROPERTY(double shearX READ shearX WRITE setShearX NOTIFY freeTransformChanged) Q_PROPERTY(double shearY READ shearY WRITE setShearY NOTIFY freeTransformChanged) Q_PROPERTY(WarpType warpType READ warpType WRITE setWarpType NOTIFY warpTransformChanged) Q_PROPERTY(double warpFlexibility READ warpFlexibility WRITE setWarpFlexibility NOTIFY warpTransformChanged) Q_PROPERTY(int warpPointDensity READ warpPointDensity WRITE setWarpPointDensity NOTIFY warpTransformChanged) public: enum TransformToolMode { FreeTransformMode, WarpTransformMode, CageTransformMode, LiquifyTransformMode, PerspectiveTransformMode }; Q_ENUMS(TransformToolMode) enum WarpType { RigidWarpType, AffineWarpType, SimilitudeWarpType }; Q_ENUMS(WarpType) KisToolTransform(KoCanvasBase * canvas); virtual ~KisToolTransform(); virtual QWidget* createOptionWidget(); virtual void mousePressEvent(KoPointerEvent *e); virtual void mouseMoveEvent(KoPointerEvent *e); virtual void mouseReleaseEvent(KoPointerEvent *e); virtual void touchEvent(QTouchEvent *event); void beginActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action); void continueActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action); void endActionImpl(KoPointerEvent *event, bool usePrimaryAction, KisTool::AlternateAction action); void beginPrimaryAction(KoPointerEvent *event); void continuePrimaryAction(KoPointerEvent *event); void endPrimaryAction(KoPointerEvent *event); void activateAlternateAction(AlternateAction action); void deactivateAlternateAction(AlternateAction action); void beginAlternateAction(KoPointerEvent *event, AlternateAction action); void continueAlternateAction(KoPointerEvent *event, AlternateAction action); void endAlternateAction(KoPointerEvent *event, AlternateAction action); void paint(QPainter& gc, const KoViewConverter &converter); TransformToolMode transformMode() const; double translateX() const; double translateY() const; double rotateX() const; double rotateY() const; double rotateZ() const; double scaleX() const; double scaleY() const; double shearX() const; double shearY() const; WarpType warpType() const; double warpFlexibility() const; int warpPointDensity() const; bool wantsTouch() const { return true; } public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); virtual void deactivate(); // Applies the current transformation to the original paint device and commits it to the undo stack void applyTransform(); void setTransformMode( KisToolTransform::TransformToolMode newMode ); void setTranslateX(double translateX); void setTranslateY(double translateY); void setRotateX(double rotation); void setRotateY(double rotation); void setRotateZ(double rotation); void setScaleX(double scaleX); void setScaleY(double scaleY); void setShearX(double shearX); void setShearY(double shearY); void setWarpType(WarpType type); void setWarpFlexibility(double flexibility); void setWarpPointDensity(int density); protected Q_SLOTS: virtual void resetCursorStyle(); Q_SIGNALS: void transformModeChanged(); void freeTransformChanged(); void warpTransformChanged(); public Q_SLOTS: void requestUndoDuringStroke(); void requestStrokeEnd(); void requestStrokeCancellation(); void canvasUpdateRequested(); void cursorOutlineUpdateRequested(const QPointF &imagePos); // Update the widget according to m_currentArgs void updateOptionWidget(); void resetRotationCenterButtonsRequested(); void imageTooBigRequested(bool value); private: - void clearDevices(KisNodeSP node, bool recursive); + bool clearDevices(KisNodeSP node, bool recursive); void transformDevices(KisNodeSP node, bool recursive); void startStroke(ToolTransformArgs::TransformMode mode); void endStroke(); void cancelStroke(); private: void outlineChanged(); // Sets the cursor according to mouse position (doesn't take shearing into account well yet) void setFunctionalCursor(); // Sets m_function according to mouse position and modifier void setTransformFunction(QPointF mousePos, Qt::KeyboardModifiers modifiers); void commitChanges(); bool tryInitTransformModeFromNode(KisNodeSP node); bool tryFetchArgsFromCommandAndUndo(ToolTransformArgs *args, ToolTransformArgs::TransformMode mode, KisNodeSP currentNode); void initTransformMode(ToolTransformArgs::TransformMode mode); void initGuiAfterTransformMode(); void initThumbnailImage(KisPaintDeviceSP previewDevice); void updateSelectionPath(); void updateApplyResetAvailability(); private: ToolTransformArgs m_currentArgs; bool m_actuallyMoveWhileSelected; // true <=> selection has been moved while clicked KisPaintDeviceSP m_selectedPortionCache; struct StrokeData { StrokeData() {} StrokeData(KisStrokeId strokeId) : m_strokeId(strokeId) {} void clear() { m_strokeId.clear(); m_clearedNodes.clear(); } const KisStrokeId strokeId() const { return m_strokeId; } void addClearedNode(KisNodeSP node) { m_clearedNodes.append(node); } const QVector& clearedNodes() const { return m_clearedNodes; } private: KisStrokeId m_strokeId; QVector m_clearedNodes; }; StrokeData m_strokeData; bool m_workRecursively; QPainterPath m_selectionPath; // original (unscaled) selection outline, used for painting decorations KisToolTransformConfigWidget *m_optionsWidget; KisCanvas2 *m_canvas; TransformTransactionProperties m_transaction; TransformChangesTracker m_changesTracker; /** * This artificial rect is used to store the image to flake * transformation. We check against this rect to get to know * whether zoom has changed. */ QRectF m_refRect; QScopedPointer m_warpStrategy; QScopedPointer m_cageStrategy; QScopedPointer m_liquifyStrategy; QScopedPointer m_freeStrategy; QScopedPointer m_perspectiveStrategy; KisTransformStrategyBase* currentStrategy() const; QPainterPath m_cursorOutline; private Q_SLOTS: void slotTrackerChangedConfig(); void slotUiChangedConfig(); void slotApplyTransform(); void slotResetTransform(); void slotRestartTransform(); void slotEditingFinished(); }; class KisToolTransformFactory : public KoToolFactoryBase { public: KisToolTransformFactory(const QStringList&) : KoToolFactoryBase("KisToolTransform") { setToolTip(i18n("Transform a layer or a selection")); setToolType(TOOL_TYPE_TRANSFORM); setIconName(koIconNameCStr("krita_tool_transform")); setShortcut(KShortcut( QKeySequence(Qt::CTRL + Qt::Key_T) )); setPriority(11); setActivationShapeId(KRITA_TOOL_ACTIVATION_ID); } virtual ~KisToolTransformFactory() {} virtual KoToolBase * createTool(KoCanvasBase *canvas) { return new KisToolTransform(canvas); } }; #endif // KIS_TOOL_TRANSFORM_H_ diff --git a/krita/libpsd/libkispsd_export.h b/krita/plugins/tools/tool_transform2/kritatooltransform_export.h similarity index 54% rename from krita/libpsd/libkispsd_export.h rename to krita/plugins/tools/tool_transform2/kritatooltransform_export.h index fa028e7f943..eb3e1edf6b2 100644 --- a/krita/libpsd/libkispsd_export.h +++ b/krita/plugins/tools/tool_transform2/kritatooltransform_export.h @@ -1,45 +1,40 @@ -/* This file is part of the KDE project - Copyright (C) 2006 David Faure +/* + This file is part of krita + Copyright (c) 2015 Friedrich W. H. Kossebau 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. + * Boston, MA 02110-1301, USA. */ -#ifndef LIBKISPSD_EXPORT_H -#define LIBKISPSD_EXPORT_H +#ifndef KRITATOOLTRANSFORM_EXPORT_H +#define KRITATOOLTRANSFORM_EXPORT_H -/* needed for KDE_EXPORT and KDE_IMPORT macros */ #include -/* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ -#if defined _WIN32 || defined _WIN64 - -#ifndef KRITAPSD_EXPORT -# if defined(MAKE_KRITAPSD_LIB) -/* We are building this library */ -# define KRITAPSD_EXPORT KDE_EXPORT -# else -/* We are using this library */ -# define KRITAPSD_EXPORT KDE_IMPORT -# endif -#endif - -#else /* UNIX */ - -#define KRITAPSD_EXPORT KDE_EXPORT - +#ifdef COMPILING_TESTS +# if defined _WIN32 || defined _WIN64 +# if defined(MAKE_KRITATOOLTRANSFORM_LIB) +# define KRITATOOLTRANSFORM_TEST_EXPORT KDE_EXPORT +# else +# define KRITATOOLTRANSFORM_TEST_EXPORT KDE_IMPORT +# endif +# else /* not windows */ +# define KRITATOOLTRANSFORM_TEST_EXPORT KDE_EXPORT +# endif +#else /* not compiling tests */ +# define KRITATOOLTRANSFORM_TEST_EXPORT #endif -#endif +#endif /* KRITATOOLTRANSFORM_EXPORT_H */ diff --git a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h index b18d0e60b55..a0c5b74177e 100644 --- a/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h +++ b/krita/plugins/tools/tool_transform2/strokes/transform_stroke_strategy.h @@ -1,125 +1,125 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __TRANSFORM_STROKE_STRATEGY_H #define __TRANSFORM_STROKE_STRATEGY_H #include #include #include #include #include "tool_transform_args.h" #include class KisPostExecutionUndoAdapter; -class KDE_EXPORT TransformStrokeStrategy : public KisStrokeStrategyUndoCommandBased +class TransformStrokeStrategy : public KisStrokeStrategyUndoCommandBased { public: - class KDE_EXPORT TransformData : public KisStrokeJobData { + class TransformData : public KisStrokeJobData { public: enum Destination { PAINT_DEVICE, SELECTION, }; public: TransformData(Destination _destination, const ToolTransformArgs &_config, KisNodeSP _node) : KisStrokeJobData(CONCURRENT, NORMAL), destination(_destination), config(_config), node(_node) { } Destination destination; ToolTransformArgs config; KisNodeSP node; }; - class KDE_EXPORT ClearSelectionData : public KisStrokeJobData { + class ClearSelectionData : public KisStrokeJobData { public: ClearSelectionData(KisNodeSP _node) : KisStrokeJobData(SEQUENTIAL, NORMAL), node(_node) { } KisNodeSP node; }; public: TransformStrokeStrategy(KisNodeSP rootNode, KisSelectionSP selection, KisPostExecutionUndoAdapter *undoAdapter); ~TransformStrokeStrategy(); KisPaintDeviceSP previewDevice() const; KisSelectionSP realSelection() const; void initStrokeCallback(); void finishStrokeCallback(); void cancelStrokeCallback(); void doStrokeCallback(KisStrokeJobData *data); static bool fetchArgsFromCommand(const KUndo2Command *command, ToolTransformArgs *args, KisNodeSP *rootNode); protected: void postProcessToplevelCommand(KUndo2Command *command); private: KoUpdaterPtr fetchUpdater(KisNodeSP node); void transformAndMergeDevice(const ToolTransformArgs &config, KisPaintDeviceSP src, KisPaintDeviceSP dst, KisProcessingVisitor::ProgressHelper *helper); void transformDevice(const ToolTransformArgs &config, KisPaintDeviceSP device, KisProcessingVisitor::ProgressHelper *helper); void clearSelection(KisPaintDeviceSP device); //void transformDevice(KisPaintDeviceSP src, KisPaintDeviceSP dst, KisProcessingVisitor::ProgressHelper *helper); bool checkBelongsToSelection(KisPaintDeviceSP device) const; KisPaintDeviceSP createDeviceCache(KisPaintDeviceSP src); bool haveDeviceInCache(KisPaintDeviceSP src); void putDeviceCache(KisPaintDeviceSP src, KisPaintDeviceSP cache); KisPaintDeviceSP getDeviceCache(KisPaintDeviceSP src); private: KisSelectionSP m_selection; QMutex m_devicesCacheMutex; QHash m_devicesCacheHash; KisPaintDeviceSP m_previewDevice; KisTransformMaskSP writeToTransformMask; ToolTransformArgs m_savedTransformArgs; KisNodeSP m_savedRootNode; }; #endif /* __TRANSFORM_STROKE_STRATEGY_H */ diff --git a/krita/plugins/tools/tool_transform2/tool_transform_args.h b/krita/plugins/tools/tool_transform2/tool_transform_args.h index 7f5b4995929..8a0f8d5cb31 100644 --- a/krita/plugins/tools/tool_transform2/tool_transform_args.h +++ b/krita/plugins/tools/tool_transform2/tool_transform_args.h @@ -1,315 +1,316 @@ /* * tool_transform_args.h - part of Krita * * Copyright (c) 2010 Marc Pegon * * 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 TOOL_TRANSFORM_ARGS_H_ #define TOOL_TRANSFORM_ARGS_H_ #include #include #include #include #include "kis_liquify_properties.h" +#include #include class KisLiquifyTransformWorker; class QDomElement; /** * Class used to store the parameters of a transformation. * Some parameters are specific to free transform mode, and * others to warp mode : maybe add a union to save a little more * memory. */ -class KDE_EXPORT ToolTransformArgs +class KRITATOOLTRANSFORM_TEST_EXPORT ToolTransformArgs { public: enum TransformMode {FREE_TRANSFORM = 0, WARP, CAGE, LIQUIFY, PERSPECTIVE_4POINT, N_MODES}; /** * Initializes the parameters for an identity transformation, * with mode set to free transform. */ ToolTransformArgs(); /** * The object return will be a copy of args. */ ToolTransformArgs(const ToolTransformArgs& args); /** * If mode is warp, original and transformed vector points will be of size 0. * Use setPoints method to set those vectors. */ ToolTransformArgs(TransformMode mode, QPointF transformedCenter, QPointF originalCenter, QPointF rotationCenterOffset, double aX, double aY, double aZ, double scaleX, double scaleY, double shearX, double shearY, KisWarpTransformWorker::WarpType warpType, double alpha, bool defaultPoints, const QString &filterId); ~ToolTransformArgs(); ToolTransformArgs& operator=(const ToolTransformArgs& args); bool operator==(const ToolTransformArgs& other) const; inline TransformMode mode() const { return m_mode; } inline void setMode(TransformMode mode) { m_mode = mode; } //warp-related inline int numPoints() const { KIS_ASSERT_RECOVER_NOOP(m_origPoints.size() == m_transfPoints.size()); return m_origPoints.size(); } inline QPointF &origPoint(int i) { return m_origPoints[i]; } inline QPointF &transfPoint(int i) { return m_transfPoints[i]; } inline const QVector &origPoints() const { return m_origPoints; } inline const QVector &transfPoints() const { return m_transfPoints; } inline QVector &refOriginalPoints() { return m_origPoints; } inline QVector &refTransformedPoints() { return m_transfPoints; } inline KisWarpTransformWorker::WarpType warpType() const { return m_warpType; } inline double alpha() const { return m_alpha; } inline bool defaultPoints() const { return m_defaultPoints; } inline void setPoints(QVector origPoints, QVector transfPoints) { m_origPoints = QVector(origPoints); m_transfPoints = QVector(transfPoints); } inline void setWarpType(KisWarpTransformWorker::WarpType warpType) { m_warpType = warpType; } inline void setAlpha(double alpha) { m_alpha = alpha; } inline void setDefaultPoints(bool defaultPoints) { m_defaultPoints = defaultPoints; } //"free transform"-related inline QPointF transformedCenter() const { return m_transformedCenter; } inline QPointF originalCenter() const { return m_originalCenter; } inline QPointF rotationCenterOffset() const { return m_rotationCenterOffset; } inline double aX() const { return m_aX; } inline double aY() const { return m_aY; } inline double aZ() const { return m_aZ; } inline QVector3D cameraPos() const { return m_cameraPos; } inline double scaleX() const { return m_scaleX; } inline double scaleY() const { return m_scaleY; } inline bool keepAspectRatio() const { return m_keepAspectRatio; } inline double shearX() const { return m_shearX; } inline double shearY() const { return m_shearY; } inline void setTransformedCenter(QPointF transformedCenter) { m_transformedCenter = transformedCenter; } inline void setOriginalCenter(QPointF originalCenter) { m_originalCenter = originalCenter; } inline void setRotationCenterOffset(QPointF rotationCenterOffset) { m_rotationCenterOffset = rotationCenterOffset; } inline void setAX(double aX) { KIS_ASSERT_RECOVER_NOOP(aX == normalizeAngle(aX)); m_aX = aX; } inline void setAY(double aY) { KIS_ASSERT_RECOVER_NOOP(aY == normalizeAngle(aY)); m_aY = aY; } inline void setAZ(double aZ) { KIS_ASSERT_RECOVER_NOOP(aZ == normalizeAngle(aZ)); m_aZ = aZ; } inline void setCameraPos(const QVector3D &pos) { m_cameraPos = pos; } inline void setScaleX(double scaleX) { m_scaleX = scaleX; } inline void setScaleY(double scaleY) { m_scaleY = scaleY; } inline void setKeepAspectRatio(bool value) { m_keepAspectRatio = value; } inline void setShearX(double shearX) { m_shearX = shearX; } inline void setShearY(double shearY) { m_shearY = shearY; } inline QString filterId() const { return m_filter->id(); } void setFilterId(const QString &id); inline KisFilterStrategy* filter() const { return m_filter; } bool isIdentity() const; inline QTransform flattenedPerspectiveTransform() const { return m_flattenedPerspectiveTransform; } inline void setFlattenedPerspectiveTransform(const QTransform &value) { m_flattenedPerspectiveTransform = value; } bool isEditingTransformPoints() const { return m_editTransformPoints; } void setEditingTransformPoints(bool value) { m_editTransformPoints = value; } const KisLiquifyProperties* liquifyProperties() const { return m_liquifyProperties.data(); } KisLiquifyProperties* liquifyProperties() { return m_liquifyProperties.data(); } void initLiquifyTransformMode(const QRect &srcRect); void saveLiquifyTransformMode() const; KisLiquifyTransformWorker* liquifyWorker() const { return m_liquifyWorker.data(); } void toXML(QDomElement *e) const; static ToolTransformArgs fromXML(const QDomElement &e); void translate(const QPointF &offset); void saveContinuedState(); void restoreContinuedState(); const ToolTransformArgs* continuedTransform() const; private: void clear(); void init(const ToolTransformArgs& args); TransformMode m_mode; // warp-related arguments // these are basically the arguments taken by the warp transform worker bool m_defaultPoints; // true : the original points are set to make a grid // which density is given by numPoints() QVector m_origPoints; QVector m_transfPoints; KisWarpTransformWorker::WarpType m_warpType; double m_alpha; //'free transform'-related // basically the arguments taken by the transform worker QPointF m_transformedCenter; QPointF m_originalCenter; QPointF m_rotationCenterOffset; // the position of the rotation center relative to // the original top left corner of the selection // before any transformation double m_aX; double m_aY; double m_aZ; QVector3D m_cameraPos; double m_scaleX; double m_scaleY; double m_shearX; double m_shearY; bool m_keepAspectRatio; // perspective trasform related QTransform m_flattenedPerspectiveTransform; KisFilterStrategy *m_filter; bool m_editTransformPoints; QSharedPointer m_liquifyProperties; QScopedPointer m_liquifyWorker; /** * When we continue a transformation, m_continuedTransformation * stores the initial step of our transform. All cancel and revert * operations should revert to it. */ QScopedPointer m_continuedTransformation; }; #endif // TOOL_TRANSFORM_ARGS_H_ diff --git a/krita/ui/CMakeLists.txt b/krita/ui/CMakeLists.txt index 195d9b5e1f0..6c1248552d4 100644 --- a/krita/ui/CMakeLists.txt +++ b/krita/ui/CMakeLists.txt @@ -1,525 +1,528 @@ # Disable -Wswitch because of the extra definitions we here: # kis_input_manager.cpp: In member function ‘virtual bool KisInputManager::eventFilter(QObject*, QEvent*)’: # warning: case value ‘1001’ not in enumerated type ‘QEvent::Type’ [-Wswitch] # warning: case value ‘1002’ not in enumerated type ‘QEvent::Type’ [-Wswitch] if (CMAKE_COMPILER_IS_GNUCXX) add_definitions(${KDE4_ENABLE_EXCEPTIONS} -Wno-switch) else () add_definitions(${KDE4_ENABLE_EXCEPTIONS} ) endif () include_directories( ${CMAKE_SOURCE_DIR}/libs/pigment/colorprofiles ${CMAKE_CURRENT_SOURCE_DIR}/flake ${CMAKE_CURRENT_SOURCE_DIR}/pigment/resources ${CMAKE_CURRENT_SOURCE_DIR}/widgets/resources ${CMAKE_CURRENT_SOURCE_DIR}/ora ${CMAKE_SOURCE_DIR}/krita/image/metadata ${CMAKE_SOURCE_DIR}/krita/ui/qtsingleapplication ${CMAKE_SOURCE_DIR}/krita/ui/qtlockedfile ${EXIV2_INCLUDE_DIR} ${OCIO_INCLUDE_DIR}) add_subdirectory( tests ) if (APPLE) find_library(FOUNDATION_LIBRARY Foundation) endif () set(kritaui_LIB_SRCS canvas/kis_canvas_widget_base.cpp canvas/kis_canvas2.cpp canvas/kis_canvas_updates_compressor.cpp canvas/kis_canvas_controller.cpp canvas/kis_paintop_transformation_connector.cpp canvas/kis_display_color_converter.cpp canvas/kis_display_filter.cpp canvas/kis_exposure_gamma_correction_interface.cpp canvas/kis_tool_proxy.cpp canvas/kis_canvas_decoration.cc canvas/kis_coordinates_converter.cpp canvas/kis_grid_manager.cpp canvas/kis_grid_decoration.cpp canvas/kis_grid_painter_configuration.cpp canvas/kis_perspective_grid_manager.cpp canvas/kis_perspective_grid_decoration.cpp canvas/kis_prescaled_projection.cpp canvas/kis_qpainter_canvas.cpp canvas/kis_projection_backend.cpp canvas/kis_update_info.cpp canvas/kis_image_patch.cpp canvas/kis_image_pyramid.cpp canvas/kis_qpainter_canvas_widget_factory.cpp canvas/kis_infinity_manager.cpp dialogs/kis_about_application.cpp dialogs/kis_dlg_adj_layer_props.cc dialogs/kis_dlg_adjustment_layer.cc dialogs/kis_dlg_filter.cpp dialogs/kis_dlg_generator_layer.cpp dialogs/kis_dlg_file_layer.cpp dialogs/kis_dlg_image_properties.cc dialogs/kis_dlg_layer_properties.cc dialogs/kis_dlg_preferences.cc dialogs/slider_and_spin_box_sync.cpp dialogs/kis_dlg_blacklist_cleanup.cpp dialogs/kis_dlg_layer_style.cpp dialogs/kis_dlg_png_import.cpp flake/kis_node_dummies_graph.cpp flake/kis_dummies_facade_base.cpp flake/kis_dummies_facade.cpp flake/kis_node_shapes_graph.cpp flake/kis_node_shape.cpp flake/kis_shape_controller.cpp flake/kis_shape_layer.cc flake/kis_shape_layer_canvas.cpp flake/kis_shape_selection.cpp flake/kis_shape_selection_canvas.cpp flake/kis_shape_selection_model.cpp flake/kis_take_all_shapes_command.cpp kis_aboutdata.cpp kis_autogradient.cc kis_bookmarked_configurations_editor.cc kis_bookmarked_configurations_model.cc kis_bookmarked_filter_configurations_model.cc kis_canvas_resource_provider.cpp kis_categories_mapper.cpp kis_categorized_list_model.cpp kis_categorized_item_delegate.cpp kis_clipboard.cc kis_config.cc kis_config_notifier.cpp kis_control_frame.cpp kis_composite_ops_model.cc kis_paint_ops_model.cpp kis_cursor.cc kis_custom_pattern.cc kis_factory2.cc kis_file_layer.cpp kis_safe_document_loader.cpp kis_splash_screen.cpp kis_filter_manager.cc kis_filters_model.cc kis_histogram_view.cc kis_image_manager.cc kis_image_view_converter.cpp kis_import_catcher.cc kis_layer_manager.cc kis_mask_manager.cc kis_mimedata.cpp kis_node_commands_adapter.cpp kis_node_manager.cpp kis_node_model.cpp kis_model_index_converter_base.cpp kis_model_index_converter.cpp kis_model_index_converter_show_all.cpp kis_painting_assistant.cc kis_painting_assistants_decoration.cpp kis_painting_assistants_manager.cpp kis_paintop_box.cc kis_paintop_option.cpp kis_paintop_options_model.cpp kis_paintop_settings_widget.cpp kis_popup_palette.cpp kis_png_converter.cpp kis_preference_set_registry.cpp kis_resource_server_provider.cpp kis_selection_decoration.cc kis_selection_manager.cc kis_statusbar.cc kis_zoom_manager.cc kis_favorite_resource_manager.cpp kis_workspace_resource.cpp kis_action.cpp kis_action_manager.cpp kis_view_plugin.cpp kis_canvas_controls_manager.cpp kis_tooltip_manager.cpp kisexiv2/kis_exif_io.cpp kisexiv2/kis_exiv2.cpp kisexiv2/kis_iptc_io.cpp kisexiv2/kis_xmp_io.cpp kra/kis_kra_utils.cpp kra/kis_kra_load_visitor.cpp kra/kis_kra_loader.cpp kra/kis_kra_save_visitor.cpp kra/kis_kra_saver.cpp kra/kis_kra_savexml_visitor.cpp opengl/kis_opengl.cpp opengl/kis_opengl_canvas2.cpp opengl/kis_opengl_image_textures.cpp opengl/kis_texture_tile.cpp opengl/kis_texture_tile_update_info.cpp ora/kis_open_raster_stack_load_visitor.cpp ora/kis_open_raster_stack_save_visitor.cpp ora/ora_load_context.cc ora/ora_save_context.cc recorder/kis_node_query_path_editor.cc recorder/kis_recorded_action_creator.cc recorder/kis_recorded_action_creator_factory.cc recorder/kis_recorded_action_creator_factory_registry.cc recorder/kis_recorded_action_editor_factory.cc recorder/kis_recorded_action_editor_factory_registry.cc recorder/kis_recorded_filter_action_editor.cc recorder/kis_recorded_filter_action_creator.cpp recorder/kis_recorded_paint_action_editor.cc tool/kis_selection_tool_helper.cpp tool/kis_selection_tool_config_widget_helper.cpp tool/kis_rectangle_constraint_widget.cpp tool/kis_shape_tool_helper.cpp tool/kis_tool.cc tool/kis_delegated_tool_policies.cpp tool/kis_tool_freehand.cc tool/kis_speed_smoother.cpp tool/kis_painting_information_builder.cpp tool/kis_tool_freehand_helper.cpp tool/kis_tool_multihand_helper.cpp tool/kis_figure_painting_tool_helper.cpp tool/kis_recording_adapter.cpp tool/kis_tool_paint.cc tool/kis_tool_shape.cc tool/kis_tool_ellipse_base.cpp tool/kis_tool_rectangle_base.cpp tool/kis_tool_polyline_base.cpp tool/kis_tool_utils.cpp tool/kis_resources_snapshot.cpp tool/kis_smoothing_options.cpp tool/strokes/freehand_stroke.cpp tool/strokes/kis_painter_based_stroke_strategy.cpp tool/strokes/kis_filter_stroke_strategy.cpp widgets/kis_channelflags_widget.cpp widgets/kis_cmb_composite.cc widgets/kis_cmb_contour.cpp widgets/kis_cmb_gradient.cpp widgets/kis_paintop_list_widget.cpp widgets/kis_cmb_idlist.cc widgets/kis_color_space_selector.cc widgets/kis_curve_widget.cpp widgets/kis_custom_image_widget.cc widgets/kis_image_from_clipboard_widget.cpp widgets/kis_double_widget.cc widgets/kis_filter_selector_widget.cc widgets/kis_gradient_chooser.cc widgets/kis_gradient_slider_widget.cc widgets/kis_gradient_slider.cpp widgets/kis_iconwidget.cc widgets/kis_mask_widgets.cpp widgets/kis_meta_data_merge_strategy_chooser_widget.cc widgets/kis_multi_bool_filter_widget.cc widgets/kis_multi_double_filter_widget.cc widgets/kis_multi_integer_filter_widget.cc widgets/kis_multipliers_double_slider_spinbox.cpp widgets/kis_paintop_presets_popup.cpp widgets/kis_tool_options_popup.cpp widgets/kis_paintop_presets_chooser_popup.cpp widgets/kis_pattern_chooser.cc widgets/kis_popup_button.cc widgets/kis_preset_chooser.cpp widgets/kis_progress_widget.cpp widgets/kis_selection_options.cc widgets/kis_scratch_pad.cpp widgets/kis_scratch_pad_event_filter.cpp widgets/kis_preset_selector_strip.cpp widgets/kis_tree_view_popup.cc widgets/kis_slider_spin_box.cpp widgets/kis_wdg_generator.cpp widgets/kis_workspace_chooser.cpp widgets/squeezedcombobox.cpp widgets/kis_categorized_list_view.cpp widgets/kis_widget_chooser.cpp widgets/kis_tool_button.cpp widgets/kis_floating_message.cpp input/kis_input_manager.cpp input/kis_extended_modifiers_mapper.cpp input/kis_abstract_input_action.cpp input/kis_tool_invocation_action.cpp input/kis_pan_action.cpp input/kis_alternate_invocation_action.cpp input/kis_rotate_canvas_action.cpp input/kis_zoom_action.cpp input/kis_gamma_exposure_action.cpp input/kis_show_palette_action.cpp input/kis_change_primary_setting_action.cpp input/kis_abstract_shortcut.cpp input/kis_single_action_shortcut.cpp input/kis_stroke_shortcut.cpp input/kis_shortcut_matcher.cpp input/kis_select_layer_action.cpp operations/kis_operation.cpp operations/kis_operation_configuration.cpp operations/kis_operation_registry.cpp operations/kis_operation_ui_factory.cpp operations/kis_operation_ui_widget.cpp operations/kis_filter_selection_operation.cpp actions/kis_selection_action_factories.cpp input/kis_touch_shortcut.cpp kis_document_undo_store.cpp kis_transaction_based_command.cpp kis_gui_context_command.cpp kis_gui_context_command_p.cpp input/kis_tablet_debugger.cpp input/kis_input_profile_manager.cpp input/kis_input_profile.cpp input/kis_shortcut_configuration.cpp input/config/kis_input_configuration_page.cpp input/config/kis_edit_profiles_dialog.cpp input/config/kis_input_profile_model.cpp input/config/kis_input_configuration_page_item.cpp input/config/kis_action_shortcuts_model.cpp input/config/kis_input_type_delegate.cpp input/config/kis_input_mode_delegate.cpp input/config/kis_input_button.cpp input/config/kis_input_editor_delegate.cpp input/config/kis_mouse_input_editor.cpp input/config/kis_wheel_input_editor.cpp input/config/kis_key_input_editor.cpp processing/fill_processing_visitor.cpp kis_asl_layer_style_serializer.cpp kis_psd_layer_style_resource.cpp canvas/kis_mirror_axis.cpp kis_abstract_perspective_grid.cpp KisApplication.cpp KisAutoSaveRecoveryDialog.cpp KisDetailsPane.cpp KisDocument.cpp KisDocumentEntry.cpp KisDocumentSectionDelegate.cpp KisDocumentSectionToolTip.cpp KisDocumentSectionView.cpp KisFilterChain.cpp KisFilterChainLink.cpp KisFilterChainLinkList.cpp KisImportExportFilter.cpp KisFilterEdge.cpp KisFilterEntry.cpp KisFilterGraph.cpp KisImportExportManager.cpp KisImportExportManager_p.cpp KisFilterVertex.cpp KisMainWindow.cpp KisOpenPane.cpp KisPart.cpp KisPrintJob.cpp KisRecentDocumentsPane.cpp KisStartupDialog.cpp KisTemplate.cpp KisTemplateCreateDia.cpp KisTemplateGroup.cpp KisTemplates.cpp KisTemplatesPane.cpp KisTemplateTree.cpp KisUndoStackAction.cpp KisView.cpp thememanager.cpp + kis_icon_utils.cpp kis_mainwindow_observer.cpp KisViewManager.cpp kis_mirror_manager.cpp qtlockedfile/qtlockedfile.cpp qtsingleapplication/qtlocalpeer.cpp qtsingleapplication/qtsingleapplication.cpp widgets/kis_url_requester.cpp + kis_md5_generator.cpp ) if(WIN32) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support_win.cpp input/wintab/kis_screen_size_choice_dialog.cpp qtlockedfile/qtlockedfile_win.cpp ) endif() if(UNIX) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/kis_tablet_event.cpp input/wintab/kis_tablet_support.cpp qtlockedfile/qtlockedfile_unix.cpp ) if(NOT APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} input/wintab/kis_tablet_support_x11.cpp ) endif() endif() if (APPLE) set(kritaui_LIB_SRCS ${kritaui_LIB_SRCS} MacSupport.mm ) endif () add_definitions(${KDE4_ENABLE_EXCEPTIONS}) if(WIN32) #kde4_add_ui_files( # input/wintab/kis_screen_size_choice_dialog.ui #) endif() kde4_add_ui_files(kritaui_LIB_SRCS forms/wdgdlgpngimport.ui forms/wdgfullscreensettings.ui forms/wdgautogradient.ui forms/wdggeneralsettings.ui forms/wdgperformancesettings.ui forms/wdggridsettings.ui forms/wdggenerators.ui forms/wdgcustompalette.ui forms/wdgbookmarkedconfigurationseditor.ui forms/wdgapplyprofile.ui forms/wdgcustompattern.ui forms/wdglayerproperties.ui forms/wdgcolorsettings.ui forms/wdgtabletsettings.ui forms/wdgcolorspaceselector.ui forms/wdgdisplaysettings.ui forms/kis_previewwidgetbase.ui forms/kis_matrix_widget.ui forms/wdgselectionoptions.ui forms/wdggeometryoptions.ui forms/wdgnewimage.ui forms/wdgimageproperties.ui forms/wdgmaskfromselection.ui forms/wdgmasksource.ui forms/wdgfilterdialog.ui forms/wdgmetadatamergestrategychooser.ui forms/wdgpaintoppresets.ui forms/wdgpaintopsettings.ui forms/wdgdlggeneratorlayer.ui forms/wdgdlgfilelayer.ui forms/wdgfilterselector.ui forms/wdgfilternodecreation.ui forms/wdgpaintactioneditor.ui forms/wdgmultipliersdoublesliderspinbox.ui forms/wdgnodequerypatheditor.ui forms/wdgpresetselectorstrip.ui forms/wdgdlgblacklistcleanup.ui forms/wdgrectangleconstraints.ui forms/KisDetailsPaneBase.ui forms/KisOpenPaneBase.ui input/config/kis_input_configuration_page.ui input/config/kis_edit_profiles_dialog.ui input/config/kis_input_configuration_page_item.ui input/config/kis_mouse_input_editor.ui input/config/kis_wheel_input_editor.ui input/config/kis_key_input_editor.ui layerstyles/wdgBevelAndEmboss.ui layerstyles/wdgblendingoptions.ui layerstyles/WdgColorOverlay.ui layerstyles/wdgContour.ui layerstyles/wdgdropshadow.ui layerstyles/WdgGradientOverlay.ui layerstyles/wdgInnerGlow.ui layerstyles/wdglayerstyles.ui layerstyles/WdgPatternOverlay.ui layerstyles/WdgSatin.ui layerstyles/WdgStroke.ui layerstyles/wdgstylesselector.ui layerstyles/wdgTexture.ui wdgsplash.ui input/wintab/kis_screen_size_choice_dialog.ui forms/wdg_url_requester.ui ) kde4_add_library(kritaui SHARED ${kritaui_LIB_SRCS} ) target_link_libraries(kritaui ${QT_QTDECLARATIVE_LIBRARY} ${X11_X11_LIB} ${X11_Xinput_LIB} ${KDE4_KIO_LIBS} ) if(APPLE) target_link_libraries(kritaui ${FOUNDATION_LIBRARY}) endif () if(GHNS) target_link_libraries(kritaui ${KDE4_KFILE_LIBRARY} kritacolor kritaimage kritalibbrush kowidgets kowidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES} ${KDE4_KNEWSTUFF3_LIBS}) else() target_link_libraries(kritaui ${KDE4_KFILE_LIBRARY} kritacolor kritaimage kritalibbrush kowidgets kowidgetutils ${PNG_LIBRARIES} ${EXIV2_LIBRARIES}) endif () if(HAVE_OPENGL) target_link_libraries(kritaui ${OPENGL_LIBRARIES} ${QT_QTOPENGL_LIBRARY} ${OPENEXR_LIBRARIES}) # activate workaround for the VSync disable if(NOT WIN32) target_link_libraries(kritaui ${CMAKE_DL_LIBS}) endif() set (GL_INTERFACE_LIBRARIES ";${OPENGL_LIBRARIES};${QT_QTOPENGL_LIBRARY}") if(HAVE_GLEW) target_link_libraries(kritaui ${GLEW_LIBRARIES}) endif() endif() -target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush ${KDE4_KIO_LIBS} ${GL_INTERFACE_LIBRARIES} ) +target_link_libraries(kritaui LINK_INTERFACE_LIBRARIES kritaimage kritalibbrush pigmentcms ${KDE4_KIO_LIBS} ${GL_INTERFACE_LIBRARIES} ) set_target_properties(kritaui PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kritaui ${INSTALL_TARGETS_DEFAULT_ARGS}) ########### install files ############### if (APPLE) install(FILES osx.stylesheet DESTINATION ${DATA_INSTALL_DIR}/krita) endif () install( FILES + kritaui_export.h canvas/kis_canvas2.h canvas/kis_canvas_decoration.h canvas/kis_coordinates_converter.h tool/kis_tool.h kis_canvas_resource_provider.h kis_cursor.h KisViewManager.h kis_ui_types.h # kis_cmb_composite.h # kis_cmb_idlist.h # kis_color_cup.h # kis_config.h # kis_double_click_event.h # kis_double_widget.h # kis_filter_manager.h # kis_gradient_chooser.h # kis_gradient_slider_widget.h # kis_histogram_view.h # kis_icon_item.h # kis_iconwidget.h # kis_itemchooser.h # kis_label_zoom.h # kis_move_event.h widgets/kis_multi_bool_filter_widget.h widgets/kis_multi_double_filter_widget.h widgets/kis_multi_integer_filter_widget.h # kis_paintop_box.h # kis_previewwidget.h # kis_tool_non_paint.h # kis_tool_paint.h # kis_tool_freehand.h # kis_tool_dummy.h # kis_tool_manager.h # kis_tool_types.h # KoInputDevice.h # canvas/kis_perspective_grid_manager.h kis_paintop_option.h kis_paintop_options_model.h kis_paintop_settings_widget.h processing/fill_processing_visitor.h DESTINATION ${INCLUDE_INSTALL_DIR}/krita) diff --git a/krita/ui/KisApplication.h b/krita/ui/KisApplication.h index 5e74a0d5bc3..d1be826c971 100644 --- a/krita/ui/KisApplication.h +++ b/krita/ui/KisApplication.h @@ -1,133 +1,133 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis 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_APPLICATION_H #define KIS_APPLICATION_H #include -#include "krita_export.h" +#include "kritaui_export.h" class KisMainWindow; class KisApplicationPrivate; class KCmdLineArgs; class QWidget; class QStringList; #include #define koApp KisApplication::koApplication() /** * @brief Base class for all %Calligra apps * * This class handles arguments given on the command line and * shows a generic about dialog for all Calligra apps. * * In addition it adds the standard directories where Calligra applications * can find their images etc. * * If the last mainwindow becomes closed, KisApplication automatically * calls QApplication::quit. */ class KRITAUI_EXPORT KisApplication : public QtSingleApplication { Q_OBJECT public: /** * Creates an application object, adds some standard directories and * initializes kimgio. */ explicit KisApplication(const QString &key); /** * Destructor. */ virtual ~KisApplication(); /** * Call this to start the application. * * Parses command line arguments and creates the initial main windowss and docs * from them (or an empty doc if no cmd-line argument is specified ). * * You must call this method directly before calling QApplication::exec. * * It is valid behaviour not to call this method at all. In this case you * have to process your command line parameters by yourself. */ virtual bool start(); /** * Checks if user is holding ctrl+alt+shift keys and asks if the settings file should be cleared. * * Typically called during startup before reading the config. */ void askClearConfig(); /** * Tell KisApplication to show this splashscreen when you call start(); * when start returns, the splashscreen is hidden. Use KSplashScreen * to have the splash show correctly on Xinerama displays. */ void setSplashScreen(QWidget *splash); /** * return a list of mimetypes this application supports. */ QStringList mimeFilter(KisImportExportManager::Direction direction) const; /// Overridden to handle exceptions from event handlers. bool notify(QObject *receiver, QEvent *event); /** * Returns the current application object. * * This is similar to the global QApplication pointer qApp. It * allows access to the single global KisApplication object, since * more than one cannot be created in the same application. It * saves you the trouble of having to pass the pointer explicitly * to every function that may require it. * @return the current application object */ static KisApplication* koApplication(); protected: // Current application object. static KisApplication *KoApp; public Q_SLOTS: void remoteArguments(const QByteArray &message, QObject*socket); void fileOpenRequested(const QString & url); private: /// @return the number of autosavefiles opened QList checkAutosaveFiles(); bool createNewDocFromTemplate(KCmdLineArgs *args, int argNumber, KisMainWindow *mainWindow); void clearConfig(); private: KisApplicationPrivate * const d; class ResetStarting; friend class ResetStarting; }; #endif diff --git a/krita/ui/KisDocument.cpp b/krita/ui/KisDocument.cpp index 4f86f25c618..de406b250c1 100644 --- a/krita/ui/KisDocument.cpp +++ b/krita/ui/KisDocument.cpp @@ -1,2636 +1,2643 @@ /* This file is part of the Krita project * * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisMainWindow.h" // XXX: remove #include // XXX: remove #include "KisApplication.h" #include "KisDocument.h" #include "KisImportExportManager.h" #include "KisPart.h" #include "KisView.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kundo2stack.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // Krita Image #include #include #include #include #include #include #include #include #include #include #include #include #include // Local #include "kis_factory2.h" #include "KisViewManager.h" #include "kis_clipboard.h" #include "widgets/kis_custom_image_widget.h" #include "canvas/kis_canvas2.h" #include "flake/kis_shape_controller.h" #include "kra/kis_kra_loader.h" #include "kra/kis_kra_saver.h" #include "kis_statusbar.h" #include "widgets/kis_progress_widget.h" #include "kis_canvas_resource_provider.h" #include "kis_resource_server_provider.h" #include "kis_node_manager.h" #include "KisPart.h" static const char CURRENT_DTD_VERSION[] = "2.0"; // Define the protocol used here for embedded documents' URL // This used to "store" but KUrl didn't like it, // so let's simply make it "tar" ! #define STORE_PROTOCOL "tar" // The internal path is a hack to make KUrl happy and for document children #define INTERNAL_PROTOCOL "intern" #define INTERNAL_PREFIX "intern:/" // Warning, keep it sync in koStore.cc #include using namespace std; /********************************************************** * * KisDocument * **********************************************************/ namespace { class DocumentProgressProxy : public KoProgressProxy { public: KisMainWindow *m_mainWindow; DocumentProgressProxy(KisMainWindow *mainWindow) : m_mainWindow(mainWindow) { } ~DocumentProgressProxy() { // signal that the job is done setValue(-1); } int maximum() const { return 100; } void setValue(int value) { if (m_mainWindow) { m_mainWindow->slotProgress(value); } } void setRange(int /*minimum*/, int /*maximum*/) { } void setFormat(const QString &/*format*/) { } }; } //static QString KisDocument::newObjectName() { static int s_docIFNumber = 0; QString name; name.setNum(s_docIFNumber++); name.prepend("document_"); return name; } class UndoStack : public KUndo2Stack { public: UndoStack(KisDocument *doc) : m_doc(doc) { } void setIndex(int idx) { KisImageWSP image = this->image(); image->requestStrokeCancellation(); if(image->tryBarrierLock()) { KUndo2Stack::setIndex(idx); image->unlock(); } } void undo() { KisImageWSP image = this->image(); image->requestUndoDuringStroke(); if(image->tryBarrierLock()) { KUndo2Stack::undo(); image->unlock(); } } void redo() { KisImageWSP image = this->image(); if(image->tryBarrierLock()) { KUndo2Stack::redo(); image->unlock(); } } private: KisImageWSP image() { KisImageWSP currentImage = m_doc->image(); Q_ASSERT(currentImage); return currentImage; } private: KisDocument *m_doc; }; class KisDocument::Private { public: Private(KisDocument *document) : document(document), // XXX: the part should _not_ be modified from the document docInfo(0), progressUpdater(0), progressProxy(0), profileStream(0), filterManager(0), specialOutputFlag(0), // default is native format isImporting(false), isExporting(false), password(QString()), modifiedAfterAutosave(false), autosaving(false), shouldCheckAutoSaveFile(true), autoErrorHandlingEnabled(true), backupFile(true), backupPath(QString()), doNotSaveExtDoc(false), storeInternal(false), isLoading(false), undoStack(0), modified(false), readwrite(true), disregardAutosaveFailure(false), nserver(0), macroNestDepth(0), kraLoader(0) { m_job = 0; m_statJob = 0; m_uploadJob = 0; m_saveOk = false; m_waitForSave = false; m_duringSaveAs = false; m_bTemp = false; m_bAutoDetectedMime = false; confirmNonNativeSave[0] = true; confirmNonNativeSave[1] = true; if (KGlobal::locale()->measureSystem() == KLocale::Imperial) { unit = KoUnit::Inch; } else { unit = KoUnit::Centimeter; } } ~Private() { // Don't delete m_d->shapeController because it's in a QObject hierarchy. delete nserver; } KisDocument *document; KoDocumentInfo *docInfo; KoProgressUpdater *progressUpdater; KoProgressProxy *progressProxy; QTextStream *profileStream; QTime profileReferenceTime; KoUnit unit; KisImportExportManager *filterManager; // The filter-manager to use when loading/saving [for the options] QByteArray mimeType; // The actual mimetype of the document QByteArray outputMimeType; // The mimetype to use when saving bool confirmNonNativeSave [2]; // used to pop up a dialog when saving for the // first time if the file is in a foreign format // (Save/Save As, Export) int specialOutputFlag; // See KoFileDialog in koMainWindow.cc bool isImporting; bool isExporting; // File --> Import/Export vs File --> Open/Save QString password; // The password used to encrypt an encrypted document QTimer autoSaveTimer; QString lastErrorMessage; // see openFile() int autoSaveDelay; // in seconds, 0 to disable. bool modifiedAfterAutosave; bool autosaving; bool shouldCheckAutoSaveFile; // usually true bool autoErrorHandlingEnabled; // usually true bool backupFile; QString backupPath; bool doNotSaveExtDoc; // makes it possible to save only internally stored child documents bool storeInternal; // Store this doc internally even if url is external bool isLoading; // True while loading (openUrl is async) KUndo2Stack *undoStack; KoGridData gridData; KoGuidesData guidesData; bool isEmpty; KoPageLayout pageLayout; KIO::FileCopyJob * m_job; KIO::StatJob * m_statJob; KIO::FileCopyJob * m_uploadJob; KUrl m_originalURL; // for saveAs QString m_originalFilePath; // for saveAs bool m_saveOk : 1; bool m_waitForSave : 1; bool m_duringSaveAs : 1; bool m_bTemp: 1; // If @p true, @p m_file is a temporary file that needs to be deleted later. bool m_bAutoDetectedMime : 1; // whether the mimetype in the arguments was detected by the part itself KUrl m_url; // Remote (or local) url - the one displayed to the user. QString m_file; // Local file - the only one the part implementation should deal with. QEventLoop m_eventLoop; bool modified; bool readwrite; bool disregardAutosaveFailure; KisNameServer *nserver; qint32 macroNestDepth; KisImageSP image; KisNodeSP preActivatedNode; KisShapeController* shapeController; KoShapeController* koShapeController; KisKraLoader* kraLoader; KisKraSaver* kraSaver; QList assistants; bool openFile() { DocumentProgressProxy *progressProxy = 0; if (!document->progressProxy()) { KisMainWindow *mainWindow = 0; if (KisPart::instance()->mainWindows().count() > 0) { mainWindow = KisPart::instance()->mainWindows()[0]; } progressProxy = new DocumentProgressProxy(mainWindow); document->setProgressProxy(progressProxy); } document->setUrl(m_url); bool ok = document->openFile(); if (progressProxy) { document->setProgressProxy(0); delete progressProxy; } return ok; } bool openLocalFile() { m_bTemp = false; // set the mimetype only if it was not already set (for example, by the host application) if (mimeType.isEmpty()) { // get the mimetype of the file // using findByUrl() to avoid another string -> url conversion KMimeType::Ptr mime = KMimeType::findByUrl(m_url, 0, true /* local file*/); if (mime) { mimeType = mime->name().toLocal8Bit(); m_bAutoDetectedMime = true; } } const bool ret = openFile(); if (ret) { emit document->completed(); } else { emit document->canceled(QString()); } return ret; } void openRemoteFile() { m_bTemp = true; // Use same extension as remote file. This is important for mimetype-determination (e.g. koffice) QString fileName = m_url.fileName(); QFileInfo fileInfo(fileName); QString ext = fileInfo.completeSuffix(); QString extension; if (!ext.isEmpty() && m_url.query().isNull()) // not if the URL has a query, e.g. cgi.pl?something extension = '.'+ext; // keep the '.' KTemporaryFile tempFile; tempFile.setSuffix(extension); tempFile.setAutoRemove(false); tempFile.open(); m_file = tempFile.fileName(); KUrl destURL; destURL.setPath( m_file ); KIO::JobFlags flags = KIO::DefaultFlags; flags |= KIO::Overwrite; m_job = KIO::file_copy(m_url, destURL, 0600, flags); QObject::connect(m_job, SIGNAL(result(KJob*)), document, SLOT(_k_slotJobFinished(KJob*))); QObject::connect(m_job, SIGNAL(mimetype(KIO::Job*,QString)), document, SLOT(_k_slotGotMimeType(KIO::Job*,QString))); } // Set m_file correctly for m_url void prepareSaving() { // Local file if ( m_url.isLocalFile() ) { if ( m_bTemp ) // get rid of a possible temp file first { // (happens if previous url was remote) QFile::remove( m_file ); m_bTemp = false; } m_file = m_url.toLocalFile(); } else { // Remote file // We haven't saved yet, or we did but locally - provide a temp file if ( m_file.isEmpty() || !m_bTemp ) { KTemporaryFile tempFile; tempFile.setAutoRemove(false); tempFile.open(); m_file = tempFile.fileName(); m_bTemp = true; } // otherwise, we already had a temp file } } void _k_slotJobFinished( KJob * job ) { Q_ASSERT( job == m_job ); m_job = 0; if (job->error()) emit document->canceled( job->errorString() ); else { if ( openFile() ) { emit document->completed(); } else { emit document->canceled(QString()); } } } void _k_slotStatJobFinished(KJob * job) { Q_ASSERT(job == m_statJob); m_statJob = 0; // this could maybe confuse some apps? So for now we'll just fallback to KIO::get // and error again. Well, maybe this even helps with wrong stat results. if (!job->error()) { #if KDE_IS_VERSION(4,4,0) const KUrl localUrl = static_cast(job)->mostLocalUrl(); #else const KUrl localUrl = static_cast(job)->url(); #endif if (localUrl.isLocalFile()) { m_file = localUrl.toLocalFile(); openLocalFile(); return; } } openRemoteFile(); } void _k_slotGotMimeType(KIO::Job *job, const QString &mime) { kDebug(1000) << mime; Q_ASSERT(job == m_job); Q_UNUSED(job); // set the mimetype only if it was not already set (for example, by the host application) if (mimeType.isEmpty()) { mimeType = mime.toLocal8Bit(); m_bAutoDetectedMime = true; } } void _k_slotUploadFinished( KJob * ) { if (m_uploadJob->error()) { QFile::remove(m_uploadJob->srcUrl().toLocalFile()); m_uploadJob = 0; if (m_duringSaveAs) { document->setUrl(m_originalURL); m_file = m_originalFilePath; } } else { KUrl dirUrl( m_url ); dirUrl.setPath( dirUrl.directory() ); ::org::kde::KDirNotify::emitFilesAdded( dirUrl.url() ); m_uploadJob = 0; document->setModified( false ); emit document->completed(); m_saveOk = true; } m_duringSaveAs = false; m_originalURL = KUrl(); m_originalFilePath.clear(); if (m_waitForSave) { m_eventLoop.quit(); } } }; KisDocument::KisDocument() : d(new Private(this)) { d->undoStack = new UndoStack(this); d->undoStack->setParent(this); d->isEmpty = true; d->filterManager = new KisImportExportManager(this, d->progressUpdater); connect(&d->autoSaveTimer, SIGNAL(timeout()), this, SLOT(slotAutoSave())); setAutoSave(defaultAutoSave()); setObjectName(newObjectName()); d->docInfo = new KoDocumentInfo(this); d->pageLayout.width = 0; d->pageLayout.height = 0; d->pageLayout.topMargin = 0; d->pageLayout.bottomMargin = 0; d->pageLayout.leftMargin = 0; d->pageLayout.rightMargin = 0; KConfigGroup cfgGrp(KisFactory::componentData().config(), "Undo"); d->undoStack->setUndoLimit(cfgGrp.readEntry("UndoLimit", 1000)); connect(d->undoStack, SIGNAL(indexChanged(int)), this, SLOT(slotUndoStackIndexChanged(int))); // preload the krita resources KisResourceServerProvider::instance(); init(); undoStack()->setUndoLimit(KisConfig().undoStackLimit()); setBackupFile(KisConfig().backupFile()); + + gridData().setShowGrid(false); + KisConfig cfg; + gridData().setGrid(cfg.getGridHSpacing(), cfg.getGridVSpacing()); + } KisDocument::~KisDocument() { /** * Push a timebomb, which will try to release the memory after * the document has been deleted */ KisPaintDevice::createMemoryReleaseObject()->deleteLater(); d->autoSaveTimer.disconnect(this); d->autoSaveTimer.stop(); delete d->filterManager; // Despite being QObject they needs to be deleted before the image delete d->shapeController; delete d->koShapeController; if (d->image) { d->image->notifyAboutToBeDeleted(); } // The following line trigger the deletion of the image d->image.clear(); delete d; } void KisDocument::init() { delete d->nserver; d->nserver = 0; d->nserver = new KisNameServer(1); Q_CHECK_PTR(d->nserver); d->shapeController = new KisShapeController(this, d->nserver); d->koShapeController = new KoShapeController(0, d->shapeController); d->kraSaver = 0; d->kraLoader = 0; } bool KisDocument::reload() { // XXX: reimplement! return false; } bool KisDocument::exportDocument(const KUrl & _url) { bool ret; d->isExporting = true; // // Preserve a lot of state here because we need to restore it in order to // be able to fake a File --> Export. Can't do this in saveFile() because, // for a start, KParts has already set url and m_file and because we need // to restore the modified flag etc. and don't want to put a load on anyone // reimplementing saveFile() (Note: importDocument() and exportDocument() // will remain non-virtual). // KUrl oldURL = url(); QString oldFile = localFilePath(); bool wasModified = isModified(); QByteArray oldMimeType = mimeType(); // save... ret = saveAs(_url); // // This is sooooo hacky :( // Hopefully we will restore enough state. // kDebug(30003) << "Restoring KisDocument state to before export"; // always restore url & m_file because KParts has changed them // (regardless of failure or success) setUrl(oldURL); setLocalFilePath(oldFile); // on successful export we need to restore modified etc. too // on failed export, mimetype/modified hasn't changed anyway if (ret) { setModified(wasModified); d->mimeType = oldMimeType; } d->isExporting = false; return ret; } bool KisDocument::saveFile() { kDebug(30003) << "doc=" << url().url(); // Save it to be able to restore it after a failed save const bool wasModified = isModified(); // The output format is set by koMainWindow, and by openFile QByteArray outputMimeType = d->outputMimeType; if (outputMimeType.isEmpty()) outputMimeType = d->outputMimeType = nativeFormatMimeType(); QApplication::setOverrideCursor(Qt::WaitCursor); if (backupFile()) { if (url().isLocalFile()) KSaveFile::backupFile(url().toLocalFile(), d->backupPath); else { KIO::UDSEntry entry; if (KIO::NetAccess::stat(url(), entry, KisPart::instance()->currentMainwindow())) { // this file exists => backup emit statusBarMessage(i18n("Making backup...")); KUrl backup; if (d->backupPath.isEmpty()) backup = url(); else backup = d->backupPath + '/' + url().fileName(); backup.setPath(backup.path() + QString::fromLatin1("~")); KFileItem item(entry, url()); Q_ASSERT(item.name() == url().fileName()); KIO::FileCopyJob *job = KIO::file_copy(url(), backup, item.permissions(), KIO::Overwrite | KIO::HideProgressInfo); job->exec(); } } } emit statusBarMessage(i18n("Saving...")); qApp->processEvents(); bool ret = false; bool suppressErrorDialog = false; if (!isNativeFormat(outputMimeType)) { kDebug(30003) << "Saving to format" << outputMimeType << "in" << localFilePath(); // Not native format : save using export filter KisImportExportFilter::ConversionStatus status = d->filterManager->exportDocument(localFilePath(), outputMimeType); ret = status == KisImportExportFilter::OK; suppressErrorDialog = (status == KisImportExportFilter::UserCancelled || status == KisImportExportFilter::BadConversionGraph); } else { // Native format => normal save Q_ASSERT(!localFilePath().isEmpty()); ret = saveNativeFormat(localFilePath()); } if (ret) { d->undoStack->setClean(); removeAutoSaveFiles(); // Restart the autosave timer // (we don't want to autosave again 2 seconds after a real save) setAutoSave(d->autoSaveDelay); } QApplication::restoreOverrideCursor(); if (!ret) { if (!suppressErrorDialog) { if (errorMessage().isEmpty()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not save\n%1", localFilePath()) + "\n\n" + i18n("Most likely a layer is still processing effects.")); } else if (errorMessage() != "USER_CANCELED") { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not save %1\nReason: %2", localFilePath(), errorMessage())); } } // couldn't save file so this new URL is invalid // FIXME: we should restore the current document's true URL instead of // setting it to nothing otherwise anything that depends on the URL // being correct will not work (i.e. the document will be called // "Untitled" which may not be true) // // Update: now the URL is restored in KisMainWindow but really, this // should still be fixed in KisDocument/KParts (ditto for file). // We still resetURL() here since we may or may not have been called // by KisMainWindow - Clarence resetURL(); // As we did not save, restore the "was modified" status setModified(wasModified); } if (ret) { d->mimeType = outputMimeType; setConfirmNonNativeSave(isExporting(), false); } emit clearStatusBarMessage(); return ret; } QByteArray KisDocument::mimeType() const { return d->mimeType; } void KisDocument::setMimeType(const QByteArray & mimeType) { d->mimeType = mimeType; } void KisDocument::setOutputMimeType(const QByteArray & mimeType, int specialOutputFlag) { d->outputMimeType = mimeType; d->specialOutputFlag = specialOutputFlag; } QByteArray KisDocument::outputMimeType() const { return d->outputMimeType; } int KisDocument::specialOutputFlag() const { return d->specialOutputFlag; } bool KisDocument::confirmNonNativeSave(const bool exporting) const { // "exporting ? 1 : 0" is different from "exporting" because a bool is // usually implemented like an "int", not "unsigned : 1" return d->confirmNonNativeSave [ exporting ? 1 : 0 ]; } void KisDocument::setConfirmNonNativeSave(const bool exporting, const bool on) { d->confirmNonNativeSave [ exporting ? 1 : 0] = on; } bool KisDocument::saveInBatchMode() const { return d->filterManager->getBatchMode(); } void KisDocument::setSaveInBatchMode(const bool batchMode) { d->filterManager->setBatchMode(batchMode); } bool KisDocument::isImporting() const { return d->isImporting; } bool KisDocument::isExporting() const { return d->isExporting; } void KisDocument::setCheckAutoSaveFile(bool b) { d->shouldCheckAutoSaveFile = b; } void KisDocument::setAutoErrorHandlingEnabled(bool b) { d->autoErrorHandlingEnabled = b; } bool KisDocument::isAutoErrorHandlingEnabled() const { return d->autoErrorHandlingEnabled; } void KisDocument::slotAutoSave() { if (d->modified && d->modifiedAfterAutosave && !d->isLoading) { // Give a warning when trying to autosave an encrypted file when no password is known (should not happen) if (d->specialOutputFlag == SaveEncrypted && d->password.isNull()) { // That advice should also fix this error from occurring again emit statusBarMessage(i18n("The password of this encrypted document is not known. Autosave aborted! Please save your work manually.")); } else { connect(this, SIGNAL(sigProgress(int)), KisPart::instance()->currentMainwindow(), SLOT(slotProgress(int))); emit statusBarMessage(i18n("Autosaving...")); d->autosaving = true; bool ret = saveNativeFormat(autoSaveFile(localFilePath())); setModified(true); if (ret) { d->modifiedAfterAutosave = false; d->autoSaveTimer.stop(); // until the next change } d->autosaving = false; emit clearStatusBarMessage(); disconnect(this, SIGNAL(sigProgress(int)), KisPart::instance()->currentMainwindow(), SLOT(slotProgress(int))); if (!ret && !d->disregardAutosaveFailure) { emit statusBarMessage(i18n("Error during autosave! Partition full?")); } } } } void KisDocument::setReadWrite(bool readwrite) { d->readwrite = readwrite; setAutoSave(d->autoSaveDelay); foreach(KisMainWindow *mainWindow, KisPart::instance()->mainWindows()) { mainWindow->setReadWrite(readwrite); } } void KisDocument::setAutoSave(int delay) { d->autoSaveDelay = delay; if (isReadWrite() && d->autoSaveDelay > 0) d->autoSaveTimer.start(d->autoSaveDelay * 1000); else d->autoSaveTimer.stop(); } KoDocumentInfo *KisDocument::documentInfo() const { return d->docInfo; } bool KisDocument::isModified() const { return d->modified; } bool KisDocument::saveNativeFormat(const QString & file) { const int realAutoSaveInterval = KisConfig().autoSaveInterval(); const int emergencyAutoSaveInterval = 10; // sec if (!d->image->tryBarrierLock()) { if (isAutosaving()) { setDisregardAutosaveFailure(true); if (realAutoSaveInterval) { setAutoSave(emergencyAutoSaveInterval); } return false; } else { d->image->requestStrokeEnd(); QApplication::processEvents(); if (!d->image->tryBarrierLock()) { return false; } } } setDisregardAutosaveFailure(false); d->lastErrorMessage.clear(); //kDebug(30003) <<"Saving to store"; KoStore::Backend backend = KoStore::Auto; if (d->specialOutputFlag == SaveAsDirectoryStore) { backend = KoStore::Directory; kDebug(30003) << "Saving as uncompressed XML, using directory store."; } else if (d->specialOutputFlag == SaveAsFlatXML) { kDebug(30003) << "Saving as a flat XML file."; QFile f(file); if (f.open(QIODevice::WriteOnly | QIODevice::Text)) { bool success = saveToStream(&f); f.close(); return success; } else return false; } kDebug(30003) << "KisDocument::saveNativeFormat nativeFormatMimeType=" << nativeFormatMimeType(); // TODO: use std::auto_ptr or create store on stack [needs API fixing], // to remove all the 'delete store' in all the branches KoStore *store = KoStore::createStore(file, KoStore::Write, d->outputMimeType, backend); if (d->specialOutputFlag == SaveEncrypted && !d->password.isNull()) { store->setPassword(d->password); } if (store->bad()) { d->lastErrorMessage = i18n("Could not create the file for saving"); // more details needed? delete store; d->image->unlock(); setAutoSave(realAutoSaveInterval); return false; } d->image->unlock(); setAutoSave(realAutoSaveInterval); return saveNativeFormatCalligra(store); } bool KisDocument::saveNativeFormatCalligra(KoStore *store) { kDebug(30003) << "Saving root"; if (store->open("root")) { KoStoreDevice dev(store); if (!saveToStream(&dev) || !store->close()) { kDebug(30003) << "saveToStream failed"; delete store; return false; } } else { d->lastErrorMessage = i18n("Not able to write '%1'. Partition full?", QString("maindoc.xml")); delete store; return false; } if (store->open("documentinfo.xml")) { QDomDocument doc = KisDocument::createDomDocument("document-info" /*DTD name*/, "document-info" /*tag name*/, "1.1"); doc = d->docInfo->save(doc); KoStoreDevice dev(store); QByteArray s = doc.toByteArray(); // this is already Utf8! (void)dev.write(s.data(), s.size()); (void)store->close(); } if (store->open("preview.png")) { // ### TODO: missing error checking (The partition could be full!) savePreview(store); (void)store->close(); } if (!completeSaving(store)) { delete store; return false; } kDebug(30003) << "Saving done of url:" << url().url(); if (!store->finalize()) { delete store; return false; } // Success delete store; return true; } bool KisDocument::saveToStream(QIODevice *dev) { QDomDocument doc = saveXML(); // Save to buffer QByteArray s = doc.toByteArray(); // utf8 already dev->open(QIODevice::WriteOnly); int nwritten = dev->write(s.data(), s.size()); if (nwritten != (int)s.size()) kWarning(30003) << "wrote " << nwritten << "- expected" << s.size(); return nwritten == (int)s.size(); } QString KisDocument::checkImageMimeTypes(const QString &mimeType, const KUrl &url) const { if (!url.isLocalFile()) return mimeType; if (url.toLocalFile().endsWith(".kpp")) return "image/png"; QStringList imageMimeTypes; imageMimeTypes << "image/jpeg" << "image/x-psd" << "image/photoshop" << "image/x-photoshop" << "image/x-vnd.adobe.photoshop" << "image/vnd.adobe.photoshop" << "image/x-portable-pixmap" << "image/x-portable-graymap" << "image/x-portable-bitmap" << "application/pdf" << "image/x-exr" << "image/x-xcf" << "image/x-eps" << "image/png" << "image/bmp" << "image/x-xpixmap" << "image/gif" << "image/x-xbitmap" << "image/tiff" << "image/jp2"; if (!imageMimeTypes.contains(mimeType)) return mimeType; int accuracy = 0; QFile f(url.toLocalFile()); if (!f.open(QIODevice::ReadOnly)) { qWarning() << "Could not open file to check the mimetype" << url; } QByteArray ba = f.read(qMin(f.size(), (qint64)512)); // should be enough for images KMimeType::Ptr mime = KMimeType::findByContent(ba, &accuracy); f.close(); if (!mime) { return mimeType; } // Checking the content failed as well, so let's fall back on the extension again if (mime->name() == "application/octet-stream") { return mimeType; } return mime->name(); } // Called for embedded documents bool KisDocument::saveToStore(KoStore *_store, const QString & _path) { kDebug(30003) << "Saving document to store" << _path; _store->pushDirectory(); // Use the path as the internal url if (_path.startsWith(STORE_PROTOCOL)) setUrl(KUrl(_path)); else // ugly hack to pass a relative URI setUrl(KUrl(INTERNAL_PREFIX + _path)); // In the current directory we're the king :-) if (_store->open("root")) { KoStoreDevice dev(_store); if (!saveToStream(&dev)) { _store->close(); return false; } if (!_store->close()) return false; } if (!completeSaving(_store)) return false; // Now that we're done leave the directory again _store->popDirectory(); kDebug(30003) << "Saved document to store"; return true; } bool KisDocument::savePreview(KoStore *store) { QPixmap pix = generatePreview(QSize(256, 256)); const QImage preview(pix.toImage().convertToFormat(QImage::Format_ARGB32, Qt::ColorOnly)); KoStoreDevice io(store); if (!io.open(QIODevice::WriteOnly)) return false; if (! preview.save(&io, "PNG")) // ### TODO What is -9 in quality terms? return false; io.close(); return true; } QPixmap KisDocument::generatePreview(const QSize& size) { if (d->image) { QRect bounds = d->image->bounds(); QSize newSize = bounds.size(); newSize.scale(size, Qt::KeepAspectRatio); QImage image; if (bounds.width() < 10000 && bounds.height() < 10000) { image = d->image->convertToQImage(d->image->bounds(), 0); } else { image = d->image->convertToQImage(QRect(0, 0, newSize.width(), newSize.height()), newSize, 0); } image = image.scaled(newSize, Qt::KeepAspectRatio, Qt::SmoothTransformation); return QPixmap::fromImage(image); } return QPixmap(size); } QString KisDocument::autoSaveFile(const QString & path) const { QString retval; // Using the extension allows to avoid relying on the mime magic when opening KMimeType::Ptr mime = KMimeType::mimeType(nativeFormatMimeType()); if (! mime) { qFatal("It seems your installation is broken/incomplete because we failed to load the native mimetype \"%s\".", nativeFormatMimeType().constData()); } QString extension = mime->property("X-KDE-NativeExtension").toString(); if (extension.isEmpty()) extension = mime->mainExtension(); if (path.isEmpty()) { // Never saved? #ifdef Q_OS_WIN // On Windows, use the temp location (https://bugs.kde.org/show_bug.cgi?id=314921) retval = QString("%1/.%2-%3-%4-autosave%5").arg(QDir::tempPath()).arg(KisFactory::componentName()).arg(qApp->applicationPid()).arg(objectName()).arg(extension); #else // On Linux, use a temp file in $HOME then. Mark it with the pid so two instances don't overwrite each other's autosave file retval = QString("%1/.%2-%3-%4-autosave%5").arg(QDir::homePath()).arg(KisFactory::componentName()).arg(qApp->applicationPid()).arg(objectName()).arg(extension); #endif } else { KUrl url = KUrl::fromPath(path); Q_ASSERT(url.isLocalFile()); QString dir = url.directory(KUrl::AppendTrailingSlash); QString filename = url.fileName(); retval = QString("%1.%2-autosave%3").arg(dir).arg(filename).arg(extension); } return retval; } void KisDocument::setDisregardAutosaveFailure(bool disregardFailure) { d->disregardAutosaveFailure = disregardFailure; } bool KisDocument::importDocument(const KUrl & _url) { bool ret; kDebug(30003) << "url=" << _url.url(); d->isImporting = true; // open... ret = openUrl(_url); // reset url & m_file (kindly? set by KisParts::openUrl()) to simulate a // File --> Import if (ret) { kDebug(30003) << "success, resetting url"; resetURL(); setTitleModified(); } d->isImporting = false; return ret; } -bool KisDocument::openUrl(const KUrl & _url) +bool KisDocument::openUrl(const KUrl & _url, KisDocument::OpenUrlFlags flags) { kDebug(30003) << "url=" << _url.url(); d->lastErrorMessage.clear(); // Reimplemented, to add a check for autosave files and to improve error reporting if (!_url.isValid()) { d->lastErrorMessage = i18n("Malformed URL\n%1", _url.url()); // ## used anywhere ? return false; } KUrl url(_url); bool autosaveOpened = false; d->isLoading = true; if (url.isLocalFile() && d->shouldCheckAutoSaveFile) { QString file = url.toLocalFile(); QString asf = autoSaveFile(file); if (QFile::exists(asf)) { //kDebug(30003) <<"asf=" << asf; // ## TODO compare timestamps ? int res = QMessageBox::warning(0, i18nc("@title:window", "Krita"), i18n("An autosaved file exists for this document.\nDo you want to open it instead?"), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); switch (res) { case QMessageBox::Yes : url.setPath(asf); autosaveOpened = true; break; case QMessageBox::No : QFile::remove(asf); break; default: // Cancel d->isLoading = false; return false; } } } bool ret = openUrlInternal(url); if (autosaveOpened) { resetURL(); // Force save to act like 'Save As' setReadWrite(true); // enable save button setModified(true); } else { - KisPart::instance()->addRecentURLToAllMainWindows(_url); + if( !(flags & OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES) ) { + KisPart::instance()->addRecentURLToAllMainWindows(_url); + } if (ret) { // Detect readonly local-files; remote files are assumed to be writable, unless we add a KIO::stat here (async). KFileItem file(url, mimeType(), KFileItem::Unknown); setReadWrite(file.isWritable()); } } return ret; } bool KisDocument::openFile() { //kDebug(30003) <<"for" << localFilePath(); if (!QFile::exists(localFilePath())) { QApplication::restoreOverrideCursor(); if (d->autoErrorHandlingEnabled) // Maybe offer to create a new document with that name ? QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("File %1 does not exist.", localFilePath())); d->isLoading = false; return false; } QApplication::setOverrideCursor(Qt::WaitCursor); d->specialOutputFlag = 0; QByteArray _native_format = nativeFormatMimeType(); KUrl u(localFilePath()); QString typeName = mimeType(); if (typeName.isEmpty()) { typeName = KMimeType::findByUrl(u, 0, true)->name(); } // for images, always check content. typeName = checkImageMimeTypes(typeName, u); //kDebug(30003) << "mimetypes 4:" << typeName; // Allow to open backup files, don't keep the mimetype application/x-trash. if (typeName == "application/x-trash") { QString path = u.path(); KMimeType::Ptr mime = KMimeType::mimeType(typeName); const QStringList patterns = mime ? mime->patterns() : QStringList(); // Find the extension that makes it a backup file, and remove it for (QStringList::ConstIterator it = patterns.begin(); it != patterns.end(); ++it) { QString ext = *it; if (!ext.isEmpty() && ext[0] == '*') { ext.remove(0, 1); if (path.endsWith(ext)) { path.chop(ext.length()); break; } } } typeName = KMimeType::findByPath(path, 0, true)->name(); } // Special case for flat XML files (e.g. using directory store) if (u.fileName() == "maindoc.xml" || u.fileName() == "content.xml" || typeName == "inode/directory") { typeName = _native_format; // Hmm, what if it's from another app? ### Check mimetype d->specialOutputFlag = SaveAsDirectoryStore; kDebug(30003) << "loading" << u.fileName() << ", using directory store for" << localFilePath() << "; typeName=" << typeName; } kDebug(30003) << localFilePath() << "type:" << typeName; QString importedFile = localFilePath(); // create the main progress monitoring object for loading, this can // contain subtasks for filtering and loading KoProgressProxy *progressProxy = 0; if (d->progressProxy) { progressProxy = d->progressProxy; } d->progressUpdater = new KoProgressUpdater(progressProxy, KoProgressUpdater::Unthreaded, d->profileStream); d->progressUpdater->setReferenceTime(d->profileReferenceTime); d->progressUpdater->start(100, i18n("Opening Document")); setupOpenFileSubProgress(); if (!isNativeFormat(typeName.toLatin1())) { KisImportExportFilter::ConversionStatus status; importedFile = d->filterManager->importDocument(localFilePath(), typeName, status); if (status != KisImportExportFilter::OK) { QApplication::restoreOverrideCursor(); QString msg; switch (status) { case KisImportExportFilter::OK: break; case KisImportExportFilter::FilterCreationError: msg = i18n("Could not create the filter plugin"); break; case KisImportExportFilter::CreationError: msg = i18n("Could not create the output document"); break; case KisImportExportFilter::FileNotFound: msg = i18n("File not found"); break; case KisImportExportFilter::StorageCreationError: msg = i18n("Cannot create storage"); break; case KisImportExportFilter::BadMimeType: msg = i18n("Bad MIME type"); break; case KisImportExportFilter::EmbeddedDocError: msg = i18n("Error in embedded document"); break; case KisImportExportFilter::WrongFormat: msg = i18n("Format not recognized"); break; case KisImportExportFilter::NotImplemented: msg = i18n("Not implemented"); break; case KisImportExportFilter::ParsingError: msg = i18n("Parsing error"); break; case KisImportExportFilter::PasswordProtected: msg = i18n("Document is password protected"); break; case KisImportExportFilter::InvalidFormat: msg = i18n("Invalid file format"); break; case KisImportExportFilter::InternalError: case KisImportExportFilter::UnexpectedEOF: case KisImportExportFilter::UnexpectedOpcode: case KisImportExportFilter::StupidError: // ?? what is this ?? case KisImportExportFilter::UsageError: msg = i18n("Internal error"); break; case KisImportExportFilter::OutOfMemory: msg = i18n("Out of memory"); break; case KisImportExportFilter::FilterEntryNull: msg = i18n("Empty Filter Plugin"); break; case KisImportExportFilter::NoDocumentCreated: msg = i18n("Trying to load into the wrong kind of document"); break; case KisImportExportFilter::DownloadFailed: msg = i18n("Failed to download remote file"); break; case KisImportExportFilter::UserCancelled: case KisImportExportFilter::BadConversionGraph: // intentionally we do not prompt the error message here break; default: msg = i18n("Unknown error"); break; } if (d->autoErrorHandlingEnabled && !msg.isEmpty()) { QString errorMsg(i18n("Could not open %2.\nReason: %1.\n%3", msg, prettyPathOrUrl(), errorMessage())); QMessageBox::critical(0, i18nc("@title:window", "Krita"), errorMsg); } d->isLoading = false; delete d->progressUpdater; d->progressUpdater = 0; return false; } d->isEmpty = false; kDebug(30003) << "importedFile" << importedFile << "status:" << static_cast(status); } QApplication::restoreOverrideCursor(); bool ok = true; if (!importedFile.isEmpty()) { // Something to load (tmp or native file) ? // The filter, if any, has been applied. It's all native format now. if (!loadNativeFormat(importedFile)) { ok = false; if (d->autoErrorHandlingEnabled) { showLoadingErrorDialog(); } } } if (importedFile != localFilePath()) { // We opened a temporary file (result of an import filter) // Set document URL to empty - we don't want to save in /tmp ! // But only if in readwrite mode (no saving problem otherwise) // -- // But this isn't true at all. If this is the result of an // import, then importedFile=temporary_file.kwd and // file/m_url=foreignformat.ext so m_url is correct! // So don't resetURL() or else the caption won't be set when // foreign files are opened (an annoying bug). // - Clarence // #if 0 if (isReadWrite()) resetURL(); #endif // remove temp file - uncomment this to debug import filters if (!importedFile.isEmpty()) { #ifndef NDEBUG if (!getenv("CALLIGRA_DEBUG_FILTERS")) #endif QFile::remove(importedFile); } } if (ok) { setMimeTypeAfterLoading(typeName); emit sigLoadingFinished(); } if (progressUpdater()) { QPointer updater = progressUpdater()->startSubtask(1, "clear undo stack"); updater->setProgress(0); undoStack()->clear(); updater->setProgress(100); } delete d->progressUpdater; d->progressUpdater = 0; d->isLoading = false; return ok; } KoProgressUpdater *KisDocument::progressUpdater() const { return d->progressUpdater; } void KisDocument::setProgressProxy(KoProgressProxy *progressProxy) { d->progressProxy = progressProxy; } KoProgressProxy* KisDocument::progressProxy() const { if (!d->progressProxy) { KisMainWindow *mainWindow = 0; if (KisPart::instance()->mainwindowCount() > 0) { mainWindow = KisPart::instance()->mainWindows()[0]; } d->progressProxy = new DocumentProgressProxy(mainWindow); } return d->progressProxy; } // shared between openFile and koMainWindow's "create new empty document" code void KisDocument::setMimeTypeAfterLoading(const QString& mimeType) { d->mimeType = mimeType.toLatin1(); d->outputMimeType = d->mimeType; const bool needConfirm = !isNativeFormat(d->mimeType); setConfirmNonNativeSave(false, needConfirm); setConfirmNonNativeSave(true, needConfirm); } // The caller must call store->close() if loadAndParse returns true. bool KisDocument::oldLoadAndParse(KoStore *store, const QString& filename, KoXmlDocument& doc) { //kDebug(30003) <<"Trying to open" << filename; if (!store->open(filename)) { kWarning(30003) << "Entry " << filename << " not found!"; d->lastErrorMessage = i18n("Could not find %1", filename); return false; } // Error variables for QDomDocument::setContent QString errorMsg; int errorLine, errorColumn; bool ok = doc.setContent(store->device(), &errorMsg, &errorLine, &errorColumn); store->close(); if (!ok) { kError(30003) << "Parsing error in " << filename << "! Aborting!" << endl << " In line: " << errorLine << ", column: " << errorColumn << endl << " Error message: " << errorMsg << endl; d->lastErrorMessage = i18n("Parsing error in %1 at line %2, column %3\nError message: %4" , filename , errorLine, errorColumn , QCoreApplication::translate("QXml", errorMsg.toUtf8(), 0, QCoreApplication::UnicodeUTF8)); return false; } kDebug(30003) << "File" << filename << " loaded and parsed"; return true; } bool KisDocument::loadNativeFormat(const QString & file_) { QString file = file_; QFileInfo fileInfo(file); if (!fileInfo.exists()) { // check duplicated from openUrl, but this is useful for templates d->lastErrorMessage = i18n("The file %1 does not exist.", file); return false; } if (!fileInfo.isFile()) { file += "/content.xml"; QFileInfo fileInfo2(file); if (!fileInfo2.exists() || !fileInfo2.isFile()) { d->lastErrorMessage = i18n("%1 is not a file." , file_); return false; } } QApplication::setOverrideCursor(Qt::WaitCursor); kDebug(30003) << file; QFile in; bool isRawXML = false; if (d->specialOutputFlag != SaveAsDirectoryStore) { // Don't try to open a directory ;) in.setFileName(file); if (!in.open(QIODevice::ReadOnly)) { QApplication::restoreOverrideCursor(); d->lastErrorMessage = i18n("Could not open the file for reading (check read permissions)."); return false; } char buf[6]; buf[5] = 0; int pos = 0; do { if (in.read(buf + pos , 1) < 1) { QApplication::restoreOverrideCursor(); in.close(); d->lastErrorMessage = i18n("Could not read the beginning of the file."); return false; } if (QChar(buf[pos]).isSpace()) continue; pos++; } while (pos < 5); isRawXML = (qstrnicmp(buf, "lastErrorMessage = i18n("parsing error in the main document at line %1, column %2\nError message: %3", errorLine, errorColumn, i18n(errorMsg.toUtf8())); res = false; } QApplication::restoreOverrideCursor(); in.close(); d->isEmpty = false; return res; } else { // It's a calligra store (tar.gz, zip, directory, etc.) in.close(); KoStore::Backend backend = (d->specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto; KoStore *store = KoStore::createStore(file, KoStore::Read, "", backend); if (store->bad()) { d->lastErrorMessage = i18n("Not a valid Krita file: %1", file); delete store; QApplication::restoreOverrideCursor(); return false; } // Remember that the file was encrypted if (d->specialOutputFlag == 0 && store->isEncrypted() && !d->isImporting) d->specialOutputFlag = SaveEncrypted; const bool success = loadNativeFormatFromStoreInternal(store); // Retrieve the password after loading the file, only then is it guaranteed to exist if (success && store->isEncrypted() && !d->isImporting) d->password = store->password(); delete store; return success; } } bool KisDocument::loadNativeFormatFromByteArray(QByteArray &data) { bool succes; KoStore::Backend backend = (d->specialOutputFlag == SaveAsDirectoryStore) ? KoStore::Directory : KoStore::Auto; QBuffer buffer(&data); KoStore *store = KoStore::createStore(&buffer, KoStore::Read, "", backend); if (store->bad()) { delete store; return false; } // Remember that the file was encrypted if (d->specialOutputFlag == 0 && store->isEncrypted() && !d->isImporting) d->specialOutputFlag = SaveEncrypted; succes = loadNativeFormatFromStoreInternal(store); // Retrieve the password after loading the file, only then is it guaranteed to exist if (succes && store->isEncrypted() && !d->isImporting) d->password = store->password(); delete store; return succes; } bool KisDocument::loadNativeFormatFromStoreInternal(KoStore *store) { if (store->hasFile("root") || store->hasFile("maindoc.xml")) { // Fallback to "old" file format (maindoc.xml) KoXmlDocument doc = KoXmlDocument(true); bool ok = oldLoadAndParse(store, "root", doc); if (ok) ok = loadXML(doc, store); if (!ok) { QApplication::restoreOverrideCursor(); return false; } } else { kError(30003) << "ERROR: No maindoc.xml" << endl; d->lastErrorMessage = i18n("Invalid document: no file 'maindoc.xml'."); QApplication::restoreOverrideCursor(); return false; } if (store->hasFile("documentinfo.xml")) { KoXmlDocument doc = KoXmlDocument(true); if (oldLoadAndParse(store, "documentinfo.xml", doc)) { d->docInfo->load(doc); } } else { //kDebug( 30003 ) <<"cannot open document info"; delete d->docInfo; d->docInfo = new KoDocumentInfo(this); } bool res = completeLoading(store); QApplication::restoreOverrideCursor(); d->isEmpty = false; return res; } // For embedded documents bool KisDocument::loadFromStore(KoStore *_store, const QString& url) { if (_store->open(url)) { KoXmlDocument doc = KoXmlDocument(true); doc.setContent(_store->device()); if (!loadXML(doc, _store)) { _store->close(); return false; } _store->close(); } else { kWarning() << "couldn't open " << url; } _store->pushDirectory(); // Store as document URL if (url.startsWith(STORE_PROTOCOL)) { setUrl(url); } else { setUrl(KUrl(INTERNAL_PREFIX + url)); _store->enterDirectory(url); } bool result = completeLoading(_store); // Restore the "old" path _store->popDirectory(); return result; } bool KisDocument::loadOdf(KoOdfReadStore & odfStore) { Q_UNUSED(odfStore); setErrorMessage(i18n("Krita does not support the OpenDocument file format.")); return false; } bool KisDocument::saveOdf(SavingContext &documentContext) { Q_UNUSED(documentContext); setErrorMessage(i18n("Krita does not support the OpenDocument file format.")); return false; } bool KisDocument::isStoredExtern() const { return !storeInternal() && hasExternURL(); } void KisDocument::setModified() { d->modified = true; } void KisDocument::setModified(bool mod) { if (isAutosaving()) // ignore setModified calls due to autosaving return; if ( !d->readwrite && d->modified ) { kError(1000) << "Can't set a read-only document to 'modified' !" << endl; return; } //kDebug(30003)<<" url:" << url.path(); //kDebug(30003)<<" mod="<image) { if (d->kraLoader->errorMessages().isEmpty()) { setErrorMessage(i18n("Unknown error.")); } else { setErrorMessage(d->kraLoader->errorMessages().join(".\n")); } return false; } d->kraLoader->loadBinaryData(store, d->image, url().url(), isStoredExtern()); bool retval = true; if (!d->kraLoader->errorMessages().isEmpty()) { setErrorMessage(d->kraLoader->errorMessages().join(".\n")); retval = false; } if (retval) { vKisNodeSP preselectedNodes = d->kraLoader->selectedNodes(); if (preselectedNodes.size() > 0) { d->preActivatedNode = preselectedNodes.first(); } // before deleting the kraloader, get the list with preloaded assistants and save it d->assistants = d->kraLoader->assistants(); d->shapeController->setImage(d->image); connect(d->image.data(), SIGNAL(sigImageModified()), this, SLOT(setImageModified())); if (d->image) { d->image->initialRefreshGraph(); } setAutoSave(KisConfig().autoSaveInterval()); emit sigLoadingFinished(); } delete d->kraLoader; d->kraLoader = 0; return retval; } bool KisDocument::completeSaving(KoStore* store) { QString uri = url().url(); d->kraSaver->saveBinaryData(store, d->image, url().url(), isStoredExtern(), isAutosaving()); bool retval = true; if (!d->kraSaver->errorMessages().isEmpty()) { setErrorMessage(d->kraSaver->errorMessages().join(".\n")); retval = false; } delete d->kraSaver; d->kraSaver = 0; emit sigSavingFinished(); return retval; } QDomDocument KisDocument::createDomDocument(const QString& tagName, const QString& version) const { return createDomDocument(KisFactory::componentName(), tagName, version); } //static QDomDocument KisDocument::createDomDocument(const QString& appName, const QString& tagName, const QString& version) { QDomImplementation impl; QString url = QString("http://www.calligra.org/DTD/%1-%2.dtd").arg(appName).arg(version); QDomDocumentType dtype = impl.createDocumentType(tagName, QString("-//KDE//DTD %1 %2//EN").arg(appName).arg(version), url); // The namespace URN doesn't need to include the version number. QString namespaceURN = QString("http://www.calligra.org/DTD/%1").arg(appName); QDomDocument doc = impl.createDocument(namespaceURN, tagName, dtype); doc.insertBefore(doc.createProcessingInstruction("xml", "version=\"1.0\" encoding=\"UTF-8\""), doc.documentElement()); return doc; } bool KisDocument::loadXML(const KoXmlDocument& doc, KoStore */*store*/) { if (d->image) { d->shapeController->setImage(0); d->image = 0; } KoXmlElement root; KoXmlNode node; KisImageWSP image; init(); if (doc.doctype().name() != "DOC") { setErrorMessage(i18n("The format is not supported or the file is corrupted")); return false; } root = doc.documentElement(); int syntaxVersion = root.attribute("syntaxVersion", "3").toInt(); if (syntaxVersion > 2) { setErrorMessage(i18n("The file is too new for this version of Krita (%1).", syntaxVersion)); return false; } if (!root.hasChildNodes()) { setErrorMessage(i18n("The file has no layers.")); return false; } if (d->kraLoader) delete d->kraLoader; d->kraLoader = new KisKraLoader(this, syntaxVersion); // Legacy from the multi-image .kra file period. for (node = root.firstChild(); !node.isNull(); node = node.nextSibling()) { if (node.isElement()) { if (node.nodeName() == "IMAGE") { KoXmlElement elem = node.toElement(); if (!(image = d->kraLoader->loadXML(elem))) { if (d->kraLoader->errorMessages().isEmpty()) { setErrorMessage(i18n("Unknown error.")); } else { setErrorMessage(d->kraLoader->errorMessages().join(".\n")); } return false; } } else { if (d->kraLoader->errorMessages().isEmpty()) { setErrorMessage(i18n("The file does not contain an image.")); } return false; } } } if (d->image) { // Disconnect existing sig/slot connections d->image->disconnect(this); } d->image = image; return true; } QDomDocument KisDocument::saveXML() { dbgFile << url(); QDomDocument doc = createDomDocument("DOC", CURRENT_DTD_VERSION); QDomElement root = doc.documentElement(); root.setAttribute("editor", "Krita"); root.setAttribute("syntaxVersion", "2"); if (d->kraSaver) delete d->kraSaver; d->kraSaver = new KisKraSaver(this); root.appendChild(d->kraSaver->saveXML(doc, d->image)); if (!d->kraSaver->errorMessages().isEmpty()) { setErrorMessage(d->kraSaver->errorMessages().join(".\n")); } return doc; } bool KisDocument::isNativeFormat(const QByteArray& mimetype) const { if (mimetype == nativeFormatMimeType()) return true; return extraNativeMimeTypes().contains(mimetype); } int KisDocument::supportedSpecialFormats() const { return 0; // we don't support encryption. } void KisDocument::setErrorMessage(const QString& errMsg) { d->lastErrorMessage = errMsg; } QString KisDocument::errorMessage() const { return d->lastErrorMessage; } void KisDocument::showLoadingErrorDialog() { if (errorMessage().isEmpty()) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not open\n%1", localFilePath())); } else if (errorMessage() != "USER_CANCELED") { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("Could not open %1\nReason: %2", localFilePath(), errorMessage())); } } bool KisDocument::isAutosaving() const { return d->autosaving; } bool KisDocument::isLoading() const { return d->isLoading; } void KisDocument::removeAutoSaveFiles() { // Eliminate any auto-save file QString asf = autoSaveFile(localFilePath()); // the one in the current dir if (QFile::exists(asf)) QFile::remove(asf); asf = autoSaveFile(QString()); // and the one in $HOME if (QFile::exists(asf)) QFile::remove(asf); } void KisDocument::setBackupFile(bool _b) { d->backupFile = _b; } bool KisDocument::backupFile()const { return d->backupFile; } void KisDocument::setBackupPath(const QString & _path) { d->backupPath = _path; } QString KisDocument::backupPath()const { return d->backupPath; } bool KisDocument::storeInternal() const { return d->storeInternal; } void KisDocument::setStoreInternal(bool i) { d->storeInternal = i; //kDebug(30003)<<"="<storeInternal<<" doc:"<pageLayout; } void KisDocument::setPageLayout(const KoPageLayout &pageLayout) { d->pageLayout = pageLayout; } KoUnit KisDocument::unit() const { return d->unit; } void KisDocument::setUnit(const KoUnit &unit) { if (d->unit != unit) { d->unit = unit; emit unitChanged(unit); } } void KisDocument::saveUnitOdf(KoXmlWriter *settingsWriter) const { settingsWriter->addConfigItem("unit", unit().symbol()); } KUndo2Stack *KisDocument::undoStack() { return d->undoStack; } void KisDocument::addCommand(KUndo2Command *command) { if (command) d->undoStack->push(command); } void KisDocument::beginMacro(const KUndo2MagicString & text) { d->undoStack->beginMacro(text); } void KisDocument::endMacro() { d->undoStack->endMacro(); } void KisDocument::slotUndoStackIndexChanged(int idx) { // even if the document was already modified, call setModified to re-start autosave timer setModified(idx != d->undoStack->cleanIndex()); } void KisDocument::setProfileStream(QTextStream *profilestream) { d->profileStream = profilestream; } void KisDocument::setProfileReferenceTime(const QTime& referenceTime) { d->profileReferenceTime = referenceTime; } void KisDocument::clearUndoHistory() { d->undoStack->clear(); } KoGridData &KisDocument::gridData() { return d->gridData; } KoGuidesData &KisDocument::guidesData() { return d->guidesData; } bool KisDocument::isEmpty() const { return d->isEmpty; } void KisDocument::setEmpty() { d->isEmpty = true; } // static int KisDocument::defaultAutoSave() { return 300; } void KisDocument::resetURL() { setUrl(KUrl()); setLocalFilePath(QString()); } int KisDocument::pageCount() const { return 1; } void KisDocument::setupOpenFileSubProgress() {} KoDocumentInfoDlg *KisDocument::createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const { return new KoDocumentInfoDlg(parent, docInfo); } bool KisDocument::isReadWrite() const { return d->readwrite; } KUrl KisDocument::url() const { return d->m_url; } bool KisDocument::closeUrl(bool promptToSave) { if (promptToSave) { if ( d->document->isReadWrite() && d->document->isModified()) { foreach(KisView *view, KisPart::instance()->views()) { if (view && view->document() == this) { if (!view->queryClose()) { return false; } } } } } // Not modified => ok and delete temp file. d->mimeType = QByteArray(); if ( d->m_bTemp ) { QFile::remove( d->m_file ); d->m_bTemp = false; } // It always succeeds for a read-only part, // but the return value exists for reimplementations // (e.g. pressing cancel for a modified read-write part) return true; } bool KisDocument::saveAs( const KUrl & kurl ) { if (!kurl.isValid()) { kError(1000) << "saveAs: Malformed URL " << kurl.url() << endl; return false; } d->m_duringSaveAs = true; d->m_originalURL = d->m_url; d->m_originalFilePath = d->m_file; d->m_url = kurl; // Store where to upload in saveToURL d->prepareSaving(); bool result = save(); // Save local file and upload local file if (!result) { d->m_url = d->m_originalURL; d->m_file = d->m_originalFilePath; d->m_duringSaveAs = false; d->m_originalURL = KUrl(); d->m_originalFilePath.clear(); } return result; } bool KisDocument::save() { d->m_saveOk = false; if ( d->m_file.isEmpty() ) // document was created empty d->prepareSaving(); DocumentProgressProxy *progressProxy = 0; if (!d->document->progressProxy()) { KisMainWindow *mainWindow = 0; if (KisPart::instance()->mainwindowCount() > 0) { mainWindow = KisPart::instance()->mainWindows()[0]; } progressProxy = new DocumentProgressProxy(mainWindow); d->document->setProgressProxy(progressProxy); } d->document->setUrl(url()); // THIS IS WRONG! KisDocument::saveFile should move here, and whoever subclassed KisDocument to // reimplement saveFile shold now subclass KisPart. bool ok = d->document->saveFile(); if (progressProxy) { d->document->setProgressProxy(0); delete progressProxy; } if (ok) { return saveToUrl(); } else { emit canceled(QString()); } return false; } bool KisDocument::waitSaveComplete() { if (!d->m_uploadJob) return d->m_saveOk; d->m_waitForSave = true; d->m_eventLoop.exec(QEventLoop::ExcludeUserInputEvents); d->m_waitForSave = false; return d->m_saveOk; } void KisDocument::setUrl(const KUrl &url) { d->m_url = url; } QString KisDocument::localFilePath() const { return d->m_file; } void KisDocument::setLocalFilePath( const QString &localFilePath ) { d->m_file = localFilePath; } bool KisDocument::saveToUrl() { if ( d->m_url.isLocalFile() ) { d->document->setModified( false ); emit completed(); // if m_url is a local file there won't be a temp file -> nothing to remove Q_ASSERT( !d->m_bTemp ); d->m_saveOk = true; d->m_duringSaveAs = false; d->m_originalURL = KUrl(); d->m_originalFilePath.clear(); return true; // Nothing to do } #ifndef Q_OS_WIN else { if (d->m_uploadJob) { QFile::remove(d->m_uploadJob->srcUrl().toLocalFile()); d->m_uploadJob->kill(); d->m_uploadJob = 0; } KTemporaryFile *tempFile = new KTemporaryFile(); tempFile->open(); QString uploadFile = tempFile->fileName(); delete tempFile; KUrl uploadUrl; uploadUrl.setPath( uploadFile ); // Create hardlink if (::link(QFile::encodeName(d->m_file), QFile::encodeName(uploadFile)) != 0) { // Uh oh, some error happened. return false; } d->m_uploadJob = KIO::file_move( uploadUrl, d->m_url, -1, KIO::Overwrite ); connect( d->m_uploadJob, SIGNAL(result(KJob*)), this, SLOT(_k_slotUploadFinished(KJob*)) ); return true; } #else return false; #endif } bool KisDocument::openUrlInternal(const KUrl &url) { if ( !url.isValid() ) return false; if (d->m_bAutoDetectedMime) { d->mimeType = QByteArray(); d->m_bAutoDetectedMime = false; } QByteArray mimetype = d->mimeType; if ( !closeUrl() ) return false; d->mimeType = mimetype; setUrl(url); d->m_file.clear(); if (d->m_url.isLocalFile()) { d->m_file = d->m_url.toLocalFile(); return d->openLocalFile(); } else { d->openRemoteFile(); return true; } } KisImageWSP KisDocument::newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace* colorspace) { KoColor backgroundColor(Qt::white, colorspace); /** * FIXME: check whether this is a good value */ double defaultResolution=1.; newImage(name, width, height, colorspace, backgroundColor, "", defaultResolution); return image(); } bool KisDocument::newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * cs, const KoColor &bgColor, const QString &imageDescription, const double imageResolution) { return newImage(name, width, height, cs, bgColor, false, 1, imageDescription, imageResolution); } bool KisDocument::newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace* cs, const KoColor &bgColor, bool backgroundAsLayer, int numberOfLayers, const QString &description, const double imageResolution) { Q_ASSERT(cs); init(); KisConfig cfg; KisImageWSP image; KisPaintLayerSP layer; if (!cs) return false; QApplication::setOverrideCursor(Qt::BusyCursor); image = new KisImage(createUndoStore(), width, height, cs, name); Q_CHECK_PTR(image); connect(image.data(), SIGNAL(sigImageModified()), this, SLOT(setImageModified())); image->setResolution(imageResolution, imageResolution); image->assignImageProfile(cs->profile()); documentInfo()->setAboutInfo("title", name); if (name != i18n("Unnamed") && !name.isEmpty()) { setUrl(KUrl(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation) + '/' + name + ".kra")); } documentInfo()->setAboutInfo("comments", description); layer = new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, cs); Q_CHECK_PTR(layer); if (backgroundAsLayer) { image->setDefaultProjectionColor(KoColor(cs)); if (bgColor.opacityU8() == OPACITY_OPAQUE_U8) { layer->paintDevice()->setDefaultPixel(bgColor.data()); } else { // Hack: with a semi-transparent background color, the projection isn't composited right if we just set the default pixel KisFillPainter painter; painter.begin(layer->paintDevice()); painter.fillRect(0, 0, width, height, bgColor, bgColor.opacityU8()); } } else { image->setDefaultProjectionColor(bgColor); } layer->setDirty(QRect(0, 0, width, height)); image->addNode(layer.data(), image->rootLayer().data()); setCurrentImage(image); for(int i = 1; i < numberOfLayers; ++i) { KisPaintLayerSP layer = new KisPaintLayer(image, image->nextLayerName(), OPACITY_OPAQUE_U8, cs); image->addNode(layer, image->root(), i); layer->setDirty(QRect(0, 0, width, height)); } cfg.defImageWidth(width); cfg.defImageHeight(height); cfg.defImageResolution(imageResolution); cfg.defColorModel(image->colorSpace()->colorModelId().id()); cfg.setDefaultColorDepth(image->colorSpace()->colorDepthId().id()); cfg.defColorProfile(image->colorSpace()->profile()->name()); QApplication::restoreOverrideCursor(); return true; } KoShapeBasedDocumentBase *KisDocument::shapeController() const { return d->shapeController; } KoShapeLayer* KisDocument::shapeForNode(KisNodeSP layer) const { return d->shapeController->shapeForNode(layer); } vKisNodeSP KisDocument::activeNodes() const { vKisNodeSP nodes; foreach(KisView *v, KisPart::instance()->views()) { if (v->document() == this && v->viewManager()) { KisNodeSP activeNode = v->viewManager()->activeNode(); if (activeNode && !nodes.contains(activeNode)) { if (activeNode->inherits("KisMask")) { activeNode = activeNode->parent(); } nodes.append(activeNode); } } } return nodes; } QList KisDocument::assistants() { QList assistants; foreach(KisView *view, KisPart::instance()->views()) { if (view && view->document() == this) { KisPaintingAssistantsDecoration* assistantsDecoration = view->canvasBase()->paintingAssistantsDecoration(); assistants.append(assistantsDecoration->assistants()); } } return assistants; } QList KisDocument::preLoadedAssistants() { return d->assistants; } void KisDocument::setPreActivatedNode(KisNodeSP activatedNode) { d->preActivatedNode = activatedNode; } KisNodeSP KisDocument::preActivatedNode() const { return d->preActivatedNode; } void KisDocument::prepareForImport() { if (d->nserver == 0) { init(); } } KisImageWSP KisDocument::image() const { return d->image; } void KisDocument::setCurrentImage(KisImageWSP image) { if (!image || !image.isValid()) return; if (d->image) { // Disconnect existing sig/slot connections d->image->disconnect(this); d->shapeController->setImage(0); } d->image = image; d->shapeController->setImage(image); setModified(false); connect(d->image, SIGNAL(sigImageModified()), this, SLOT(setImageModified())); d->image->initialRefreshGraph(); setAutoSave(KisConfig().autoSaveInterval()); } void KisDocument::initEmpty() { KisConfig cfg; const KoColorSpace * rgb = KoColorSpaceRegistry::instance()->rgb8(); newImage("", cfg.defImageWidth(), cfg.defImageHeight(), rgb); } void KisDocument::setImageModified() { setModified(true); } KisUndoStore* KisDocument::createUndoStore() { return new KisDocumentUndoStore(this); } #include diff --git a/krita/ui/KisDocument.h b/krita/ui/KisDocument.h index bf86dd94431..755c2dfb1e7 100644 --- a/krita/ui/KisDocument.h +++ b/krita/ui/KisDocument.h @@ -1,835 +1,842 @@ /* This file is part of the Krita project * * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KISDOCUMENT_H #define KISDOCUMENT_H #include #include #include #include #include "KoGridData.h" #include "KoGuidesData.h" #include #include #include #include #include #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" class QString; class KUndo2Command; class KoUnit; class KoColor; class KoColorSpace; class KoShapeBasedDocumentBase; class KoShapeLayer; class KoStore; class KoOdfReadStore; class KoDocumentInfo; class KoProgressUpdater; class KoProgressProxy; class KoDocumentInfoDlg; class KisUndoStore; class KisPaintingAssistant; class KisPart; class KisPart; #define KIS_MIME_TYPE "application/x-krita" /** * The %Calligra document class * * This class provides some functionality each %Calligra document should have. * * @short The %Calligra document class */ class KRITAUI_EXPORT KisDocument : public QObject, public KoDocumentBase { Q_OBJECT Q_PROPERTY(bool backupFile READ backupFile WRITE setBackupFile) Q_PROPERTY(int pageCount READ pageCount) protected: explicit KisDocument(); public: + enum OpenUrlFlags { + OPEN_URL_FLAG_NONE = 1 << 0, + OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES = 1 << 1, + }; + /** * Destructor. * * The destructor does not delete any attached KisView objects and it does not * delete the attached widget as returned by widget(). */ virtual ~KisDocument(); /** * @brief reload Reloads the document from the original url * @return the result of loading the document */ virtual bool reload(); /** - * Reimplemented from KisParts::ReadWritePart for internal reasons - * (for the autosave functionality) + * @brief openUrl Open an URL + * @param url The URL to open + * @param flags Control specific behavior + * @return success status */ - virtual bool openUrl(const KUrl & url); + virtual bool openUrl(const KUrl & url, OpenUrlFlags flags = OPEN_URL_FLAG_NONE); /** * Opens the document given by @p url, without storing the URL * in the KisDocument. * Call this instead of openUrl() to implement KisMainWindow's * File --> Import feature. * * @note This will call openUrl(). To differentiate this from an ordinary * Open operation (in any reimplementation of openUrl() or openFile()) * call isImporting(). */ bool importDocument(const KUrl &url); /** * Saves the document as @p url without changing the state of the * KisDocument (URL, modified flag etc.). Call this instead of * KisParts::ReadWritePart::saveAs() to implement KisMainWindow's * File --> Export feature. * * @note This will call KisDocument::saveAs(). To differentiate this * from an ordinary Save operation (in any reimplementation of * saveFile()) call isExporting(). */ bool exportDocument(const KUrl &url); /** * @brief Sets whether the document can be edited or is read only. * * This recursively applied to all child documents and * KisView::updateReadWrite is called for every attached * view. */ virtual void setReadWrite(bool readwrite = true); /** * To be preferred when a document exists. It is fast when calling * it multiple times since it caches the result that readNativeFormatMimeType() * delivers. * This comes from the X-KDE-NativeMimeType key in the .desktop file. */ virtual QByteArray nativeFormatMimeType() const { return KIS_MIME_TYPE; } /** * Returns the OASIS OpenDocument mimetype of the document, if supported * This comes from the X-KDE-NativeOasisMimeType key in the * desktop file * * @return the oasis mimetype or, if it hasn't one, the nativeformatmimetype. */ virtual QByteArray nativeOasisMimeType() const { return ""; } /// Checks whether a given mimetype can be handled natively. bool isNativeFormat(const QByteArray& mimetype) const; /// Returns a list of the mimetypes considered "native", i.e. which can /// be saved by KisDocument without a filter, in *addition* to the main one virtual QStringList extraNativeMimeTypes() const { return QStringList() << KIS_MIME_TYPE; } /// Enum values used by specialOutputFlag - note that it's a bitfield for supportedSpecialFormats enum { /*SaveAsCalligra1dot1 = 1,*/ // old and removed SaveAsDirectoryStore = 2, SaveAsFlatXML = 4, SaveEncrypted = 8 // bitfield! next value is 16 }; /** * Return the set of SupportedSpecialFormats that the application wants to * offer in the "Save" file dialog. */ virtual int supportedSpecialFormats() const; /** * Returns the actual mimetype of the document */ QByteArray mimeType() const; /** * @brief Sets the mime type for the document. * * When choosing "save as" this is also the mime type * selected by default. */ void setMimeType(const QByteArray & mimeType); /** * @brief Set the format in which the document should be saved. * * This is called on loading, and in "save as", so you shouldn't * have to call it. * * @param mimeType the mime type (format) to use. * @param specialOutputFlag is for "save as older version" etc. */ void setOutputMimeType(const QByteArray & mimeType, int specialOutputFlag = 0); QByteArray outputMimeType() const; int specialOutputFlag() const; /** * Returns true if this document was the result of opening a foreign * file format and if the user hasn't yet saved the document (in any * format). * * Used by KisMainWindow to warn the user when s/he lazily presses * CTRL+S to save in the same foreign format, putting all his/her * formatting at risk (normally an export confirmation only comes up * with Save As). * * @param exporting specifies whether this is the setting for a * File --> Export or File --> Save/Save As operation. */ bool confirmNonNativeSave(const bool exporting) const; void setConfirmNonNativeSave(const bool exporting, const bool on); /** * @return true if saving/exporting should inhibit the option dialog */ bool saveInBatchMode() const; /** * @param batchMode if true, do not show the option dialog when saving or exporting. */ void setSaveInBatchMode(const bool batchMode); /** * Sets the error message to be shown to the user (use i18n()!) * when loading or saving fails. * If you asked the user about something and they chose "Cancel", * set the message to the magic string "USER_CANCELED", to skip the error dialog. */ void setErrorMessage(const QString& errMsg); /** * Return the last error message. Usually KisDocument takes care of * showing it; this method is mostly provided for non-interactive use. */ QString errorMessage() const; /** * Show the last error message in a message box. * The dialog box will mention a loading problem. * openUrl/openFile takes care of doing it, but not loadNativeFormat itself, * so this is often called after loadNativeFormat returned false. */ void showLoadingErrorDialog(); /** * @brief Generates a preview picture of the document * @note The preview is used in the File Dialog and also to create the Thumbnail */ virtual QPixmap generatePreview(const QSize& size); /** * Tells the document that its title has been modified, either because * the modified status changes (this is done by setModified() ) or * because the URL or the document-info's title changed. */ void setTitleModified(); /** * @return true if the document is empty. */ virtual bool isEmpty() const; /** * @brief Sets the document to empty. * * Used after loading a template * (which is not empty, but not the user's input). * * @see isEmpty() */ virtual void setEmpty(); /** * @brief Loads a document from a store. * * You should never have to reimplement. * * @param store The store to load from * @param url An internal url, like tar:/1/2 */ virtual bool loadFromStore(KoStore *store, const QString& url); /// Unused virtual bool loadOdf(KoOdfReadStore & odfStore); /// Unused virtual bool saveOdf(SavingContext &documentContext); /** * @brief Saves a sub-document to a store. * * You should not have to reimplement this. */ virtual bool saveToStore(KoStore *store, const QString& path); /** * Reimplement this method to load the contents of your Calligra document, * from the XML document. This is for the pre-Oasis file format (maindoc.xml). */ virtual bool loadXML(const KoXmlDocument & doc, KoStore *store); /** * Reimplement this to save the contents of the %Calligra document into * a QDomDocument. The framework takes care of saving it to the store. */ virtual QDomDocument saveXML(); /** * Return a correctly created QDomDocument for this KisDocument, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * @param tagName the name of the tag for the root element * @param version the DTD version (usually the application's version). */ QDomDocument createDomDocument(const QString& tagName, const QString& version) const; /** * Return a correctly created QDomDocument for an old (1.3-style) %Calligra document, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * This static method can be used e.g. by filters. * @param appName the app's instance name, e.g. words, kspread, kpresenter etc. * @param tagName the name of the tag for the root element, e.g. DOC for words/kpresenter. * @param version the DTD version (usually the application's version). */ static QDomDocument createDomDocument(const QString& appName, const QString& tagName, const QString& version); /** * The first thing to do in loadOasis is get hold of the office:body tag, then its child. * If the child isn't the expected one, the error message can indicate what it is instead. * This method returns a translated name for the type of document, * e.g. i18n("Word Processing") for office:text. */ static QString tagNameToDocumentType(const QString& localName); /** * Loads a document in the native format from a given URL. * Reimplement if your native format isn't XML. * * @param file the file to load - usually KReadOnlyPart::m_file or the result of a filter */ virtual bool loadNativeFormat(const QString & file); /** * Saves the document in native format, to a given file * You should never have to reimplement. * Made public for writing templates. */ virtual bool saveNativeFormat(const QString & file); /** * Saves the document in the native format to the given store. */ bool saveNativeFormatCalligra(KoStore *store); /** * Activate/deactivate/configure the autosave feature. * @param delay in seconds, 0 to disable */ void setAutoSave(int delay); /** * Checks whether the document is currently in the process of autosaving */ bool isAutosaving() const; /** * Set whether the next openUrl call should check for an auto-saved file * and offer to open it. This is usually true, but can be turned off * (e.g. for the preview module). This only checks for names auto-saved * files, unnamed auto-saved files are only checked on KisApplication startup. */ void setCheckAutoSaveFile(bool b); /** * Set whether the next openUrl call should show error message boxes in case * of errors. This is usually the case, but e.g. not when generating thumbnail * previews. */ void setAutoErrorHandlingEnabled(bool b); /** * Checks whether error message boxes should be shown. */ bool isAutoErrorHandlingEnabled() const; /** * Retrieve the default value for autosave in seconds. * Called by the applications to use the correct default in their config */ static int defaultAutoSave(); /** * @return the information concerning this document. * @see KoDocumentInfo */ KoDocumentInfo *documentInfo() const; /** * @return the object to report progress to. * One can add more KoUpdaters to it to make the progress reporting more * accurate. If no active progress reporter is present, 0 is returned. **/ KoProgressUpdater *progressUpdater() const; /** * Set a custom progress proxy to use to report loading * progress to. */ void setProgressProxy(KoProgressProxy *progressProxy); KoProgressProxy* progressProxy() const; /** * Return true if url() is a real filename, false if url() is * an internal url in the store, like "tar:/..." */ virtual bool isStoredExtern() const; /** * @return the page layout associated with this document (margins, pageSize, etc). * Override this if you want to provide different sized pages. * * @see KoPageLayout */ virtual KoPageLayout pageLayout(int pageNumber = 0) const; virtual void setPageLayout(const KoPageLayout &pageLayout); /** * Performs a cleanup of unneeded backup files */ void removeAutoSaveFiles(); void setBackupFile(bool _b); bool backupFile()const; /** * Returns true if this document or any of its internal child documents are modified. */ bool isModified() const; /** * Returns true during loading (openUrl can be asynchronous) */ bool isLoading() const; /** * Sets the backup path of the document */ void setBackupPath(const QString & _path); /** * @return path to the backup document */ QString backupPath()const; /** * @return caption of the document * * Caption is of the form "[title] - [url]", * built out of the document info (title) and pretty-printed * document URL. * If the title is not present, only the URL it returned. */ QString caption() const; /** * Sets the document URL to empty URL * KParts doesn't allow this, but %Calligra apps have e.g. templates * After using loadNativeFormat on a template, one wants * to set the url to KUrl() */ void resetURL(); /** * Set when you want an external embedded document to be stored internally */ void setStoreInternal(bool i); /** * @return true when external embedded documents are stored internally */ bool storeInternal() const; bool hasExternURL() const; /** * @internal (public for KisMainWindow) */ void setMimeTypeAfterLoading(const QString& mimeType); /** * @return returns the number of pages in the document. */ virtual int pageCount() const; /** * Returns the unit used to display all measures/distances. */ KoUnit unit() const; /** * Sets the unit used to display all measures/distances. */ void setUnit(const KoUnit &unit); /** * Save the unit to the settings writer * * @param settingsWriter */ void saveUnitOdf(KoXmlWriter *settingsWriter) const; bool loadNativeFormatFromByteArray(QByteArray &data); /// return the grid data for this document. KoGridData &gridData(); /// returns the guides data for this document. KoGuidesData &guidesData(); void clearUndoHistory(); /** * Sets the modified flag on the document. This means that it has * to be saved or not before deleting it. */ virtual void setModified(bool _mod); /** * Initialize an empty document using default values */ virtual void initEmpty(); /** * Returns the global undo stack */ KUndo2Stack *undoStack(); /** * Set the output stream to report profile information to. */ void setProfileStream(QTextStream *profilestream); /** * Set the output stream to report profile information to. */ void setProfileReferenceTime(const QTime& referenceTime); public Q_SLOTS: /** * Adds a command to the undo stack and executes it by calling the redo() function. * @param command command to add to the undo stack */ virtual void addCommand(KUndo2Command *command); /** * Begins recording of a macro command. At the end endMacro needs to be called. * @param text command description */ virtual void beginMacro(const KUndo2MagicString &text); /** * Ends the recording of a macro command. */ virtual void endMacro(); Q_SIGNALS: /** * This signal is emitted when the unit is changed by setUnit(). * It is common to connect views to it, in order to change the displayed units * (e.g. in the rulers) */ void unitChanged(const KoUnit &unit); /** * Progress info while loading or saving. The value is in percents (i.e. a number between 0 and 100) * Your KisDocument-derived class should emit the signal now and then during load/save. * KisMainWindow will take care of displaying a progress bar automatically. */ void sigProgress(int value); /** * Emitted e.g. at the beginning of a save operation * This is emitted by KisDocument and used by KisView to display a statusbar message */ void statusBarMessage(const QString& text); /** * Emitted e.g. at the end of a save operation * This is emitted by KisDocument and used by KisView to clear the statusbar message */ void clearStatusBarMessage(); /** * Emitted when the document is modified */ void modified(bool); void titleModified(const QString &caption, bool isModified); void sigLoadingFinished(); void sigSavingFinished(); private: friend class KisPart; /** * Generate a name for the document. */ QString newObjectName(); QString autoSaveFile(const QString & path) const; void setDisregardAutosaveFailure(bool disregardFailure); /** * Loads a document from KReadOnlyPart::m_file (KParts takes care of downloading * remote documents). * Applies a filter if necessary, and calls loadNativeFormat in any case * You should not have to reimplement, except for very special cases. * * NOTE: this method also creates a new KisView instance! * * This method is called from the KReadOnlyPart::openUrl method. */ virtual bool openFile(); /** * This method is called by @a openFile() to allow applications to setup there * own KoProgressUpdater-subTasks which are then taken into account for the * displayed progressbar during loading. */ virtual void setupOpenFileSubProgress(); /** * Saves a document to KReadOnlyPart::m_file (KParts takes care of uploading * remote documents) * Applies a filter if necessary, and calls saveNativeFormat in any case * You should not have to reimplement, except for very special cases. */ virtual bool saveFile(); /** * Overload this function if you have to load additional files * from a store. This function is called after loadXML() * and after loadChildren() have been called. */ virtual bool completeLoading(KoStore *store); /** * If you want to write additional files to a store, * then you must do it here. * In the implementation, you should prepend the document * url (using url().url()) before the filename, so that everything is kept relative * to this document. For instance it will produce urls such as * tar:/1/pictures/picture0.png, if the doc url is tar:/1 * But do this ONLY if the document is not stored extern (see isStoredExtern() ). * If it is, then the pictures should be saved to tar:/pictures. */ virtual bool completeSaving(KoStore *store); /** @internal */ virtual void setModified(); /** * Returns whether or not the current openUrl() or openFile() call is * actually an import operation (like File --> Import). * This is for informational purposes only. */ bool isImporting() const; /** * Returns whether or not the current saveFile() call is actually an export * operation (like File --> Export). * If this function returns true during saveFile() and you are changing * some sort of state, you _must_ restore it before the end of saveFile(); * otherwise, File --> Export will not work properly. */ bool isExporting() const; public: QString localFilePath() const; void setLocalFilePath( const QString &localFilePath ); KoDocumentInfoDlg* createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const; bool isReadWrite() const; KUrl url() const; void setUrl(const KUrl &url); virtual bool closeUrl(bool promptToSave = true); virtual bool saveAs( const KUrl &url ); public Q_SLOTS: virtual bool save(); bool waitSaveComplete(); Q_SIGNALS: void completed(); void canceled(const QString &); private Q_SLOTS: void setImageModified(); void slotAutoSave(); /// Called by the undo stack when undo or redo is called void slotUndoStackIndexChanged(int idx); protected: bool oldLoadAndParse(KoStore *store, const QString& filename, KoXmlDocument& doc); public: /** * Create a new image that has this document as a parent and * replace the current image with this image. */ bool newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * cs, const KoColor &bgColor, const QString &imageDescription, const double imageResolution); /** * Create a new image that has this document as a parent and * replace the current image with this image. */ bool newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * cs, const KoColor &bgColor, bool backgroundAsLayer, int numberOfLayers, const QString &imageDescription, const double imageResolution); /** * Create a new image that has this document as a parent and * replace the current image with this image. */ KisImageWSP newImage(const QString& name, qint32 width, qint32 height, const KoColorSpace * colorspace); KisImageWSP image() const; /** * Makes an otherwise empty document ready for import/export */ void prepareForImport(); /** * Set the current image to the specified image and turn undo on. */ void setCurrentImage(KisImageWSP image); KisUndoStore* createUndoStore(); /** * The shape controller matches internal krita image layers with * the flake shape hierarchy. */ KoShapeBasedDocumentBase * shapeController() const; KoShapeLayer* shapeForNode(KisNodeSP layer) const; /** * @return a list of all layers that are active in all current views */ vKisNodeSP activeNodes() const; /** * set the list of nodes that were marked as currently active */ void setPreActivatedNode(KisNodeSP activatedNode); /** * @return the node that was set as active during loading */ KisNodeSP preActivatedNode() const; /** *@return a list of all the assistants in all current views */ QList assistants(); /** * @return a list of assistants loaded from a document */ QList preLoadedAssistants(); private: void init(); bool saveToStream(QIODevice *dev); QString checkImageMimeTypes(const QString &mimeType, const KUrl& url) const; bool loadNativeFormatFromStoreInternal(KoStore *store); bool savePreview(KoStore *store); QString prettyPathOrUrl() const; bool saveToUrl(); bool openUrlInternal(const KUrl &url); class Private; Private *const d; Q_PRIVATE_SLOT(d, void _k_slotJobFinished( KJob * job )) Q_PRIVATE_SLOT(d, void _k_slotStatJobFinished(KJob*)) Q_PRIVATE_SLOT(d, void _k_slotGotMimeType(KIO::Job *job, const QString &mime)) Q_PRIVATE_SLOT(d, void _k_slotUploadFinished( KJob * job )) }; Q_DECLARE_METATYPE(KisDocument*) #endif diff --git a/krita/ui/KisDocumentEntry.h b/krita/ui/KisDocumentEntry.h index bcbbd23acf7..81b74005da6 100644 --- a/krita/ui/KisDocumentEntry.h +++ b/krita/ui/KisDocumentEntry.h @@ -1,98 +1,98 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright 2007 David Faure 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_DOCUMENT_ENTRY_H #define KIS_DOCUMENT_ENTRY_H #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" class QStringList; class KisDocument; /** * Represents an available Calligra component * that supports the document interface. */ class KRITAUI_EXPORT KisDocumentEntry { public: /** * Represents an invalid entry (as returned by queryByMimeType for instance) */ explicit KisDocumentEntry(); /** * Represents a valid entry */ explicit KisDocumentEntry(const KService::Ptr& service); ~KisDocumentEntry(); static QString nativeMimeType(); static QStringList extraNativeMimeTypes(); KService::Ptr service() const; /** * @return TRUE if the service pointer is null */ bool isEmpty() const; /** * @return name of the associated service */ QString name() const; /** * Mimetypes (and other service types) which this document can handle. */ QStringList mimeTypes() const; /** * @return TRUE if the document can handle the requested mimetype. */ bool supportsMimeType(const QString & _mimetype) const; /** * This function will query ksycoca to find all available components. * The result will only contain parts, which are embeddable into a document * * @param _constr is a constraint expression as used by KTrader. * You can use it to set additional restrictions on the available * components. */ static QList query(const QString & mimetype = QString()); /** * This is a convenience function. * * @return a document entry for the Calligra component that supports * the requested mimetype and fits the user best. */ static KisDocumentEntry queryByMimeType(const QString & mimetype); private: KService::Ptr m_service; }; #endif diff --git a/krita/ui/KisDocumentSectionView.h b/krita/ui/KisDocumentSectionView.h index 440f546326d..af93eb8d7a7 100644 --- a/krita/ui/KisDocumentSectionView.h +++ b/krita/ui/KisDocumentSectionView.h @@ -1,172 +1,172 @@ /* Copyright (c) 2006 Gábor Lehel 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_DOCUMENT_SECTION_VIEW_H #define KIS_DOCUMENT_SECTION_VIEW_H #include -#include "krita_export.h" +#include "kritaui_export.h" class QStyleOptionViewItem; class KisDocumentSectionModel; /** * A View widget on document sections (for example, layers, pages, * sheets...). The widget can show the document sections as big * thumbnails, in a listview with two rows of informative text and * icons per document section or as single rows of text and property * icons. * * The KisDocumentSectionView is designed as a Qt4 model-view widget. * See the relevant (extensive) Qt documentation about the design * basis for this widget. * * Usage: simply use this widget in your designer .ui file. Krita's * and karbon's layerboxes are KisDocumentSectionView based. */ class KRITAUI_EXPORT KisDocumentSectionView: public QTreeView { Q_OBJECT Q_SIGNALS: /** * Emitted whenever the user clicks with the secondary mouse * button on an item. It is up to the application to design the * contents of the context menu and show it. */ void contextMenuRequested(const QPoint &globalPos, const QModelIndex &index); void selectionChanged(const QModelIndexList &); public: /** * Create a new KisDocumentSectionView. */ explicit KisDocumentSectionView(QWidget *parent = 0); virtual ~KisDocumentSectionView(); /// how items should be displayed enum DisplayMode { /// large fit-to-width thumbnails, with only titles or page numbers ThumbnailMode, /// smaller thumbnails, with titles and property icons in two rows DetailedMode, /// no thumbnails, with titles and property icons in a single row MinimalMode }; virtual void paintEvent (QPaintEvent *event); virtual void dropEvent(QDropEvent *ev); virtual void dragEnterEvent(QDragEnterEvent *e); virtual void dragMoveEvent(QDragMoveEvent *ev); virtual void dragLeaveEvent(QDragLeaveEvent *e); /** * Set the display mode of the view to one of the options. * * @param mode The KisDocumentSectionView::DisplayMode mode */ void setDisplayMode(DisplayMode mode); /** * @return the currently active display mode */ DisplayMode displayMode() const; /** * Add toggle actions for all the properties associated with the * current document section associated with the model index to the * specified menu. * * For instance, if a document section can be locked and visible, * the menu will be expanded with locked and visilbe toggle * actions. * * For instance @code KisDocumentSectionView * sectionView; QModelIndex index = getCurrentDocumentSection(); QMenu menu; if (index.isValid()) { sectionView->addPropertyActions(&menu, index); } else { menu.addAction(...); // Something to create a new document section, for example. } @endcode * * @param menu A pointer to the menu that will be expanded with * the toglge actions * @param index The model index associated with the document * section that may or may not provide a number of toggle actions. */ void addPropertyActions(QMenu *menu, const QModelIndex &index); void updateNode(const QModelIndex &index); protected: virtual bool viewportEvent(QEvent *event); virtual void contextMenuEvent(QContextMenuEvent *event); virtual void showContextMenu(const QPoint &globalPos, const QModelIndex &index); virtual void startDrag (Qt::DropActions supportedActions); QPixmap createDragPixmap() const; /** * Calculates the index of the nearest item to the cursor position */ int cursorPageIndex() const; protected Q_SLOTS: virtual void currentChanged(const QModelIndex ¤t, const QModelIndex &previous); virtual void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight); virtual void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); private Q_SLOTS: void slotActionToggled(bool on, const QPersistentModelIndex &index, int property); private: /** * Permit to know if a slide is dragging * * @return boolean */ bool isDragging() const; /** * Setter for the dragging flag * * @param flag boolean */ void setDraggingFlag(bool flag = true); bool m_draggingFlag; QStyleOptionViewItem optionForIndex(const QModelIndex &index) const; typedef KisDocumentSectionModel Model; class PropertyAction; class Private; Private* const d; }; #endif diff --git a/krita/ui/KisFilterChain.h b/krita/ui/KisFilterChain.h index ea948639125..f5ec9504f10 100644 --- a/krita/ui/KisFilterChain.h +++ b/krita/ui/KisFilterChain.h @@ -1,213 +1,213 @@ /* This file is part of the Calligra libraries Copyright (C) 2001 Werner Trobin 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_FILTER_CHAIN_H #define KIS_FILTER_CHAIN_H #include #include #include #include "KisImportExportFilter.h" #include "KisFilterEntry.h" #include -#include "krita_export.h" +#include "kritaui_export.h" #include "KisFilterChainLinkList.h" class KTemporaryFile; class KisImportExportManager; class KisDocument; namespace CalligraFilter { class Graph; class ChainLink; class Vertex; class Edge; } /** * @brief This class represents a chain of plain @ref KisImportExportFilter instances. * * Instances of this class are shared, so please just hold * KisFilterChain::Ptr pointers to it. * * @author Werner Trobin * @todo the class has no constructor and therefore cannot initialize its private class */ class KRITAUI_EXPORT KisFilterChain : public KShared { // Only Calligra::Graph is allowed to construct instances and // add chain links. friend class Graph; friend class KisImportExportManager; public: typedef KSharedPtr Ptr; virtual ~KisFilterChain(); /** * The filter manager returned may be 0! */ const KisImportExportManager* manager() const { return m_manager; } /** * Starts the filtering process. * @return The return status of the conversion. KisImportExportFilter::OK * if everything is alright. */ KisImportExportFilter::ConversionStatus invokeChain(); /** * Tells the @ref KisFilterManager the output file of the * filter chain in case of an import operation. If it's * an empty QString we directly manipulated the document. */ QString chainOutput() const; /** * Get the current file to read from. This part of the API * is for the filters in our chain. */ QString inputFile(); /** * Get the current file to write to. This part of the API * is for the filters in our chain. */ QString outputFile(); /** * Get a file from a storage. May return 0! * This part of the API is for the filters in our chain. * If you call it multiple times with the same stream name * the stream will be closed and re-opened. * Note: @em Don't delete that @ref KoStoreDevice we return. * @param name The name of the stream inside the storage * @param mode Whether we want to read or write from/to the stream * @return The storage device to access the stream. May be 0! */ KoStoreDevice* storageFile(const QString& name = "root", KoStore::Mode mode = KoStore::Read); /** * This method allows your filter to work directly on the * @ref KisDocument of the application. * This part of the API is for the filters in our chain. * @return The document containing the data. May return 0 on error. */ KisDocument* inputDocument(); /** * This method allows your filter to work directly on the * @ref KisDocument of the application. * This part of the API is for the filters in our chain. * @return The document you have to write to. May return 0 on error. */ KisDocument* outputDocument(); /// returns the amount of filters this chain contains representing the weight int weight() const; // debugging void dump(); private: // ### API for Calligra::Graph: // Construct a filter chain belonging to some KisFilterManager. // The parent filter manager may be 0. friend class CalligraFilter::Graph; explicit KisFilterChain(const KisImportExportManager* manager); void appendChainLink(KisFilterEntry::Ptr filterEntry, const QByteArray& from, const QByteArray& to); void prependChainLink(KisFilterEntry::Ptr filterEntry, const QByteArray& from, const QByteArray& to); // These methods are friends of KisFilterManager and provide access // to a private part of its API. As I don't want to include // koFilterManager.h in this header the direction is "int" here. QString filterManagerImportFile() const; QString filterManagerExportFile() const; KisDocument* filterManagerKisDocument() const; int filterManagerDirection() const; KisFilterChain* filterManagerParentChain() const; // Helper methods which keep track of all the temp files, documents, // storages,... and properly delete them as soon as they are not // needed anymore. void manageIO(); void finalizeIO(); bool createTempFile(KTemporaryFile** tempFile, bool autoDelete = true); void inputFileHelper(KisDocument* document, const QString& alternativeFile); void outputFileHelper(bool autoDelete); KoStoreDevice* storageNewStreamHelper(KoStore** storage, KoStoreDevice** device, const QString& name); KoStoreDevice* storageHelper(const QString& file, const QString& streamName, KoStore::Mode mode, KoStore** storage, KoStoreDevice** device); void storageInit(const QString& file, KoStore::Mode mode, KoStore** storage); KoStoreDevice* storageCreateFirstStream(const QString& streamName, KoStore** storage, KoStoreDevice** device); KoStoreDevice* storageCleanupHelper(KoStore** storage); KisDocument* createDocument(const QString& file); KisDocument* createDocument(const QByteArray& mimeType); // "A whole is that which has beginning, middle, and end" - Aristotle // ...but we also need to signal "Done" state, Mr. Aristotle enum Whole { Beginning = 1, Middle = 2, End = 4, Done = 8 }; // Don't copy or assign filter chains KisFilterChain(const KisFilterChain& rhs); KisFilterChain& operator=(const KisFilterChain& rhs); const KisImportExportManager* const m_manager; CalligraFilter::ChainLinkList m_chainLinks; // stuff needed for bookkeeping int m_state; QString m_inputFile; // Did we pass around plain files? QString m_outputFile; KoStore* m_inputStorage; // ...or was it a storage+device? KoStoreDevice* m_inputStorageDevice; KoStore* m_outputStorage; KoStoreDevice* m_outputStorageDevice; KisDocument* m_inputDocument; // ...or even documents? KisDocument* m_outputDocument; KTemporaryFile* m_inputTempFile; KTemporaryFile* m_outputTempFile; // These two flags keep track of the input/output the // filter (=user) asked for enum IOState { Nil, File, Storage, Document }; IOState m_inputQueried, m_outputQueried; class Private; Private * const d; }; #endif // __KO_FILTER_CHAIN_H__ diff --git a/krita/ui/KisFilterEntry.h b/krita/ui/KisFilterEntry.h index 79a30a94fc6..acbcef8a0e2 100644 --- a/krita/ui/KisFilterEntry.h +++ b/krita/ui/KisFilterEntry.h @@ -1,95 +1,95 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright 2007 David Faure 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_FILTER_ENTRY_H #define KIS_FILTER_ENTRY_H #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" class QObject; class QStringList; class KisImportExportFilter; class KisFilterChain; /** * Represents an available filter. */ class KRITAUI_EXPORT KisFilterEntry : public KShared { public: typedef KSharedPtr Ptr; //KisFilterEntry() : weight( 0 ) { m_service = 0; } // for QList explicit KisFilterEntry(const KService::Ptr& service); ~KisFilterEntry() { } KisImportExportFilter* createFilter(KisFilterChain* chain, QObject* parent = 0); /** * The imported mimetype(s). */ QStringList import; /** * The exported mimetype(s). */ QStringList export_; /** * The "weight" of this filter path. Has to be > 0 to be valid. */ unsigned int weight; /** * Do we have to check during runtime? */ QString available; /** * @return TRUE if the filter can import the requested mimetype. */ bool imports(const QString& _mimetype) const { return (import.contains(_mimetype)); } /** * @return TRUE if the filter can export the requested mimetype. */ bool exports(const QString& _m) const { return (export_.contains(_m)); } /** * This function will query KDED to find all available filters. */ static QList query(); KService::Ptr service() const { return m_service; } private: KService::Ptr m_service; }; #endif diff --git a/krita/ui/KisFilterGraph.h b/krita/ui/KisFilterGraph.h index 67ad474976f..3ad922a8033 100644 --- a/krita/ui/KisFilterGraph.h +++ b/krita/ui/KisFilterGraph.h @@ -1,79 +1,79 @@ /* This file is part of the Calligra libraries Copyright (C) 2001 Werner Trobin 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_FILTERGRAPH_H #define KIS_FILTERGRAPH_H -#include "krita_export.h" +#include "kritaui_export.h" #include "KisFilterChain.h" #include "KisFilterVertex.h" #include #include namespace CalligraFilter { /** * The main worker behind the scenes. Manages the creation of the graph, * processing the information in it, and creating the filter chains. * @internal * Only exported for unit tests. */ class KRITAUI_EXPORT Graph { public: explicit Graph(const QByteArray& from); ~Graph(); bool isValid() const { return m_graphValid; } QByteArray sourceMimeType() const { return m_from; } void setSourceMimeType(const QByteArray& from); // Creates a chain from "from" to the "to" mimetype // If the "to" mimetype isEmpty() then we try to find the // closest Calligra mimetype and use that as destination. // After such a search "to" will contain the dest. mimetype (return value) // if the search was successful. Might return 0! KisFilterChain::Ptr chain(const KisImportExportManager* manager, QByteArray& to) const; // debugging void dump() const; private: Graph(const Graph& rhs); Graph& operator=(const Graph& rhs); void buildGraph(); void shortestPaths(); QByteArray findCalligraPart() const; QHash m_vertices; QByteArray m_from; bool m_graphValid; class Private; Private * const d; }; } #endif // KOFILTERGRAPH_H diff --git a/krita/ui/KisImportExportFilter.h b/krita/ui/KisImportExportFilter.h index 341a8d37684..e364a36cafe 100644 --- a/krita/ui/KisImportExportFilter.h +++ b/krita/ui/KisImportExportFilter.h @@ -1,133 +1,133 @@ /* This file is part of the Calligra libraries Copyright (C) 2001 Werner Trobin 2002 Werner Trobin 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_IMPORT_EXPORT_FILTER_H #define KIS_IMPORT_EXPORT_FILTER_H #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KisFilterChain; class KoUpdater; /** * @brief The base class for import and export filters. * * Derive your filter class from this base class and implement * the @ref convert() method. Don't forget to specify the Q_OBJECT * macro in your class even if you don't use signals or slots. * This is needed as filters are created on the fly. * The m_chain member allows access to the @ref KisFilterChain * which invokes the filter to query for input/output. * * @note Take care: The m_chain pointer is invalid while the constructor * runs due to the implementation -- @em don't use it in the constructor. * After the constructor, when running the @ref convert() method it's * guaranteed to be valid, so no need to check against 0. * * @note If the code is compiled in debug mode, setting CALLIGRA_DEBUG_FILTERS * environment variable to any value disables deletion of temporary files while * importing/exporting. This is useful for testing purposes. * * @author Werner Trobin * @todo the class has no constructor and therefore cannot initialize its private class */ class KRITAUI_EXPORT KisImportExportFilter : public QObject { Q_OBJECT friend class KisFilterEntry; // needed for the filter chain pointer :( friend class KisFilterChain; public: /** * This enum is used to signal the return state of your filter. * Return OK in @ref convert() in case everything worked as expected. * Feel free to add some more error conditions @em before the last item * if it's needed. */ enum ConversionStatus { OK, StupidError, UsageError, CreationError, FileNotFound, StorageCreationError, BadMimeType, BadConversionGraph, EmbeddedDocError, WrongFormat, NotImplemented, ParsingError, InternalError, UnexpectedEOF, UnexpectedOpcode, UserCancelled, OutOfMemory, PasswordProtected, InvalidFormat, FilterEntryNull, NoDocumentCreated, DownloadFailed, FilterCreationError, JustInCaseSomeBrokenCompilerUsesLessThanAByte = 255 }; virtual ~KisImportExportFilter(); /** * The filter chain calls this method to perform the actual conversion. * The passed mimetypes should be a pair of those you specified in your * .desktop file. * You @em have to implement this method to make the filter work. * * @param from The mimetype of the source file/document * @param to The mimetype of the destination file/document * @return The error status, see the @ref #ConversionStatus enum. * KisImportExportFilter::OK means that everything is alright. */ virtual ConversionStatus convert(const QByteArray& from, const QByteArray& to) = 0; /** * Set the updater to which the filter will report progress. * Every emit of the sigProgress signal is reported to the updater. */ void setUpdater(const QPointer& updater); Q_SIGNALS: /** * Emit this signal with a value in the range of 1...100 to have some * progress feedback for the user in the statusbar of the application. * * @param value The actual progress state. Should always remain in * the range 1..100. */ void sigProgress(int value); protected: /** * This is the constructor your filter has to call, obviously. */ KisImportExportFilter(QObject *parent = 0); /** * Use this pointer to access all information about input/output * during the conversion. @em Don't use it in the constructor - * it's invalid while constructing the object! */ KisFilterChain *m_chain; private: KisImportExportFilter(const KisImportExportFilter& rhs); KisImportExportFilter& operator=(const KisImportExportFilter& rhs); class Private; Private *const d; private Q_SLOTS: void slotProgress(int value); }; #endif diff --git a/krita/ui/KisImportExportManager.h b/krita/ui/KisImportExportManager.h index 0179525ce55..27745923215 100644 --- a/krita/ui/KisImportExportManager.h +++ b/krita/ui/KisImportExportManager.h @@ -1,202 +1,202 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis 2000, 2001 Werner Trobin Copyright (C) 2004 Nicolas Goutte 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_IMPORT_EXPORT_MANAGER_H #define KIS_IMPORT_EXPORT_MANAGER_H #include #include #include #include "KisFilterChain.h" #include "KisFilterGraph.h" -#include "krita_export.h" +#include "kritaui_export.h" class KisDocument; class KoProgressUpdater; /** * @brief The class managing all the filters. * * This class manages all filters for a %Calligra application. Normally * you will not have to use it, since KisMainWindow takes care of loading * and saving documents. * * @ref KisFilter * * @author Kalle Dalheimer * @author Torben Weis * @author Werner Trobin */ class KRITAUI_EXPORT KisImportExportManager : public QObject { Q_OBJECT public: /** * This enum is used to distinguish the import/export cases */ enum Direction { Import = 1, Export = 2 }; /** * Create a filter manager for a document */ explicit KisImportExportManager(KisDocument *document, KoProgressUpdater *progressUpdater = 0); /** * Create a filter manager for the Shape Collection docker. * @param mimeType the mimetype to import to. */ explicit KisImportExportManager(const QByteArray& mimeType); /** * Create a filter manager for a filter which wants to embed something. * The url it passes is the file to convert, obviously. You cannot use * the @ref importDocument() method -- use @ref exportDocument() to convert * the file to the destination mimetype you prefer. * * @param url The file you want to export * @param mimetypeHint The mimetype of the file you want to export. You have * to specify this information only if the automatic detection will * fail because e.g. you saved an embedded stream to a *.tmp file. * Most likely you do not have to care about that. * @param parentChain The parent filter chain of this filter manager. Used * to allow embedding for filters. Most likely you do not have to care. */ explicit KisImportExportManager(const QString& url, const QByteArray& mimetypeHint = QByteArray(), KisFilterChain * const parentChain = 0); virtual ~KisImportExportManager(); /** * Imports the passed URL and returns the resultant filename * (most likely some file in /tmp). * @p documentMimeType gives importDocument a hint about what type * the document may be. It can be left empty. * The @p status variable signals the success/error of the conversion * If the QString which is returned isEmpty() and the status is OK, * then we imported the file directly into the document. */ QString importDocument(const QString& url, const QString& documentMimeType, KisImportExportFilter::ConversionStatus& status); /** * @brief Exports the given file/document to the specified URL/mimetype. * * If @p mimeType is empty, then the closest matching Calligra part is searched * and when the method returns @p mimeType contains this mimetype. * Oh, well, export is a C++ keyword ;) */ KisImportExportFilter::ConversionStatus exportDocument(const QString& url, QByteArray& mimeType); ///@name Static API //@{ /** * Suitable for passing to KoFileDialog::setMimeTypeFilters. The default mime * gets set by the "users" of this method, as we do not have enough * information here. * Optionally, @p extraNativeMimeTypes are added after the native mimetype. */ static QStringList mimeFilter(const QByteArray& mimetype, Direction direction, const QStringList& extraNativeMimeTypes = QStringList()); /** * The same method as KisFilterManager::mimeFilter but suited for KoShell. * We do not need the mimetype, as we will simply use all available * %Calligra mimetypes. The Direction enum is omitted, as we only * call this for importing. When saving from KoShell we already * know the Calligra part we are using. */ static QStringList mimeFilter(); /** * Method used to check if that filter is available at all. * @note Slow, but cached */ static bool filterAvailable(KisFilterEntry::Ptr entry); //@} /** * Set the filter manager is batch mode (no dialog shown) * instead of the interactive mode (dialog shown) */ void setBatchMode(const bool batch); /** * Get if the filter manager is batch mode (true) * or in interactive mode (true) */ bool getBatchMode(void) const; /** * Return the KoProgressUpdater or NULL if there is none. **/ KoProgressUpdater *progressUpdater() const; private: // === API for KisFilterChains === (internal) // The friend methods are private in KisFilterChain and // just forward calls to the methods here. Should be // pretty safe. friend QString KisFilterChain::filterManagerImportFile() const; QString importFile() const { return m_importUrl; } friend QString KisFilterChain::filterManagerExportFile() const; QString exportFile() const { return m_exportUrl; } friend KisDocument *KisFilterChain::filterManagerKisDocument() const; KisDocument *document() const { return m_document; } friend int KisFilterChain::filterManagerDirection() const; int direction() const { return static_cast(m_direction); } friend KisFilterChain *KisFilterChain::filterManagerParentChain() const; KisFilterChain *parentChain() const { return m_parentChain; } // Private API KisImportExportManager(const KisImportExportManager& rhs); KisImportExportManager &operator=(const KisImportExportManager& rhs); void importErrorHelper(const QString& mimeType, const bool suppressDialog = false); KisDocument *m_document; KisFilterChain *const m_parentChain; QString m_importUrl, m_exportUrl; QByteArray m_importUrlMimetypeHint; ///< suggested mimetype CalligraFilter::Graph m_graph; Direction m_direction; /// A static cache for the availability checks of filters static QMap m_filterAvailable; class Private; Private * const d; }; #endif // __KO_FILTER_MANAGER_H__ diff --git a/krita/ui/KisMainWindow.cpp b/krita/ui/KisMainWindow.cpp index 6a64ae78aef..4304fd1683c 100644 --- a/krita/ui/KisMainWindow.cpp +++ b/krita/ui/KisMainWindow.cpp @@ -1,2285 +1,2273 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2006 David Faure Copyright (C) 2007, 2009 Thomas zander Copyright (C) 2010 Benjamin Port 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 "KisMainWindow.h" #if defined (Q_OS_MAC) && QT_VERSION < 0x050000 #include "MacSupport.h" #endif // qt includes #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #if KDE_IS_VERSION(4,6,0) #include #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KoDockFactoryBase.h" #include "KoDockWidgetTitleBar.h" #include "KoDocumentInfoDlg.h" #include "KoDocumentInfo.h" #include "KoFileDialog.h" #include #include #include #include #include #include "KoToolDocker.h" #include #include #include #include #include "KisView.h" #include "KisDocument.h" #include "KisImportExportManager.h" #include "KisPrintJob.h" #include "KisPart.h" #include "KisApplication.h" #include "kis_factory2.h" #include "kis_action.h" #include "kis_canvas_controller.h" #include "kis_canvas2.h" #include "KisViewManager.h" #include "KisDocument.h" #include "KisView.h" #include "dialogs/kis_dlg_preferences.h" #include "kis_config_notifier.h" #include "kis_canvas_resource_provider.h" #include "kis_node.h" #include "kis_image.h" #include "kis_group_layer.h" #include "kis_paintop_settings.h" #include "kis_paintop_box.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "dialogs/kis_about_application.h" #include "kis_mainwindow_observer.h" #include "kis_action_manager.h" #include "thememanager.h" #include "kis_resource_server_provider.h" +#include "kis_icon_utils.h" + #include "calligraversion.h" class ToolDockerFactory : public KoDockFactoryBase { public: ToolDockerFactory() : KoDockFactoryBase() { } QString id() const { return "sharedtooldocker"; } QDockWidget* createDockWidget() { KoToolDocker* dockWidget = new KoToolDocker(); dockWidget->setTabEnabled(false); return dockWidget; } DockPosition defaultDockPosition() const { return DockRight; } }; class KisMainWindow::Private { public: Private(KisMainWindow *parent) : viewManager(0) , firstTime(true) , windowSizeDirty(false) , readOnly(false) , isImporting(false) , isExporting(false) , noCleanup(false) , showDocumentInfo(0) , saveAction(0) , saveActionAs(0) , printAction(0) , printActionPreview(0) , exportPdf(0) , closeAll(0) // , reloadFile(0) , importFile(0) , exportFile(0) , undo(0) , redo(0) , newWindow(0) , close(0) , mdiCascade(0) , mdiTile(0) , mdiNextWindow(0) , mdiPreviousWindow(0) , toggleDockers(0) , toggleDockerTitleBars(0) , dockWidgetMenu(new KActionMenu(i18nc("@action:inmenu", "&Dockers"), parent)) , windowMenu(new KActionMenu(i18nc("@action:inmenu", "&Window"), parent)) , documentMenu(new KActionMenu(i18nc("@action:inmenu", "New &View"), parent)) , helpMenu(0) , brushesAndStuff(0) , recentFiles(0) , toolOptionsDocker(0) , deferredClosingEvent(0) , themeManager(0) , mdiArea(new QMdiArea(parent)) , activeSubWindow(0) , windowMapper(new QSignalMapper(parent)) , documentMapper(new QSignalMapper(parent)) , lastExportSpecialOutputFlag(0) { } ~Private() { qDeleteAll(toolbarList); } KisViewManager *viewManager; QPointer activeView; QPointer progress; QMutex progressMutex; QList toolbarList; bool firstTime; bool windowSizeDirty; bool readOnly; bool isImporting; bool isExporting; bool noCleanup; KisAction *showDocumentInfo; KisAction *saveAction; KisAction *saveActionAs; KisAction *printAction; KisAction *printActionPreview; KisAction *exportPdf; KisAction *closeAll; // KisAction *reloadFile; KisAction *importFile; KisAction *exportFile; KisAction *undo; KisAction *redo; KisAction *newWindow; KisAction *close; KisAction *mdiCascade; KisAction *mdiTile; KisAction *mdiNextWindow; KisAction *mdiPreviousWindow; KisAction *toggleDockers; KisAction *toggleDockerTitleBars; KisAction *expandingSpacers[2]; KActionMenu *dockWidgetMenu; KActionMenu *windowMenu; KActionMenu *documentMenu; KHelpMenu *helpMenu; KToolBar *brushesAndStuff; KRecentFilesAction *recentFiles; KUrl lastExportUrl; QMap dockWidgetsMap; QMap dockWidgetVisibilityMap; QByteArray dockerStateBeforeHiding; KoToolDocker *toolOptionsDocker; QCloseEvent *deferredClosingEvent; Digikam::ThemeManager *themeManager; QMdiArea *mdiArea; QMdiSubWindow *activeSubWindow; QSignalMapper *windowMapper; QSignalMapper *documentMapper; QByteArray lastExportedFormat; int lastExportSpecialOutputFlag; }; KisMainWindow::KisMainWindow() : KXmlGuiWindow() , d(new Private(this)) { setComponentData(KisFactory::componentData()); KGlobal::setActiveComponent(KisFactory::componentData()); KisConfig cfg; d->viewManager = new KisViewManager(this, actionCollection()); d->themeManager = new Digikam::ThemeManager(this); setAcceptDrops(true); setStandardToolBarMenuEnabled(true); setTabPosition(Qt::AllDockWidgetAreas, QTabWidget::North); setDockNestingEnabled(true); qApp->setStartDragDistance(25); // 25 px is a distance that works well for Tablet and Mouse events #ifdef Q_OS_MAC #if QT_VERSION < 0x050000 MacSupport::addFullscreen(this); #endif #if QT_VERSION >= 0x050201 setUnifiedTitleAndToolBarOnMac(true); #endif #endif connect(this, SIGNAL(restoringDone()), this, SLOT(forceDockTabFonts())); connect(this, SIGNAL(documentSaved()), d->viewManager, SLOT(slotDocumentSaved())); connect(this, SIGNAL(themeChanged()), d->viewManager, SLOT(updateIcons())); connect(KisPart::instance(), SIGNAL(documentClosed(QString)), SLOT(updateWindowMenu())); connect(KisPart::instance(), SIGNAL(documentOpened(QString)), SLOT(updateWindowMenu())); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), this, SLOT(configChanged())); actionCollection()->addAssociatedWidget(this); QMetaObject::invokeMethod(this, "initializeGeometry", Qt::QueuedConnection); KoToolBoxFactory toolBoxFactory; - createDockWidget(&toolBoxFactory); + QDockWidget *toolbox = createDockWidget(&toolBoxFactory); + toolbox->setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable | QDockWidget::DockWidgetClosable); + if (cfg.toolOptionsInDocker()) { ToolDockerFactory toolDockerFactory; d->toolOptionsDocker = qobject_cast(createDockWidget(&toolDockerFactory)); } + + QMap dockwidgetActions; foreach(const QString & docker, KoDockRegistry::instance()->keys()) { KoDockFactoryBase *factory = KoDockRegistry::instance()->value(docker); - createDockWidget(factory); + QDockWidget *dw = createDockWidget(factory); + dockwidgetActions[dw->toggleViewAction()->text()] = dw->toggleViewAction(); } + foreach(QString title, dockwidgetActions.keys()) { + d->dockWidgetMenu->addAction(dockwidgetActions[title]); + } + foreach (QDockWidget *wdg, dockWidgets()) { if ((wdg->features() & QDockWidget::DockWidgetClosable) == 0) { wdg->setVisible(true); } } foreach(KoCanvasObserverBase* observer, canvasObservers()) { observer->setObservedCanvas(0); KisMainwindowObserver* mainwindowObserver = dynamic_cast(observer); if (mainwindowObserver) { mainwindowObserver->setMainWindow(d->viewManager); } } d->mdiArea->setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); d->mdiArea->setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); d->mdiArea->setTabPosition(QTabWidget::North); #if QT_VERSION >= 0x040800 d->mdiArea->setTabsClosable(true); #endif /* QT_VERSION >= 0x040800 */ setCentralWidget(d->mdiArea); d->mdiArea->show(); connect(d->mdiArea, SIGNAL(subWindowActivated(QMdiSubWindow*)), this, SLOT(subWindowActivated())); connect(d->windowMapper, SIGNAL(mapped(QWidget*)), this, SLOT(setActiveSubWindow(QWidget*))); connect(d->documentMapper, SIGNAL(mapped(QObject*)), this, SLOT(newView(QObject*))); createActions(); setAutoSaveSettings(KisFactory::componentName(), false); KoPluginLoader::instance()->load("Krita/ViewPlugin", "Type == 'Service' and ([X-Krita-Version] == 28)", KoPluginLoader::PluginsConfig(), d->viewManager); subWindowActivated(); updateWindowMenu(); if (isHelpMenuEnabled() && !d->helpMenu) { d->helpMenu = new KHelpMenu( this, KisFactory::aboutData(), false, actionCollection() ); connect(d->helpMenu, SIGNAL(showAboutApplication()), SLOT(showAboutApplication())); } // KDE libss 4' help contents action is broken outside kde, for some reason... We can handle it just as easily ourselves QAction *helpAction = actionCollection()->action("help_contents"); helpAction->disconnect(); connect(helpAction, SIGNAL(triggered()), this, SLOT(showManual())); #if 0 //check for colliding shortcuts QSet existingShortcuts; foreach(QAction* action, actionCollection()->actions()) { if(action->shortcut() == QKeySequence(0)) { continue; } qDebug() << "shortcut " << action->text() << " " << action->shortcut(); Q_ASSERT(!existingShortcuts.contains(action->shortcut())); existingShortcuts.insert(action->shortcut()); } #endif configChanged(); QString doc; QStringList allFiles = KGlobal::dirs()->findAllResources("data", "krita/krita.rc"); KIS_ASSERT(allFiles.size() > 0); // We need at least one krita.rc file! setXMLFile(findMostRecentXMLFile(allFiles, doc)); setLocalXMLFile(KStandardDirs::locateLocal("data", "krita/krita.rc")); guiFactory()->addClient(this); // Create and plug toolbar list for Settings menu QList toolbarList; foreach(QWidget* it, guiFactory()->containers("ToolBar")) { KToolBar * toolBar = ::qobject_cast(it); if (toolBar) { if (toolBar->objectName() == "BrushesAndStuff") { toolBar->setEnabled(false); } KToggleAction* act = new KToggleAction(i18n("Show %1 Toolbar", toolBar->windowTitle()), this); actionCollection()->addAction(toolBar->objectName().toUtf8(), act); act->setCheckedState(KGuiItem(i18n("Hide %1 Toolbar", toolBar->windowTitle()))); connect(act, SIGNAL(toggled(bool)), this, SLOT(slotToolbarToggled(bool))); act->setChecked(!toolBar->isHidden()); toolbarList.append(act); } else kWarning(30003) << "Toolbar list contains a " << it->metaObject()->className() << " which is not a toolbar!"; } plugActionList("toolbarlist", toolbarList); setToolbarList(toolbarList); applyToolBarLayout(); d->viewManager->updateGUI(); d->viewManager->updateIcons(); QTimer::singleShot(1000, this, SLOT(checkSanity())); } void KisMainWindow::setNoCleanup(bool noCleanup) { d->noCleanup = noCleanup; } KisMainWindow::~KisMainWindow() { // foreach(QAction *ac, actionCollection()->actions()) { // KAction *action = qobject_cast(ac); // if (action) { // qDebug() << "", "").replace("", "") // << "iconText=" << action->iconText().replace("&", "&") // << "shortcut=" << action->shortcut(KAction::ActiveShortcut).toString() // << "defaultShortcut=" << action->shortcut(KAction::DefaultShortcut).toString() // << "isCheckable=" << QString((action->isChecked() ? "true" : "false")) // << "statusTip=" << action->statusTip() // << "/>" ; // } // else { // qDebug() << "Got a QAction:" << ac->objectName(); // } // } KConfigGroup cfg(KGlobal::config(), "MainWindow"); cfg.writeEntry("ko_geometry", saveGeometry().toBase64()); cfg.writeEntry("ko_windowstate", saveState().toBase64()); { KConfigGroup group(KGlobal::config(), "theme"); group.writeEntry("Theme", d->themeManager->currentThemeName()); } // The doc and view might still exist (this is the case when closing the window) KisPart::instance()->removeMainWindow(this); if (d->noCleanup) return; delete d->viewManager; delete d; } void KisMainWindow::addView(KisView *view) { //qDebug() << "KisMainWindow::addView" << view; if (d->activeView == view) return; if (d->activeView) { d->activeView->disconnect(this); } showView(view); updateCaption(); emit restoringDone(); if (d->activeView) { connect(d->activeView, SIGNAL(titleModified(QString,bool)), SLOT(slotDocumentTitleModified(QString,bool))); } } void KisMainWindow::showView(KisView *imageView) { if (imageView && activeView() != imageView) { // XXX: find a better way to initialize this! imageView->setViewManager(d->viewManager); imageView->canvasBase()->setFavoriteResourceManager(d->viewManager->paintOpBox()->favoriteResourcesManager()); imageView->slotLoadingFinished(); QMdiSubWindow *subwin = d->mdiArea->addSubWindow(imageView); subwin->setAttribute(Qt::WA_DeleteOnClose, true); connect(subwin, SIGNAL(destroyed()), SLOT(updateWindowMenu())); KisConfig cfg; subwin->setOption(QMdiSubWindow::RubberBandMove, cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); subwin->setOption(QMdiSubWindow::RubberBandResize, cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); subwin->setWindowIcon(qApp->windowIcon()); if (d->mdiArea->subWindowList().size() == 1) { imageView->showMaximized(); } else { imageView->show(); } setActiveView(imageView); updateWindowMenu(); updateCaption(); } } void KisMainWindow::slotPreferences() { if (KisDlgPreferences::editPreferences()) { KisConfigNotifier::instance()->notifyConfigChanged(); // XXX: should this be changed for the views in other windows as well? foreach(QPointer koview, KisPart::instance()->views()) { KisViewManager *view = qobject_cast(koview); if (view) { view->resourceProvider()->resetDisplayProfile(QApplication::desktop()->screenNumber(this)); // Update the settings for all nodes -- they don't query // KisConfig directly because they need the settings during // compositing, and they don't connect to the config notifier // because nodes are not QObjects (because only one base class // can be a QObject). KisNode* node = dynamic_cast(view->image()->rootLayer().data()); node->updateSettings(); } } d->viewManager->showHideScrollbars(); } } void KisMainWindow::slotThemeChanged() { // save theme changes instantly KConfigGroup group(KGlobal::config(), "theme"); group.writeEntry("Theme", d->themeManager->currentThemeName()); // reload action icons! foreach (QAction *action, actionCollection()->actions()) { - QIcon icon = action->icon(); - if (icon.isNull()) continue; - - QString iconName = icon.name(); - if (iconName.isNull()) continue; - - QString realIconName; - - if (iconName.startsWith("dark_")) { - realIconName = iconName.mid(5); - } - - if (iconName.startsWith("light_")) { - realIconName = iconName.mid(6); - } - - if (!realIconName.isNull()) { - QIcon newIcon = themedIcon(realIconName); - if (!newIcon.isNull()) { - action->setIcon(newIcon); - } else { - qWarning() << "WARNING: Couldn't load themed icon:" << realIconName; - } - } + KisIconUtils::updateIcon(action); } emit themeChanged(); } void KisMainWindow::updateReloadFileAction(KisDocument */*doc*/) { // d->reloadFile->setEnabled(doc && !doc->url().isEmpty()); } void KisMainWindow::setReadWrite(bool readwrite) { d->saveAction->setEnabled(readwrite); d->importFile->setEnabled(readwrite); d->readOnly = !readwrite; updateCaption(); } void KisMainWindow::addRecentURL(const KUrl& url) { kDebug(30003) << "KisMainWindow::addRecentURL url=" << url.prettyUrl(); // Add entry to recent documents list // (call coming from KisDocument because it must work with cmd line, template dlg, file/open, etc.) if (!url.isEmpty()) { bool ok = true; if (url.isLocalFile()) { QString path = url.toLocalFile(KUrl::RemoveTrailingSlash); const QStringList tmpDirs = KGlobal::dirs()->resourceDirs("tmp"); for (QStringList::ConstIterator it = tmpDirs.begin() ; ok && it != tmpDirs.end() ; ++it) if (path.contains(*it)) ok = false; // it's in the tmp resource if (ok) { KRecentDocument::add(path); #if KDE_IS_VERSION(4,6,0) KRecentDirs::add(":OpenDialog", QFileInfo(path).dir().canonicalPath()); #endif } } else { KRecentDocument::add(url.url(KUrl::RemoveTrailingSlash), true); } if (ok) { d->recentFiles->addUrl(url); } saveRecentFiles(); } } void KisMainWindow::saveRecentFiles() { // Save list of recent files KSharedConfigPtr config = KisFactory::componentData().config(); d->recentFiles->saveEntries(config->group("RecentFiles")); config->sync(); // Tell all windows to reload their list, after saving // Doesn't work multi-process, but it's a start foreach(KMainWindow* window, KMainWindow::memberList()) static_cast(window)->reloadRecentFileList(); } void KisMainWindow::reloadRecentFileList() { KSharedConfigPtr config = KisFactory::componentData().config(); d->recentFiles->loadEntries(config->group("RecentFiles")); } void KisMainWindow::updateCaption() { if (!d->mdiArea->activeSubWindow()) { updateCaption(QString(), false); } else { QString caption( d->activeView->document()->caption() ); if (d->readOnly) { caption += ' ' + i18n("(write protected)"); } d->activeView->setWindowTitle(caption); updateCaption(caption, d->activeView->document()->isModified()); if (!d->activeView->document()->url().fileName(KUrl::ObeyTrailingSlash).isEmpty()) d->saveAction->setToolTip(i18n("Save as %1", d->activeView->document()->url().fileName(KUrl::ObeyTrailingSlash))); else d->saveAction->setToolTip(i18n("Save")); } } void KisMainWindow::updateCaption(const QString & caption, bool mod) { kDebug(30003) << "KisMainWindow::updateCaption(" << caption << "," << mod << ")"; #ifdef CALLIGRA_ALPHA setCaption(QString("ALPHA %1: %2").arg(CALLIGRA_ALPHA).arg(caption), mod); return; #endif #ifdef CALLIGRA_BETA setCaption(QString("BETA %1: %2").arg(CALLIGRA_BETA).arg(caption), mod); return; #endif #ifdef CALLIGRA_RC setCaption(QString("RELEASE CANDIDATE %1: %2").arg(CALLIGRA_RC).arg(caption), mod); return; #endif setCaption(caption, mod); } KisView *KisMainWindow::activeView() const { if (d->activeView) { return d->activeView; } return 0; } bool KisMainWindow::openDocument(const KUrl & url) { if (!KIO::NetAccess::exists(url, KIO::NetAccess::SourceSide, 0)) { QMessageBox::critical(0, i18nc("@title:window", "Krita"), i18n("The file %1 does not exist.", url.url())); d->recentFiles->removeUrl(url); //remove the file from the recent-opened-file-list saveRecentFiles(); return false; } return openDocumentInternal(url); } bool KisMainWindow::openDocumentInternal(const KUrl & url, KisDocument *newdoc) { if (!newdoc) { newdoc = KisPart::instance()->createDocument(); } d->firstTime = true; connect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); connect(newdoc, SIGNAL(completed()), this, SLOT(slotLoadCompleted())); connect(newdoc, SIGNAL(canceled(const QString &)), this, SLOT(slotLoadCanceled(const QString &))); bool openRet = (!isImporting()) ? newdoc->openUrl(url) : newdoc->importDocument(url); if (!openRet) { delete newdoc; return false; } KisPart::instance()->addDocument(newdoc); updateReloadFileAction(newdoc); KFileItem file(url, newdoc->mimeType(), KFileItem::Unknown); if (!file.isWritable()) { setReadWrite(false); } return true; } // Separate from openDocument to handle async loading (remote URLs) void KisMainWindow::slotLoadCompleted() { KisDocument *newdoc = qobject_cast(sender()); KisView *view = KisPart::instance()->createView(newdoc, resourceManager(), actionCollection(), this); addView(view); disconnect(newdoc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); disconnect(newdoc, SIGNAL(completed()), this, SLOT(slotLoadCompleted())); disconnect(newdoc, SIGNAL(canceled(const QString &)), this, SLOT(slotLoadCanceled(const QString &))); emit loadCompleted(); } void KisMainWindow::slotLoadCanceled(const QString & errMsg) { kDebug(30003) << "KisMainWindow::slotLoadCanceled"; if (!errMsg.isEmpty()) // empty when canceled by user QMessageBox::critical(this, i18nc("@title:window", "Krita"), errMsg); // ... can't delete the document, it's the one who emitted the signal... KisDocument* doc = qobject_cast(sender()); Q_ASSERT(doc); disconnect(doc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); disconnect(doc, SIGNAL(completed()), this, SLOT(slotLoadCompleted())); disconnect(doc, SIGNAL(canceled(const QString &)), this, SLOT(slotLoadCanceled(const QString &))); } void KisMainWindow::slotSaveCanceled(const QString &errMsg) { kDebug(30003) << "KisMainWindow::slotSaveCanceled"; if (!errMsg.isEmpty()) // empty when canceled by user QMessageBox::critical(this, i18nc("@title:window", "Krita"), errMsg); slotSaveCompleted(); } void KisMainWindow::slotSaveCompleted() { kDebug(30003) << "KisMainWindow::slotSaveCompleted"; KisDocument* doc = qobject_cast(sender()); Q_ASSERT(doc); disconnect(doc, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); disconnect(doc, SIGNAL(completed()), this, SLOT(slotSaveCompleted())); disconnect(doc, SIGNAL(canceled(const QString &)), this, SLOT(slotSaveCanceled(const QString &))); if (d->deferredClosingEvent) { KXmlGuiWindow::closeEvent(d->deferredClosingEvent); } } bool KisMainWindow::saveDocument(KisDocument *document, bool saveas, bool silent, int specialOutputFlag) { if (!document) { return true; } bool reset_url; if (document->url().isEmpty()) { reset_url = true; saveas = true; } else { reset_url = false; } connect(document, SIGNAL(sigProgress(int)), this, SLOT(slotProgress(int))); connect(document, SIGNAL(completed()), this, SLOT(slotSaveCompleted())); connect(document, SIGNAL(canceled(const QString &)), this, SLOT(slotSaveCanceled(const QString &))); KUrl oldURL = document->url(); QString oldFile = document->localFilePath(); QByteArray _native_format = document->nativeFormatMimeType(); QByteArray oldOutputFormat = document->outputMimeType(); int oldSpecialOutputFlag = document->specialOutputFlag(); KUrl suggestedURL = document->url(); QStringList mimeFilter; KMimeType::Ptr mime = KMimeType::mimeType(_native_format); if (! mime) mime = KMimeType::defaultMimeTypePtr(); if (specialOutputFlag) mimeFilter = mime->patterns(); else mimeFilter = KisImportExportManager::mimeFilter(_native_format, KisImportExportManager::Export, document->extraNativeMimeTypes()); if (!mimeFilter.contains(oldOutputFormat) && !isExporting()) { kDebug(30003) << "KisMainWindow::saveDocument no export filter for" << oldOutputFormat; // --- don't setOutputMimeType in case the user cancels the Save As // dialog and then tries to just plain Save --- // suggest a different filename extension (yes, we fortunately don't all live in a world of magic :)) QString suggestedFilename = suggestedURL.fileName(); if (!suggestedFilename.isEmpty()) { // ".kra" looks strange for a name int c = suggestedFilename.lastIndexOf('.'); QString ext = mime->property("X-KDE-NativeExtension").toString(); if (!ext.isEmpty()) { if (c < 0) suggestedFilename += ext; else suggestedFilename = suggestedFilename.left(c) + ext; } else { // current filename extension wrong anyway if (c > 0) { // this assumes that a . signifies an extension, not just a . suggestedFilename = suggestedFilename.left(c); } } suggestedURL.setFileName(suggestedFilename); } // force the user to choose outputMimeType saveas = true; } bool ret = false; if (document->url().isEmpty() || saveas) { // if you're just File/Save As'ing to change filter options you // don't want to be reminded about overwriting files etc. bool justChangingFilterOptions = false; KoFileDialog dialog(this, KoFileDialog::SaveFile, "SaveDocument"); dialog.setCaption(i18n("untitled")); if (isExporting() && !d->lastExportUrl.isEmpty()) { dialog.setDefaultDir(d->lastExportUrl.toLocalFile(), true); } else { dialog.setDefaultDir(suggestedURL.toLocalFile(), true); } dialog.setMimeTypeFilters(mimeFilter, KIS_MIME_TYPE); KUrl newURL = dialog.url(); if (newURL.isLocalFile()) { QString fn = newURL.toLocalFile(); if (QFileInfo(fn).completeSuffix().isEmpty()) { KMimeType::Ptr mime = KMimeType::mimeType(_native_format); fn.append(mime->mainExtension()); newURL = KUrl::fromPath(fn); } } if (document->documentInfo()->aboutInfo("title") == i18n("Unnamed")) { QString fn = newURL.toLocalFile(); QFileInfo info(fn); document->documentInfo()->setAboutInfo("title", info.baseName()); } QByteArray outputFormat = _native_format; if (!specialOutputFlag) { KMimeType::Ptr mime = KMimeType::findByUrl(newURL); QString outputFormatString = mime->name(); outputFormat = outputFormatString.toLatin1(); } if (!isExporting()) justChangingFilterOptions = (newURL == document->url()) && (outputFormat == document->mimeType()) && (specialOutputFlag == oldSpecialOutputFlag); else justChangingFilterOptions = (newURL == d->lastExportUrl) && (outputFormat == d->lastExportedFormat) && (specialOutputFlag == d->lastExportSpecialOutputFlag); bool bOk = true; if (newURL.isEmpty()) { bOk = false; } // adjust URL before doing checks on whether the file exists. if (specialOutputFlag) { QString fileName = newURL.fileName(); if ( specialOutputFlag== KisDocument::SaveAsDirectoryStore) { //qDebug() << "save to directory: " << newURL.url(); } else if (specialOutputFlag == KisDocument::SaveEncrypted) { int dot = fileName.lastIndexOf('.'); qDebug() << dot; QString ext = mime->mainExtension(); if (!ext.isEmpty()) { if (dot < 0) fileName += ext; else fileName = fileName.left(dot) + ext; } else { // current filename extension wrong anyway if (dot > 0) fileName = fileName.left(dot); } newURL.setFileName(fileName); } } if (bOk) { bool wantToSave = true; // don't change this line unless you know what you're doing :) if (!justChangingFilterOptions || document->confirmNonNativeSave(isExporting())) { if (!document->isNativeFormat(outputFormat)) wantToSave = true; } if (wantToSave) { // // Note: // If the user is stupid enough to Export to the current URL, // we do _not_ change this operation into a Save As. Reasons // follow: // // 1. A check like "isExporting() && oldURL == newURL" // doesn't _always_ work on case-insensitive filesystems // and inconsistent behaviour is bad. // 2. It is probably not a good idea to change document->mimeType // and friends because the next time the user File/Save's, // (not Save As) they won't be expecting that they are // using their File/Export settings // // As a bad side-effect of this, the modified flag will not // be updated and it is possible that what is currently on // their screen is not what is stored on disk (through loss // of formatting). But if you are dumb enough to change // mimetype but not the filename, then arguably, _you_ are // the "bug" :) // // - Clarence // document->setOutputMimeType(outputFormat, specialOutputFlag); if (!isExporting()) { // Save As ret = document->saveAs(newURL); if (ret) { kDebug(30003) << "Successful Save As!"; addRecentURL(newURL); setReadWrite(true); } else { kDebug(30003) << "Failed Save As!"; document->setUrl(oldURL); document->setLocalFilePath(oldFile); document->setOutputMimeType(oldOutputFormat, oldSpecialOutputFlag); } } else { // Export ret = document->exportDocument(newURL); if (ret) { // a few file dialog convenience things d->lastExportUrl = newURL; d->lastExportedFormat = outputFormat; d->lastExportSpecialOutputFlag = specialOutputFlag; } // always restore output format document->setOutputMimeType(oldOutputFormat, oldSpecialOutputFlag); } if (silent) // don't let the document change the window caption document->setTitleModified(); } // if (wantToSave) { else ret = false; } // if (bOk) { else ret = false; } else { // saving bool needConfirm = document->confirmNonNativeSave(false) && !document->isNativeFormat(oldOutputFormat); if (!needConfirm || (needConfirm && exportConfirmation(oldOutputFormat /* not so old :) */)) ) { // be sure document has the correct outputMimeType! if (isExporting() || document->isModified()) { ret = document->save(); } if (!ret) { kDebug(30003) << "Failed Save!"; document->setUrl(oldURL); document->setLocalFilePath(oldFile); } } else ret = false; } if (!ret && reset_url) document->resetURL(); //clean the suggested filename as the save dialog was rejected updateReloadFileAction(document); updateCaption(); return ret; } bool KisMainWindow::exportConfirmation(const QByteArray &/*outputFormat*/) { return true; } void KisMainWindow::undo() { if (activeView()) { activeView()->undoAction()->trigger(); d->undo->setText(activeView()->undoAction()->text()); } } void KisMainWindow::redo() { if (activeView()) { activeView()->redoAction()->trigger(); d->redo->setText(activeView()->redoAction()->text()); } } void KisMainWindow::closeEvent(QCloseEvent *e) { d->mdiArea->closeAllSubWindows(); if(d->activeView && d->activeView->document() && d->activeView->document()->isLoading()) { e->setAccepted(false); return; } QList childrenList = d->mdiArea->subWindowList(); if (childrenList.isEmpty()) { d->deferredClosingEvent = e; if (!d->dockerStateBeforeHiding.isEmpty()) { restoreState(d->dockerStateBeforeHiding); } statusBar()->setVisible(true); menuBar()->setVisible(true); saveWindowSettings(); if (d->noCleanup) return; foreach(QMdiSubWindow *subwin, d->mdiArea->subWindowList()) { KisView *view = dynamic_cast(subwin); if (view) { KisPart::instance()->removeView(view); } } if (!d->dockWidgetVisibilityMap.isEmpty()) { // re-enable dockers for persistency foreach(QDockWidget* dockWidget, d->dockWidgetsMap) dockWidget->setVisible(d->dockWidgetVisibilityMap.value(dockWidget)); } } else { e->setAccepted(false); } } void KisMainWindow::saveWindowSettings() { KSharedConfigPtr config = KisFactory::componentData().config(); if (d->windowSizeDirty ) { // Save window size into the config file of our componentData kDebug(30003) << "KisMainWindow::saveWindowSettings"; saveWindowSize(config->group("MainWindow")); config->sync(); d->windowSizeDirty = false; } if (!d->activeView || d->activeView->document()) { // Save toolbar position into the config file of the app, under the doc's component name KConfigGroup group = KGlobal::config()->group(KisFactory::componentName()); saveMainWindowSettings(group); // Save collapsable state of dock widgets for (QMap::const_iterator i = d->dockWidgetsMap.constBegin(); i != d->dockWidgetsMap.constEnd(); ++i) { if (i.value()->widget()) { KConfigGroup dockGroup = group.group(QString("DockWidget ") + i.key()); dockGroup.writeEntry("Collapsed", i.value()->widget()->isHidden()); dockGroup.writeEntry("Locked", i.value()->property("Locked").toBool()); dockGroup.writeEntry("DockArea", (int) dockWidgetArea(i.value())); } } } KGlobal::config()->sync(); resetAutoSaveSettings(); // Don't let KMainWindow override the good stuff we wrote down } void KisMainWindow::resizeEvent(QResizeEvent * e) { d->windowSizeDirty = true; KXmlGuiWindow::resizeEvent(e); } void KisMainWindow::setActiveView(KisView* view) { d->activeView = view; updateCaption(); actionCollection()->action("edit_undo")->setText(activeView()->undoAction()->text()); actionCollection()->action("edit_redo")->setText(activeView()->redoAction()->text()); } void KisMainWindow::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasUrls()) { event->accept(); } } void KisMainWindow::dropEvent(QDropEvent *event) { if (event->mimeData()->hasUrls() && event->mimeData()->urls().size() > 0) { foreach(const QUrl &url, event->mimeData()->urls()) { openDocument(url); } } } void KisMainWindow::slotFileNew() { KisPart::instance()->showStartUpWidget(this, true /*Always show widget*/); } void KisMainWindow::slotFileOpen() { QStringList urls; KoFileDialog dialog(this, KoFileDialog::ImportFiles, "OpenDocument"); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setMimeTypeFilters(koApp->mimeFilter(KisImportExportManager::Import)); QStringList filters = dialog.nameFilters(); filters << i18n("All files (*.*)"); dialog.setNameFilters(filters); dialog.setHideNameFilterDetailsOption(); dialog.setCaption(isImporting() ? i18n("Import Images") : i18n("Open Images")); urls = dialog.urls(); if (urls.isEmpty()) return; foreach(const QString& url, urls) { if (!url.isEmpty()) { bool res = openDocument(KUrl::fromLocalFile(url)); if (!res) { qWarning() << "Loading" << url << "failed"; } } } } void KisMainWindow::slotFileOpenRecent(const KUrl & url) { // Create a copy, because the original KUrl in the map of recent files in // KRecentFilesAction may get deleted. (void) openDocument(KUrl(url)); } void KisMainWindow::slotFileSave() { if (saveDocument(d->activeView->document())) emit documentSaved(); } void KisMainWindow::slotFileSaveAs() { if (saveDocument(d->activeView->document(), true)) emit documentSaved(); } KoCanvasResourceManager *KisMainWindow::resourceManager() const { return d->viewManager->resourceProvider()->resourceManager(); } int KisMainWindow::viewCount() const { return d->mdiArea->subWindowList().size(); } bool KisMainWindow::restoreWorkspace(const QByteArray &state) { QByteArray oldState = saveState(); const bool showTitlebars = KisConfig().showDockerTitleBars(); // needed because otherwise the layout isn't correctly restored in some situations Q_FOREACH (QDockWidget *dock, dockWidgets()) { dock->hide(); dock->titleBarWidget()->setVisible(showTitlebars); } bool success = KXmlGuiWindow::restoreState(state); if (!success) { KXmlGuiWindow::restoreState(oldState); Q_FOREACH (QDockWidget *dock, dockWidgets()) { if (dock->titleBarWidget()) { dock->titleBarWidget()->setVisible(showTitlebars || dock->isFloating()); } } return false; } Q_FOREACH (QDockWidget *dock, dockWidgets()) { if (dock->titleBarWidget()) { const bool isCollapsed = (dock->widget() && dock->widget()->isHidden()) || !dock->widget(); dock->titleBarWidget()->setVisible(showTitlebars || (dock->isFloating() && isCollapsed)); } } return success; } KisViewManager *KisMainWindow::viewManager() const { return d->viewManager; } void KisMainWindow::slotDocumentInfo() { if (!d->activeView->document()) return; KoDocumentInfo *docInfo = d->activeView->document()->documentInfo(); if (!docInfo) return; KoDocumentInfoDlg *dlg = d->activeView->document()->createDocumentInfoDialog(this, docInfo); if (dlg->exec()) { if (dlg->isDocumentSaved()) { d->activeView->document()->setModified(false); } else { d->activeView->document()->setModified(true); } d->activeView->document()->setTitleModified(); } delete dlg; } bool KisMainWindow::slotFileCloseAll() { foreach(QMdiSubWindow *subwin, d->mdiArea->subWindowList()) { if (subwin) { if(!subwin->close()) return false; } } updateCaption(); return true; } void KisMainWindow::slotFileQuit() { if(!slotFileCloseAll()) return; close(); foreach(QPointer mainWin, KisPart::instance()->mainWindows()) { if (mainWin != this) { if(!mainWin->slotFileCloseAll()) return; mainWin->close(); } } } void KisMainWindow::slotFilePrint() { if (!activeView()) return; KisPrintJob *printJob = activeView()->createPrintJob(); if (printJob == 0) return; applyDefaultSettings(printJob->printer()); QPrintDialog *printDialog = activeView()->createPrintDialog( printJob, this ); if (printDialog && printDialog->exec() == QDialog::Accepted) { printJob->printer().setPageMargins(0.0, 0.0, 0.0, 0.0, QPrinter::Point); printJob->printer().setPaperSize(QSizeF(activeView()->image()->width() / (72.0 * activeView()->image()->xRes()), activeView()->image()->height()/ (72.0 * activeView()->image()->yRes())), QPrinter::Inch); printJob->startPrinting(KisPrintJob::DeleteWhenDone); } else { delete printJob; } delete printDialog; } void KisMainWindow::slotFilePrintPreview() { if (!activeView()) return; KisPrintJob *printJob = activeView()->createPrintJob(); if (printJob == 0) return; /* Sets the startPrinting() slot to be blocking. The Qt print-preview dialog requires the printing to be completely blocking and only return when the full document has been printed. By default the KisPrintingDialog is non-blocking and multithreading, setting blocking to true will allow it to be used in the preview dialog */ printJob->setProperty("blocking", true); QPrintPreviewDialog *preview = new QPrintPreviewDialog(&printJob->printer(), this); printJob->setParent(preview); // will take care of deleting the job connect(preview, SIGNAL(paintRequested(QPrinter*)), printJob, SLOT(startPrinting())); preview->exec(); delete preview; } KisPrintJob* KisMainWindow::exportToPdf(const QString &pdfFileName) { if (!activeView()) return 0; KoPageLayout pageLayout; pageLayout = activeView()->pageLayout(); return exportToPdf(pageLayout, pdfFileName); } KisPrintJob* KisMainWindow::exportToPdf(KoPageLayout pageLayout, QString pdfFileName) { if (!activeView()) return 0; if (!activeView()->document()) return 0; if (pdfFileName.isEmpty()) { KConfigGroup group = KGlobal::config()->group("File Dialogs"); QString defaultDir = group.readEntry("SavePdfDialog"); if (defaultDir.isEmpty()) defaultDir = QDesktopServices::storageLocation(QDesktopServices::DocumentsLocation); KUrl startUrl = KUrl(defaultDir); KisDocument* pDoc = d->activeView->document(); /** if document has a file name, take file name and replace extension with .pdf */ if (pDoc && pDoc->url().isValid()) { startUrl = pDoc->url(); QString fileName = startUrl.fileName(); fileName = fileName.replace( QRegExp( "\\.\\w{2,5}$", Qt::CaseInsensitive ), ".pdf" ); startUrl.setFileName( fileName ); } QPointer layoutDlg(new KoPageLayoutDialog(this, pageLayout)); layoutDlg->setWindowModality(Qt::WindowModal); if (layoutDlg->exec() != QDialog::Accepted || !layoutDlg) { delete layoutDlg; return 0; } pageLayout = layoutDlg->pageLayout(); delete layoutDlg; KoFileDialog dialog(this, KoFileDialog::SaveFile, "SaveDocument"); dialog.setCaption(i18n("Export as PDF")); dialog.setDefaultDir(startUrl.toLocalFile()); dialog.setMimeTypeFilters(QStringList() << "application/pdf"); KUrl url = dialog.url(); pdfFileName = url.toLocalFile(); if (pdfFileName.isEmpty()) return 0; } KisPrintJob *printJob = activeView()->createPrintJob(); if (printJob == 0) return 0; if (isHidden()) { printJob->setProperty("noprogressdialog", true); } applyDefaultSettings(printJob->printer()); // TODO for remote files we have to first save locally and then upload. printJob->printer().setOutputFileName(pdfFileName); printJob->printer().setDocName(pdfFileName); printJob->printer().setColorMode(QPrinter::Color); if (pageLayout.format == KoPageFormat::CustomSize) { printJob->printer().setPaperSize(QSizeF(pageLayout.width, pageLayout.height), QPrinter::Millimeter); } else { printJob->printer().setPaperSize(KoPageFormat::printerPageSize(pageLayout.format)); } printJob->printer().setPageMargins(pageLayout.leftMargin, pageLayout.topMargin, pageLayout.rightMargin, pageLayout.bottomMargin, QPrinter::Millimeter); switch (pageLayout.orientation) { case KoPageFormat::Portrait: printJob->printer().setOrientation(QPrinter::Portrait); break; case KoPageFormat::Landscape: printJob->printer().setOrientation(QPrinter::Landscape); break; } //before printing check if the printer can handle printing if (!printJob->canPrint()) { QMessageBox::critical(this, i18nc("@title:window", "Krita"), i18n("Cannot export to the specified file")); } printJob->startPrinting(KisPrintJob::DeleteWhenDone); return printJob; } void KisMainWindow::slotConfigureKeys() { KisPart::instance()->configureShortcuts(); emit keyBindingsChanged(); } void KisMainWindow::slotConfigureToolbars() { saveMainWindowSettings(KGlobal::config()->group(KisFactory::componentName())); KEditToolBar edit(factory(), this); connect(&edit, SIGNAL(newToolBarConfig()), this, SLOT(slotNewToolbarConfig())); (void) edit.exec(); applyToolBarLayout(); } void KisMainWindow::slotNewToolbarConfig() { applyMainWindowSettings(KGlobal::config()->group(KisFactory::componentName())); KXMLGUIFactory *factory = guiFactory(); Q_UNUSED(factory); // Check if there's an active view if (!d->activeView) return; plugActionList("toolbarlist", d->toolbarList); applyToolBarLayout(); } void KisMainWindow::slotToolbarToggled(bool toggle) { //kDebug(30003) <<"KisMainWindow::slotToolbarToggled" << sender()->name() <<" toggle=" << true; // The action (sender) and the toolbar have the same name KToolBar * bar = toolBar(sender()->objectName()); if (bar) { if (toggle) { bar->show(); } else { bar->hide(); } if (d->activeView && d->activeView->document()) { saveMainWindowSettings(KGlobal::config()->group(KisFactory::componentName())); } } else kWarning(30003) << "slotToolbarToggled : Toolbar " << sender()->objectName() << " not found!"; } void KisMainWindow::viewFullscreen(bool fullScreen) { + KisConfig cfg; + cfg.setFullscreenMode(fullScreen); + if (fullScreen) { setWindowState(windowState() | Qt::WindowFullScreen); // set } else { setWindowState(windowState() & ~Qt::WindowFullScreen); // reset } } void KisMainWindow::slotProgress(int value) { qApp->processEvents(); if (!d->progressMutex.tryLock()) return; kDebug(30003) << "KisMainWindow::slotProgress" << value; if (value <= -1 || value >= 100) { if (d->progress) { statusBar()->removeWidget(d->progress); delete d->progress; d->progress = 0; } d->firstTime = true; d->progressMutex.unlock(); return; } if (d->firstTime || !d->progress) { // The statusbar might not even be created yet. // So check for that first, and create it if necessary QStatusBar *bar = findChild(); if (!bar) { statusBar()->show(); QApplication::sendPostedEvents(this, QEvent::ChildAdded); } if (d->progress) { statusBar()->removeWidget(d->progress); delete d->progress; d->progress = 0; } d->progress = new QProgressBar(statusBar()); d->progress->setMaximumHeight(statusBar()->fontMetrics().height()); d->progress->setRange(0, 100); statusBar()->addPermanentWidget(d->progress); d->progress->show(); d->firstTime = false; } if (!d->progress.isNull()) { d->progress->setValue(value); } qApp->processEvents(); d->progressMutex.unlock(); } void KisMainWindow::setMaxRecentItems(uint _number) { d->recentFiles->setMaxItems(_number); } void KisMainWindow::slotEmailFile() { if (!d->activeView || !d->activeView->document()) return; // Subject = Document file name // Attachment = The current file // Message Body = The current document in HTML export? <-- This may be an option. QString theSubject; QStringList urls; QString fileURL; if (d->activeView->document()->url().isEmpty() || d->activeView->document()->isModified()) { //Save the file as a temporary file bool const tmp_modified = d->activeView->document()->isModified(); KUrl const tmp_url = d->activeView->document()->url(); QByteArray const tmp_mimetype = d->activeView->document()->outputMimeType(); // a little open, close, delete dance to make sure we have a nice filename // to use, but won't block windows from creating a new file with this name. KTemporaryFile *tmpfile = new KTemporaryFile(); tmpfile->open(); QString fileName = tmpfile->fileName(); tmpfile->close(); delete tmpfile; KUrl u; u.setPath(fileName); d->activeView->document()->setUrl(u); d->activeView->document()->setModified(true); d->activeView->document()->setOutputMimeType(d->activeView->document()->nativeFormatMimeType()); saveDocument(d->activeView->document(), false, true); fileURL = fileName; theSubject = i18n("Document"); urls.append(fileURL); d->activeView->document()->setUrl(tmp_url); d->activeView->document()->setModified(tmp_modified); d->activeView->document()->setOutputMimeType(tmp_mimetype); } else { fileURL = d->activeView->document()->url().url(); theSubject = i18n("Document - %1", d->activeView->document()->url().fileName(KUrl::ObeyTrailingSlash)); urls.append(fileURL); } kDebug(30003) << "(" << fileURL << ")"; if (!fileURL.isEmpty()) { KToolInvocation::invokeMailer(QString(), QString(), QString(), theSubject, QString(), //body QString(), urls); // attachments } } void KisMainWindow::slotReloadFile() { KisDocument* document = d->activeView->document(); if (!document || document->url().isEmpty()) return; if (document->isModified()) { bool ok = QMessageBox::question(this, i18nc("@title:window", "Krita"), i18n("You will lose all changes made since your last save\n" "Do you want to continue?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes) == QMessageBox::Yes; if (!ok) return; } KUrl url = document->url(); saveWindowSettings(); if (!document->reload()) { QMessageBox::critical(this, i18nc("@title:window", "Krita"), i18n("Error: Could not reload this document")); } return; } void KisMainWindow::slotImportFile() { kDebug(30003) << "slotImportFile()"; d->isImporting = true; slotFileOpen(); d->isImporting = false; } void KisMainWindow::slotExportFile() { kDebug(30003) << "slotExportFile()"; d->isExporting = true; slotFileSaveAs(); d->isExporting = false; } bool KisMainWindow::isImporting() const { return d->isImporting; } bool KisMainWindow::isExporting() const { return d->isExporting; } QDockWidget* KisMainWindow::createDockWidget(KoDockFactoryBase* factory) { QDockWidget* dockWidget = 0; if (!d->dockWidgetsMap.contains(factory->id())) { dockWidget = factory->createDockWidget(); // It is quite possible that a dock factory cannot create the dock; don't // do anything in that case. if (!dockWidget) { qWarning() << "Could not create docker for" << factory->id(); return 0; } KoDockWidgetTitleBar *titleBar = dynamic_cast(dockWidget->titleBarWidget()); // Check if the dock widget is supposed to be collapsable if (!dockWidget->titleBarWidget()) { titleBar = new KoDockWidgetTitleBar(dockWidget); dockWidget->setTitleBarWidget(titleBar); titleBar->setCollapsable(factory->isCollapsable()); } dockWidget->setObjectName(factory->id()); dockWidget->setParent(this); if (dockWidget->widget() && dockWidget->widget()->layout()) dockWidget->widget()->layout()->setContentsMargins(1, 1, 1, 1); Qt::DockWidgetArea side = Qt::RightDockWidgetArea; bool visible = true; switch (factory->defaultDockPosition()) { case KoDockFactoryBase::DockTornOff: dockWidget->setFloating(true); // position nicely? break; case KoDockFactoryBase::DockTop: side = Qt::TopDockWidgetArea; break; case KoDockFactoryBase::DockLeft: side = Qt::LeftDockWidgetArea; break; case KoDockFactoryBase::DockBottom: side = Qt::BottomDockWidgetArea; break; case KoDockFactoryBase::DockRight: side = Qt::RightDockWidgetArea; break; case KoDockFactoryBase::DockMinimized: default: side = Qt::RightDockWidgetArea; visible = false; } KConfigGroup group = KGlobal::config()->group(KisFactory::componentName()).group("DockWidget " + factory->id()); side = static_cast(group.readEntry("DockArea", static_cast(side))); if (side == Qt::NoDockWidgetArea) side = Qt::RightDockWidgetArea; addDockWidget(side, dockWidget); - if (dockWidget->features() & QDockWidget::DockWidgetClosable) { - d->dockWidgetMenu->addAction(dockWidget->toggleViewAction()); - if (!visible) - dockWidget->hide(); + if (!visible) { + dockWidget->hide(); } - bool collapsed = factory->defaultCollapsed(); bool locked = false; group = KGlobal::config()->group(KisFactory::componentName()).group("DockWidget " + factory->id()); collapsed = group.readEntry("Collapsed", collapsed); locked = group.readEntry("Locked", locked); //qDebug() << "docker" << factory->id() << dockWidget << "collapsed" << collapsed << "locked" << locked << "titlebar" << titleBar; if (titleBar && collapsed) titleBar->setCollapsed(true); if (titleBar && locked) titleBar->setLocked(true); d->dockWidgetsMap.insert(factory->id(), dockWidget); } else { dockWidget = d->dockWidgetsMap[factory->id()]; } KConfigGroup group(KGlobal::config(), "GUI"); QFont dockWidgetFont = KGlobalSettings::generalFont(); qreal pointSize = group.readEntry("palettefontsize", dockWidgetFont.pointSize() * 0.75); dockWidgetFont.setPointSizeF(qMax(pointSize, KGlobalSettings::smallestReadableFont().pointSizeF())); #ifdef Q_OS_MAC dockWidget->setAttribute(Qt::WA_MacSmallSize, true); #endif dockWidget->setFont(dockWidgetFont); connect(dockWidget, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(forceDockTabFonts())); return dockWidget; } void KisMainWindow::forceDockTabFonts() { foreach(QObject *child, children()) { if (child->inherits("QTabBar")) { KConfigGroup group(KGlobal::config(), "GUI"); QFont dockWidgetFont = KGlobalSettings::generalFont(); qreal pointSize = group.readEntry("palettefontsize", dockWidgetFont.pointSize() * 0.75); dockWidgetFont.setPointSizeF(qMax(pointSize, KGlobalSettings::smallestReadableFont().pointSizeF())); ((QTabBar *)child)->setFont(dockWidgetFont); } } } QList KisMainWindow::dockWidgets() const { return d->dockWidgetsMap.values(); } QList KisMainWindow::canvasObservers() const { QList observers; foreach(QDockWidget *docker, dockWidgets()) { KoCanvasObserverBase *observer = dynamic_cast(docker); if (observer) { observers << observer; } else { qWarning() << docker << "is not a canvas observer"; } } return observers; } void KisMainWindow::toggleDockersVisibility(bool visible) { if (!visible) { d->dockerStateBeforeHiding = saveState(); foreach(QObject* widget, children()) { if (widget->inherits("QDockWidget")) { QDockWidget* dw = static_cast(widget); if (dw->isVisible()) { dw->hide(); } } } } else { restoreState(d->dockerStateBeforeHiding); } } void KisMainWindow::setToolbarList(QList toolbarList) { qDeleteAll(d->toolbarList); d->toolbarList = toolbarList; } void KisMainWindow::slotDocumentTitleModified(const QString &caption, bool mod) { updateCaption(caption, mod); updateReloadFileAction(d->activeView ? d->activeView->document() : 0); } void KisMainWindow::subWindowActivated() { bool enabled = (activeKisView() != 0); d->mdiCascade->setEnabled(enabled); d->mdiNextWindow->setEnabled(enabled); d->mdiPreviousWindow->setEnabled(enabled); d->mdiTile->setEnabled(enabled); d->close->setEnabled(enabled); d->closeAll->setEnabled(enabled); setActiveSubWindow(d->mdiArea->activeSubWindow()); foreach(QToolBar *tb, toolBars()) { if (tb->objectName() == "BrushesAndStuff") { tb->setEnabled(enabled); } } updateCaption(); d->viewManager->actionManager()->updateGUI(); } void KisMainWindow::updateWindowMenu() { KMenu *menu = d->windowMenu->menu(); menu->clear(); menu->addAction(d->newWindow); menu->addAction(d->documentMenu); KMenu *docMenu = d->documentMenu->menu(); docMenu->clear(); foreach (QPointer doc, KisPart::instance()->documents()) { if (doc) { QString title = doc->url().prettyUrl(); if (title.isEmpty()) title = doc->image()->objectName(); QAction *action = docMenu->addAction(title); action->setIcon(qApp->windowIcon()); connect(action, SIGNAL(triggered()), d->documentMapper, SLOT(map())); d->documentMapper->setMapping(action, doc); } } menu->addSeparator(); menu->addAction(d->close); menu->addAction(d->closeAll); if (d->mdiArea->viewMode() == QMdiArea::SubWindowView) { menu->addSeparator(); menu->addAction(d->mdiTile); menu->addAction(d->mdiCascade); } menu->addSeparator(); menu->addAction(d->mdiNextWindow); menu->addAction(d->mdiPreviousWindow); menu->addSeparator(); QList windows = d->mdiArea->subWindowList(); for (int i = 0; i < windows.size(); ++i) { QPointerchild = qobject_cast(windows.at(i)->widget()); if (child) { QString text; if (i < 9) { text = i18n("&%1 %2").arg(i + 1) .arg(child->document()->url().prettyUrl()); } else { text = i18n("%1 %2").arg(i + 1) .arg(child->document()->url().prettyUrl()); } QAction *action = menu->addAction(text); action->setIcon(qApp->windowIcon()); action->setCheckable(true); action->setChecked(child == activeKisView()); connect(action, SIGNAL(triggered()), d->windowMapper, SLOT(map())); d->windowMapper->setMapping(action, windows.at(i)); } } updateCaption(); } void KisMainWindow::setActiveSubWindow(QWidget *window) { if (!window) return; QMdiSubWindow *subwin = qobject_cast(window); //qDebug() << "setActiveSubWindow();" << subwin << d->activeSubWindow; if (subwin && subwin != d->activeSubWindow) { KisView *view = qobject_cast(subwin->widget()); //qDebug() << "\t" << view << activeView(); if (view && view != activeView()) { d->viewManager->setCurrentView(view); setActiveView(view); } d->activeSubWindow = subwin; } updateWindowMenu(); d->viewManager->actionManager()->updateGUI(); } void KisMainWindow::configChanged() { KisConfig cfg; QMdiArea::ViewMode viewMode = (QMdiArea::ViewMode)cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView); d->mdiArea->setViewMode(viewMode); foreach(QMdiSubWindow *subwin, d->mdiArea->subWindowList()) { subwin->setOption(QMdiSubWindow::RubberBandMove, cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); subwin->setOption(QMdiSubWindow::RubberBandResize, cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); } KConfigGroup group(KGlobal::config(), "theme"); d->themeManager->setCurrentTheme(group.readEntry("Theme", "Krita dark")); d->viewManager->actionManager()->updateGUI(); QBrush brush(cfg.getMDIBackgroundColor()); d->mdiArea->setBackground(brush); QString backgroundImage = cfg.getMDIBackgroundImage(); if (backgroundImage != "") { QImage image(backgroundImage); QBrush brush(image); d->mdiArea->setBackground(brush); } d->mdiArea->update(); } void KisMainWindow::newView(QObject *document) { KisDocument *doc = qobject_cast(document); KisView *view = KisPart::instance()->createView(doc, resourceManager(), actionCollection(), this); addView(view); d->viewManager->actionManager()->updateGUI(); } void KisMainWindow::newWindow() { KisPart::instance()->createMainWindow()->show(); } void KisMainWindow::closeCurrentWindow() { d->mdiArea->currentSubWindow()->close(); d->viewManager->actionManager()->updateGUI(); } void KisMainWindow::checkSanity() { // print error if the lcms engine is not available if (!KoColorSpaceEngineRegistry::instance()->contains("icc")) { // need to wait 1 event since exiting here would not work. m_errorMessage = i18n("The Calligra LittleCMS color management plugin is not installed. Krita will quit now."); m_dieOnError = true; QTimer::singleShot(0, this, SLOT(showErrorAndDie())); return; } KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); if (rserver->resources().isEmpty()) { m_errorMessage = i18n("Krita cannot find any brush presets! Krita will quit now."); m_dieOnError = true; QTimer::singleShot(0, this, SLOT(showErrorAndDie())); return; } } void KisMainWindow::showErrorAndDie() { QMessageBox::critical(0, i18nc("@title:window", "Installation error"), m_errorMessage); if (m_dieOnError) { exit(10); } } void KisMainWindow::showAboutApplication() { KisAboutApplication dlg(KisFactory::aboutData(), this); dlg.exec(); } QPointerKisMainWindow::activeKisView() { if (!d->mdiArea) return 0; QMdiSubWindow *activeSubWindow = d->mdiArea->activeSubWindow(); //qDebug() << "activeKisView" << activeSubWindow; if (!activeSubWindow) return 0; return qobject_cast(activeSubWindow->widget()); } void KisMainWindow::newOptionWidgets(const QList > &optionWidgetList) { KConfigGroup group(KGlobal::config(), "GUI"); QFont dockWidgetFont = KGlobalSettings::generalFont(); qreal pointSize = group.readEntry("palettefontsize", dockWidgetFont.pointSize() * 0.75); pointSize = qMax(pointSize, KGlobalSettings::smallestReadableFont().pointSizeF()); dockWidgetFont.setPointSizeF(pointSize); foreach(QWidget *w, optionWidgetList) { #ifdef Q_OS_MAC w->setAttribute(Qt::WA_MacSmallSize, true); #endif w->setFont(dockWidgetFont); } if (d->toolOptionsDocker) { d->toolOptionsDocker->setOptionWidgets(optionWidgetList); } else { d->viewManager->paintOpBox()->newOptionWidgets(optionWidgetList); } } void KisMainWindow::applyDefaultSettings(QPrinter &printer) { if (!d->activeView) return; QString title = d->activeView->document()->documentInfo()->aboutInfo("title"); if (title.isEmpty()) { title = d->activeView->document()->url().fileName(); // strip off the native extension (I don't want foobar.kwd.ps when printing into a file) KMimeType::Ptr mime = KMimeType::mimeType(d->activeView->document()->outputMimeType()); if (mime) { QString extension = mime->property("X-KDE-NativeExtension").toString(); if (title.endsWith(extension)) title.chop(extension.length()); } } if (title.isEmpty()) { // #139905 title = i18n("%1 unsaved document (%2)", KisFactory::aboutData()->programName(), KGlobal::locale()->formatDate(QDate::currentDate(), KLocale::ShortDate)); } printer.setDocName(title); } void KisMainWindow::createActions() { KisActionManager *actionManager = d->viewManager->actionManager(); actionManager->createStandardAction(KStandardAction::New, this, SLOT(slotFileNew())); actionManager->createStandardAction(KStandardAction::Open, this, SLOT(slotFileOpen())); d->recentFiles = KStandardAction::openRecent(this, SLOT(slotFileOpenRecent(const KUrl&)), actionCollection()); connect(d->recentFiles, SIGNAL(recentListCleared()), this, SLOT(saveRecentFiles())); KSharedConfigPtr configPtr = KisFactory::componentData().config(); d->recentFiles->loadEntries(configPtr->group("RecentFiles")); d->saveAction = actionManager->createStandardAction(KStandardAction::Save, this, SLOT(slotFileSave())); d->saveAction->setActivationFlags(KisAction::ACTIVE_IMAGE); d->saveActionAs = actionManager->createStandardAction(KStandardAction::SaveAs, this, SLOT(slotFileSaveAs())); d->saveActionAs->setActivationFlags(KisAction::ACTIVE_IMAGE); d->printAction = actionManager->createStandardAction(KStandardAction::Print, this, SLOT(slotFilePrint())); d->printAction->setActivationFlags(KisAction::ACTIVE_IMAGE); d->printActionPreview = actionManager->createStandardAction(KStandardAction::PrintPreview, this, SLOT(slotFilePrintPreview())); d->printActionPreview->setActivationFlags(KisAction::ACTIVE_IMAGE); d->undo = actionManager->createStandardAction(KStandardAction::Undo, this, SLOT(undo())); d->undo ->setActivationFlags(KisAction::ACTIVE_IMAGE); d->redo = actionManager->createStandardAction(KStandardAction::Redo, this, SLOT(redo())); d->redo->setActivationFlags(KisAction::ACTIVE_IMAGE); d->exportPdf = new KisAction(i18nc("@action:inmenu", "Export as PDF...")); d->exportPdf->setActivationFlags(KisAction::ACTIVE_IMAGE); d->exportPdf->setIcon(themedIcon("application-pdf")); actionManager->addAction("file_export_pdf", d->exportPdf); connect(d->exportPdf, SIGNAL(triggered()), this, SLOT(exportToPdf())); actionManager->createStandardAction(KStandardAction::Quit, this, SLOT(slotFileQuit())); d->closeAll = new KisAction(i18nc("@action:inmenu", "Close All")); d->closeAll->setActivationFlags(KisAction::ACTIVE_IMAGE); d->closeAll->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_W)); actionManager->addAction("file_close_all", d->closeAll); connect(d->closeAll, SIGNAL(triggered()), this, SLOT(slotFileCloseAll())); // d->reloadFile = new KisAction(i18nc("@action:inmenu", "Reload")); // d->reloadFile->setActivationFlags(KisAction::CURRENT_IMAGE_MODIFIED); // actionManager->addAction("file_reload_file", d->reloadFile); // connect(d->reloadFile, SIGNAL(triggered(bool)), this, SLOT(slotReloadFile())); d->importFile = new KisAction(themedIcon("document-import"), i18nc("@action:inmenu", "Open ex&isting Document as Untitled Document...")); actionManager->addAction("file_import_file", d->importFile); connect(d->importFile, SIGNAL(triggered(bool)), this, SLOT(slotImportFile())); d->exportFile = new KisAction(themedIcon("document-export"), i18nc("@action:inmenu", "E&xport...")); d->exportFile->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager->addAction("file_export_file", d->exportFile); connect(d->exportFile, SIGNAL(triggered(bool)), this, SLOT(slotExportFile())); /* The following entry opens the document information dialog. Since the action is named so it intends to show data this entry should not have a trailing ellipses (...). */ d->showDocumentInfo = new KisAction(themedIcon("configure"), i18nc("@action:inmenu", "Document Information")); d->showDocumentInfo->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager->addAction("file_documentinfo", d->showDocumentInfo); connect(d->showDocumentInfo, SIGNAL(triggered(bool)), this, SLOT(slotDocumentInfo())); actionManager->createStandardAction(KStandardAction::KeyBindings, this, SLOT(slotConfigureKeys())); actionManager->createStandardAction(KStandardAction::ConfigureToolbars, this, SLOT(slotConfigureToolbars())); d->themeManager->setThemeMenuAction(new KActionMenu(i18nc("@action:inmenu", "&Themes"), this)); d->themeManager->registerThemeActions(actionCollection()); connect(d->themeManager, SIGNAL(signalThemeChanged()), this, SLOT(slotThemeChanged())); actionManager->createStandardAction(KStandardAction::FullScreen, this, SLOT(viewFullscreen(bool))); d->toggleDockers = new KisAction(i18nc("@action:inmenu", "Show Dockers")); d->toggleDockers->setCheckable(true); d->toggleDockers->setChecked(true); actionManager->addAction("view_toggledockers", d->toggleDockers); connect(d->toggleDockers, SIGNAL(toggled(bool)), SLOT(toggleDockersVisibility(bool))); d->toggleDockerTitleBars = new KisAction(i18nc("@action:inmenu", "Show Docker Titlebars")); d->toggleDockerTitleBars->setCheckable(true); KisConfig cfg; d->toggleDockerTitleBars->setChecked(cfg.showDockerTitleBars()); actionManager->addAction("view_toggledockertitlebars", d->toggleDockerTitleBars); connect(d->toggleDockerTitleBars, SIGNAL(toggled(bool)), SLOT(showDockerTitleBars(bool))); actionCollection()->addAction("settings_dockers_menu", d->dockWidgetMenu); actionCollection()->addAction("window", d->windowMenu); d->mdiCascade = new KisAction(i18nc("@action:inmenu", "Cascade")); d->mdiCascade->setActivationFlags(KisAction::MULTIPLE_IMAGES); actionManager->addAction("windows_cascade", d->mdiCascade); connect(d->mdiCascade, SIGNAL(triggered()), d->mdiArea, SLOT(cascadeSubWindows())); d->mdiTile = new KisAction(i18nc("@action:inmenu", "Tile")); d->mdiTile->setActivationFlags(KisAction::MULTIPLE_IMAGES); actionManager->addAction("windows_tile", d->mdiTile); connect(d->mdiTile, SIGNAL(triggered()), d->mdiArea, SLOT(tileSubWindows())); d->mdiNextWindow = new KisAction(i18nc("@action:inmenu", "Next")); d->mdiNextWindow->setActivationFlags(KisAction::MULTIPLE_IMAGES); actionManager->addAction("windows_next", d->mdiNextWindow); connect(d->mdiNextWindow, SIGNAL(triggered()), d->mdiArea, SLOT(activateNextSubWindow())); d->mdiPreviousWindow = new KisAction(i18nc("@action:inmenu", "Previous")); d->mdiPreviousWindow->setActivationFlags(KisAction::MULTIPLE_IMAGES); actionCollection()->addAction("windows_previous", d->mdiPreviousWindow); connect(d->mdiPreviousWindow, SIGNAL(triggered()), d->mdiArea, SLOT(activatePreviousSubWindow())); d->newWindow = new KisAction(themedIcon("window-new"), i18nc("@action:inmenu", "&New Window")); actionManager->addAction("view_newwindow", d->newWindow); connect(d->newWindow, SIGNAL(triggered(bool)), this, SLOT(newWindow())); d->close = new KisAction(i18nc("@action:inmenu", "Close")); d->close->setActivationFlags(KisAction::ACTIVE_IMAGE); connect(d->close, SIGNAL(triggered()), SLOT(closeCurrentWindow())); actionManager->addAction("file_close", d->close); actionManager->createStandardAction(KStandardAction::Preferences, this, SLOT(slotPreferences())); for (int i = 0; i < 2; i++) { d->expandingSpacers[i] = new KisAction(i18n("Expanding Spacer")); d->expandingSpacers[i]->setDefaultWidget(new QWidget(this)); d->expandingSpacers[i]->defaultWidget()->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding); actionManager->addAction(QString("expanding_spacer_%1").arg(i), d->expandingSpacers[i]); } } void KisMainWindow::applyToolBarLayout() { const bool isPlastiqueStyle = style()->objectName() == "plastique"; Q_FOREACH (KToolBar *toolBar, toolBars()) { toolBar->layout()->setSpacing(4); if (isPlastiqueStyle) { toolBar->setContentsMargins(0, 0, 0, 2); } } } void KisMainWindow::initializeGeometry() { // if the user didn's specify the geometry on the command line (does anyone do that still?), // we first figure out some good default size and restore the x,y position. See bug 285804Z. KConfigGroup cfg(KGlobal::config(), "MainWindow"); if (!initialGeometrySet()) { QByteArray geom = QByteArray::fromBase64(cfg.readEntry("ko_geometry", QByteArray())); if (!restoreGeometry(geom)) { const int scnum = QApplication::desktop()->screenNumber(parentWidget()); QRect desk = QApplication::desktop()->availableGeometry(scnum); // if the desktop is virtual then use virtual screen size if (QApplication::desktop()->isVirtualDesktop()) { desk = QApplication::desktop()->availableGeometry(QApplication::desktop()->screen(scnum)); } quint32 x = desk.x(); quint32 y = desk.y(); quint32 w = 0; quint32 h = 0; // Default size -- maximize on small screens, something useful on big screens const int deskWidth = desk.width(); if (deskWidth > 1024) { // a nice width, and slightly less than total available // height to componensate for the window decs w = (deskWidth / 3) * 2; h = (desk.height() / 3) * 2; } else { w = desk.width(); h = desk.height(); } x += (desk.width() - w) / 2; y += (desk.height() - h) / 2; move(x,y); setGeometry(geometry().x(), geometry().y(), w, h); } } restoreWorkspace(QByteArray::fromBase64(cfg.readEntry("ko_windowstate", QByteArray()))); } void KisMainWindow::showManual() { QDesktopServices::openUrl(QUrl("https://userbase.kde.org/Special:MyLanguage/Krita/Manual")); } void KisMainWindow::showDockerTitleBars(bool show) { foreach (QDockWidget *dock, dockWidgets()) { if (dock->titleBarWidget()) { const bool isCollapsed = (dock->widget() && dock->widget()->isHidden()) || !dock->widget(); dock->titleBarWidget()->setVisible(show || (dock->isFloating() && isCollapsed)); } } KisConfig cfg; cfg.setShowDockerTitleBars(show); } #include diff --git a/krita/ui/KisMainWindow.h b/krita/ui/KisMainWindow.h index 0f1d328aff1..84a9dadf9d0 100644 --- a/krita/ui/KisMainWindow.h +++ b/krita/ui/KisMainWindow.h @@ -1,455 +1,455 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2004 David Faure 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_MAIN_WINDOW_H #define KIS_MAIN_WINDOW_H -#include "krita_export.h" +#include "kritaui_export.h" #include #include #include #include #include #include "KisView.h" class QCloseEvent; struct KoPageLayout; class KoCanvasResourceManager; class KisDocument; class KisView; class KisPrintJob; class KoDockFactoryBase; class QDockWidget; class KisView; class KisViewManager; // Calligra class but not in main module class KisDockerManager; /** * @brief Main window for Krita * * This class is used to represent a main window * of a Krita. Each main window contains * a menubar and some toolbars. */ class KRITAUI_EXPORT KisMainWindow : public KXmlGuiWindow, public KoCanvasSupervisor { Q_OBJECT public: /** * Constructor. * * Initializes a Calligra main window (with its basic GUI etc.). */ explicit KisMainWindow(); /** * Destructor. */ virtual ~KisMainWindow(); /** * Update caption from document info - call when document info * (title in the about page) changes. */ void updateCaption(); // If noCleanup is set, KisMainWindow will not delete the root document // or part manager on destruction. void setNoCleanup(bool noCleanup); /** * Add a the given view to the list of views of this mainwindow. */ void addView(KisView *view); /** * @brief showView shows the given view. Override this if you want to show * the view in a different way than by making it the central widget, for instance * as an QMdiSubWindow */ virtual void showView(KisView *view); /** * @returns the currently active view */ KisView *activeView() const; /** * Sets the maximum number of recent documents entries. */ void setMaxRecentItems(uint _number); /** * The document opened a URL -> store into recent documents list. */ void addRecentURL(const KUrl& url); /** * Load the desired document and show it. * @param url the URL to open * * @return TRUE on success. */ bool openDocument(const KUrl & url); void setReadWrite(bool readwrite); /// Return the list of dock widgets belonging to this main window. QList dockWidgets() const; QList canvasObservers() const; /** * @return the KisDockerManager which is assigned * WARNING: this could be 0, if no docker have been assigned yet. In that case create one * and assign it. * @ref setDockerManager to assign it. */ KisDockerManager * dockerManager() const; KoCanvasResourceManager *resourceManager() const; int viewCount() const; /** * A wrapper around restoreState * @param state the saved state * @return TRUE on success */ bool restoreWorkspace(const QByteArray &state); KisViewManager *viewManager() const; Q_SIGNALS: /** * This signal is emitted if the document has been saved successfully. */ void documentSaved(); /// This signal is emitted when this windows has finished loading of a /// document. The document may be opened in another window in the end. /// In this case, the signal means there is no link between the window /// and the document anymore. void loadCompleted(); /// This signal is emitted right after the docker states have been succefully restored from config void restoringDone(); /// This signal is emitted when the color theme changes void themeChanged(); /// This signal is emitted when the shortcut key configuration has changed void keyBindingsChanged(); public Q_SLOTS: /** * Slot for eMailing the document using KMail * * This is a very simple extension that will allow any document * that is currently being edited to be emailed using KMail. */ void slotEmailFile(); /** * Slot for opening a new document. * * If the current document is empty, the new document replaces it. * If not, a new mainwindow will be opened for showing the document. */ void slotFileNew(); /** * Slot for opening a saved file. * * If the current document is empty, the opened document replaces it. * If not a new mainwindow will be opened for showing the opened file. */ void slotFileOpen(); /** * Slot for opening a file among the recently opened files. * * If the current document is empty, the opened document replaces it. * If not a new mainwindow will be opened for showing the opened file. */ void slotFileOpenRecent(const KUrl &); /** * @brief slotPreferences open the preferences dialog */ void slotPreferences(); /** * Saves the current document with the current name. */ void slotFileSave(); KisPrintJob* exportToPdf(const QString &pdfFileName = QString()); void slotProgress(int value); /** * Saves the document, asking for a filename if necessary. * * @param saveas if set to TRUE the user is always prompted for a filename * * @param silent if set to TRUE rootDocument()->setTitleModified will not be called. * * @param specialOutputFlag set to enums defined in KisDocument if save to special output format * * @return TRUE on success, false on error or cancel * (don't display anything in this case, the error dialog box is also implemented here * but restore the original URL in slotFileSaveAs) */ bool saveDocument(KisDocument *document, bool saveas = false, bool silent = false, int specialOutputFlag = 0); /** * Update the option widgets to the argument ones, removing the currently set widgets. */ void newOptionWidgets(const QList > & optionWidgetList); private Q_SLOTS: /** * Save the list of recent files. */ void saveRecentFiles(); void slotLoadCompleted(); void slotLoadCanceled(const QString &); void slotSaveCompleted(); void slotSaveCanceled(const QString &); void forceDockTabFonts(); /** * @internal */ void slotDocumentTitleModified(const QString &caption, bool mod); /** * Prints the actual document. */ void slotFilePrint(); /** * Saves the current document with a new name. */ void slotFileSaveAs(); void slotFilePrintPreview(); KisPrintJob* exportToPdf(KoPageLayout pageLayout, QString pdfFileName = QString()); /** * Show a dialog with author and document information. */ void slotDocumentInfo(); /** * Closes all open documents. */ bool slotFileCloseAll(); /** * @brief showAboutApplication show the about box */ virtual void showAboutApplication(); /** * Closes the mainwindow. */ void slotFileQuit(); /** * Configure key bindings. */ void slotConfigureKeys(); /** * Configure toolbars. */ void slotConfigureToolbars(); /** * Post toolbar config. * (Plug action lists back in, etc.) */ void slotNewToolbarConfig(); /** * Shows or hides a toolbar */ void slotToolbarToggled(bool toggle); /** * Toggle full screen on/off. */ void viewFullscreen(bool fullScreen); /** * Toggle docker titlebars on/off. */ void showDockerTitleBars(bool show); /** * Reload file */ void slotReloadFile(); /** * File --> Import * * This will call slotFileOpen(). To differentiate this from an ordinary * call to slotFileOpen() call @ref isImporting(). */ void slotImportFile(); /** * File --> Export * * This will call slotFileSaveAs(). To differentiate this from an ordinary * call to slotFileSaveAs() call @ref isExporting(). */ void slotExportFile(); /** * Hide the dockers */ void toggleDockersVisibility(bool visible); /** * Handle theme changes from theme manager */ void slotThemeChanged(); void undo(); void redo(); void subWindowActivated(); void updateWindowMenu(); void setActiveSubWindow(QWidget *window); void configChanged(); void newView(QObject *document); void newWindow(); void closeCurrentWindow(); void checkSanity(); /// Quits Krita with error message from m_errorMessage. void showErrorAndDie(); protected: void closeEvent(QCloseEvent * e); void resizeEvent(QResizeEvent * e); /// Set the active view, this will update the undo/redo actions virtual void setActiveView(KisView *view); // QWidget overrides virtual void dragEnterEvent(QDragEnterEvent * event); virtual void dropEvent(QDropEvent * event); void setToolbarList(QList toolbarList); private: friend class KisApplication; /** * Returns the dockwidget specified by the @p factory. If the dock widget doesn't exist yet it's created. * Add a "view_palette_action_menu" action to your view menu if you want to use closable dock widgets. * @param factory the factory used to create the dock widget if needed * @return the dock widget specified by @p factory (may be 0) */ QDockWidget* createDockWidget(KoDockFactoryBase* factory); bool openDocumentInternal(const KUrl &url, KisDocument *newdoc = 0); /** * Returns whether or not the current slotFileSave[As]() or saveDocument() * call is actually an export operation (like File --> Export). * * If this is true, you must call KisDocument::export() instead of * KisDocument::save() or KisDocument::saveAs(), in any reimplementation of * saveDocument(). */ bool isExporting() const; /** * Returns whether or not the current slotFileOpen() or openDocument() * call is actually an import operation (like File --> Import). * * If this is true, you must call KisDocument::import() instead of * KisDocument::openUrl(), in any reimplementation of openDocument() or * openDocumentInternal(). */ bool isImporting() const; /** * Reloads the recent documents list. */ void reloadRecentFileList(); /** * Updates the window caption based on the document info and path. */ void updateCaption(const QString & caption, bool mod); void updateReloadFileAction(KisDocument *doc); void saveWindowSettings(); QPointeractiveKisView(); void applyDefaultSettings(QPrinter &printer); bool exportConfirmation(const QByteArray &outputFormat); void createActions(); void applyToolBarLayout(); private slots: void initializeGeometry(); void showManual(); private: class Private; Private * const d; QString m_errorMessage; bool m_dieOnError; }; #endif diff --git a/krita/ui/KisPageWidgetItem.h b/krita/ui/KisPageWidgetItem.h index 30dfe1d97a7..a4789049edb 100644 --- a/krita/ui/KisPageWidgetItem.h +++ b/krita/ui/KisPageWidgetItem.h @@ -1,44 +1,44 @@ /* This file is part of the KDE project Copyright (c) 2000 Simon Hausmann 2006 Martin Pfeiffer 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 KISPAGEWIDGETITEM_H #define KISPAGEWIDGETITEM_H -#include "krita_export.h" +#include "kritaui_export.h" class QWidget; class QString; // This class can be implemented when we want to extend the // dialog with new, specific pages. class KRITAUI_EXPORT KisPageWidgetItem { public: virtual ~KisPageWidgetItem() {} virtual QWidget *widget() = 0; virtual QString name() const = 0; virtual QString iconName() const = 0; virtual bool shouldDialogCloseBeVetoed() = 0; virtual void apply() = 0; }; #endif // KOPAGEWIDGETITEM_H diff --git a/krita/ui/KisPart.cpp b/krita/ui/KisPart.cpp index 33991432bda..0be6ebfc596 100644 --- a/krita/ui/KisPart.cpp +++ b/krita/ui/KisPart.cpp @@ -1,639 +1,639 @@ /* This file is part of the KDE project * Copyright (C) 1998, 1999 Torben Weis * Copyright (C) 2000-2005 David Faure * Copyright (C) 2007-2008 Thorsten Zachmann * Copyright (C) 2010-2012 Boudewijn Rempt * Copyright (C) 2011 Inge Wallin * * 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 "KisPart.h" #include "KoProgressProxy.h" #include #include #include #include #include #include #include #include -#include +#include #include "KisApplication.h" #include "KisMainWindow.h" #include "KisDocument.h" #include "KisView.h" #include "KisViewManager.h" #include "KisOpenPane.h" #include "KisImportExportManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisView.h" #include "KisDocument.h" #include "kis_factory2.h" #include "kis_config.h" #include "kis_clipboard.h" #include "kis_custom_image_widget.h" #include "kis_image_from_clipboard_widget.h" #include "kis_shape_controller.h" #include "kis_resource_server_provider.h" #include "kis_color_manager.h" #include "kis_action.h" class KisPart::Private { public: Private(KisPart *_part) : part(_part) , canvasItem(0) , startupWidget(0) , actionCollection(0) { } ~Private() { delete canvasItem; } KisPart *part; QList > views; QList > mainWindows; QList > documents; QGraphicsItem *canvasItem; QString templatesResourcePath; KisOpenPane *startupWidget; KActionCollection *actionCollection; void loadActions(); }; void KisPart::Private::loadActions() { actionCollection = new KActionCollection(part, KGlobal::mainComponent()); KGlobal::mainComponent().dirs()->addResourceType("kis_actions", "data", "krita/actions/"); QStringList actionDefinitions = KGlobal::mainComponent().dirs()->findAllResources("kis_actions", "*.action", KStandardDirs::Recursive | KStandardDirs::NoDuplicates); foreach(const QString &actionDefinition, actionDefinitions) { QDomDocument doc; QFile f(actionDefinition); f.open(QFile::ReadOnly); doc.setContent(f.readAll()); QDomElement e = doc.documentElement(); // Actions QString collection = e.attribute("name"); e = e.firstChild().toElement(); // Action while (!e.isNull()) { if (e.tagName() == "Action") { QString name = e.attribute("name"); QString icon = e.attribute("icon"); QString text = i18n(e.attribute("text").toUtf8().constData()); QString whatsthis = i18n(e.attribute("whatsThis").toUtf8().constData()); QString toolTip = i18n(e.attribute("toolTip").toUtf8().constData()); QString statusTip = i18n(e.attribute("statusTip").toUtf8().constData()); QString iconText = i18n(e.attribute("iconText").toUtf8().constData()); KShortcut shortcut = KShortcut(e.attribute("shortcut")); bool isCheckable = e.attribute("isCheckable") == "true" ? true : false; KShortcut defaultShortcut = KShortcut(e.attribute("defaultShortcut")); if (name.isEmpty()) { qDebug() << text << "has no name! From:" << actionDefinition; } - KisAction *action = new KisAction(KIcon(icon), text); + KisAction *action = new KisAction(KisIconUtils::loadIcon(icon.toLatin1()), text); action->setObjectName(name); action->setWhatsThis(whatsthis); action->setToolTip(toolTip); action->setStatusTip(statusTip); action->setIconText(iconText); action->setShortcut(shortcut, KAction::ActiveShortcut); action->setCheckable(isCheckable); action->setShortcut(defaultShortcut, KAction::DefaultShortcut); if (!actionCollection->action(name)) { actionCollection->addAction(name, action); } // else { // qDebug() << "duplicate action" << name << action << "from" << collection; // delete action; // } } e = e.nextSiblingElement(); } actionCollection->readSettings(); } //check for colliding shortcuts QMap existingShortcuts; foreach(QAction* action, actionCollection->actions()) { if(action->shortcut() == QKeySequence(0)) { continue; } if (existingShortcuts.contains(action->shortcut())) { qDebug() << "action" << action->text() << "and" << existingShortcuts[action->shortcut()]->text() << "have the same shortcut:" << action->shortcut(); } else { existingShortcuts[action->shortcut()] = action; } } } KisPart* KisPart::instance() { K_GLOBAL_STATIC(KisPart, s_instance) return s_instance; } KisPart::KisPart() : d(new Private(this)) { setTemplatesResourcePath(QLatin1String("krita/templates/")); // Preload all the resources in the background Q_UNUSED(KoResourceServerProvider::instance()); Q_UNUSED(KisResourceServerProvider::instance()); Q_UNUSED(KisColorManager::instance()); } KisPart::~KisPart() { while (!d->documents.isEmpty()) { delete d->documents.takeFirst(); } while (!d->views.isEmpty()) { delete d->views.takeFirst(); } while (!d->mainWindows.isEmpty()) { delete d->mainWindows.takeFirst(); } delete d; } void KisPart::addDocument(KisDocument *document) { //qDebug() << "Adding document to part list" << document; Q_ASSERT(document); if (!d->documents.contains(document)) { d->documents.append(document); emit documentOpened('/'+objectName()); } } QList > KisPart::documents() const { return d->documents; } KisDocument *KisPart::createDocument() const { KisDocument *doc = new KisDocument(); return doc; } int KisPart::documentCount() const { return d->documents.size(); } void KisPart::removeDocument(KisDocument *document) { d->documents.removeAll(document); emit documentClosed('/'+objectName()); document->deleteLater(); } KisMainWindow *KisPart::createMainWindow() { KisMainWindow *mw = new KisMainWindow(); addMainWindow(mw); return mw; } KisView *KisPart::createView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent) { QApplication::setOverrideCursor(Qt::WaitCursor); KisView *view = new KisView(document, resourceManager, actionCollection, parent); QApplication::restoreOverrideCursor(); addView(view); return view; } void KisPart::addView(KisView *view) { if (!view) return; if (!d->views.contains(view)) { d->views.append(view); } connect(view, SIGNAL(destroyed()), this, SLOT(viewDestroyed())); emit sigViewAdded(view); } void KisPart::removeView(KisView *view) { if (!view) return; emit sigViewRemoved(view); QPointer doc = view->document(); d->views.removeAll(view); if (doc) { bool found = false; foreach(QPointer view, d->views) { if (view && view->document() == doc) { found = true; break; } } if (!found) { removeDocument(doc); } } } QList > KisPart::views() const { return d->views; } int KisPart::viewCount(KisDocument *doc) const { if (!doc) { return d->views.count(); } else { int count = 0; foreach(QPointer view, d->views) { if (view->document() == doc) { count++; } } return count; } } QGraphicsItem *KisPart::canvasItem(KisDocument *document, bool create) { if (create && !d->canvasItem) { d->canvasItem = createCanvasItem(document); } return d->canvasItem; } QGraphicsItem *KisPart::createCanvasItem(KisDocument *document) { if (!document) return 0; KisView *view = createView(document, 0, 0, 0); QGraphicsProxyWidget *proxy = new QGraphicsProxyWidget(); QWidget *canvasController = view->findChild(); proxy->setWidget(canvasController); return proxy; } void KisPart::addMainWindow(KisMainWindow *mainWindow) { if (!mainWindow) return; if (d->mainWindows.contains(mainWindow)) return; kDebug(30003) <<"mainWindow" << (void*)mainWindow <<"added to doc" << this; d->mainWindows.append(mainWindow); } void KisPart::removeMainWindow(KisMainWindow *mainWindow) { kDebug(30003) <<"mainWindow" << (void*)mainWindow <<"removed from doc" << this; if (mainWindow) { d->mainWindows.removeAll(mainWindow); } } const QList > &KisPart::mainWindows() const { return d->mainWindows; } int KisPart::mainwindowCount() const { return d->mainWindows.count(); } KisMainWindow *KisPart::currentMainwindow() const { QWidget *widget = qApp->activeWindow(); KisMainWindow *mainWindow = qobject_cast(widget); while (!mainWindow && widget) { widget = widget->parentWidget(); mainWindow = qobject_cast(widget); } if (!mainWindow && mainWindows().size() > 0) { mainWindow = mainWindows().first(); } return mainWindow; } void KisPart::openExistingFile(const KUrl& url) { qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); if (!document->openUrl(url)) { return; } document->setModified(false); addDocument(document); KisMainWindow *mw = 0; if (d->startupWidget) { mw = qobject_cast(d->startupWidget->parent()); } if (!mw) { mw = currentMainwindow(); } KisView *view = createView(document, mw->resourceManager(), mw->actionCollection(), mw); mw->addView(view); if (d->startupWidget) { d->startupWidget->setParent(0); d->startupWidget->hide(); } qApp->restoreOverrideCursor(); } void KisPart::configureShortcuts() { if (!d->actionCollection) { d->loadActions(); } KShortcutsDialog dlg(KShortcutsEditor::WidgetAction | KShortcutsEditor::WindowAction | KShortcutsEditor::ApplicationAction); dlg.setButtons(KDialog::Reset|KDialog::Ok|KDialog::Cancel|KDialog::User1); dlg.addCollection(d->actionCollection); dlg.setButtonText(KDialog::User1, i18n("Print")); dlg.setButtonIcon(KDialog::User1, KIcon("document-print")); dlg.configure(); foreach(KisMainWindow *mainWindow, d->mainWindows) { KActionCollection *ac = mainWindow->actionCollection(); ac->readSettings(); // append shortcuts to tooltips if they exist foreach( QAction* tempAction, ac->actions()) { // find the shortcut pattern and delete (note the preceding space in the RegEx) QString strippedTooltip = tempAction->toolTip().remove(QRegExp("\\s\\(.*\\)")); // append shortcut if it exists for action if(tempAction->shortcut() == QKeySequence(0)) tempAction->setToolTip( strippedTooltip); else tempAction->setToolTip( strippedTooltip + " (" + tempAction->shortcut().toString() + ")"); } } } void KisPart::openTemplate(const KUrl& url) { qApp->setOverrideCursor(Qt::BusyCursor); KisDocument *document = createDocument(); bool ok = document->loadNativeFormat(url.toLocalFile()); document->setModified(false); document->undoStack()->clear(); if (ok) { QString mimeType = KMimeType::findByUrl( url, 0, true )->name(); // in case this is a open document template remove the -template from the end mimeType.remove( QRegExp( "-template$" ) ); document->setMimeTypeAfterLoading(mimeType); document->resetURL(); document->setEmpty(); } else { document->showLoadingErrorDialog(); document->initEmpty(); } addDocument(document); KisMainWindow *mw = qobject_cast(d->startupWidget->parent()); if (!mw) mw = currentMainwindow(); KisView *view = createView(document, mw->resourceManager(), mw->actionCollection(), mw); mw->addView(view); d->startupWidget->setParent(0); d->startupWidget->hide(); qApp->restoreOverrideCursor(); } void KisPart::viewDestroyed() { KisView *view = qobject_cast(sender()); if (view) { removeView(view); } } void KisPart::addRecentURLToAllMainWindows(KUrl url) { // Add to recent actions list in our mainWindows foreach(KisMainWindow *mainWindow, d->mainWindows) { mainWindow->addRecentURL(url); } } void KisPart::showStartUpWidget(KisMainWindow *mainWindow, bool alwaysShow) { #ifndef NDEBUG if (d->templatesResourcePath.isEmpty()) kDebug(30003) << "showStartUpWidget called, but setTemplatesResourcePath() never called. This will not show a lot"; #endif if (!alwaysShow) { KConfigGroup cfgGrp(KisFactory::componentData().config(), "TemplateChooserDialog"); QString fullTemplateName = cfgGrp.readPathEntry("AlwaysUseTemplate", QString()); if (!fullTemplateName.isEmpty()) { KUrl url(fullTemplateName); QFileInfo fi(url.toLocalFile()); if (!fi.exists()) { const QString templatesResourcePath = this->templatesResourcePath(); QString desktopfile = KGlobal::dirs()->findResource("data", templatesResourcePath + "*/" + fullTemplateName); if (desktopfile.isEmpty()) { desktopfile = KGlobal::dirs()->findResource("data", templatesResourcePath + fullTemplateName); } if (desktopfile.isEmpty()) { fullTemplateName.clear(); } else { KUrl templateURL; KDesktopFile f(desktopfile); templateURL.setPath(KUrl(desktopfile).directory() + '/' + f.readUrl()); fullTemplateName = templateURL.toLocalFile(); } } if (!fullTemplateName.isEmpty()) { openTemplate(fullTemplateName); return; } } } if (d->startupWidget) { delete d->startupWidget; } const QStringList mimeFilter = koApp->mimeFilter(KisImportExportManager::Import); d->startupWidget = new KisOpenPane(0, KisFactory::componentData(), mimeFilter, d->templatesResourcePath); d->startupWidget->setWindowModality(Qt::WindowModal); QList widgetList = createCustomDocumentWidgets(d->startupWidget); foreach(const CustomDocumentWidgetItem & item, widgetList) { d->startupWidget->addCustomDocumentWidget(item.widget, item.title, item.icon); connect(item.widget, SIGNAL(documentSelected(KisDocument*)), this, SLOT(startCustomDocument(KisDocument*))); } connect(d->startupWidget, SIGNAL(openExistingFile(const KUrl&)), this, SLOT(openExistingFile(const KUrl&))); connect(d->startupWidget, SIGNAL(openTemplate(const KUrl&)), this, SLOT(openTemplate(const KUrl&))); d->startupWidget->setParent(mainWindow); d->startupWidget->setWindowFlags(Qt::Dialog); d->startupWidget->exec(); } QList KisPart::createCustomDocumentWidgets(QWidget * parent) { KisConfig cfg; int w = cfg.defImageWidth(); int h = cfg.defImageHeight(); QList widgetList; { KisPart::CustomDocumentWidgetItem item; item.widget = new KisCustomImageWidget(parent, w, h, cfg.defImageResolution(), cfg.defColorModel(), cfg.defaultColorDepth(), cfg.defColorProfile(), i18n("Unnamed")); item.icon = "application-x-krita"; widgetList << item; } { QSize sz = KisClipboard::instance()->clipSize(); if (sz.isValid() && sz.width() != 0 && sz.height() != 0) { w = sz.width(); h = sz.height(); } KisPart::CustomDocumentWidgetItem item; item.widget = new KisImageFromClipboard(parent, w, h, cfg.defImageResolution(), cfg.defColorModel(), cfg.defaultColorDepth(), cfg.defColorProfile(), i18n("Unnamed")); item.title = i18n("Create from Clipboard"); item.icon = "klipper"; widgetList << item; } return widgetList; } void KisPart::setTemplatesResourcePath(const QString &templatesResourcePath) { Q_ASSERT(!templatesResourcePath.isEmpty()); Q_ASSERT(templatesResourcePath.endsWith(QLatin1Char('/'))); d->templatesResourcePath = templatesResourcePath; } QString KisPart::templatesResourcePath() const { return d->templatesResourcePath; } void KisPart::startCustomDocument(KisDocument* doc) { addDocument(doc); KisMainWindow *mw = qobject_cast(d->startupWidget->parent()); if (!mw) mw = currentMainwindow(); KisView *view = createView(doc, mw->resourceManager(), mw->actionCollection(), mw); mw->addView(view); d->startupWidget->setParent(0); d->startupWidget->hide(); } KisInputManager* KisPart::currentInputManager() { return instance()->currentMainwindow()->viewManager()->inputManager(); } #include diff --git a/krita/ui/KisPart.h b/krita/ui/KisPart.h index f6eb2a48c9e..1200f77e237 100644 --- a/krita/ui/KisPart.h +++ b/krita/ui/KisPart.h @@ -1,293 +1,293 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2005 David Faure Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2010 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_PART_H #define KIS_PART_H #include #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include namespace KIO { } class KisDocument; class KisView; class QGraphicsItem; class KisDocument; /** * Override this class in your application. It's the main entry point that * should provide the document, the view and the component data to the calligra * system. * * There is/will be a single KisPart instance for an application that will manage * the list of documents, views and mainwindows. * * It hasn't got much to do with kparts anymore. */ class KRITAUI_EXPORT KisPart : public QObject { Q_OBJECT public: static KisPart *instance(); private: /** * Constructor. * * @param parent may be another KisDocument, or anything else. * Usually passed by KPluginFactory::create. */ explicit KisPart(); public: /** * Destructor. * * The destructor does not delete any attached KisView objects and it does not * delete the attached widget as returned by widget(). */ ~KisPart(); // ----------------- mainwindow management ----------------- /** * create an empty document. The document is not automatically registered with the part. */ KisDocument *createDocument() const; /** * Add the specified document to the list of documents this KisPart manages. */ void addDocument(KisDocument *document); /** * @return a list of all documents this part manages */ QList > documents() const; /** * @return number of documents this part manages. */ int documentCount() const; void removeDocument(KisDocument *document); // ----------------- mainwindow management ----------------- /** * Create a new main window, but does not add it to the current set of managed main windows. */ KisMainWindow *createMainWindow(); /** * Appends the mainwindow to the list of mainwindows which this part manages. */ void addMainWindow(KisMainWindow *mainWindow); /** * Removes the mainwindow from the list. */ void removeMainWindow(KisMainWindow *mainWindow); /** * @return the list of main windows. */ const QList >& mainWindows() const; /** * @return the number of shells for the main window */ int mainwindowCount() const; void addRecentURLToAllMainWindows(KUrl url); KisMainWindow *currentMainwindow() const; public Q_SLOTS: /** * This slot loads an existing file and deletes the start up widget. * @param url the file to load */ void openExistingFile(const KUrl& url); /** * @brief configureShortcuts opens the shortcut configuration dialog. * @param parent the parent widget for the dialog * * After the user closes the dialog, all actioncollections will be updated * with the new shortcuts. */ void configureShortcuts(); protected Q_SLOTS: /** * This slot loads a template and deletes the start up widget. * @param url the template to load */ void openTemplate(const KUrl& url); private Q_SLOTS: void viewDestroyed(); void startCustomDocument(KisDocument *doc); Q_SIGNALS: /** * emitted when a new document is opened. */ void documentOpened(const QString &ref); /** * emitted when an old document is closed. */ void documentClosed(const QString &ref); void sigViewAdded(KisView *view); void sigViewRemoved(KisView *view); public: static KisInputManager *currentInputManager(); //------------------ view management ------------------ /** * Create a new view for the document. The view is added to the list of * views, and if the document wasn't known yet, it's registered as well. */ KisView *createView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent); /** * Adds a view to the document. If the part doesn't know yet about * the document, it is registered. * * This calls KisView::updateReadWrite to tell the new view * whether the document is readonly or not. */ void addView(KisView *view); /** * Removes a view of the document. */ void removeView(KisView *view); /** * @return a list of views this document is displayed in */ QList > views() const; /** * @return number of views this document is displayed in */ int viewCount(KisDocument *doc) const; /** * @return a QGraphicsItem canvas displaying this document. There is only one QGraphicsItem canvas that can * be shown by many QGraphicsView subclasses (those should reimplement KoCanvasController * as well). * * @param create if true, a new canvas item is created if there wasn't one. */ QGraphicsItem *canvasItem(KisDocument *document, bool create = true); // ------- startup/openpane etc --------------- /** * Template resource path used. This is used by the start up widget to show * the correct templates. */ QString templatesResourcePath() const; /** * Creates and shows the start up widget. * @param parent the KisMainWindow used as parent for the widget. * @param alwaysShow always show the widget even if the user has configured it to not show. */ void showStartUpWidget(KisMainWindow *parent, bool alwaysShow = false); protected: /** * Set the templates resource path used. This is used by the start up widget to show * the correct templates. */ void setTemplatesResourcePath(const QString &templatesResourcePath); /** * Struct used in the list created by createCustomDocumentWidgets() */ struct CustomDocumentWidgetItem { /// Pointer to the custom document widget QWidget *widget; /// title used in the sidebar. If left empty it will be displayed as "Custom Document" QString title; /// icon used in the sidebar. If left empty it will use the unknown icon QString icon; }; /** * Override this method in your derived class to show a widget in the startup 'dialog'. * This widget should allow the user to set settings for a custom document (i.e. one * not based on a template). * The returned widget should provide its own button (preferably 'Create') and * implement the logic to implement the document instance correctly. * After initializing the widget should emit a signal called 'documentSelected(KisDocument*)' which * will remove the startupWidget and show the document. * @param parent the parent of the to be created widget. * @return a list of KisDocument::CustomDocumentWidgetItem. */ QList createCustomDocumentWidgets(QWidget *parent); /** * Override this to create a QGraphicsItem that does not rely * on proxying a KoCanvasController. */ QGraphicsItem *createCanvasItem(KisDocument *document); private: Q_DISABLE_COPY(KisPart) class Private; Private *const d; }; #endif diff --git a/krita/ui/KisPrintJob.h b/krita/ui/KisPrintJob.h index e32a9407d01..060908ab2fc 100644 --- a/krita/ui/KisPrintJob.h +++ b/krita/ui/KisPrintJob.h @@ -1,101 +1,101 @@ /* This file is part of the KDE project * Copyright (C) 2007 Thomas Zander * * 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 KISPRINTJOB_H #define KISPRINTJOB_H #include #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include class QWidget; /** * A print job is an interface that the KisView uses to create an application-specific * class that can take care of printing. * The printjob should be able to print again after a print job has been completed, * using the same QPrinter to allow the user to alter settings on the QPrinter and * call print again. * The printjob can thus see startPrinting() called more than once, and the implementation * of that signal should honor the removePolicy passed to it. */ class KRITAUI_EXPORT KisPrintJob : public QObject { Q_OBJECT public: /** * Constructor. * @param parent the parent qobject that is passed for memory management purposes. */ explicit KisPrintJob(KisImageWSP image); virtual ~KisPrintJob(); /// A policy to allow the printjob to delete itself after its done printing. enum RemovePolicy { DeleteWhenDone, ///< Delete the job when its done with printing. DoNotDelete ///< Keep the job around so it can be started again. }; /// Returns the printer that is used for this print job so others can alter the details of the print-job. QPrinter &printer() { return m_printer; } /// If this print job is used in combination with a printdialog the option widgets this method /// retuns will be shown in the print dialog. QList createOptionWidgets() const; int documentFirstPage() const { return 1; } int documentLastPage() const { return 1; } int documentCurrentPage() const { return 1; } QAbstractPrintDialog::PrintDialogOptions printDialogOptions() const; /** *@brief Check if the painter can print to the printer *@returns true if the print job can print to the given printer */ bool canPrint(); public Q_SLOTS: /** * This is called every time the job should be executed. * When called the document should be printed a new painter using the printer * of this printJob in order to honor the settings the user made on the printer. * canPrint() should be called before startPrinting to check if the painter can print * to the printer * @param removePolicy a policy that should be honored so the caller can make sure * this job doesn't leak memory after being used. */ void startPrinting(RemovePolicy removePolicy = DoNotDelete); private: KisImageWSP m_image; QPrinter m_printer; }; #endif diff --git a/krita/ui/KisTemplateCreateDia.h b/krita/ui/KisTemplateCreateDia.h index 0f6275c78e7..218c87ee043 100644 --- a/krita/ui/KisTemplateCreateDia.h +++ b/krita/ui/KisTemplateCreateDia.h @@ -1,73 +1,73 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Reginald Stadlbauer 2000 Werner Trobin 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_TEMPLATE_CREATE_DIA_H #define KIS_TEMPLATE_CREATE_DIA_H #include -#include "krita_export.h" +#include "kritaui_export.h" class QString; class QPixmap; class KComponentData; class KisDocument; class KisTemplateCreateDiaPrivate; /**************************************************************************** * * Class: koTemplateCreateDia * ****************************************************************************/ class KRITAUI_EXPORT KisTemplateCreateDia : public KDialog { Q_OBJECT private: KisTemplateCreateDia(const QString &templatesResourcePath, const KComponentData &instance, const QString &filePath, const QPixmap &thumbnail, QWidget *parent=0 ); ~KisTemplateCreateDia(); public: static void createTemplate(const QString &templatesResourcePath, const char *suffix, const KComponentData &componentData, KisDocument *document, QWidget *parent = 0); private Q_SLOTS: void slotOk(); void slotDefault(); void slotCustom(); void slotSelect(); void slotNameChanged(const QString &name); void slotAddGroup(); void slotRemove(); void slotSelectionChanged(); private: void updatePixmap(); void fillGroupTree(); private: KisTemplateCreateDiaPrivate * const d; }; #endif diff --git a/krita/ui/KisTemplateGroup.h b/krita/ui/KisTemplateGroup.h index 39121a7a6c0..acfb2fc953c 100644 --- a/krita/ui/KisTemplateGroup.h +++ b/krita/ui/KisTemplateGroup.h @@ -1,78 +1,78 @@ /* This file is part of the KDE project Copyright (C) 2000 Werner Trobin 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_TEMPLATE_GROUP_H #define KIS_TEMPLATE_GROUP_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KisTemplate; class KRITAUI_EXPORT KisTemplateGroup { public: explicit KisTemplateGroup(const QString &name, const QString &dir = QString(), int _sortingWeight = 0, bool touched = false); ~KisTemplateGroup(); QString name() const { return m_name; } QStringList dirs() const { return m_dirs; } void addDir(const QString &dir) { m_dirs.append(dir); m_touched = true; } int sortingWeight() const { return m_sortingWeight; } void setSortingWeight(int weight) { m_sortingWeight = weight; } /// If all children are hidden, we are hidden too bool isHidden() const; /// if we should hide, we hide all the children void setHidden(bool hidden = true) const; QList templates() const { return m_templates; } bool add(KisTemplate *t, bool force = false, bool touch = true); KisTemplate *find(const QString &name) const; bool touched() const { return m_touched; } private: QString m_name; QStringList m_dirs; QList m_templates; mutable bool m_touched; int m_sortingWeight; }; #endif diff --git a/krita/ui/KisTemplateTree.h b/krita/ui/KisTemplateTree.h index a8ef11c0f90..06e8ab06ef2 100644 --- a/krita/ui/KisTemplateTree.h +++ b/krita/ui/KisTemplateTree.h @@ -1,73 +1,73 @@ /* This file is part of the KDE project Copyright (C) 2000 Werner Trobin 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_TEMPLATE_TREE_H #define KIS_TEMPLATE_TREE_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KisTemplate; class KisTemplateGroup; class KRITAUI_EXPORT KisTemplateTree { public: KisTemplateTree(const QString &templatesResourcePath, const KComponentData &instance, bool readTree = false); ~KisTemplateTree(); QString templatesResourcePath() const { return m_templatesResourcePath; } KComponentData componentData() const { return m_componentData; } void readTemplateTree(); void writeTemplateTree(); void add(KisTemplateGroup *g); KisTemplateGroup *find(const QString &name) const; KisTemplateGroup *defaultGroup() const { return m_defaultGroup; } KisTemplate *defaultTemplate() const { return m_defaultTemplate; } QList groups () const { return m_groups; } private: void readGroups(); void readTemplates(); void writeTemplate(KisTemplate *t, KisTemplateGroup *group, const QString &localDir); QString m_templatesResourcePath; KComponentData m_componentData; QList m_groups; KisTemplateGroup *m_defaultGroup; KisTemplate *m_defaultTemplate; }; #endif diff --git a/krita/ui/KisView.cpp b/krita/ui/KisView.cpp index 8837bc80323..2ec5858695c 100644 --- a/krita/ui/KisView.cpp +++ b/krita/ui/KisView.cpp @@ -1,1047 +1,1047 @@ /* * Copyright (C) 2014 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "KisView.h" #include "KisView_p.h" #include #include #include #include "KoDocumentInfo.h" #include "KoPageLayout.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_canvas_controller.h" #include "kis_canvas_resource_provider.h" #include "kis_config.h" #include "KisDocument.h" #include "kis_image_manager.h" #include "KisMainWindow.h" #include "kis_mimedata.h" #include "kis_mirror_axis.h" #include "kis_node_commands_adapter.h" #include "kis_node_manager.h" #include "KisPart.h" #include "KisPrintJob.h" #include "kis_shape_controller.h" #include "kis_tool_freehand.h" #include "KisUndoStackAction.h" #include "KisViewManager.h" #include "kis_zoom_manager.h" #include "kis_composite_progress_proxy.h" #include "kis_statusbar.h" #include "kis_painting_assistants_decoration.h" #include "kis_progress_widget.h" #include "kis_signal_compressor.h" #include "kis_filter_manager.h" #include "krita/gemini/ViewModeSwitchEvent.h" //static QString KisView::newObjectName() { static int s_viewIFNumber = 0; QString name; name.setNum(s_viewIFNumber++); name.prepend("view_"); return name; } bool KisView::s_firstView = true; class KisView::Private { public: Private() : undo(0) , redo(0) , viewConverter(0) , canvasController(0) , canvas(0) , zoomManager(0) , viewManager(0) , actionCollection(0) , paintingAssistantsDecoration(0) , isCurrent(false) , showFloatingMessage(true) , floatingMessageCompressor(100, KisSignalCompressor::POSTPONE) { tempActiveWidget = 0; documentDeleted = false; } ~Private() { if (canvasController) { KoToolManager::instance()->removeCanvasController(canvasController); } delete zoomManager; delete canvasController; delete canvas; delete viewConverter; } KisUndoStackAction *undo; KisUndoStackAction *redo; class StatusBarItem; QList statusBarItems; // Our statusbar items bool inOperation; //in the middle of an operation (no screen refreshing)? QPointer document; // our KisDocument QWidget *tempActiveWidget; bool documentDeleted; // true when document gets deleted [can't use document==0 // since this only happens in ~QObject, and views // get deleted by ~KisDocument]. KisCoordinatesConverter *viewConverter; KisCanvasController *canvasController; KisCanvas2 *canvas; KisZoomManager *zoomManager; KisViewManager *viewManager; KisNodeSP currentNode; KActionCollection* actionCollection; KisPaintingAssistantsDecoration *paintingAssistantsDecoration; bool isCurrent; bool showFloatingMessage; QPointer savedFloatingMessage; KisSignalCompressor floatingMessageCompressor; // Hmm sorry for polluting the private class with such a big inner class. // At the beginning it was a little struct :) class StatusBarItem { public: StatusBarItem() // for QValueList : m_widget(0), m_connected(false), m_hidden(false) {} StatusBarItem(QWidget * widget, int stretch, bool permanent) : m_widget(widget), m_stretch(stretch), m_permanent(permanent), m_connected(false), m_hidden(false) {} bool operator==(const StatusBarItem& rhs) { return m_widget == rhs.m_widget; } bool operator!=(const StatusBarItem& rhs) { return m_widget != rhs.m_widget; } QWidget * widget() const { return m_widget; } void ensureItemShown(KStatusBar * sb) { Q_ASSERT(m_widget); if (!m_connected) { if (m_permanent) sb->addPermanentWidget(m_widget, m_stretch); else sb->addWidget(m_widget, m_stretch); if(!m_hidden) m_widget->show(); m_connected = true; } } void ensureItemHidden(KStatusBar * sb) { if (m_connected) { m_hidden = m_widget->isHidden(); sb->removeWidget(m_widget); m_widget->hide(); m_connected = false; } } private: QWidget * m_widget; int m_stretch; bool m_permanent; bool m_connected; bool m_hidden; }; }; #if defined HAVE_OPENGL && defined Q_OS_WIN #include #endif KisView::KisView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent) : QWidget(parent) , d(new Private) { Q_ASSERT(document); connect(document, SIGNAL(titleModified(QString,bool)), this, SIGNAL(titleModified(QString,bool))); setObjectName(newObjectName()); d->document = document; d->actionCollection = actionCollection; setFocusPolicy(Qt::StrongFocus); d->undo = new KisUndoStackAction(d->document->undoStack(), KisUndoStackAction::UNDO); d->redo = new KisUndoStackAction(d->document->undoStack(), KisUndoStackAction::RED0); KStatusBar * sb = statusBar(); if (sb) { // No statusbar in e.g. konqueror connect(d->document, SIGNAL(statusBarMessage(const QString&)), this, SLOT(slotActionStatusText(const QString&))); connect(d->document, SIGNAL(clearStatusBarMessage()), this, SLOT(slotClearStatusText())); } d->viewConverter = new KisCoordinatesConverter(); KisConfig cfg; d->canvasController = new KisCanvasController(this, d->actionCollection); d->canvasController->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); d->canvasController->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); d->canvasController->setDrawShadow(false); d->canvasController->setCanvasMode(KoCanvasController::Infinite); d->canvasController->setVastScrolling(cfg.vastScrolling()); KConfigGroup grp(KGlobal::config(), "krita/crashprevention"); if (grp.readEntry("CreatingCanvas", false)) { cfg.setUseOpenGL(false); } if (cfg.canvasState() == "OPENGL_FAILED") { cfg.setUseOpenGL(false); } grp.writeEntry("CreatingCanvas", true); grp.sync(); d->canvas = new KisCanvas2(d->viewConverter, resourceManager, this, document->shapeController()); /** * Warn about Intel's broken video drivers */ #if defined HAVE_OPENGL && defined Q_OS_WIN QString renderer((const char*)glGetString(GL_RENDERER)); if (cfg.useOpenGL() && renderer.startsWith("Intel") && !cfg.readEntry("WarnedAboutIntel", false)) { QMessageBox::information(0, i18nc("@title:window", "Krita: Warning"), i18n("You have an Intel(R) HD Graphics video adapter.\n" "If you experience problems like a black or blank screen," "please update your display driver to the latest version.\n\n" "You can also disable OpenGL rendering in Krita's Settings.\n")); cfg.writeEntry("WarnedAboutIntel", true); } #endif /* defined HAVE_OPENGL && defined Q_OS_WIN32 */ grp.writeEntry("CreatingCanvas", false); grp.sync(); d->canvasController->setCanvas(d->canvas); Q_ASSERT(d->canvasController); d->zoomManager = new KisZoomManager(this, d->viewConverter, d->canvasController); d->zoomManager->setup(d->actionCollection); connect(d->canvasController, SIGNAL(documentSizeChanged()), d->zoomManager, SLOT(slotScrollAreaSizeChanged())); setAcceptDrops(true); connect(d->document, SIGNAL(sigLoadingFinished()), this, SLOT(slotLoadingFinished())); connect(d->document, SIGNAL(sigSavingFinished()), this, SLOT(slotSavingFinished())); d->paintingAssistantsDecoration = new KisPaintingAssistantsDecoration(this); d->canvas->addDecoration(d->paintingAssistantsDecoration); d->showFloatingMessage = cfg.showCanvasMessages(); } KisView::~KisView() { if (d->viewManager->filterManager()->isStrokeRunning()) { d->viewManager->filterManager()->cancel(); } KisPart::instance()->removeView(this); delete d; } void KisView::notifyCurrentStateChanged(bool isCurrent) { d->isCurrent = isCurrent; if (!d->isCurrent && d->savedFloatingMessage) { d->savedFloatingMessage->removeMessage(); } } void KisView::setShowFloatingMessage(bool show) { d->showFloatingMessage = show; } void KisView::showFloatingMessageImpl(const QString message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment) { if (!d->viewManager) return; if(d->isCurrent && d->showFloatingMessage && d->viewManager->qtMainWindow()) { if (d->savedFloatingMessage) { d->savedFloatingMessage->tryOverrideMessage(message, icon, timeout, priority, alignment); } else { d->savedFloatingMessage = new KisFloatingMessage(message, this->canvasBase()->canvasWidget(), false, timeout, priority, alignment); d->savedFloatingMessage->setShowOverParent(true); d->savedFloatingMessage->setIcon(icon); connect(&d->floatingMessageCompressor, SIGNAL(timeout()), d->savedFloatingMessage, SLOT(showMessage())); d->floatingMessageCompressor.start(); } } } void KisView::setViewManager(KisViewManager *view) { d->viewManager = view; connect(canvasController(), SIGNAL(toolOptionWidgetsChanged(QList >)), d->viewManager->mainWindow(), SLOT(newOptionWidgets(QList >))); KoToolManager::instance()->addController(d->canvasController); KoToolManager::instance()->registerTools(d->actionCollection, d->canvasController); dynamic_cast(d->document->shapeController())->setInitialShapeForCanvas(d->canvas); if (resourceProvider()) { resourceProvider()->slotImageSizeChanged(); } if (d->viewManager && d->viewManager->nodeManager()) { d->viewManager->nodeManager()->nodesUpdated(); } connect(image(), SIGNAL(sigSizeChanged(const QPointF&, const QPointF&)), this, SLOT(slotImageSizeChanged(const QPointF&, const QPointF&))); connect(image(), SIGNAL(sigResolutionChanged(double,double)), this, SLOT(slotImageResolutionChanged())); /* * WARNING: Currently we access the global progress bar in two ways: * connecting to composite progress proxy (strokes) and creating * progress updaters. The latter way should be deprecated in favour * of displaying the status of the global strokes queue */ image()->compositeProgressProxy()->addProxy(d->viewManager->statusBar()->progress()->progressProxy()); connect(d->viewManager->statusBar()->progress(), SIGNAL(sigCancellationRequested()), image(), SLOT(requestStrokeCancellation())); d->viewManager->updateGUI(); KoToolManager::instance()->switchToolRequested("KritaShape/KisToolBrush"); } KisViewManager* KisView::viewManager() const { return d->viewManager; } KAction *KisView::undoAction() const { return d->undo; } KAction *KisView::redoAction() const { return d->redo; } KoZoomController *KisView::zoomController() const { return d->zoomManager->zoomController(); } KisZoomManager *KisView::zoomManager() const { return d->zoomManager; } KisCanvasController *KisView::canvasController() const { return d->canvasController; } KisCanvasResourceProvider *KisView::resourceProvider() const { if (d->viewManager) { return d->viewManager->resourceProvider(); } return 0; } KisInputManager* KisView::globalInputManager() const { return d->viewManager ? d->viewManager->inputManager() : 0; } KisCanvas2 *KisView::canvasBase() const { return d->canvas; } KisImageWSP KisView::image() const { if (d->document) { return d->document->image(); } return 0; } KisCoordinatesConverter *KisView::viewConverter() const { return d->viewConverter; } void KisView::dragEnterEvent(QDragEnterEvent *event) { if (event->mimeData()->hasImage() || event->mimeData()->hasUrls() || event->mimeData()->hasFormat("application/x-krita-node")) { event->accept(); // activate view if it should accept the drop this->setFocus(); } else { event->ignore(); } } void KisView::dropEvent(QDropEvent *event) { - KisImageSP kisimage = image(); + KisImageWSP kisimage = image(); Q_ASSERT(kisimage); QPoint cursorPos = canvasBase()->coordinatesConverter()->widgetToImage(event->pos()).toPoint(); QRect imageBounds = kisimage->bounds(); QPoint pasteCenter; bool forceRecenter; if (event->keyboardModifiers() & Qt::ShiftModifier && imageBounds.contains(cursorPos)) { pasteCenter = cursorPos; forceRecenter = true; } else { pasteCenter = imageBounds.center(); forceRecenter = false; } if (event->mimeData()->hasFormat("application/x-krita-node") || event->mimeData()->hasImage()) { KisShapeController *kritaShapeController = dynamic_cast(d->document->shapeController()); QList nodes = KisMimeData::loadNodes(event->mimeData(), imageBounds, pasteCenter, forceRecenter, kisimage, kritaShapeController); foreach(KisNodeSP node, nodes) { if (node) { KisNodeCommandsAdapter adapter(viewManager()); if (!viewManager()->nodeManager()->activeLayer()) { adapter.addNode(node, kisimage->rootLayer() , 0); } else { adapter.addNode(node, viewManager()->nodeManager()->activeLayer()->parent(), viewManager()->nodeManager()->activeLayer()); } } } } else if (event->mimeData()->hasUrls()) { QList urls = event->mimeData()->urls(); if (urls.length() > 0) { KMenu popup; popup.setObjectName("drop_popup"); QAction *insertAsNewLayer = new KAction(i18n("Insert as New Layer"), &popup); QAction *insertManyLayers = new KAction(i18n("Insert Many Layers"), &popup); QAction *openInNewDocument = new KAction(i18n("Open in New Document"), &popup); QAction *openManyDocuments = new KAction(i18n("Open Many Documents"), &popup); QAction *cancel = new KAction(i18n("Cancel"), &popup); popup.addAction(insertAsNewLayer); popup.addAction(openInNewDocument); popup.addAction(insertManyLayers); popup.addAction(openManyDocuments); insertAsNewLayer->setEnabled(image() && urls.count() == 1); openInNewDocument->setEnabled(urls.count() == 1); insertManyLayers->setEnabled(image() && urls.count() > 1); openManyDocuments->setEnabled(urls.count() > 1); popup.addSeparator(); popup.addAction(cancel); QAction *action = popup.exec(QCursor::pos()); if (action != 0 && action != cancel) { foreach(const QUrl &url, urls) { if (action == insertAsNewLayer || action == insertManyLayers) { d->viewManager->imageManager()->importImage(KUrl(url)); activateWindow(); } else { Q_ASSERT(action == openInNewDocument || action == openManyDocuments); if (mainWindow()) { mainWindow()->openDocument(url); } } } } } } } KisDocument *KisView::document() const { return d->document; } void KisView::setDocument(KisDocument *document) { d->document->disconnect(this); d->document = document; KStatusBar *sb = statusBar(); if (sb) { // No statusbar in e.g. konqueror connect(d->document, SIGNAL(statusBarMessage(const QString&)), this, SLOT(slotActionStatusText(const QString&))); connect(d->document, SIGNAL(clearStatusBarMessage()), this, SLOT(slotClearStatusText())); } } void KisView::setDocumentDeleted() { d->documentDeleted = true; } void KisView::addStatusBarItem(QWidget * widget, int stretch, bool permanent) { Private::StatusBarItem item(widget, stretch, permanent); KStatusBar * sb = statusBar(); if (sb) { item.ensureItemShown(sb); } d->statusBarItems.append(item); } void KisView::removeStatusBarItem(QWidget *widget) { KStatusBar *sb = statusBar(); int itemCount = d->statusBarItems.count(); for (int i = itemCount-1; i >= 0; --i) { Private::StatusBarItem &sbItem = d->statusBarItems[i]; if (sbItem.widget() == widget) { if (sb) { sbItem.ensureItemHidden(sb); } d->statusBarItems.removeOne(sbItem); break; } } } KoPageLayout KisView::pageLayout() const { return document()->pageLayout(); } QPrintDialog *KisView::createPrintDialog(KisPrintJob *printJob, QWidget *parent) { QPrintDialog *printDialog = KdePrint::createPrintDialog(&printJob->printer(), printJob->createOptionWidgets(), parent); printDialog->setMinMax(printJob->printer().fromPage(), printJob->printer().toPage()); printDialog->setEnabledOptions(printJob->printDialogOptions()); return printDialog; } KisMainWindow * KisView::mainWindow() const { return dynamic_cast(window()); } KStatusBar * KisView::statusBar() const { KisMainWindow *mw = mainWindow(); return mw ? mw->statusBar() : 0; } void KisView::slotActionStatusText(const QString &text) { KStatusBar *sb = statusBar(); if (sb) sb->showMessage(text); } void KisView::slotClearStatusText() { KStatusBar *sb = statusBar(); if (sb) sb->clearMessage(); } QList KisView::createChangeUnitActions(bool addPixelUnit) { UnitActionGroup* unitActions = new UnitActionGroup(d->document, addPixelUnit, this); return unitActions->actions(); } bool KisView::event(QEvent *event) { switch(static_cast(event->type())) { case ViewModeSwitchEvent::AboutToSwitchViewModeEvent: { ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); d->canvasController->setFocus(); qApp->processEvents(); KisCanvasResourceProvider* provider = resourceProvider(); syncObject->backgroundColor = provider->bgColor(); syncObject->foregroundColor = provider->fgColor(); syncObject->exposure = provider->HDRExposure(); syncObject->gamma = provider->HDRGamma(); syncObject->compositeOp = provider->currentCompositeOp(); syncObject->pattern = provider->currentPattern(); syncObject->gradient = provider->currentGradient(); syncObject->node = provider->currentNode(); syncObject->paintOp = provider->currentPreset(); syncObject->opacity = provider->opacity(); syncObject->globalAlphaLock = provider->globalAlphaLock(); syncObject->documentOffset = d->canvasController->scrollBarValue() - pos(); syncObject->zoomLevel = zoomController()->zoomAction()->effectiveZoom(); syncObject->rotationAngle = canvasBase()->rotationAngle(); syncObject->activeToolId = KoToolManager::instance()->activeToolId(); syncObject->gridData = &document()->gridData(); syncObject->mirrorHorizontal = provider->mirrorHorizontal(); syncObject->mirrorVertical = provider->mirrorVertical(); syncObject->mirrorAxesCenter = provider->resourceManager()->resource(KisCanvasResourceProvider::MirrorAxesCenter).toPointF(); KisToolFreehand* tool = qobject_cast(KoToolManager::instance()->toolById(canvasBase(), syncObject->activeToolId)); if(tool) { syncObject->smoothingOptions = tool->smoothingOptions(); } syncObject->initialized = true; QMainWindow* mainWindow = qobject_cast(qApp->activeWindow()); if(mainWindow) { QList dockWidgets = mainWindow->findChildren(); foreach(QDockWidget* widget, dockWidgets) { if (widget->isFloating()) { widget->hide(); } } } return true; } case ViewModeSwitchEvent::SwitchedToDesktopModeEvent: { ViewModeSynchronisationObject* syncObject = static_cast(event)->synchronisationObject(); d->canvasController->setFocus(); qApp->processEvents(); if(syncObject->initialized) { KisCanvasResourceProvider* provider = resourceProvider(); provider->resourceManager()->setResource(KisCanvasResourceProvider::MirrorAxesCenter, syncObject->mirrorAxesCenter); if (provider->mirrorHorizontal() != syncObject->mirrorHorizontal) { QAction* mirrorAction = d->actionCollection->action("hmirror_action"); mirrorAction->setChecked(syncObject->mirrorHorizontal); provider->setMirrorHorizontal(syncObject->mirrorHorizontal); } if (provider->mirrorVertical() != syncObject->mirrorVertical) { QAction* mirrorAction = d->actionCollection->action("vmirror_action"); mirrorAction->setChecked(syncObject->mirrorVertical); provider->setMirrorVertical(syncObject->mirrorVertical); } provider->setPaintOpPreset(syncObject->paintOp); qApp->processEvents(); KoToolManager::instance()->switchToolRequested(syncObject->activeToolId); qApp->processEvents(); KisPaintOpPresetSP preset = canvasBase()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); preset->settings()->setProperty("CompositeOp", syncObject->compositeOp); if(preset->settings()->hasProperty("OpacityValue")) preset->settings()->setProperty("OpacityValue", syncObject->opacity); provider->setPaintOpPreset(preset); provider->setBGColor(syncObject->backgroundColor); provider->setFGColor(syncObject->foregroundColor); provider->setHDRExposure(syncObject->exposure); provider->setHDRGamma(syncObject->gamma); provider->slotPatternActivated(syncObject->pattern); provider->slotGradientActivated(syncObject->gradient); provider->slotNodeActivated(syncObject->node); provider->setOpacity(syncObject->opacity); provider->setGlobalAlphaLock(syncObject->globalAlphaLock); provider->setCurrentCompositeOp(syncObject->compositeOp); document()->gridData().setGrid(syncObject->gridData->gridX(), syncObject->gridData->gridY()); document()->gridData().setGridColor(syncObject->gridData->gridColor()); document()->gridData().setPaintGridInBackground(syncObject->gridData->paintGridInBackground()); document()->gridData().setShowGrid(syncObject->gridData->showGrid()); document()->gridData().setSnapToGrid(syncObject->gridData->snapToGrid()); d->actionCollection->action("zoom_in")->trigger(); qApp->processEvents(); QMainWindow* mainWindow = qobject_cast(qApp->activeWindow()); if(mainWindow) { QList dockWidgets = mainWindow->findChildren(); foreach(QDockWidget* widget, dockWidgets) { if (widget->isFloating()) { widget->show(); } } } zoomController()->setZoom(KoZoomMode::ZOOM_CONSTANT, syncObject->zoomLevel); d->canvasController->rotateCanvas(syncObject->rotationAngle - canvasBase()->rotationAngle()); QPoint newOffset = syncObject->documentOffset + pos(); qApp->processEvents(); d->canvasController->setScrollBarValue(newOffset); KisToolFreehand* tool = qobject_cast(KoToolManager::instance()->toolById(canvasBase(), syncObject->activeToolId)); if(tool && syncObject->smoothingOptions) { tool->smoothingOptions()->setSmoothingType(syncObject->smoothingOptions->smoothingType()); tool->smoothingOptions()->setSmoothPressure(syncObject->smoothingOptions->smoothPressure()); tool->smoothingOptions()->setTailAggressiveness(syncObject->smoothingOptions->tailAggressiveness()); tool->smoothingOptions()->setUseScalableDistance(syncObject->smoothingOptions->useScalableDistance()); tool->smoothingOptions()->setSmoothnessDistance(syncObject->smoothingOptions->smoothnessDistance()); tool->smoothingOptions()->setUseDelayDistance(syncObject->smoothingOptions->useDelayDistance()); tool->smoothingOptions()->setDelayDistance(syncObject->smoothingOptions->delayDistance()); tool->smoothingOptions()->setFinishStabilizedCurve(syncObject->smoothingOptions->finishStabilizedCurve()); tool->smoothingOptions()->setStabilizeSensors(syncObject->smoothingOptions->stabilizeSensors()); tool->updateSettingsViews(); } } return true; } default: break; } return QWidget::event( event ); } void KisView::closeEvent(QCloseEvent *event) { // Check whether we're the last view int viewCount = KisPart::instance()->viewCount(document()); if (viewCount > 1) { // there are others still, so don't bother the user event->accept(); return; } if (queryClose()) { d->viewManager->removeStatusBarItem(zoomManager()->zoomActionWidget()); event->accept(); return; } event->ignore(); } bool KisView::queryClose() { if (!document()) return true; if (document()->isModified()) { QString name; if (document()->documentInfo()) { name = document()->documentInfo()->aboutInfo("title"); } if (name.isEmpty()) name = document()->url().fileName(); if (name.isEmpty()) name = i18n("Untitled"); int res = QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("

The document '%1' has been modified.

Do you want to save it?

", name), QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel, QMessageBox::Yes); switch (res) { case QMessageBox::Yes : { bool isNative = (document()->outputMimeType() == document()->nativeFormatMimeType()); if (!viewManager()->mainWindow()->saveDocument(document(), !isNative)) return false; break; } case QMessageBox::No : document()->removeAutoSaveFiles(); document()->setModified(false); // Now when queryClose() is called by closeEvent it won't do anything. break; default : // case QMessageBox::Cancel : return false; } } return true; } void KisView::resetImageSizeAndScroll(bool changeCentering, const QPointF oldImageStillPoint, const QPointF newImageStillPoint) { const KisCoordinatesConverter *converter = d->canvas->coordinatesConverter(); QPointF oldPreferredCenter = d->canvasController->preferredCenter(); /** * Calculating the still point in old coordinates depending on the * parameters given */ QPointF oldStillPoint; if (changeCentering) { oldStillPoint = converter->imageToWidget(oldImageStillPoint) + converter->documentOffset(); } else { QSize oldDocumentSize = d->canvasController->documentSize(); oldStillPoint = QPointF(0.5 * oldDocumentSize.width(), 0.5 * oldDocumentSize.height()); } /** * Updating the document size */ QSizeF size(image()->width() / image()->xRes(), image()->height() / image()->yRes()); KoZoomController *zc = d->zoomManager->zoomController(); zc->setZoom(KoZoomMode::ZOOM_CONSTANT, zc->zoomAction()->effectiveZoom()); zc->setPageSize(size); zc->setDocumentSize(size, true); /** * Calculating the still point in new coordinates depending on the * parameters given */ QPointF newStillPoint; if (changeCentering) { newStillPoint = converter->imageToWidget(newImageStillPoint) + converter->documentOffset(); } else { QSize newDocumentSize = d->canvasController->documentSize(); newStillPoint = QPointF(0.5 * newDocumentSize.width(), 0.5 * newDocumentSize.height()); } d->canvasController->setPreferredCenter(oldPreferredCenter - oldStillPoint + newStillPoint); } void KisView::setCurrentNode(KisNodeSP node) { d->currentNode = node; } KisNodeSP KisView::currentNode() const { return d->currentNode; } KisLayerSP KisView::currentLayer() const { KisNodeSP node; KisMaskSP mask = currentMask(); if (mask) { node = mask->parent(); } else { node = d->currentNode; } return dynamic_cast(node.data()); } KisMaskSP KisView::currentMask() const { return dynamic_cast(d->currentNode.data()); } KisSelectionSP KisView::selection() { KisLayerSP layer = currentLayer(); if (layer) return layer->selection(); // falls through to the global // selection, or 0 in the end if (image()) { return image()->globalSelection(); } return 0; } void KisView::slotLoadingFinished() { if (!document()) return; /** * Cold-start of image size/resolution signals */ slotImageResolutionChanged(); if (image()->locked()) { // If this is the first view on the image, the image will have been locked // so unlock it. image()->blockSignals(false); image()->unlock(); } if (d->paintingAssistantsDecoration){ foreach(KisPaintingAssistant* assist, document()->preLoadedAssistants()){ d->paintingAssistantsDecoration->addAssistant(assist); } d->paintingAssistantsDecoration->setVisible(true); } canvasBase()->initializeImage(); /** * Dirty hack alert */ d->zoomManager->zoomController()->setAspectMode(true); if (viewConverter()) { viewConverter()->setZoomMode(KoZoomMode::ZOOM_PAGE); } connect(image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), this, SIGNAL(sigColorSpaceChanged(const KoColorSpace*))); connect(image(), SIGNAL(sigProfileChanged(const KoColorProfile*)), this, SIGNAL(sigProfileChanged(const KoColorProfile*))); connect(image(), SIGNAL(sigSizeChanged(QPointF,QPointF)), this, SIGNAL(sigSizeChanged(QPointF,QPointF))); KisNodeSP activeNode = document()->preActivatedNode(); document()->setPreActivatedNode(0); // to make sure that we don't keep a reference to a layer the user can later delete. if (!activeNode) { activeNode = image()->rootLayer()->lastChild(); } while (activeNode && !activeNode->inherits("KisLayer")) { activeNode = activeNode->prevSibling(); } setCurrentNode(activeNode); } void KisView::slotSavingFinished() { if (d->viewManager && d->viewManager->mainWindow()) { d->viewManager->mainWindow()->updateCaption(); } } KisPrintJob * KisView::createPrintJob() { return new KisPrintJob(image()); } void KisView::slotImageResolutionChanged() { resetImageSizeAndScroll(false); zoomManager()->updateGUI(); // update KoUnit value for the document if (resourceProvider()) { resourceProvider()->resourceManager()-> setResource(KoCanvasResourceManager::Unit, d->canvas->unit()); } } void KisView::slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint) { resetImageSizeAndScroll(true, oldStillPoint, newStillPoint); zoomManager()->updateGUI(); } #include #include diff --git a/krita/ui/KisView.h b/krita/ui/KisView.h index 53dfdf3149c..38a08603d4f 100644 --- a/krita/ui/KisView.h +++ b/krita/ui/KisView.h @@ -1,261 +1,261 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2007 Thomas Zander Copyright (C) 2010 Benjamin Port 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_VIEW_H #define KIS_VIEW_H #include #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include "widgets/kis_floating_message.h" class KisDocument; class KisMainWindow; class KisPrintJob; class KisCanvasController; class KisZoomManager; class KisCanvas2; class KisViewManager; class KisDocument; class KisCanvasResourceProvider; class KisCoordinatesConverter; class KisInputManager; class KoZoomController; class KoZoomController; struct KoPageLayout; class KoCanvasResourceManager; // KDE classes class KStatusBar; class KAction; class KActionCollection; // Qt classes class QDragEnterEvent; class QDropEvent; class QPrintDialog; class QCloseEvent; /** * This class is used to display a @ref KisDocument. * * Multiple views can be attached to one document at a time. */ class KRITAUI_EXPORT KisView : public QWidget { Q_OBJECT public: /** * Creates a new view for the document. */ KisView(KisDocument *document, KoCanvasResourceManager *resourceManager, KActionCollection *actionCollection, QWidget *parent = 0); ~KisView(); KAction *undoAction() const; KAction *redoAction() const; // Temporary while teasing apart view and mainwindow void setViewManager(KisViewManager *view); KisViewManager *viewManager() const; public: /** * Retrieves the document object of this view. */ KisDocument *document() const; /** * Reset the view to show the given document. */ void setDocument(KisDocument *document); /** * Tells this view that its document has got deleted (called internally) */ void setDocumentDeleted(); /** * In order to print the document represented by this view a new print job should * be constructed that is capable of doing the printing. * The default implementation returns 0, which silently cancels printing. */ KisPrintJob * createPrintJob(); /** * @return the page layout to be used for printing. * Default is the documents layout. * Reimplement if your application needs to use a different layout. */ KoPageLayout pageLayout() const; /** * Create a QPrintDialog based on the @p printJob */ QPrintDialog *createPrintDialog(KisPrintJob *printJob, QWidget *parent); /** * @return the KisMainWindow in which this view is currently. */ KisMainWindow * mainWindow() const; /** * @return the statusbar of the KisMainWindow in which this view is currently. */ KStatusBar * statusBar() const; /** * This adds a widget to the statusbar for this view. * If you use this method instead of using statusBar() directly, * KisView will take care of removing the items when the view GUI is deactivated * and readding them when it is reactivated. * The parameters are the same as QStatusBar::addWidget(). * * Note that you can't use KStatusBar methods (inserting text items by id). * But you can create a KStatusBarLabel with a dummy id instead, and use * it directly, to get the same look and feel. */ void addStatusBarItem(QWidget * widget, int stretch = 0, bool permanent = false); /** * Remove a widget from the statusbar for this view. */ void removeStatusBarItem(QWidget * widget); /** * Return the zoomController for this view. */ KoZoomController *zoomController() const; /// create a list of actions that when activated will change the unit on the document. QList createChangeUnitActions(bool addPixelUnit = false); public: /** * The zoommanager handles everything action-related to zooming */ KisZoomManager *zoomManager() const; /** * The CanvasController decorates the canvas with scrollbars * and knows where to start painting on the canvas widget, i.e., * the document offset. */ KisCanvasController *canvasController() const; KisCanvasResourceProvider *resourceProvider() const; /** * Filters events and sends them to canvas actions. Shared * among all the views/canvases * * NOTE: May be null while initialization! */ KisInputManager* globalInputManager() const; /** * @return the canvas object */ KisCanvas2 *canvasBase() const; /// @return the image this view is displaying KisImageWSP image() const; KisCoordinatesConverter *viewConverter() const; void resetImageSizeAndScroll(bool changeCentering, const QPointF oldImageStillPoint = QPointF(), const QPointF newImageStillPoint = QPointF()); void setCurrentNode(KisNodeSP node); KisNodeSP currentNode() const; KisLayerSP currentLayer() const; KisMaskSP currentMask() const; /// Convenience method to get at the active selection (the /// selection of the current layer, or, if that does not exist, /// the global selection. KisSelectionSP selection(); void notifyCurrentStateChanged(bool isCurrent); void setShowFloatingMessage(bool show); void showFloatingMessageImpl(const QString message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment); public Q_SLOTS: /** * Display a message in the status bar (calls QStatusBar::message()) * @todo rename to something more generic */ void slotActionStatusText(const QString &text); /** * End of the message in the status bar (calls QStatusBar::clear()) * @todo rename to something more generic */ void slotClearStatusText(); bool queryClose(); Q_SIGNALS: // From KisImage void sigSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint); void sigProfileChanged(const KoColorProfile * profile); void sigColorSpaceChanged(const KoColorSpace* cs); void titleModified(QString,bool); protected: // QWidget overrides void dragEnterEvent(QDragEnterEvent * event); void dropEvent(QDropEvent * event); bool event( QEvent* event ); void closeEvent(QCloseEvent *event); /** * Generate a name for this view. */ QString newObjectName(); public Q_SLOTS: void slotLoadingFinished(); void slotSavingFinished(); void slotImageResolutionChanged(); void slotImageSizeChanged(const QPointF &oldStillPoint, const QPointF &newStillPoint); private: class Private; Private * const d; static bool s_firstView; }; #endif diff --git a/krita/ui/KisViewManager.cpp b/krita/ui/KisViewManager.cpp index 5a2598c988e..60220e7d286 100644 --- a/krita/ui/KisViewManager.cpp +++ b/krita/ui/KisViewManager.cpp @@ -1,1374 +1,1352 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 1999 Matthias Elter * 1999 Michael Koch * 1999 Carsten Pfeiffer * 2002 Patrick Julien * 2003-2011 Boudewijn Rempt * 2004 Clarence Dang * 2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include #include "KisViewManager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "input/kis_input_manager.h" #include "canvas/kis_canvas2.h" #include "canvas/kis_canvas_controller.h" #include "canvas/kis_grid_manager.h" #include "canvas/kis_perspective_grid_manager.h" #include "dialogs/kis_dlg_blacklist_cleanup.h" #include "input/kis_input_profile_manager.h" #include "kis_action_manager.h" #include "kis_action.h" #include "kis_canvas_controls_manager.h" #include "kis_canvas_resource_provider.h" #include "kis_composite_progress_proxy.h" #include "kis_config.h" #include "kis_config_notifier.h" #include "kis_control_frame.h" #include "kis_coordinates_converter.h" #include #include "KisDocument.h" #include "kis_factory2.h" #include "kis_favorite_resource_manager.h" #include "kis_filter_manager.h" #include "kis_group_layer.h" #include #include "kis_image_manager.h" #include #include "KisMainWindow.h" #include "kis_mainwindow_observer.h" #include "kis_mask_manager.h" #include "kis_mimedata.h" #include "kis_mirror_manager.h" #include "kis_node_commands_adapter.h" #include "kis_node.h" #include "kis_node_manager.h" #include "kis_painting_assistants_manager.h" #include #include "kis_paintop_box.h" #include #include "KisPart.h" #include "KisPrintJob.h" #include "kis_progress_widget.h" #include "kis_resource_server_provider.h" #include "kis_selection.h" #include "kis_selection_manager.h" #include "kis_shape_controller.h" #include "kis_shape_layer.h" #include #include "kis_statusbar.h" #include #include #include "kis_tooltip_manager.h" #include #include "KisView.h" #include "kis_zoom_manager.h" #include "kra/kis_kra_loader.h" #include "widgets/kis_floating_message.h" #include "kis_signal_auto_connection.h" +#include "kis_icon_utils.h" class StatusBarItem { public: StatusBarItem() // for QValueList : m_widget(0), m_connected(false), m_hidden(false) {} StatusBarItem(QWidget * widget, int stretch, bool permanent) : m_widget(widget), m_stretch(stretch), m_permanent(permanent), m_connected(false), m_hidden(false) {} bool operator==(const StatusBarItem& rhs) { return m_widget == rhs.m_widget; } bool operator!=(const StatusBarItem& rhs) { return m_widget != rhs.m_widget; } QWidget * widget() const { return m_widget; } void ensureItemShown(KStatusBar * sb) { Q_ASSERT(m_widget); if (!m_connected) { if (m_permanent) sb->addPermanentWidget(m_widget, m_stretch); else sb->addWidget(m_widget, m_stretch); if(!m_hidden) m_widget->show(); m_connected = true; } } void ensureItemHidden(KStatusBar * sb) { if (m_connected) { m_hidden = m_widget->isHidden(); sb->removeWidget(m_widget); m_widget->hide(); m_connected = false; } } private: QWidget * m_widget; int m_stretch; bool m_permanent; bool m_connected; bool m_hidden; }; class BlockingUserInputEventFilter : public QObject { bool eventFilter(QObject *watched, QEvent *event) { Q_UNUSED(watched); if(dynamic_cast(event) || dynamic_cast(event) || dynamic_cast(event)) { return true; } else { return false; } } }; class KisViewManager::KisViewManagerPrivate { public: KisViewManagerPrivate() : filterManager(0) , statusBar(0) , createTemplate(0) , saveIncremental(0) , saveIncrementalBackup(0) , openResourcesDirectory(0) , rotateCanvasRight(0) , rotateCanvasLeft(0) , wrapAroundAction(0) , showRulersAction(0) , zoomTo100pct(0) , zoomIn(0) , zoomOut(0) , showGuidesAction(0) , selectionManager(0) , controlFrame(0) , nodeManager(0) , imageManager(0) , gridManager(0) , perspectiveGridManager(0) , paintingAssistantsManager(0) , actionManager(0) , mainWindow(0) , showFloatingMessage(true) , currentImageView(0) , canvasResourceProvider(0) , canvasResourceManager(0) , guiUpdateCompressor(0) , actionCollection(0) , mirrorManager(0) , actionAuthor(0) { } ~KisViewManagerPrivate() { delete filterManager; delete selectionManager; delete nodeManager; delete imageManager; delete gridManager; delete perspectiveGridManager; delete paintingAssistantsManager; delete statusBar; delete actionManager; delete canvasControlsManager; delete canvasResourceProvider; delete canvasResourceManager; delete mirrorManager; } public: KisFilterManager *filterManager; KisStatusBar *statusBar; KisAction *createTemplate; KisAction *createCopy; KisAction *saveIncremental; KisAction *saveIncrementalBackup; KisAction *openResourcesDirectory; KisAction *rotateCanvasRight; KisAction *rotateCanvasLeft; KisAction *wrapAroundAction; KisAction *showRulersAction; KisAction *zoomTo100pct; KisAction *zoomIn; KisAction *zoomOut; KisAction *showGuidesAction; KisSelectionManager *selectionManager; KisControlFrame *controlFrame; KisNodeManager *nodeManager; KisImageManager *imageManager; KisGridManager *gridManager; KisCanvasControlsManager *canvasControlsManager; KisPerspectiveGridManager * perspectiveGridManager; KisPaintingAssistantsManager *paintingAssistantsManager; BlockingUserInputEventFilter blockingEventFilter; KisActionManager* actionManager; QMainWindow* mainWindow; QPointer savedFloatingMessage; bool showFloatingMessage; QPointer currentImageView; KisCanvasResourceProvider* canvasResourceProvider; KoCanvasResourceManager* canvasResourceManager; QList statusBarItems; KisSignalCompressor* guiUpdateCompressor; KActionCollection *actionCollection; KisMirrorManager *mirrorManager; QPointer inputManager; KisSignalAutoConnectionsStore viewConnections; KSelectAction *actionAuthor; // Select action for author profile. }; KisViewManager::KisViewManager(QWidget *parent, KActionCollection *_actionCollection) : d(new KisViewManagerPrivate()) { d->actionCollection = _actionCollection; d->actionManager = new KisActionManager(this); d->mainWindow = dynamic_cast(parent); d->canvasResourceProvider = new KisCanvasResourceProvider(this); d->canvasResourceManager = new KoCanvasResourceManager(); d->canvasResourceProvider->setResourceManager(d->canvasResourceManager); d->guiUpdateCompressor = new KisSignalCompressor(30, KisSignalCompressor::POSTPONE, this); connect(d->guiUpdateCompressor, SIGNAL(timeout()), this, SLOT(guiUpdateTimeout())); createActions(); createManagers(); d->controlFrame = new KisControlFrame(this, parent); //Check to draw scrollbars after "Canvas only mode" toggle is created. this->showHideScrollbars(); KoCanvasController *dummy = new KoDummyCanvasController(actionCollection()); KoToolManager::instance()->registerTools(actionCollection(), dummy); d->statusBar = new KisStatusBar(this); QTimer::singleShot(0, this, SLOT(makeStatusBarVisible())); connect(KoToolManager::instance(), SIGNAL(inputDeviceChanged(KoInputDevice)), d->controlFrame->paintopBox(), SLOT(slotInputDeviceChanged(KoInputDevice))); connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*,int)), d->controlFrame->paintopBox(), SLOT(slotToolChanged(KoCanvasController*,int))); connect(d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), resourceProvider(), SLOT(slotNodeActivated(KisNodeSP))); connect(resourceProvider()->resourceManager(), SIGNAL(canvasResourceChanged(int,QVariant)), d->controlFrame->paintopBox(), SLOT(slotCanvasResourceChanged(int,QVariant))); connect(KisPart::instance(), SIGNAL(sigViewAdded(KisView*)), SLOT(slotViewAdded(KisView*))); connect(KisPart::instance(), SIGNAL(sigViewRemoved(KisView*)), SLOT(slotViewRemoved(KisView*))); connect(KisConfigNotifier::instance(), SIGNAL(configChanged()), SLOT(slotUpdateAuthorProfileActions())); KisInputProfileManager::instance()->loadProfiles(); KisConfig cfg; d->showFloatingMessage = cfg.showCanvasMessages(); } KisViewManager::~KisViewManager() { KisConfig cfg; if (resourceProvider() && resourceProvider()->currentPreset()) { cfg.writeEntry("LastPreset", resourceProvider()->currentPreset()->name()); } cfg.writeEntry("baseLength", KoResourceItemChooserSync::instance()->baseLength()); delete d; } KActionCollection *KisViewManager::actionCollection() const { return d->actionCollection; } void KisViewManager::slotViewAdded(KisView *view) { d->inputManager->addTrackedCanvas(view->canvasBase()); } void KisViewManager::slotViewRemoved(KisView *view) { d->inputManager->removeTrackedCanvas(view->canvasBase()); } void KisViewManager::setCurrentView(KisView *view) { bool first = true; if (d->currentImageView) { d->currentImageView->notifyCurrentStateChanged(false); d->currentImageView->canvasBase()->setCursor(QCursor(Qt::ArrowCursor)); first = false; KisDocument* doc = d->currentImageView->document(); if (doc) { doc->disconnect(this); } d->currentImageView->canvasController()->proxyObject->disconnect(d->statusBar); d->viewConnections.clear(); } QPointerimageView = qobject_cast(view); if (imageView) { d->viewConnections.addUniqueConnection(resourceProvider(), SIGNAL(sigDisplayProfileChanged(const KoColorProfile*)), imageView->canvasBase(), SLOT(slotSetDisplayProfile(const KoColorProfile*))); resourceProvider()->resetDisplayProfile(QApplication::desktop()->screenNumber(mainWindow())); // Wait for the async image to have loaded KisDocument* doc = view->document(); // connect(canvasController()->proxyObject, SIGNAL(documentMousePositionChanged(QPointF)), d->statusBar, SLOT(documentMousePositionChanged(QPointF))); d->currentImageView = imageView; KisCanvasController *canvasController = dynamic_cast(d->currentImageView->canvasController()); d->viewConnections.addUniqueConnection(d->nodeManager, SIGNAL(sigNodeActivated(KisNodeSP)), doc->image(), SLOT(requestStrokeEnd())); d->viewConnections.addUniqueConnection(d->rotateCanvasRight, SIGNAL(triggered()), canvasController, SLOT(rotateCanvasRight15())); d->viewConnections.addUniqueConnection(d->rotateCanvasLeft, SIGNAL(triggered()),canvasController, SLOT(rotateCanvasLeft15())); d->viewConnections.addUniqueConnection(d->wrapAroundAction, SIGNAL(toggled(bool)), canvasController, SLOT(slotToggleWrapAroundMode(bool))); d->wrapAroundAction->setChecked(canvasController->wrapAroundMode()); d->viewConnections.addUniqueConnection(d->currentImageView->canvasController(), SIGNAL(toolOptionWidgetsChanged(QList >)), mainWindow(), SLOT(newOptionWidgets(QList >))); d->viewConnections.addUniqueConnection(d->currentImageView->image(), SIGNAL(sigColorSpaceChanged(const KoColorSpace*)), d->controlFrame->paintopBox(), SLOT(slotColorSpaceChanged(const KoColorSpace*))); d->viewConnections.addUniqueConnection(d->showRulersAction, SIGNAL(toggled(bool)), imageView->zoomManager(), SLOT(toggleShowRulers(bool))); d->showRulersAction->setChecked(imageView->zoomManager()->horizontalRulerVisible() && imageView->zoomManager()->verticalRulerVisible()); d->viewConnections.addUniqueConnection(d->zoomTo100pct, SIGNAL(triggered()), imageView->zoomManager(), SLOT(zoomTo100())); d->viewConnections.addUniqueConnection(d->zoomIn, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomIn())); d->viewConnections.addUniqueConnection(d->zoomOut, SIGNAL(triggered()), imageView->zoomController()->zoomAction(), SLOT(zoomOut())); d->viewConnections.addUniqueConnection(d->showGuidesAction, SIGNAL(triggered(bool)), imageView->zoomManager(), SLOT(showGuides(bool))); showHideScrollbars(); } d->filterManager->setView(imageView); d->selectionManager->setView(imageView); d->nodeManager->setView(imageView); d->imageManager->setView(imageView); d->canvasControlsManager->setView(imageView); d->actionManager->setView(imageView); d->gridManager->setView(imageView); d->statusBar->setView(imageView); d->paintingAssistantsManager->setView(imageView); d->perspectiveGridManager->setView(imageView); d->mirrorManager->setView(imageView); if (d->currentImageView) { d->currentImageView->notifyCurrentStateChanged(true); d->currentImageView->canvasController()->activate(); d->currentImageView->canvasController()->setFocus(); } d->actionManager->updateGUI(); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigSizeChanged(const QPointF&, const QPointF&)), resourceProvider(), SLOT(slotImageSizeChanged())); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigResolutionChanged(double,double)), resourceProvider(), SLOT(slotOnScreenResolutionChanged())); d->viewConnections.addUniqueConnection( image(), SIGNAL(sigNodeChanged(KisNodeSP)), this, SLOT(updateGUI())); d->viewConnections.addUniqueConnection( view->zoomManager()->zoomController(), SIGNAL(zoomChanged(KoZoomMode::Mode,qreal)), resourceProvider(), SLOT(slotOnScreenResolutionChanged())); resourceProvider()->slotImageSizeChanged(); resourceProvider()->slotOnScreenResolutionChanged(); // Restore the last used brush preset if (first) { KisConfig cfg; KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); QString lastPreset = cfg.readEntry("LastPreset", QString("Basic_tip_default")); KisPaintOpPresetSP preset = rserver->resourceByName(lastPreset); if (!preset) { preset = rserver->resourceByName("Basic_tip_default"); } if (!preset) { preset = rserver->resources().first(); } if (preset) { paintOpBox()->restoreResource(preset.data()); } } } KoZoomController *KisViewManager::zoomController() const { if (d->currentImageView) { return d->currentImageView->zoomController(); } return 0; } KisImageWSP KisViewManager::image() const { if (document()) { return document()->image(); } return 0; } KisCanvasResourceProvider * KisViewManager::resourceProvider() { return d->canvasResourceProvider; } KisCanvas2 * KisViewManager::canvasBase() const { if (d && d->currentImageView) { return d->currentImageView->canvasBase(); } return 0; } QWidget* KisViewManager::canvas() const { if (d && d->currentImageView && d->currentImageView->canvasBase()->canvasWidget()) { return d->currentImageView->canvasBase()->canvasWidget(); } return 0; } KisStatusBar * KisViewManager::statusBar() const { return d->statusBar; } void KisViewManager::addStatusBarItem(QWidget * widget, int stretch, bool permanent) { if (!mainWindow()) return; StatusBarItem item(widget, stretch, permanent); KStatusBar * sb = mainWindow()->statusBar(); if (sb) { item.ensureItemShown(sb); } d->statusBarItems.append(item); } void KisViewManager::removeStatusBarItem(QWidget * widget) { KStatusBar *sb = mainWindow()->statusBar(); int itemCount = d->statusBarItems.count(); for (int i = itemCount-1; i >= 0; --i) { StatusBarItem &sbItem = d->statusBarItems[i]; if (sbItem.widget() == widget) { if (sb) { sbItem.ensureItemHidden(sb); } d->statusBarItems.removeOne(sbItem); break; } } } KisPaintopBox* KisViewManager::paintOpBox() const { return d->controlFrame->paintopBox(); } KoProgressUpdater* KisViewManager::createProgressUpdater(KoProgressUpdater::Mode mode) { return new KisProgressUpdater(d->statusBar->progress(), document()->progressProxy(), mode); } KisSelectionManager * KisViewManager::selectionManager() { return d->selectionManager; } KisNodeSP KisViewManager::activeNode() { if (d->nodeManager) return d->nodeManager->activeNode(); else return 0; } KisLayerSP KisViewManager::activeLayer() { if (d->nodeManager) return d->nodeManager->activeLayer(); else return 0; } KisPaintDeviceSP KisViewManager::activeDevice() { if (d->nodeManager) return d->nodeManager->activePaintDevice(); else return 0; } KisZoomManager * KisViewManager::zoomManager() { if (d->currentImageView) { return d->currentImageView->zoomManager(); } return 0; } KisFilterManager * KisViewManager::filterManager() { return d->filterManager; } KisImageManager * KisViewManager::imageManager() { return d->imageManager; } KisInputManager* KisViewManager::inputManager() const { return d->inputManager; } KisSelectionSP KisViewManager::selection() { if (d->currentImageView) { return d->currentImageView->selection(); } return 0; } bool KisViewManager::selectionEditable() { KisLayerSP layer = activeLayer(); if (layer) { KoProperties properties; QList masks = layer->childNodes(QStringList("KisSelectionMask"), properties); if (masks.size() == 1) { return masks[0]->isEditable(); } } // global selection is always editable return true; } KisUndoAdapter * KisViewManager::undoAdapter() { if (!document()) return 0; KisImageWSP image = document()->image(); Q_ASSERT(image); return image->undoAdapter(); } void KisViewManager::createActions() { d->saveIncremental = new KisAction(i18n("Save Incremental &Version"), this); d->saveIncremental->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_S)); d->saveIncremental->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("save_incremental_version", d->saveIncremental); connect(d->saveIncremental, SIGNAL(triggered()), this, SLOT(slotSaveIncremental())); d->saveIncrementalBackup = new KisAction(i18n("Save Incremental Backup"), this); d->saveIncrementalBackup->setShortcut(Qt::Key_F4); d->saveIncrementalBackup->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("save_incremental_backup", d->saveIncrementalBackup); connect(d->saveIncrementalBackup, SIGNAL(triggered()), this, SLOT(slotSaveIncrementalBackup())); connect(mainWindow(), SIGNAL(documentSaved()), this, SLOT(slotDocumentSaved())); d->saveIncremental->setEnabled(false); d->saveIncrementalBackup->setEnabled(false); KisAction *tabletDebugger = new KisAction(i18n("Toggle Tablet Debugger"), this); actionManager()->addAction("tablet_debugger", tabletDebugger ); tabletDebugger->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_T)); connect(tabletDebugger, SIGNAL(triggered()), this, SLOT(toggleTabletLogger())); d->createTemplate = new KisAction( i18n( "&Create Template From Image..." ), this); d->createTemplate->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("create_template", d->createTemplate); connect(d->createTemplate, SIGNAL(triggered()), this, SLOT(slotCreateTemplate())); d->createCopy = new KisAction( i18n( "&Create Copy From Current Image" ), this); d->createCopy->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("create_copy", d->createCopy); connect(d->createCopy, SIGNAL(triggered()), this, SLOT(slotCreateCopy())); d->openResourcesDirectory = new KisAction(i18n("Open Resources Folder"), this); d->openResourcesDirectory->setToolTip(i18n("Opens a file browser at the location Krita saves resources such as brushes to.")); d->openResourcesDirectory->setWhatsThis(i18n("Opens a file browser at the location Krita saves resources such as brushes to.")); actionManager()->addAction("open_resources_directory", d->openResourcesDirectory); connect(d->openResourcesDirectory, SIGNAL(triggered()), SLOT(openResourcesDirectory())); d->rotateCanvasRight = new KisAction(i18n("Rotate Canvas Right"), this); actionManager()->addAction("rotate_canvas_right", d->rotateCanvasRight); d->rotateCanvasRight->setActivationFlags(KisAction::ACTIVE_IMAGE); d->rotateCanvasRight->setShortcut(QKeySequence("Ctrl+]")); d->rotateCanvasLeft = new KisAction(i18n("Rotate Canvas Left"), this); actionManager()->addAction("rotate_canvas_left", d->rotateCanvasLeft); d->rotateCanvasLeft->setActivationFlags(KisAction::ACTIVE_IMAGE); d->rotateCanvasLeft->setShortcut(QKeySequence("Ctrl+[")); d->wrapAroundAction = new KisAction(i18n("Wrap Around Mode"), this); d->wrapAroundAction->setCheckable(true); d->wrapAroundAction->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("wrap_around_mode", d->wrapAroundAction); d->wrapAroundAction->setShortcut(QKeySequence(Qt::Key_W)); KisAction *tAction = new KisAction(i18n("Show Status Bar"), this); tAction->setCheckable(true); tAction->setChecked(true); tAction->setToolTip(i18n("Shows or hides the status bar")); actionManager()->addAction("showStatusBar", tAction); tAction->setActivationFlags(KisAction::ACTIVE_IMAGE); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showStatusBar(bool))); tAction = new KisAction(i18n("Show Canvas Only"), this); tAction->setActivationFlags(KisAction::ACTIVE_IMAGE); tAction->setCheckable(true); tAction->setToolTip(i18n("Shows just the canvas or the whole window")); QList shortcuts; shortcuts << QKeySequence(Qt::Key_Tab); tAction->setShortcuts(shortcuts); tAction->setChecked(false); actionManager()->addAction("view_show_just_the_canvas", tAction); connect(tAction, SIGNAL(toggled(bool)), this, SLOT(showJustTheCanvas(bool))); //Workaround, by default has the same shortcut as mirrorCanvas KisAction *a = dynamic_cast(actionCollection()->action("format_italic")); if (a) { a->setShortcut(QKeySequence(), KAction::DefaultShortcut); a->setShortcut(QKeySequence(), KAction::ActiveShortcut); a->setActivationConditions(KisAction::SELECTION_EDITABLE); } a = new KisAction(i18n("Cleanup removed files..."), this); actionManager()->addAction("edit_blacklist_cleanup", a); connect(a, SIGNAL(triggered()), this, SLOT(slotBlacklistCleanup())); d->showRulersAction = new KisAction(i18n("Show Rulers"), this); d->showRulersAction->setCheckable(true); d->showRulersAction->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("view_ruler", d->showRulersAction); d->showRulersAction->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.

Uncheck this to hide the rulers.

")); KisConfig cfg; d->showRulersAction->setChecked(cfg.showRulers()); d->showGuidesAction = new KisAction(i18n("Show Guides"), this); d->showGuidesAction->setCheckable(true); d->showGuidesAction->setCheckable(false); d->showGuidesAction->setActivationFlags(KisAction::ACTIVE_IMAGE); d->showGuidesAction->setToolTip(i18n("Shows or hides guides")); actionManager()->addAction("view_show_guides", d->showGuidesAction); d->zoomTo100pct = new KisAction(i18n("Reset zoom"), this); d->zoomTo100pct->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager()->addAction("zoom_to_100pct", d->zoomTo100pct); d->zoomTo100pct->setShortcut( QKeySequence( Qt::CTRL + Qt::Key_0 ) ); d->zoomIn = actionManager()->createStandardAction(KStandardAction::ZoomIn, 0, ""); d->zoomOut = actionManager()->createStandardAction(KStandardAction::ZoomOut, 0, ""); d->actionAuthor = new KSelectAction(themedIcon("im-user"), i18n("Active Author Profile"), this); connect(d->actionAuthor, SIGNAL(triggered(const QString &)), this, SLOT(changeAuthorProfile(const QString &))); actionCollection()->addAction("settings_active_author", d->actionAuthor); slotUpdateAuthorProfileActions(); } void KisViewManager::createManagers() { // Create the managers for filters, selections, layers etc. // XXX: When the currentlayer changes, call updateGUI on all // managers d->filterManager = new KisFilterManager(this); d->filterManager->setup(actionCollection(), actionManager()); d->selectionManager = new KisSelectionManager(this); d->selectionManager->setup(actionManager()); d->nodeManager = new KisNodeManager(this); d->nodeManager->setup(actionCollection(), actionManager()); d->imageManager = new KisImageManager(this); d->imageManager->setup(actionManager()); d->gridManager = new KisGridManager(this); d->gridManager->setup(this->actionManager()); d->perspectiveGridManager = new KisPerspectiveGridManager(this); d->perspectiveGridManager->setup(actionCollection()); d->paintingAssistantsManager = new KisPaintingAssistantsManager(this); d->paintingAssistantsManager->setup(actionManager()); d->canvasControlsManager = new KisCanvasControlsManager(this); d->canvasControlsManager->setup(actionManager()); d->mirrorManager = new KisMirrorManager(this); d->mirrorManager->setup(actionCollection()); d->inputManager = new KisInputManager(this); } void KisViewManager::updateGUI() { d->guiUpdateCompressor->start(); } void KisViewManager::slotBlacklistCleanup() { KisDlgBlacklistCleanup dialog; dialog.exec(); } KisNodeManager * KisViewManager::nodeManager() const { return d->nodeManager; } KisActionManager* KisViewManager::actionManager() const { return d->actionManager; } KisPerspectiveGridManager* KisViewManager::perspectiveGridManager() const { return d->perspectiveGridManager; } KisGridManager * KisViewManager::gridManager() const { return d->gridManager; } KisPaintingAssistantsManager* KisViewManager::paintingAssistantsManager() const { return d->paintingAssistantsManager; } KisDocument *KisViewManager::document() const { if (d->currentImageView && d->currentImageView->document()) { return d->currentImageView->document(); } return 0; } int KisViewManager::viewCount() const { KisMainWindow *mw = qobject_cast(d->mainWindow); if (mw) { return mw->viewCount(); } return 0; } void KisViewManager::slotCreateTemplate() { if (!document()) return; KisTemplateCreateDia::createTemplate(KisPart::instance()->templatesResourcePath(), ".kra", KisFactory::componentData(), document(), mainWindow()); } void KisViewManager::slotCreateCopy() { if (!document()) return; KisDocument *doc = KisPart::instance()->createDocument(); QString name = document()->documentInfo()->aboutInfo("name"); if (name.isEmpty()) { name = document()->url().toLocalFile(); } name = i18n("%1 (Copy)", name); doc->documentInfo()->setAboutInfo("title", name); KisImageWSP image = document()->image(); KisImageSP newImage = new KisImage(doc->createUndoStore(), image->width(), image->height(), image->colorSpace(), name); newImage->setRootLayer(dynamic_cast(image->rootLayer()->clone().data())); doc->setCurrentImage(newImage); KisPart::instance()->addDocument(doc); KisMainWindow *mw = qobject_cast(d->mainWindow); KisView *view = KisPart::instance()->createView(doc, resourceProvider()->resourceManager(), mw->actionCollection(), mw); mw->addView(view); } QMainWindow* KisViewManager::qtMainWindow() const { if (d->mainWindow) return d->mainWindow; //Fallback for when we have not yet set the main window. QMainWindow* w = qobject_cast(qApp->activeWindow()); if(w) return w; return mainWindow(); } void KisViewManager::setQtMainWindow(QMainWindow* newMainWindow) { d->mainWindow = newMainWindow; } void KisViewManager::slotDocumentSaved() { d->saveIncremental->setEnabled(true); d->saveIncrementalBackup->setEnabled(true); } void KisViewManager::slotSaveIncremental() { if (!document()) return; bool foundVersion; bool fileAlreadyExists; bool isBackup; QString version = "000"; QString newVersion; QString letter; QString fileName = document()->localFilePath(); // Find current version filenames // v v Regexp to find incremental versions in the filename, taking our backup scheme into account as well // Considering our incremental version and backup scheme, format is filename_001~001.ext QRegExp regex("_\\d{1,4}[.]|_\\d{1,4}[a-z][.]|_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); foundVersion = matches.at(0).isEmpty() ? false : true; // Ensure compatibility with Save Incremental Backup // If this regex is not kept separate, the entire algorithm needs modification; // It's simpler to just add this. QRegExp regexAux("_\\d{1,4}[~]|_\\d{1,4}[a-z][~]"); regexAux.indexIn(fileName); // Perform the search QStringList matchesAux = regexAux.capturedTexts(); isBackup = matchesAux.at(0).isEmpty() ? false : true; // If the filename has a version, prepare it for incrementation if (foundVersion) { version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "_" } else { // ...else, simply add a version to it so the next loop works QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(fileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(version); extensionPlusVersion.prepend("_"); fileName.replace(regex2, extensionPlusVersion); } // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("_"); if (!letter.isNull()) newVersion.append(letter); if (isBackup) { newVersion.append("~"); } else { newVersion.append("."); } fileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(fileName, KIO::NetAccess::DestinationSide, mainWindow()); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = 'a'; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental version"), i18n("Alternative names exhausted, try manually saving with a higher number")); return; } document()->setSaveInBatchMode(true); document()->saveAs(fileName); document()->setSaveInBatchMode(false); if (mainWindow()) { mainWindow()->updateCaption(); } } void KisViewManager::slotSaveIncrementalBackup() { if (!document()) return; bool workingOnBackup; bool fileAlreadyExists; QString version = "000"; QString newVersion; QString letter; QString fileName = document()->localFilePath(); // First, discover if working on a backup file, or a normal file QRegExp regex("~\\d{1,4}[.]|~\\d{1,4}[a-z][.]"); regex.indexIn(fileName); // Perform the search QStringList matches = regex.capturedTexts(); workingOnBackup = matches.at(0).isEmpty() ? false : true; if (workingOnBackup) { // Try to save incremental version (of backup), use letter for alt versions version = matches.at(matches.count() - 1); // Look at the last index, we don't care about other matches if (version.contains(QRegExp("[a-z]"))) { version.chop(1); // Trim "." letter = version.right(1); // Save letter version.chop(1); // Trim letter } else { version.chop(1); // Trim "." } version.remove(0, 1); // Trim "~" // Prepare the base for new version filename int intVersion = version.toInt(0); ++intVersion; QString baseNewVersion = QString::number(intVersion); QString backupFileName = document()->localFilePath(); while (baseNewVersion.length() < version.length()) { baseNewVersion.prepend("0"); } // Check if the file exists under the new name and search until options are exhausted (test appending a to z) do { newVersion = baseNewVersion; newVersion.prepend("~"); if (!letter.isNull()) newVersion.append(letter); newVersion.append("."); backupFileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(backupFileName, KIO::NetAccess::DestinationSide, mainWindow()); if (fileAlreadyExists) { if (!letter.isNull()) { char letterCh = letter.at(0).toLatin1(); ++letterCh; letter = QString(QChar(letterCh)); } else { letter = 'a'; } } } while (fileAlreadyExists && letter != "{"); // x, y, z, {... if (letter == "{") { QMessageBox::critical(mainWindow(), i18nc("@title:window", "Couldn't save incremental backup"), i18n("Alternative names exhausted, try manually saving with a higher number")); return; } QFile::copy(fileName, backupFileName); document()->saveAs(fileName); if (mainWindow()) mainWindow()->updateCaption(); } else { // if NOT working on a backup... // Navigate directory searching for latest backup version, ignore letters const quint8 HARDCODED_DIGIT_COUNT = 3; QString baseNewVersion = "000"; QString backupFileName = document()->localFilePath(); QRegExp regex2("[.][a-z]{2,4}$"); // Heuristic to find file extension regex2.indexIn(backupFileName); QStringList matches2 = regex2.capturedTexts(); QString extensionPlusVersion = matches2.at(0); extensionPlusVersion.prepend(baseNewVersion); extensionPlusVersion.prepend("~"); backupFileName.replace(regex2, extensionPlusVersion); // Save version with 1 number higher than the highest version found ignoring letters do { newVersion = baseNewVersion; newVersion.prepend("~"); newVersion.append("."); backupFileName.replace(regex, newVersion); fileAlreadyExists = KIO::NetAccess::exists(backupFileName, KIO::NetAccess::DestinationSide, mainWindow()); if (fileAlreadyExists) { // Prepare the base for new version filename, increment by 1 int intVersion = baseNewVersion.toInt(0); ++intVersion; baseNewVersion = QString::number(intVersion); while (baseNewVersion.length() < HARDCODED_DIGIT_COUNT) { baseNewVersion.prepend("0"); } } } while (fileAlreadyExists); // Save both as backup and on current file for interapplication workflow document()->setSaveInBatchMode(true); QFile::copy(fileName, backupFileName); document()->saveAs(fileName); document()->setSaveInBatchMode(false); if (mainWindow()) mainWindow()->updateCaption(); } } void KisViewManager::disableControls() { // prevents possible crashes, if somebody changes the paintop during dragging by using the mousewheel // this is for Bug 250944 // the solution blocks all wheel, mouse and key event, while dragging with the freehand tool // see KisToolFreehand::initPaint() and endPaint() d->controlFrame->paintopBox()->installEventFilter(&d->blockingEventFilter); foreach(QObject* child, d->controlFrame->paintopBox()->children()) { child->installEventFilter(&d->blockingEventFilter); } } void KisViewManager::enableControls() { d->controlFrame->paintopBox()->removeEventFilter(&d->blockingEventFilter); foreach(QObject* child, d->controlFrame->paintopBox()->children()) { child->removeEventFilter(&d->blockingEventFilter); } } void KisViewManager::showStatusBar(bool toggled) { if (d->currentImageView && d->currentImageView->statusBar()) { d->currentImageView->statusBar()->setVisible(toggled); } } #if defined HAVE_OPENGL && defined Q_OS_WIN32 #include #endif void KisViewManager::showJustTheCanvas(bool toggled) { KisConfig cfg; KisMainWindow* main = mainWindow(); if(!main) { dbgUI << "Unable to switch to canvas-only mode, main window not found"; return; } if (cfg.hideStatusbarFullscreen()) { if(main->statusBar() && main->statusBar()->isVisible() == toggled) { main->statusBar()->setVisible(!toggled); } } if (cfg.hideDockersFullscreen()) { KisAction* action = qobject_cast(main->actionCollection()->action("view_toggledockers")); action->setCheckable(true); if (action && action->isChecked() == toggled) { action->setChecked(!toggled); } } - if (cfg.hideTitlebarFullscreen()) { + if (cfg.hideTitlebarFullscreen() && !cfg.fullscreenMode()) { if(toggled) { main->setWindowState( main->windowState() | Qt::WindowFullScreen); } else { main->setWindowState( main->windowState() & ~Qt::WindowFullScreen); } } if (cfg.hideMenuFullscreen()) { if (main->menuBar()->isVisible() == toggled) { main->menuBar()->setVisible(!toggled); } } if (cfg.hideToolbarFullscreen()) { QList toolBars = main->findChildren(); foreach(QToolBar* toolbar, toolBars) { if (toolbar->isVisible() == toggled) { toolbar->setVisible(!toggled); } } } showHideScrollbars(); if (toggled) { // show a fading heads-up display about the shortcut to go back showFloatingMessage(i18n("Going into Canvas-Only mode.\nPress %1 to go back.", actionCollection()->action("view_show_just_the_canvas")->shortcut().toString()), QIcon()); } } void KisViewManager::toggleTabletLogger() { d->inputManager->toggleTabletLogger(); } void KisViewManager::openResourcesDirectory() { QString dir = KStandardDirs::locateLocal("data", "krita"); QDesktopServices::openUrl(QUrl::fromLocalFile(dir)); } void KisViewManager::updateIcons() { #if QT_VERSION >= 0x040700 - QColor background = mainWindow()->palette().background().color(); - - bool useDarkIcons = background.value() > 100; - QString prefix = useDarkIcons ? QString("dark_") : QString("light_"); - - QStringList whitelist; - whitelist << "ToolBox" << "KisLayerBox"; - - QStringList blacklistedIcons; - blacklistedIcons << "editpath" << "artistictext-tool" << "view-choose"; - if (mainWindow()) { QList dockers = mainWindow()->dockWidgets(); foreach(QDockWidget* dock, dockers) { kDebug() << "name " << dock->objectName(); KoDockWidgetTitleBar* titlebar = dynamic_cast(dock->titleBarWidget()); if (titlebar) { titlebar->updateIcons(); } - if (!whitelist.contains(dock->objectName())) { - continue; - } QObjectList objects; objects.append(dock); while (!objects.isEmpty()) { QObject* object = objects.takeFirst(); objects.append(object->children()); - QAbstractButton* button = dynamic_cast(object); - if (button && !button->icon().name().isEmpty()) { - QString name = button->icon().name(); name = name.remove("dark_").remove("light_"); - - if (!blacklistedIcons.contains(name)) { - QString iconName = prefix + name; - KIcon icon = koIcon(iconName.toLatin1()); - button->setIcon(icon); - } - } + KisIconUtils::updateIconCommon(object); } } } #endif } void KisViewManager::makeStatusBarVisible() { d->mainWindow->statusBar()->setVisible(true); } void KisViewManager::guiUpdateTimeout() { d->nodeManager->updateGUI(); d->selectionManager->updateGUI(); d->filterManager->updateGUI(); if (zoomManager()) { zoomManager()->updateGUI(); } d->gridManager->updateGUI(); d->perspectiveGridManager->updateGUI(); d->actionManager->updateGUI(); } void KisViewManager::showFloatingMessage(const QString message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment) { if (!d->currentImageView) return; d->currentImageView->showFloatingMessageImpl(message, icon, timeout, priority, alignment); #if QT_VERSION >= 0x040700 emit floatingMessageRequested(message, icon.name()); #endif } KisMainWindow *KisViewManager::mainWindow() const { return qobject_cast(d->mainWindow); } void KisViewManager::showHideScrollbars() { if (!d->currentImageView) return; if (!d->currentImageView->canvasController()) return; KisConfig cfg; bool toggled = actionCollection()->action("view_show_just_the_canvas")->isChecked(); if ( (toggled && cfg.hideScrollbarsFullscreen()) || (!toggled && cfg.hideScrollbars()) ) { d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); } else { d->currentImageView->canvasController()->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); d->currentImageView->canvasController()->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); } } void KisViewManager::setShowFloatingMessage(bool show) { d->showFloatingMessage = show; } void KisViewManager::changeAuthorProfile(const QString &profileName) { KConfigGroup appAuthorGroup(KoGlobal::calligraConfig(), "Author"); if (profileName.isEmpty()) { appAuthorGroup.writeEntry("active-profile", ""); } else if (profileName == i18nc("choice for author profile", "Anonymous")) { appAuthorGroup.writeEntry("active-profile", "anonymous"); } else { appAuthorGroup.writeEntry("active-profile", profileName); } appAuthorGroup.sync(); foreach(KisDocument *doc, KisPart::instance()->documents()) { doc->documentInfo()->updateParameters(); } } void KisViewManager::slotUpdateAuthorProfileActions() { Q_ASSERT(d->actionAuthor); if (!d->actionAuthor) { return; } d->actionAuthor->clear(); d->actionAuthor->addAction(i18n("Default Author Profile")); d->actionAuthor->addAction(i18nc("choice for author profile", "Anonymous")); KConfigGroup authorGroup(KoGlobal::calligraConfig(), "Author"); QStringList profiles = authorGroup.readEntry("profile-names", QStringList()); foreach (const QString &profile , profiles) { d->actionAuthor->addAction(profile); } KConfigGroup appAuthorGroup(KoGlobal::calligraConfig(), "Author"); QString profileName = appAuthorGroup.readEntry("active-profile", ""); if (profileName == "anonymous") { d->actionAuthor->setCurrentItem(1); } else if (profiles.contains(profileName)) { d->actionAuthor->setCurrentAction(profileName); } else { d->actionAuthor->setCurrentItem(0); } } #include "KisViewManager.moc" diff --git a/krita/ui/KisViewManager.h b/krita/ui/KisViewManager.h index ba5804eab5e..31a5270912a 100644 --- a/krita/ui/KisViewManager.h +++ b/krita/ui/KisViewManager.h @@ -1,252 +1,252 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_GUI_CLIENT_H #define KIS_GUI_CLIENT_H #include #include #include #include #include #include #include -#include +#include #include #include "kis_floating_message.h" #include "KisView.h" class KisAction; class QPoint; class KisCanvas2; class KisCanvasResourceProvider; class KisDocument; class KisFilterManager; class KisGridManager; class KisImage; class KisImageManager; class KisNodeManager; class KisPaintingAssistantsManager; class KisPaintopBox; class KisPerspectiveGridManager; class KisSelectionManager; class KisStatusBar; class KisUndoAdapter; class KisZoomManager; class KisPaintopBox; class KisActionManager; class KisInputManager; /** * Krita view class * * Following the broad model-view-controller idea this class shows you one view on the document. * There can be multiple views of the same document each in with independent settings for viewMode and zoom etc. */ class KRITAUI_EXPORT KisViewManager : public QObject { Q_OBJECT public: /** * Construct a new view on the krita document. * @param document the document we show. * @param parent a parent widget we show ourselves in. */ KisViewManager(QWidget *parent, KActionCollection *actionCollection); virtual ~KisViewManager(); /** * Retrieves the entire action collection. */ virtual KActionCollection* actionCollection() const; public: // Krita specific interfaces void setCurrentView(KisView *view); /// Return the image this view is displaying KisImageWSP image() const; KoZoomController *zoomController() const; /// The resource provider contains all per-view settings, such as /// current color, current paint op etc. KisCanvasResourceProvider * resourceProvider(); /// Return the canvasbase class KisCanvas2 * canvasBase() const; /// Return the actual widget that is displaying the current image QWidget* canvas() const; /// Return the wrapper class around the statusbar KisStatusBar * statusBar() const; /** * This adds a widget to the statusbar for this view. * If you use this method instead of using statusBar() directly, * KisView will take care of removing the items when the view GUI is deactivated * and readding them when it is reactivated. * The parameters are the same as QStatusBar::addWidget(). * * Note that you can't use KStatusBar methods (inserting text items by id). * But you can create a KStatusBarLabel with a dummy id instead, and use * it directly, to get the same look and feel. */ void addStatusBarItem(QWidget * widget, int stretch = 0, bool permanent = false); /** * Remove a widget from the statusbar for this view. */ void removeStatusBarItem(QWidget * widget); KisPaintopBox* paintOpBox() const; /// create a new progress updater KoProgressUpdater *createProgressUpdater(KoProgressUpdater::Mode mode = KoProgressUpdater::Threaded); /// The selection manager handles everything action related to /// selections. KisSelectionManager *selectionManager(); /// The node manager handles everything about nodes KisNodeManager *nodeManager() const; KisActionManager *actionManager() const; /** * Convenience method to get at the active node, which may be * a layer or a mask or a selection */ KisNodeSP activeNode(); /// Convenience method to get at the active layer KisLayerSP activeLayer(); /// Convenience method to get at the active paint device KisPaintDeviceSP activeDevice(); /// The filtermanager handles everything action-related to filters KisFilterManager *filterManager(); /// The image manager handles everything action-related to the /// current image KisImageManager *imageManager(); /// Filters events and sends them to canvas actions KisInputManager *inputManager() const; /// Convenience method to get at the active selection (the /// selection of the current layer, or, if that does not exist, /// the global selection. KisSelectionSP selection(); /// Checks if the current global or local selection is editable bool selectionEditable(); /// The undo adapter is used to add commands to the undo stack KisUndoAdapter *undoAdapter(); KisDocument *document() const; int viewCount() const; public: KisGridManager * gridManager() const; KisPerspectiveGridManager* perspectiveGridManager() const; KisPaintingAssistantsManager* paintingAssistantsManager() const; /// disable and enable toolbar controls. used for disabling them during painting. void enableControls(); void disableControls(); /// shows a floating message in the top right corner of the canvas void showFloatingMessage(const QString message, const QIcon& icon, int timeout = 4500, KisFloatingMessage::Priority priority = KisFloatingMessage::Medium, int alignment = Qt::AlignCenter | Qt::TextWordWrap); /// @return the KoMaindow this view is in, or 0 KisMainWindow *mainWindow() const; /// The QMainWindow associated with this view. This is most likely going to be shell(), but /// when running as Gemini or Sketch, this will be set to the applications' own QMainWindow. /// This can be checked by qobject_casting to KisMainWindow to check the difference. QMainWindow* qtMainWindow() const; /// The mainWindow function will return the shell() value, unless this function is called /// with a non-null value. To make it return shell() again, simply pass null to this function. void setQtMainWindow(QMainWindow* newMainWindow); public Q_SLOTS: void showJustTheCanvas(bool toggled); void setShowFloatingMessage(bool show); void showHideScrollbars(); /// Go to all managers and enable or disable all actions and other /// gui elements void updateGUI(); /// Update the style of all the icons void updateIcons(); void slotViewAdded(KisView *view); void slotViewRemoved(KisView *view); Q_SIGNALS: void floatingMessageRequested(QString message, QString iconName); private Q_SLOTS: void slotBlacklistCleanup(); void slotCreateTemplate(); void slotCreateCopy(); void slotDocumentSaved(); void slotSaveIncremental(); void slotSaveIncrementalBackup(); void showStatusBar(bool toggled); void toggleTabletLogger(); void openResourcesDirectory(); void makeStatusBarVisible(); void guiUpdateTimeout(); void changeAuthorProfile(const QString &profileName); void slotUpdateAuthorProfileActions(); private: void createActions(); void createManagers(); /// The zoommanager handles everything action-related to zooming KisZoomManager * zoomManager(); private: class KisViewManagerPrivate; KisViewManagerPrivate * const d; }; #endif diff --git a/krita/ui/actions/kis_selection_action_factories.cpp b/krita/ui/actions/kis_selection_action_factories.cpp index aa2b2476132..f350f9bf6d6 100644 --- a/krita/ui/actions/kis_selection_action_factories.cpp +++ b/krita/ui/actions/kis_selection_action_factories.cpp @@ -1,535 +1,537 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_selection_action_factories.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisViewManager.h" #include "kis_canvas_resource_provider.h" #include "kis_clipboard.h" #include "kis_pixel_selection.h" #include "kis_paint_layer.h" #include "kis_image.h" #include "kis_image_barrier_locker.h" #include "kis_fill_painter.h" #include "kis_transaction.h" #include "kis_iterator_ng.h" #include "kis_processing_applicator.h" #include "commands/kis_selection_commands.h" #include "commands/kis_image_layer_add_command.h" #include "kis_tool_proxy.h" #include "kis_canvas2.h" #include "kis_canvas_controller.h" #include "kis_selection_manager.h" #include "kis_transaction_based_command.h" #include "kis_selection_filters.h" #include "kis_shape_selection.h" #include "KisPart.h" #include "kis_shape_layer.h" #include #include #include namespace ActionHelper { void copyFromDevice(KisViewManager *view, KisPaintDeviceSP device, bool makeSharpClip = false) { KisImageWSP image = view->image(); if (!image) return; KisSelectionSP selection = view->selection(); QRect rc = (selection) ? selection->selectedExactRect() : image->bounds(); KisPaintDeviceSP clip = new KisPaintDevice(device->colorSpace()); Q_CHECK_PTR(clip); const KoColorSpace *cs = clip->colorSpace(); // TODO if the source is linked... copy from all linked layers?!? // Copy image data KisPainter::copyAreaOptimized(QPoint(), device, clip, rc); if (selection) { // Apply selection mask. KisPaintDeviceSP selectionProjection = selection->projection(); KisHLineIteratorSP layerIt = clip->createHLineIteratorNG(0, 0, rc.width()); KisHLineConstIteratorSP selectionIt = selectionProjection->createHLineIteratorNG(rc.x(), rc.y(), rc.width()); const KoColorSpace *selCs = selection->projection()->colorSpace(); for (qint32 y = 0; y < rc.height(); y++) { for (qint32 x = 0; x < rc.width(); x++) { /** * Sharp method is an exact reverse of COMPOSITE_OVER * so if you cover the cut/copied piece over its source * you get an exactly the same image without any seams */ if (makeSharpClip) { qreal dstAlpha = cs->opacityF(layerIt->rawData()); qreal sel = selCs->opacityF(selectionIt->oldRawData()); qreal newAlpha = sel * dstAlpha / (1.0 - dstAlpha + sel * dstAlpha); float mask = newAlpha / dstAlpha; cs->applyAlphaNormedFloatMask(layerIt->rawData(), &mask, 1); } else { cs->applyAlphaU8Mask(layerIt->rawData(), selectionIt->oldRawData(), 1); } layerIt->nextPixel(); selectionIt->nextPixel(); } layerIt->nextRow(); selectionIt->nextRow(); } } KisClipboard::instance()->setClip(clip, rc.topLeft()); } } void KisSelectAllActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Select All")); if (!image->globalSelection()) { ap->applyCommand(new KisSetEmptyGlobalSelectionCommand(image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); } struct SelectAll : public KisTransactionBasedCommand { SelectAll(KisImageSP image) : m_image(image) {} KisImageSP m_image; KUndo2Command* paint() { KisSelectionSP selection = m_image->globalSelection(); KisSelectionTransaction transaction(selection->pixelSelection()); selection->pixelSelection()->select(m_image->bounds()); return transaction.endAndTake(); } }; ap->applyCommand(new SelectAll(image), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisDeselectActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KUndo2Command *cmd = new KisDeselectGlobalSelectionCommand(image); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisReselectActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KUndo2Command *cmd = new KisReselectGlobalSelectionCommand(image); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisFillActionFactory::run(const QString &fillSource, KisViewManager *view) { KisNodeSP node = view->activeNode(); if (!node || !node->hasEditablePaintDevice()) return; KisSelectionSP selection = view->selection(); QRect selectedRect = selection ? selection->selectedRect() : view->image()->bounds(); Q_UNUSED(selectedRect); KisPaintDeviceSP filled = node->paintDevice()->createCompositionSourceDevice(); Q_UNUSED(filled); bool usePattern = false; bool useBgColor = false; if (fillSource == "pattern") { usePattern = true; } else if (fillSource == "bg") { useBgColor = true; } KisProcessingApplicator applicator(view->image(), node, KisProcessingApplicator::NONE, KisImageSignalVector() << ModifiedSignal, kundo2_i18n("Flood Fill Layer")); KisResourcesSnapshotSP resources = new KisResourcesSnapshot(view->image(), node, 0, view->resourceProvider()->resourceManager()); - resources->setOpacity(1.0); + if (!fillSource.contains("opacity")) { + resources->setOpacity(1.0); + } KisProcessingVisitorSP visitor = new FillProcessingVisitor(QPoint(0, 0), // start position selection, resources, false, // fast mode usePattern, true, // fill only selection, 0, // feathering radius 0, // sizemod 80, // threshold, false, // unmerged useBgColor); applicator.applyVisitor(visitor, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); applicator.end(); } void KisClearActionFactory::run(KisViewManager *view) { // XXX: "Add saving of XML data for Clear action" view->canvasBase()->toolProxy()->deleteSelection(); } void KisImageResizeToSelectionActionFactory::run(KisViewManager *view) { // XXX: "Add saving of XML data for Image Resize To Selection action" KisSelectionSP selection = view->selection(); if (!selection) return; view->image()->cropImage(selection->selectedExactRect()); } void KisCutCopyActionFactory::run(bool willCut, bool makeSharpClip, KisViewManager *view) { KisImageSP image = view->image(); if (!image) return; bool haveShapesSelected = view->selectionManager()->haveShapesSelected(); if (haveShapesSelected) { // XXX: "Add saving of XML data for Cut/Copy of shapes" KisImageBarrierLocker locker(image); if (willCut) { view->canvasBase()->toolProxy()->cut(); } else { view->canvasBase()->toolProxy()->copy(); } } else { KisNodeSP node = view->activeNode(); if (!node) return; KisSelectionSP selection = view->selection(); if (selection.isNull()) return; { KisImageBarrierLocker locker(image); KisPaintDeviceSP dev = node->paintDevice(); if (!dev) { dev = node->projection(); } if (!dev) { view->showFloatingMessage( i18nc("floating message when cannot copy from a node", "Cannot copy pixels from this type of layer "), QIcon(), 3000, KisFloatingMessage::Medium); return; } if (dev->exactBounds().isEmpty()) { view->showFloatingMessage( i18nc("floating message when copying empty selection", "Selection is empty: no pixels were copied "), QIcon(), 3000, KisFloatingMessage::Medium); return; } ActionHelper::copyFromDevice(view, dev, makeSharpClip); } if (willCut) { KUndo2Command *command = 0; if (willCut && node->hasEditablePaintDevice()) { struct ClearSelection : public KisTransactionBasedCommand { ClearSelection(KisNodeSP node, KisSelectionSP sel) : m_node(node), m_sel(sel) {} KisNodeSP m_node; KisSelectionSP m_sel; KUndo2Command* paint() { KisSelectionSP cutSelection = m_sel; // Shrinking the cutting area was previously used // for getting seamless cut-paste. Now we use makeSharpClip // instead. // QRect originalRect = cutSelection->selectedExactRect(); // static const int preciseSelectionThreshold = 16; // // if (originalRect.width() > preciseSelectionThreshold || // originalRect.height() > preciseSelectionThreshold) { // cutSelection = new KisSelection(*m_sel); // delete cutSelection->flatten(); // // KisSelectionFilter* filter = new KisShrinkSelectionFilter(1, 1, false); // // QRect processingRect = filter->changeRect(originalRect); // filter->process(cutSelection->pixelSelection(), processingRect); // } KisTransaction transaction(m_node->paintDevice()); m_node->paintDevice()->clearSelection(cutSelection); m_node->setDirty(cutSelection->selectedRect()); return transaction.endAndTake(); } }; command = new ClearSelection(node, selection); } KUndo2MagicString actionName = willCut ? kundo2_i18n("Cut") : kundo2_i18n("Copy"); KisProcessingApplicator *ap = beginAction(view, actionName); if (command) { ap->applyCommand(command, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); } KisOperationConfiguration config(id()); config.setProperty("will-cut", willCut); endAction(ap, config.toXML()); } } } void KisCopyMergedActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; image->barrierLock(); KisPaintDeviceSP dev = image->root()->projection(); ActionHelper::copyFromDevice(view, dev); image->unlock(); KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Copy Merged")); endAction(ap, KisOperationConfiguration(id()).toXML()); } void KisPasteActionFactory::run(KisViewManager *view) { KisImageWSP image = view->image(); if (!image) return; KisPaintDeviceSP clip = KisClipboard::instance()->clip(image->bounds(), true); if (clip) { KisPaintLayer *newLayer = new KisPaintLayer(image.data(), image->nextLayerName() + i18n("(pasted)"), OPACITY_OPAQUE_U8, clip); KisNodeSP aboveNode = view->activeLayer(); KisNodeSP parentNode = aboveNode ? aboveNode->parent() : image->root(); KUndo2Command *cmd = new KisImageLayerAddCommand(image, newLayer, parentNode, aboveNode); KisProcessingApplicator *ap = beginAction(view, cmd->text()); ap->applyCommand(cmd, KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::NORMAL); endAction(ap, KisOperationConfiguration(id()).toXML()); } else { // XXX: "Add saving of XML data for Paste of shapes" view->canvasBase()->toolProxy()->paste(); } } void KisPasteNewActionFactory::run(KisViewManager *viewManager) { Q_UNUSED(viewManager); KisPaintDeviceSP clip = KisClipboard::instance()->clip(QRect(), true); if (!clip) return; QRect rect = clip->exactBounds(); if (rect.isEmpty()) return; KisDocument *doc = KisPart::instance()->createDocument(); KisImageSP image = new KisImage(doc->createUndoStore(), rect.width(), rect.height(), clip->colorSpace(), i18n("Pasted")); KisPaintLayerSP layer = new KisPaintLayer(image.data(), clip->objectName(), OPACITY_OPAQUE_U8, clip->colorSpace()); KisPainter::copyAreaOptimized(QPoint(), clip, layer->paintDevice(), rect); image->addNode(layer.data(), image->rootLayer()); doc->setCurrentImage(image); KisPart::instance()->addDocument(doc); KisMainWindow *win = viewManager->mainWindow(); KisView *view = KisPart::instance()->createView(doc, win->resourceManager(), win->actionCollection(), win); win->addView(view); } void KisInvertSelectionOperaton::runFromXML(KisViewManager* view, const KisOperationConfiguration& config) { KisSelectionFilter* filter = new KisInvertSelectionFilter(); runFilter(filter, view, config); } void KisSelectionToVectorActionFactory::run(KisViewManager *view) { KisSelectionSP selection = view->selection(); if (selection->hasShapeSelection() || !selection->outlineCacheValid()) { return; } QPainterPath selectionOutline = selection->outlineCache(); QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform(); KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline)); shape->setShapeId(KoPathShapeId); /** * Mark a shape that it belongs to a shape selection */ if(!shape->userData()) { shape->setUserData(new KisShapeSelectionMarker); } KisProcessingApplicator *ap = beginAction(view, kundo2_i18n("Convert to Vector Selection")); ap->applyCommand(view->canvasBase()->shapeController()->addShape(shape), KisStrokeJobData::SEQUENTIAL, KisStrokeJobData::EXCLUSIVE); endAction(ap, KisOperationConfiguration(id()).toXML()); } class KisShapeSelectionPaste : public KoOdfPaste { public: KisShapeSelectionPaste(KisViewManager* view) : m_view(view) { } virtual ~KisShapeSelectionPaste() { } virtual bool process(const KoXmlElement & body, KoOdfReadStore & odfStore) { KoOdfLoadingContext loadingContext(odfStore.styles(), odfStore.store()); KoShapeLoadingContext context(loadingContext, m_view->canvasBase()->shapeController()->resourceManager()); KoXmlElement child; QList shapes; forEachElement(child, body) { KoShape * shape = KoShapeRegistry::instance()->createShapeFromOdf(child, context); if (shape) { shapes.append(shape); } } if (!shapes.isEmpty()) { KisSelectionToolHelper helper(m_view->canvasBase(), kundo2_i18n("Convert shapes to vector selection")); helper.addSelectionShapes(shapes); } return true; } private: KisViewManager* m_view; }; void KisShapesToVectorSelectionActionFactory::run(KisViewManager* view) { QList shapes = view->canvasBase()->shapeManager()->selection()->selectedShapes(); KoShapeOdfSaveHelper saveHelper(shapes); KoDrag drag; drag.setOdf(KoOdf::mimeType(KoOdf::Text), saveHelper); QMimeData* mimeData = drag.mimeData(); Q_ASSERT(mimeData->hasFormat(KoOdf::mimeType(KoOdf::Text))); KisShapeSelectionPaste paste(view); paste.paste(KoOdf::Text, mimeData); } void KisSelectionToShapeActionFactory::run(KisViewManager *view) { KisSelectionSP selection = view->selection(); if (!selection->outlineCacheValid()) { return; } QPainterPath selectionOutline = selection->outlineCache(); QTransform transform = view->canvasBase()->coordinatesConverter()->imageToDocumentTransform(); KoShape *shape = KoPathShape::createShapeFromPainterPath(transform.map(selectionOutline)); shape->setShapeId(KoPathShapeId); KoColor fgColor = view->canvasBase()->resourceManager()->resource(KoCanvasResourceManager::ForegroundColor).value(); KoShapeStroke* border = new KoShapeStroke(1.0, fgColor.toQColor()); shape->setStroke(border); view->document()->shapeController()->addShape(shape); } diff --git a/krita/ui/canvas/kis_canvas2.h b/krita/ui/canvas/kis_canvas2.h index a47bd1be352..d7baee36ad6 100644 --- a/krita/ui/canvas/kis_canvas2.h +++ b/krita/ui/canvas/kis_canvas2.h @@ -1,264 +1,264 @@ /* This file is part of the KDE project * Copyright (C) 2006, 2010 Boudewijn Rempt * Copyright (C) 2011 Silvio Heinrich * * 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 #include #include #include #include #include #include -#include +#include #include #include #include "kis_ui_types.h" #include "kis_coordinates_converter.h" class KoToolProxy; class KoColorProfile; class KisCanvasDecoration; class KisViewManager; class KisFavoriteResourceManager; class KisDisplayFilter; class KisDisplayColorConverter; struct KisExposureGammaCorrectionInterface; class KisPaintingAssistantsDecoration; class KisView; class KisInputManager; enum KisCanvasType { QPAINTER, OPENGL }; class KisCoordinatesConverter; class KoViewConverter; /** * KisCanvas2 is not an actual widget class, but rather an adapter for * the widget it contains, which may be either a QPainter based * canvas, or an OpenGL based canvas: that are the real widgets. */ class KRITAUI_EXPORT KisCanvas2 : public QObject, public KoCanvasBase { Q_OBJECT public: /** * Create a new canvas. The canvas manages a widget that will do * the actual painting: the canvas itself is not a widget. * * @param viewConverter the viewconverter for converting between * window and document coordinates. */ KisCanvas2(KisCoordinatesConverter* coordConverter, KoCanvasResourceManager *resourceManager, QPointer viewManager, KoShapeBasedDocumentBase* sc); virtual ~KisCanvas2(); void setCanvasWidget(QWidget * widget); void notifyZoomChanged(); virtual void disconnectCanvasObserver(QObject *object); public: // KoCanvasBase implementation KoGuidesData *guidesData(); bool canvasIsOpenGL(); void gridSize(qreal *horizontal, qreal *vertical) const; bool snapToGrid() const; // XXX: Why? void addCommand(KUndo2Command *command); virtual QPoint documentOrigin() const; QPoint documentOffset() const; /** * Return the right shape manager for the current layer. That is * to say, if the current layer is a vector layer, return the shape * layer's canvas' shapemanager, else the shapemanager associated * with the global krita canvas. */ KoShapeManager * shapeManager() const; /** * Return the shape manager associated with this canvas */ KoShapeManager * globalShapeManager() const; void updateCanvas(const QRectF& rc); virtual void updateInputMethodInfo(); const KisCoordinatesConverter* coordinatesConverter() const; virtual KoViewConverter *viewConverter() const; virtual QWidget* canvasWidget(); virtual const QWidget* canvasWidget() const; virtual KoUnit unit() const; virtual KoToolProxy* toolProxy() const; const KoColorProfile* monitorProfile(); /** * Prescale the canvas represention of the image (if necessary, it * is for QPainter, not for OpenGL). */ void preScale(); // FIXME: // Temporary! Either get the current layer and image from the // resource provider, or use this, which gets them from the // current shape selection. KisImageWSP currentImage() const; /** * Filters events and sends them to canvas actions. Shared * among all the views/canvases * * NOTE: May be null while initialization! */ KisInputManager* globalInputManager() const; KisPaintingAssistantsDecoration* paintingAssistantsDecoration(); public: // KisCanvas2 methods KisImageWSP image() const; KisViewManager* viewManager() const; QPointer imageView() const; /// @return true if the canvas image should be displayed in vertically mirrored mode void addDecoration(KisCanvasDecoration* deco); KisCanvasDecoration* decoration(const QString& id) const; void setDisplayFilter(KisDisplayFilter *displayFilter); KisDisplayFilter *displayFilter() const; KisDisplayColorConverter* displayColorConverter() const; KisExposureGammaCorrectionInterface* exposureGammaCorrectionInterface() const; void setCursor(const QCursor &cursor); Q_SIGNALS: void imageChanged(KisImageWSP image); void sigCanvasCacheUpdated(); void sigContinueResizeImage(qint32 w, qint32 h); void documentOffsetUpdateFinished(); // emitted whenever the canvas widget thinks sketch should update void updateCanvasRequested(const QRect &rc); public Q_SLOTS: /// Update the entire canvas area void updateCanvas(); void startResizingImage(); void finishResizingImage(qint32 w, qint32 h); /// canvas rotation in degrees qreal rotationAngle() const; /// Bools indicating canvasmirroring. bool xAxisMirrored() const; bool yAxisMirrored() const; void channelSelectionChanged(); private Q_SLOTS: /// The image projection has changed, now start an update /// of the canvas representation. void startUpdateCanvasProjection(const QRect & rc); void updateCanvasProjection(); void startUpdateInPatches(QRect imageRect); /** * Called whenever the view widget needs to show a different part of * the document * * @param documentOffset the offset in widget pixels */ void documentOffsetMoved(const QPoint &documentOffset); /** * Called whenever the configuration settings change. */ void slotConfigChanged(); /** * Called whenever the display monitor profile resource changes */ void slotSetDisplayProfile(const KoColorProfile * profile); void slotSelectionChanged(); void slotDoCanvasUpdate(); public: bool isPopupPaletteVisible(); void slotShowPopupPalette(const QPoint& = QPoint(0,0)); // interface for KisCanvasController only void setWrapAroundViewingMode(bool value); bool wrapAroundViewingMode() const; void initializeImage(); // interface for KisViewManager only void resetCanvas(bool useOpenGL); void setFavoriteResourceManager(KisFavoriteResourceManager* favoriteResourceManager); private: Q_DISABLE_COPY(KisCanvas2) void connectCurrentCanvas(); void disconnectCurrentCanvas(); void pan(QPoint shift); void createCanvas(bool useOpenGL); void createQPainterCanvas(); void createOpenGLCanvas(); void updateCanvasWidgetImpl(const QRect &rc = QRect()); private: class KisCanvas2Private; KisCanvas2Private * const m_d; }; #endif diff --git a/krita/ui/canvas/kis_canvas_controller.h b/krita/ui/canvas/kis_canvas_controller.h index 8faa8918412..37ebe9b05fd 100644 --- a/krita/ui/canvas/kis_canvas_controller.h +++ b/krita/ui/canvas/kis_canvas_controller.h @@ -1,64 +1,64 @@ /* * Copyright (c) 2010 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CANVAS_CONTROLLER_H #define KIS_CANVAS_CONTROLLER_H #include -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_types.h" class KisView; class KRITAUI_EXPORT KisCanvasController : public KoCanvasControllerWidget { Q_OBJECT public: KisCanvasController(QPointerparent, KActionCollection * actionCollection); ~KisCanvasController(); virtual void setCanvas(KoCanvasBase *canvas); virtual void changeCanvasWidget(QWidget *widget); virtual void keyPressEvent(QKeyEvent *event); virtual bool eventFilter(QObject *watched, QEvent *event); virtual void updateDocumentSize(const QSize &sz, bool recalculateCenter); virtual void activate(); public: using KoCanvasController::documentSize; bool wrapAroundMode() const; public Q_SLOTS: void mirrorCanvas(bool enable); void rotateCanvas(qreal angle); void rotateCanvasRight15(); void rotateCanvasLeft15(); void resetCanvasRotation(); void slotToggleWrapAroundMode(bool value); Q_SIGNALS: void documentSizeChanged(); private: struct Private; Private * const m_d; }; #endif /* KIS_CANVAS_CONTROLLER_H */ diff --git a/krita/ui/canvas/kis_canvas_decoration.h b/krita/ui/canvas/kis_canvas_decoration.h index 501bab41fa0..406c166b965 100644 --- a/krita/ui/canvas/kis_canvas_decoration.h +++ b/krita/ui/canvas/kis_canvas_decoration.h @@ -1,88 +1,88 @@ /* * Copyright (c) 2008 Cyrille Berger * * 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_DECORATION_H_ #define _KIS_CANVAS_DECORATION_H_ #include #include -#include +#include #include #include #include class QPoint; class QRect; class QRectF; class QPainter; class KisCoordinatesConverter; /** * This class is the base class for object that draw a decoration on the canvas, * for instance, selections, grids, tools, ... */ class KRITAUI_EXPORT KisCanvasDecoration : public QObject { Q_OBJECT public: KisCanvasDecoration(const QString& id, QPointerparent); ~KisCanvasDecoration(); void setView(QPointer imageView); const QString& id() const; /** * @return whether the decoration is visible. */ bool visible() const; /** * Will paint the decoration on the QPainter, if the visible is set to true. * * @param updateRect dirty rect in document pixels */ void paint(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter,KisCanvas2* canvas); public Q_SLOTS: /** * Set if the decoration is visible or not. */ virtual void setVisible(bool v); /** * If decoration is visible, hide it, if not show it. */ void toggleVisibility(); protected: virtual void drawDecoration(QPainter& gc, const QRectF& updateArea, const KisCoordinatesConverter *converter,KisCanvas2* canvas) = 0; /// XXX: unify view and imageview! QPointerimageView(); /** * @return the parent KisView */ QPointer view() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/canvas/kis_canvas_widget_base.h b/krita/ui/canvas/kis_canvas_widget_base.h index 00c7f3f8904..8806a61adcb 100644 --- a/krita/ui/canvas/kis_canvas_widget_base.h +++ b/krita/ui/canvas/kis_canvas_widget_base.h @@ -1,101 +1,101 @@ /* * Copyright (C) 2007 Boudewijn Rempt , (C) * Copyright (C) 2010 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_CANVAS_WIDGET_BASE_ #define _KIS_CANVAS_WIDGET_BASE_ #include #include #include class QColor; class QImage; class QInputMethodEvent; class QVariant; class KisCoordinatesConverter; class KisDisplayFilter; -#include "krita_export.h" +#include "kritaui_export.h" class KRITAUI_EXPORT KisCanvasWidgetBase : public KisAbstractCanvasWidget { public: KisCanvasWidgetBase(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter); virtual ~KisCanvasWidgetBase(); public: // KisAbstractCanvasWidget virtual KoToolProxy *toolProxy() const; /// set the specified display filter on the canvas virtual void setDisplayFilter(KisDisplayFilter *displayFilter); /** * Draw the specified decorations on the view. */ virtual void drawDecorations(QPainter & gc, const QRect &updateWidgetRect) const; virtual void addDecoration(KisCanvasDecoration* deco); virtual KisCanvasDecoration* decoration(const QString& id) const; virtual void setDecorations(const QList &); virtual QList decorations() const; virtual void setWrapAroundViewingMode(bool value); /** * Returns the color of the border, i.e. the part of the canvas * outside the image contents. * */ QColor borderColor() const; /** * Returns one check of the background checkerboard pattern. */ static QImage createCheckersImage(qint32 checkSize = -1); KisCoordinatesConverter* coordinatesConverter() const; protected: KisCanvas2 *canvas() const; /** * Event handlers to be called by derived canvas event handlers. * All common event processing is carried out by these * functions. */ QVariant processInputMethodQuery(Qt::InputMethodQuery query) const; void processInputMethodEvent(QInputMethodEvent *event); void notifyConfigChanged(); /// To be implemented by the derived canvas virtual bool callFocusNextPrevChild(bool next) = 0; private: struct Private; Private * const m_d; }; #endif // _KIS_CANVAS_WIDGET_BASE_ diff --git a/krita/ui/canvas/kis_coordinates_converter.h b/krita/ui/canvas/kis_coordinates_converter.h index 771142410f3..0ecb6ad65bc 100644 --- a/krita/ui/canvas/kis_coordinates_converter.h +++ b/krita/ui/canvas/kis_coordinates_converter.h @@ -1,154 +1,154 @@ /* * Copyright (c) 2010 Dmitry Kazakov * Copyright (c) 2011 Silvio Heinrich * * 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_COORDINATES_CONVERTER_H #define KIS_COORDINATES_CONVERTER_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_types.h" #define EPSILON 1e-6 #define SCALE_LESS_THAN(scX, scY, value) \ (scX < (value) - EPSILON && scY < (value) - EPSILON) #define SCALE_MORE_OR_EQUAL_TO(scX, scY, value) \ (scX > (value) - EPSILON && scY > (value) - EPSILON) namespace _Private { template struct Traits { typedef T Result; static T map(const QTransform& transform, const T& obj) { return transform.map(obj); } }; template<> struct Traits { typedef QRectF Result; static QRectF map(const QTransform& transform, const QRectF& rc) { return transform.mapRect(rc); } }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; template<> struct Traits: public Traits { }; } class KRITAUI_EXPORT KisCoordinatesConverter: public KoZoomHandler { public: KisCoordinatesConverter(); ~KisCoordinatesConverter(); void setCanvasWidgetSize(QSize size); void setImage(KisImageWSP image); void setDocumentOffset(const QPoint &offset); QPoint documentOffset() const; qreal rotationAngle() const; QPoint rotate(QPointF center, qreal angle); QPoint mirror(QPointF center, bool mirrorXAxis, bool mirrorYAxis, bool keepOrientation=false); bool xAxisMirrored() const; bool yAxisMirrored() const; QPoint resetRotation(QPointF center); virtual void setZoom(qreal zoom); template typename _Private::Traits::Result imageToViewport(const T& obj) const { return _Private::Traits::map(imageToViewportTransform(), obj); } template typename _Private::Traits::Result viewportToImage(const T& obj) const { return _Private::Traits::map(imageToViewportTransform().inverted(), obj); } template typename _Private::Traits::Result flakeToWidget(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToFlake(const T& obj) const { return _Private::Traits::map(flakeToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result widgetToViewport(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result viewportToWidget(const T& obj) const { return _Private::Traits::map(viewportToWidgetTransform(), obj); } template typename _Private::Traits::Result documentToWidget(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToDocument(const T& obj) const { return _Private::Traits::map(documentToWidgetTransform().inverted(), obj); } template typename _Private::Traits::Result imageToDocument(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform(), obj); } template typename _Private::Traits::Result documentToImage(const T& obj) const { return _Private::Traits::map(imageToDocumentTransform().inverted(), obj); } template typename _Private::Traits::Result documentToFlake(const T& obj) const { return _Private::Traits::map(documentToFlakeTransform(), obj); } template typename _Private::Traits::Result flakeToDocument(const T& obj) const { return _Private::Traits::map(documentToFlakeTransform().inverted(), obj); } template typename _Private::Traits::Result imageToWidget(const T& obj) const { return _Private::Traits::map(imageToWidgetTransform(), obj); } template typename _Private::Traits::Result widgetToImage(const T& obj) const { return _Private::Traits::map(imageToWidgetTransform().inverted(), obj); } QTransform imageToWidgetTransform() const; QTransform imageToDocumentTransform() const; QTransform documentToFlakeTransform() const; QTransform imageToViewportTransform() const; QTransform viewportToWidgetTransform() const; QTransform flakeToWidgetTransform() const; QTransform documentToWidgetTransform() const; void getQPainterCheckersInfo(QTransform *transform, QPointF *brushOrigin, QPolygonF *poligon) const; void getOpenGLCheckersInfo(const QRectF &viewportRect, QTransform *textureTransform, QTransform *modelTransform, QRectF *textureRect, QRectF *modelRect) const; QPointF imageCenterInWidgetPixel() const; QRectF imageRectInWidgetPixels() const; QRectF imageRectInViewportPixels() const; QSizeF imageSizeInFlakePixels() const; QRectF widgetRectInFlakePixels() const; QPointF flakeCenterPoint() const; QPointF widgetCenterPoint() const; void imageScale(qreal *scaleX, qreal *scaleY) const; private: friend class KisZoomAndPanTest; QPointF centeringCorrection() const; void correctOffsetToTransformation(); void correctTransformationToOffset(); void recalculateTransformations(); private: struct Private; Private * const m_d; }; #endif /* KIS_COORDINATES_CONVERTER_H */ diff --git a/krita/ui/canvas/kis_display_filter.h b/krita/ui/canvas/kis_display_filter.h index bc10e311399..021ab1baac9 100644 --- a/krita/ui/canvas/kis_display_filter.h +++ b/krita/ui/canvas/kis_display_filter.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2012 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_DISPLAY_FILTER_H #define KIS_DISPLAY_FILTER_H #include #include #include -#include +#include #include "kis_exposure_gamma_correction_interface.h" /** * @brief The KisDisplayFilter class is the base class for filters that * are applied by the canvas to the projection before displaying. */ class KRITAUI_EXPORT KisDisplayFilter : public QObject { Q_OBJECT public: explicit KisDisplayFilter(QObject *parent = 0); #ifdef HAVE_OPENGL virtual QString program() const = 0; virtual GLuint lutTexture() const = 0; #endif virtual void filter(quint8 *pixels, quint32 numPixels) = 0; virtual void approximateInverseTransformation(quint8 *pixels, quint32 numPixels) = 0; virtual void approximateForwardTransformation(quint8 *pixels, quint32 numPixels) = 0; virtual bool useInternalColorManagement() const = 0; virtual KisExposureGammaCorrectionInterface *correctionInterface() const = 0; virtual bool lockCurrentColorVisualRepresentation() const = 0; }; #endif diff --git a/krita/ui/canvas/kis_exposure_gamma_correction_interface.h b/krita/ui/canvas/kis_exposure_gamma_correction_interface.h index 53da8063fb4..b409ef0e51a 100644 --- a/krita/ui/canvas/kis_exposure_gamma_correction_interface.h +++ b/krita/ui/canvas/kis_exposure_gamma_correction_interface.h @@ -1,49 +1,49 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_EXPOSURE_GAMMA_CORRECTION_INTERFACE_H #define __KIS_EXPOSURE_GAMMA_CORRECTION_INTERFACE_H #include -#include +#include /** * A special interface for OCIO filter providing functionality for the * main UI module. See Dependency Inversion Principle for more. */ struct KRITAUI_EXPORT KisExposureGammaCorrectionInterface { virtual ~KisExposureGammaCorrectionInterface(); virtual bool canChangeExposureAndGamma() const = 0; virtual qreal currentExposure() const = 0; virtual void setCurrentExposure(qreal value) = 0; virtual qreal currentGamma() const = 0; virtual void setCurrentGamma(qreal value) = 0; }; struct KRITAUI_EXPORT KisDumbExposureGammaCorrectionInterface : public KisExposureGammaCorrectionInterface { static KisDumbExposureGammaCorrectionInterface* instance(); bool canChangeExposureAndGamma() const; qreal currentExposure() const; void setCurrentExposure(qreal value); qreal currentGamma() const; void setCurrentGamma(qreal value); }; #endif /* __KIS_EXPOSURE_GAMMA_CORRECTION_INTERFACE_H */ diff --git a/krita/ui/canvas/kis_grid_manager.cpp b/krita/ui/canvas/kis_grid_manager.cpp index 02f7f01fd30..8ec248843cd 100644 --- a/krita/ui/canvas/kis_grid_manager.cpp +++ b/krita/ui/canvas/kis_grid_manager.cpp @@ -1,228 +1,106 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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" #include #include #include #include #include #include "kis_coordinates_converter.h" #include "kis_config.h" #include "kis_grid_painter_configuration.h" #include "kis_grid_decoration.h" #include "kis_image.h" #include "KisViewManager.h" #include "KisDocument.h" #include "KisView.h" #include "kis_action.h" KisGridManager::KisGridManager(KisViewManager * parent) : QObject(parent) { } KisGridManager::~KisGridManager() { } void KisGridManager::setup(KisActionManager* actionManager) { - //there is no grid by default -// m_view->document()->gridData().setShowGrid(false); -// -// KisConfig config; -// m_view->document()->gridData().setGrid(config.getGridHSpacing(), config.getGridVSpacing()); - m_toggleGrid = new KisAction(themedIcon("view-grid"), i18n("Show Grid"), 0); m_toggleGrid->setCheckable(true); m_toggleGrid->setActivationFlags(KisAction::ACTIVE_NODE); m_toggleGrid->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Apostrophe)); actionManager->addAction("view_grid", m_toggleGrid); m_toggleSnapToGrid = new KisAction(i18n("Snap To Grid"), this); m_toggleSnapToGrid->setCheckable(true); m_toggleSnapToGrid->setActivationFlags(KisAction::ACTIVE_NODE); m_toggleSnapToGrid->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Semicolon)); //actionManager->addAction("view_snap_to_grid", m_toggleSnapToGrid); connect(m_toggleSnapToGrid, SIGNAL(triggered()), this, SLOT(toggleSnapToGrid())); - - // Fast grid config - m_gridFastConfig1x1 = new KisAction(i18n("1x1"), this); - m_gridFastConfig1x1->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_1x1", m_gridFastConfig1x1); - connect(m_gridFastConfig1x1, SIGNAL(triggered()), this, SLOT(fastConfig1x1())); - - m_gridFastConfig2x2 = new KisAction(i18n("2x2"), this); - m_gridFastConfig2x2->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_2x2", m_gridFastConfig2x2); - connect(m_gridFastConfig2x2, SIGNAL(triggered()), this, SLOT(fastConfig2x2())); - - m_gridFastConfig4x4 = new KisAction(i18n("4x4"), this); - m_gridFastConfig4x4->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_4x4", m_gridFastConfig4x4); - connect(m_gridFastConfig4x4, SIGNAL(triggered()), this, SLOT(fastConfig4x4())); - - m_gridFastConfig5x5 = new KisAction(i18n("5x5"), this); - m_gridFastConfig5x5->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_5x5", m_gridFastConfig5x5); - connect(m_gridFastConfig5x5, SIGNAL(triggered()), this, SLOT(fastConfig5x5())); - - m_gridFastConfig8x8 = new KisAction(i18n("8x8"), this); - m_gridFastConfig8x8->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_8x8", m_gridFastConfig8x8); - connect(m_gridFastConfig8x8, SIGNAL(triggered()), this, SLOT(fastConfig8x8())); - - m_gridFastConfig10x10 = new KisAction(i18n("10x10"), this); - m_gridFastConfig10x10->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_10x10", m_gridFastConfig10x10); - connect(m_gridFastConfig10x10, SIGNAL(triggered()), this, SLOT(fastConfig10x10())); - - m_gridFastConfig16x16 = new KisAction(i18n("16x16"), this); - m_gridFastConfig16x16->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_16x16", m_gridFastConfig16x16); - connect(m_gridFastConfig16x16, SIGNAL(triggered()), this, SLOT(fastConfig16x16())); - - m_gridFastConfig20x20 = new KisAction(i18n("20x20"), this); - m_gridFastConfig20x20->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_20x20", m_gridFastConfig20x20); - connect(m_gridFastConfig20x20, SIGNAL(triggered()), this, SLOT(fastConfig20x20())); - - m_gridFastConfig32x32 = new KisAction(i18n("32x32"), this); - m_gridFastConfig32x32->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_32x32", m_gridFastConfig32x32); - connect(m_gridFastConfig32x32, SIGNAL(triggered()), this, SLOT(fastConfig32x32())); - - m_gridFastConfig40x40 = new KisAction(i18n("40x40"), this); - m_gridFastConfig40x40->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_40x40", m_gridFastConfig40x40); - connect(m_gridFastConfig40x40, SIGNAL(triggered()), this, SLOT(fastConfig40x40())); - - m_gridFastConfig64x64 = new KisAction(i18n("64x64"), this); - m_gridFastConfig64x64->setActivationFlags(KisAction::ACTIVE_NODE); - actionManager->addAction("view_fast_grid_64x64", m_gridFastConfig64x64); - connect(m_gridFastConfig64x64, SIGNAL(triggered()), this, SLOT(fastConfig64x64())); } void KisGridManager::updateGUI() { } -void KisGridManager::setView(QPointer< KisView > imageView) +void KisGridManager::setView(QPointer imageView) { + qDebug() << "KisGridManager::setView();" << imageView; + if (m_imageView) { m_toggleGrid->disconnect(); m_gridDecoration = 0; } + m_imageView = imageView; + if (imageView) { m_gridDecoration = qobject_cast(imageView->canvasBase()->decoration("grid")); if (!m_gridDecoration) { m_gridDecoration = new KisGridDecoration(imageView); imageView->canvasBase()->addDecoration(m_gridDecoration); } checkVisibilityAction(m_gridDecoration->visible()); connect(m_toggleGrid, SIGNAL(triggered()), m_gridDecoration, SLOT(toggleVisibility())); } } void KisGridManager::checkVisibilityAction(bool check) { m_toggleGrid->setChecked(check); } void KisGridManager::toggleSnapToGrid() { if (m_imageView) { m_imageView->document()->gridData().setSnapToGrid(m_toggleSnapToGrid->isChecked()); m_imageView->canvasBase()->updateCanvas(); } } -void KisGridManager::setFastConfig(int size) -{ - if (m_imageView) { - m_imageView->document()->gridData().setGrid(size, size); - m_imageView->canvasBase()->updateCanvas(); - } -} - -void KisGridManager::fastConfig1x1() -{ - setFastConfig(1); -} - -void KisGridManager::fastConfig2x2() -{ - setFastConfig(2); -} - -void KisGridManager::fastConfig5x5() -{ - setFastConfig(5); -} - -void KisGridManager::fastConfig10x10() -{ - setFastConfig(10); -} - -void KisGridManager::fastConfig20x20() -{ - setFastConfig(20); -} - -void KisGridManager::fastConfig40x40() -{ - setFastConfig(40); -} - -void KisGridManager::fastConfig4x4() -{ - setFastConfig(4); -} - -void KisGridManager::fastConfig8x8() -{ - setFastConfig(4); -} - -void KisGridManager::fastConfig16x16() -{ - setFastConfig(16); -} - -void KisGridManager::fastConfig32x32() -{ - setFastConfig(32); -} - -void KisGridManager::fastConfig64x64() -{ - setFastConfig(64); -} - - #include "kis_grid_manager.moc" diff --git a/krita/ui/canvas/kis_grid_manager.h b/krita/ui/canvas/kis_grid_manager.h index 0d7c439a405..fb90d3a473d 100644 --- a/krita/ui/canvas/kis_grid_manager.h +++ b/krita/ui/canvas/kis_grid_manager.h @@ -1,89 +1,67 @@ /* * This file is part of Krita * * Copyright (c) 2006 Cyrille Berger * * 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 "kis_canvas_decoration.h" #include #include "kis_types.h" -#include +#include #include "kis_action_manager.h" #include "kis_action.h" class KisGridDecoration; class KisViewManager; class KRITAUI_EXPORT KisGridManager : public QObject { Q_OBJECT public: KisGridManager(KisViewManager * parent); virtual ~KisGridManager(); public: void setup(KisActionManager * actionManager); void setView(QPointerimageView); public Q_SLOTS: void updateGUI(); void checkVisibilityAction(bool check); private Q_SLOTS: void toggleSnapToGrid(); - void fastConfig1x1(); - void fastConfig2x2(); - void fastConfig5x5(); - void fastConfig10x10(); - void fastConfig20x20(); - void fastConfig40x40(); - void fastConfig4x4(); - void fastConfig8x8(); - void fastConfig16x16(); - void fastConfig32x32(); - void fastConfig64x64(); private: void setFastConfig(int size); KisAction *m_toggleGrid; KisAction* m_toggleSnapToGrid; - KisAction* m_gridFastConfig1x1; - KisAction* m_gridFastConfig2x2; - KisAction* m_gridFastConfig5x5; - KisAction* m_gridFastConfig10x10; - KisAction* m_gridFastConfig20x20; - KisAction* m_gridFastConfig40x40; - KisAction* m_gridFastConfig4x4; - KisAction* m_gridFastConfig8x8; - KisAction* m_gridFastConfig16x16; - KisAction* m_gridFastConfig32x32; - KisAction* m_gridFastConfig64x64; QPointer m_imageView; KisGridDecoration* m_gridDecoration; }; #endif diff --git a/krita/ui/canvas/kis_perspective_grid_decoration.h b/krita/ui/canvas/kis_perspective_grid_decoration.h index 626b7160cbd..ebe47d66b93 100644 --- a/krita/ui/canvas/kis_perspective_grid_decoration.h +++ b/krita/ui/canvas/kis_perspective_grid_decoration.h @@ -1,54 +1,54 @@ /* * This file is part of Krita * * Copyright (c) 2006,2008 Cyrille Berger * Copyright (c) 2014 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_PERSPECTIVE_GRID_DECORATION_H #define KIS_PERSPECTIVE_GRID_DECORATION_H #include "kis_canvas_decoration.h" -#include +#include class KisView; class KRITAUI_EXPORT KisPerspectiveGridDecoration : public KisCanvasDecoration { Q_OBJECT public: KisPerspectiveGridDecoration(QPointer parent); virtual ~KisPerspectiveGridDecoration(); protected: virtual void drawDecoration(QPainter& gc, const QRectF& updateArea, const KisCoordinatesConverter* converter, KisCanvas2* canvas); private: class LineWrapper; struct SubdivisionLinesInfo; void drawSubdivisions(QPainter& gc, const SubdivisionLinesInfo &info); SubdivisionLinesInfo getSubdivisionsInfo(const LineWrapper &l0, const LineWrapper &l1, const QPointF &focusPoint, int numSubdivisions); }; #endif // KIS_PERSPECTIVE_GRID_DECORATION_H diff --git a/krita/ui/canvas/kis_perspective_grid_manager.h b/krita/ui/canvas/kis_perspective_grid_manager.h index 3b138017d69..5f2b5e25792 100644 --- a/krita/ui/canvas/kis_perspective_grid_manager.h +++ b/krita/ui/canvas/kis_perspective_grid_manager.h @@ -1,71 +1,71 @@ /* * This file is part of Krita * * Copyright (c) 2006,2008 Cyrille Berger * * 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 "kis_canvas_decoration.h" #include -#include +#include class KisPerspectiveGridDecoration; class KAction; class KActionCollection; class KToggleAction; class KisViewManager; class KRITAUI_EXPORT KisPerspectiveGridManager : public QObject { Q_OBJECT public: /** Create a perspective manager for this view */ KisPerspectiveGridManager(KisViewManager * parent); ~KisPerspectiveGridManager(); void setup(KActionCollection * collection); /** * Call this function to start editing the grid, to disable display */ void startEdition(); /** * Call this function when the edition of the grid is finished. Trigger a redisplay of the perspective * grid if necesserary */ void stopEdition(); void setView(QPointer imageView); public Q_SLOTS: void updateGUI(); /** * Call this to remove all the perspective subgrids. */ void clearPerspectiveGrid(); private: KisPerspectiveGridDecoration* decoration(); QPointer m_imageView; KToggleAction* m_toggleGrid; KAction* m_gridClear; }; #endif diff --git a/krita/ui/canvas/kis_prescaled_projection.h b/krita/ui/canvas/kis_prescaled_projection.h index 8f26b5d32d8..92d1dc53a5f 100644 --- a/krita/ui/canvas/kis_prescaled_projection.h +++ b/krita/ui/canvas/kis_prescaled_projection.h @@ -1,182 +1,182 @@ /* * Copyright (C) Boudewijn Rempt , (C) 2006 * * 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_PRESCALED_PROJECTION_H #define KIS_PRESCALED_PROJECTION_H #include -#include +#include #include #include "kis_update_info.h" #include "KoColorConversionTransformation.h" class QImage; class QPoint; class QRect; class QSize; class QPainter; class KoColorProfile; class KisCoordinatesConverter; class KisDisplayFilter; #include #include "kis_ui_types.h" /** * KisPrescaledProjection is responsible for keeping around a * prescaled QImage representation that is always suitable for * painting onto the canvas. * * Note: the export macro is only for the unittest. */ class KRITAUI_EXPORT KisPrescaledProjection : public QObject, public KisShared { Q_OBJECT public: KisPrescaledProjection(); virtual ~KisPrescaledProjection(); void setImage(KisImageWSP image); /** * Return the prescaled QImage. The prescaled image is exactly as big as * the canvas widget in pixels. */ QImage prescaledQImage() const; void setCoordinatesConverter(KisCoordinatesConverter *coordinatesConverter); public Q_SLOTS: /** * Retrieves image's data from KisImage object and updates * internal cache * @param dirtyImageRect the rect changed on the image * @see recalculateCache */ KisUpdateInfoSP updateCache(const QRect &dirtyImageRect); /** * Updates the prescaled cache at current zoom level * @param info update structure returned by updateCache * @see updateCache */ void recalculateCache(KisUpdateInfoSP info); /** * Called whenever the configuration settings change. */ void updateSettings(); /** * Called whenever the view widget needs to show a different part of * the document */ void viewportMoved(const QPointF &offset); /** * Called whenever the size of the KisImage changes. * It is a part of a complex update ritual, when the size * fo the image changes. This method just resizes the storage * for the image cache, it doesn't update any cached data. */ void slotImageSizeChanged(qint32 w, qint32 h); /** * Checks whether it is needed to resize the prescaled image and * updates it. The size is given in canvas widget pixels. */ void notifyCanvasSizeChanged(const QSize &widgetSize); void notifyZoomChanged(); /** * Set the current monitor profile */ void setMonitorProfile(const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); void setChannelFlags(const QBitArray &channelFlags); void setDisplayFilter(KisDisplayFilter *displayFilter); /** * Called whenever the zoom level changes or another chunk of the * image becomes visible. The currently visible area of the image * is complete scaled again. */ void preScale(); private: friend class KisPrescaledProjectionTest; KisPrescaledProjection(const KisPrescaledProjection &); KisPrescaledProjection operator=(const KisPrescaledProjection &); void updateViewportSize(); /** * This creates an empty update information and fills it with the only * parameter: @p dirtyImageRect * This function is supposed to be run in the context of the image * threads, so it does no accesses to zoom or any UI specific values. * All the needed information for zooming will be fetched in the context * of the UI thread in fillInUpdateInformation(). * * @see fillInUpdateInformation() */ KisPPUpdateInfoSP getInitialUpdateInformation(const QRect &dirtyImageRect); /** * Prepare all the information about rects needed during * projection updating. * * @param viewportRect the part of the viewport that has to be updated * @param info the structure to be filled in. It's member dirtyImageRect * is supposed to have already been set up in the previous step of the * update in getInitialUpdateInformation(). Though it is allowed to * be null rect. * * @see getInitialUpdateInformation() */ void fillInUpdateInformation(const QRect &viewportRect, KisPPUpdateInfoSP info); /** * Initiates the process of prescaled image update * * @param info prepared information */ void updateScaledImage(KisPPUpdateInfoSP info); /** * Atual drawing is done here * @param info prepared information * @param gc The painter we draw on */ void drawUsingBackend(QPainter &gc, KisPPUpdateInfoSP info); struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/canvas/kis_update_info.h b/krita/ui/canvas/kis_update_info.h index d534f99de8d..690452355f0 100644 --- a/krita/ui/canvas/kis_update_info.h +++ b/krita/ui/canvas/kis_update_info.h @@ -1,117 +1,118 @@ /* * Copyright (c) 2010, Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_UPDATE_INFO_H_ #define KIS_UPDATE_INFO_H_ #include #include "kis_image_patch.h" #include "kis_shared.h" #include "opengl/kis_opengl.h" +#include "kritaui_export.h" #include "kis_ui_types.h" class KRITAUI_EXPORT KisUpdateInfo : public KisShared { public: KisUpdateInfo(); virtual ~KisUpdateInfo(); virtual QRect dirtyViewportRect(); virtual QRect dirtyImageRect() const = 0; }; Q_DECLARE_METATYPE(KisUpdateInfoSP) #ifdef HAVE_OPENGL #include "opengl/kis_texture_tile_update_info.h" class KisOpenGLUpdateInfo; typedef KisSharedPtr KisOpenGLUpdateInfoSP; class KisOpenGLUpdateInfo : public KisUpdateInfo { public: KisTextureTileUpdateInfoSPList tileList; QRect dirtyViewportRect(); QRect dirtyImageRect() const; void assignDirtyImageRect(const QRect &rect); private: QRect m_dirtyImageRect; }; #endif /* HAVE_OPENGL */ class KisPPUpdateInfo : public KisUpdateInfo { public: enum TransferType { DIRECT, PATCH }; QRect dirtyViewportRect(); QRect dirtyImageRect() const; /** * The rect that was reported by KisImage as dirty */ QRect dirtyImageRectVar; /** * Rect of KisImage corresponding to @viewportRect. * It is cropped and aligned corresponding to the canvas. */ QRect imageRect; /** * Rect of canvas widget corresponding to @imageRect */ QRectF viewportRect; qreal scaleX; qreal scaleY; /** * Defines the way the source image is painted onto * prescaled QImage */ TransferType transfer; /** * Render hints for painting the direct painting/patch painting */ QPainter::RenderHints renderHints; /** * The number of additional pixels those should be added * to the patch */ qint32 borderWidth; /** * Used for temporary sorage of KisImage's data * by KisProjectionCache */ KisImagePatch patch; }; #endif /* KIS_UPDATE_INFO_H_ */ diff --git a/krita/ui/dialogs/kis_dlg_preferences.cc b/krita/ui/dialogs/kis_dlg_preferences.cc index ca9cbd5906a..98ede86361e 100644 --- a/krita/ui/dialogs/kis_dlg_preferences.cc +++ b/krita/ui/dialogs/kis_dlg_preferences.cc @@ -1,1128 +1,1128 @@ /* * preferencesdlg.cc - part of KImageShop * * Copyright (c) 1999 Michael Koch * Copyright (c) 2003-2011 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_dlg_preferences.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_OPENGL #include #endif #include #include #include #include #include #include -#include +#include #include #include "KoID.h" #include #include #include #include #include #include "widgets/squeezedcombobox.h" #include "kis_clipboard.h" #include "widgets/kis_cmb_idlist.h" #include "KoColorSpace.h" #include "KoColorSpaceRegistry.h" #include "kis_cursor.h" #include "kis_config.h" #include "kis_canvas_resource_provider.h" #include "kis_preference_set_registry.h" #include "kis_factory2.h" #include "kis_color_manager.h" #include "slider_and_spin_box_sync.h" // for the performance update #include #include "input/config/kis_input_configuration_page.h" GeneralTab::GeneralTab(QWidget *_parent, const char *_name) : WdgGeneralSettings(_parent, _name) { KisConfig cfg; m_cmbCursorShape->addItem(i18n("No Cursor")); m_cmbCursorShape->addItem(i18n("Tool Icon")); m_cmbCursorShape->addItem(i18n("Arrow")); m_cmbCursorShape->addItem(i18n("Small Circle")); m_cmbCursorShape->addItem(i18n("Crosshair")); m_cmbCursorShape->addItem(i18n("Triangle Righthanded")); m_cmbCursorShape->addItem(i18n("Triangle Lefthanded")); m_cmbOutlineShape->addItem(i18n("No Outline")); m_cmbOutlineShape->addItem(i18n("Circle Outline")); m_cmbOutlineShape->addItem(i18n("Preview Outline")); m_cmbOutlineShape->addItem(i18n("Tilt Outline")); m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle()); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle()); chkShowRootLayer->setChecked(cfg.showRootLayer()); int autosaveInterval = cfg.autoSaveInterval(); //convert to minutes m_autosaveSpinBox->setValue(autosaveInterval / 60); m_autosaveCheckBox->setChecked(autosaveInterval > 0); m_undoStackSize->setValue(cfg.undoStackLimit()); m_backupFileCheckBox->setChecked(cfg.backupFile()); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting()); m_hideSplashScreen->setChecked(cfg.hideSplashScreen()); m_cmbMDIType->setCurrentIndex(cfg.readEntry("mdi_viewmode", (int)QMdiArea::TabbedView)); m_chkRubberBand->setChecked(cfg.readEntry("mdi_rubberband", cfg.useOpenGL())); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets()); m_mdiColor->setColor(cfg.getMDIBackgroundColor()); m_backgroundimage->setText(cfg.getMDIBackgroundImage()); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages()); m_chkCompressKra->setChecked(cfg.compressKra()); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker()); connect(m_bnFileName, SIGNAL(clicked()), SLOT(getBackgroundImage())); connect(clearBgImageButton, SIGNAL(clicked()), SLOT(clearBackgroundImage())); } void GeneralTab::setDefault() { KisConfig cfg; m_cmbCursorShape->setCurrentIndex(cfg.newCursorStyle(true)); m_cmbOutlineShape->setCurrentIndex(cfg.newOutlineStyle(true)); chkShowRootLayer->setChecked(cfg.showRootLayer(true)); m_autosaveCheckBox->setChecked(cfg.autoSaveInterval(true) > 0); //convert to minutes m_autosaveSpinBox->setValue(cfg.autoSaveInterval(true) / 60); m_undoStackSize->setValue(cfg.undoStackLimit(true)); m_backupFileCheckBox->setChecked(cfg.backupFile(true)); m_showOutlinePainting->setChecked(cfg.showOutlineWhilePainting(true)); m_hideSplashScreen->setChecked(cfg.hideSplashScreen(true)); m_cmbMDIType->setCurrentIndex((int)QMdiArea::TabbedView); m_chkRubberBand->setChecked(cfg.useOpenGL(true)); m_favoritePresetsSpinBox->setValue(cfg.favoritePresets(true)); m_mdiColor->setColor(cfg.getMDIBackgroundColor(true)); m_backgroundimage->setText(cfg.getMDIBackgroundImage(true)); m_chkCanvasMessages->setChecked(cfg.showCanvasMessages(true)); m_chkCompressKra->setChecked(cfg.compressKra(true)); m_radioToolOptionsInDocker->setChecked(cfg.toolOptionsInDocker(true)); } CursorStyle GeneralTab::cursorStyle() { return (CursorStyle)m_cmbCursorShape->currentIndex(); } OutlineStyle GeneralTab::outlineStyle() { return (OutlineStyle)m_cmbOutlineShape->currentIndex(); } bool GeneralTab::showRootLayer() { return chkShowRootLayer->isChecked(); } int GeneralTab::autoSaveInterval() { //convert to seconds return m_autosaveCheckBox->isChecked() ? m_autosaveSpinBox->value()*60 : 0; } int GeneralTab::undoStackSize() { return m_undoStackSize->value(); } bool GeneralTab::showOutlineWhilePainting() { return m_showOutlinePainting->isChecked(); } bool GeneralTab::hideSplashScreen() { return m_hideSplashScreen->isChecked(); } int GeneralTab::mdiMode() { return m_cmbMDIType->currentIndex(); } int GeneralTab::favoritePresets() { return m_favoritePresetsSpinBox->value(); } bool GeneralTab::showCanvasMessages() { return m_chkCanvasMessages->isChecked(); } bool GeneralTab::compressKra() { return m_chkCompressKra->isChecked(); } bool GeneralTab::toolOptionsInDocker() { return m_radioToolOptionsInDocker->isChecked(); } void GeneralTab::getBackgroundImage() { KoFileDialog dialog(this, KoFileDialog::OpenFile, "BackgroundImages"); dialog.setCaption(i18n("Select a Background Image")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setImageFilters(); QString fn = dialog.url(); // dialog box was canceled or somehow no file was selected if (fn.isEmpty()) { return; } QImage image(fn); if (image.isNull()) { QMessageBox::warning(this, i18nc("@title:window", "Krita"), i18n("%1 is not a valid image file!", fn)); } else { m_backgroundimage->setText(fn); } } void GeneralTab::clearBackgroundImage() { // clearing the background image text will implicitly make the background color be used m_backgroundimage->setText(""); } ColorSettingsTab::ColorSettingsTab(QWidget *parent, const char *name) : QWidget(parent) { setObjectName(name); // XXX: Make sure only profiles that fit the specified color model // are shown in the profile combos QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgColorSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile()); connect(m_page->chkUseSystemMonitorProfile, SIGNAL(toggled(bool)), this, SLOT(toggleAllowMonitorProfileSelection(bool))); // XXX: no color management integration on Windows or OSX yet #ifndef Q_WS_X11 m_page->chkUseSystemMonitorProfile->setVisible(false); #endif m_page->cmbWorkingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbWorkingColorSpace->setCurrent(cfg.workingColorSpace()); m_page->cmbPrintingColorSpace->setIDList(KoColorSpaceRegistry::instance()->listKeys()); m_page->cmbPrintingColorSpace->setCurrent(cfg.printerColorSpace()); - m_page->bnAddColorProfile->setIcon(themedIcon("document-open")); + m_page->bnAddColorProfile->setIcon(KisIconUtils::loadIcon("document-open")); m_page->bnAddColorProfile->setToolTip( i18n("Open Color Profile") ); connect(m_page->bnAddColorProfile, SIGNAL(clicked()), SLOT(installProfile())); refillPrintProfiles(KoID(cfg.printerColorSpace(), "")); //hide printing settings m_page->groupBox2->hide(); QGridLayout *monitorProfileGrid = new QGridLayout(m_page->monitorprofileholder); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { - QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen: %1", i + 1)); + QLabel *lbl = new QLabel(i18nc("The number of the screen", "Screen %1:", i + 1)); monitorProfileGrid->addWidget(lbl, i, 0); m_monitorProfileLabels << lbl; SqueezedComboBox *cmb = new SqueezedComboBox(); monitorProfileGrid->addWidget(cmb, i, 1); m_monitorProfileWidgets << cmb; } refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } if (m_page->cmbPrintProfile->contains(cfg.printerProfile())) m_page->cmbPrintProfile->setCurrentIndex(m_page->cmbPrintProfile->findText(cfg.printerProfile())); m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation()); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization()); m_pasteBehaviourGroup.addButton(m_page->radioPasteWeb, PASTE_ASSUME_WEB); m_pasteBehaviourGroup.addButton(m_page->radioPasteMonitor, PASTE_ASSUME_MONITOR); m_pasteBehaviourGroup.addButton(m_page->radioPasteAsk, PASTE_ASK); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour()); Q_ASSERT(button); if (button) { button->setChecked(true); } m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent()); toggleAllowMonitorProfileSelection(cfg.useSystemMonitorProfile()); connect(m_page->cmbPrintingColorSpace, SIGNAL(activated(const KoID &)), this, SLOT(refillPrintProfiles(const KoID &))); } void ColorSettingsTab::installProfile() { QStringList mime; mime << "ICM Profile (*.icm)" << "ICC Profile (*.icc)"; KoFileDialog dialog(this, KoFileDialog::OpenFiles, "OpenDocumentICC"); dialog.setCaption(i18n("Install Color Profiles")); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::HomeLocation)); dialog.setNameFilters(mime); QStringList profileNames = dialog.urls(); KoColorSpaceEngine *iccEngine = KoColorSpaceEngineRegistry::instance()->get("icc"); Q_ASSERT(iccEngine); QString saveLocation = KGlobal::mainComponent().dirs()->saveLocation("icc_profiles"); foreach (const QString &profileName, profileNames) { KUrl file(profileName); if (!QFile::copy(profileName, saveLocation + file.fileName())) { kWarning() << "Could not install profile!"; return; } iccEngine->addProfile(saveLocation + file.fileName()); } KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); refillPrintProfiles(KoID(cfg.printerColorSpace(), "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } if (m_page->cmbPrintProfile->contains(cfg.printerProfile())) m_page->cmbPrintProfile->setCurrentIndex(m_page->cmbPrintProfile->findText(cfg.printerProfile())); } void ColorSettingsTab::toggleAllowMonitorProfileSelection(bool useSystemProfile) { if (useSystemProfile) { KisConfig cfg; QStringList devices = KisColorManager::instance()->devices(); if (devices.size() == QApplication::desktop()->screenCount()) { for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); QString monitorForScreen = cfg.monitorForScreen(i, devices[i]); foreach(const QString &device, devices) { m_monitorProfileLabels[i]->setText(i18nc("The display/screen we got from Qt", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->addSqueezedItem(KisColorManager::instance()->deviceName(device), device); if (devices[i] == monitorForScreen) { m_monitorProfileWidgets[i]->setCurrentIndex(i); } } } } } else { KisConfig cfg; refillMonitorProfiles(KoID("RGBA", "")); for(int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (m_monitorProfileWidgets[i]->contains(cfg.monitorProfile(i))) { m_monitorProfileWidgets[i]->setCurrent(cfg.monitorProfile(i)); } } } } void ColorSettingsTab::setDefault() { m_page->cmbWorkingColorSpace->setCurrent("RGBA"); m_page->cmbPrintingColorSpace->setCurrent("CMYK"); refillPrintProfiles(KoID("CMYK", "")); refillMonitorProfiles(KoID("RGBA", "")); KisConfig cfg; m_page->chkBlackpoint->setChecked(cfg.useBlackPointCompensation(true)); m_page->chkAllowLCMSOptimization->setChecked(cfg.allowLCMSOptimization(true)); m_page->cmbMonitorIntent->setCurrentIndex(cfg.monitorRenderIntent(true)); m_page->chkUseSystemMonitorProfile->setChecked(cfg.useSystemMonitorProfile(true)); QAbstractButton *button = m_pasteBehaviourGroup.button(cfg.pasteBehaviour(true)); Q_ASSERT(button); if (button) { button->setChecked(true); } } void ColorSettingsTab::refillMonitorProfiles(const KoID & s) { const KoColorSpaceFactory * csf = KoColorSpaceRegistry::instance()->colorSpaceFactory(s.id()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->clear(); } if (!csf) return; QList profileList = KoColorSpaceRegistry::instance()->profilesFor(csf); foreach (const KoColorProfile *profile, profileList) { // qDebug() << "Profile" << profile->name() << profile->isSuitableForDisplay() << csf->defaultProfile(); if (profile->isSuitableForDisplay()) { for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { m_monitorProfileWidgets[i]->addSqueezedItem(profile->name()); } } } for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { - m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen: %1", i + 1)); + m_monitorProfileLabels[i]->setText(i18nc("The number of the screen", "Screen %1:", i + 1)); m_monitorProfileWidgets[i]->setCurrent(csf->defaultProfile()); } } void ColorSettingsTab::refillPrintProfiles(const KoID & s) { const KoColorSpaceFactory * csf = KoColorSpaceRegistry::instance()->colorSpaceFactory(s.id()); m_page->cmbPrintProfile->clear(); if (!csf) return; QList profileList = KoColorSpaceRegistry::instance()->profilesFor(csf); foreach(const KoColorProfile *profile, profileList) { if (profile->isSuitableForPrinting()) m_page->cmbPrintProfile->addSqueezedItem(profile->name()); } m_page->cmbPrintProfile->setCurrent(csf->defaultProfile()); } //--------------------------------------------------------------------------------------------------- void TabletSettingsTab::setDefault() { KisCubicCurve curve; curve.fromString(DEFAULT_CURVE_STRING); m_page->pressureCurve->setCurve(curve); } TabletSettingsTab::TabletSettingsTab(QWidget* parent, const char* name): QWidget(parent) { setObjectName(name); QGridLayout * l = new QGridLayout(this); l->setMargin(0); m_page = new WdgTabletSettings(this); l->addWidget(m_page, 0, 0); KisConfig cfg; KisCubicCurve curve; curve.fromString( cfg.pressureTabletCurve() ); m_page->pressureCurve->setMaximumSize(QSize(QWIDGETSIZE_MAX, QWIDGETSIZE_MAX)); m_page->pressureCurve->setCurve(curve); } //--------------------------------------------------------------------------------------------------- #include "kis_image_config.h" #include "kis_acyclic_signal_connector.h" int getTotalRAM() { KisImageConfig cfg; return cfg.totalRAM(); } int PerformanceTab::realTilesRAM() { return intMemoryLimit->value() - intPoolLimit->value(); } PerformanceTab::PerformanceTab(QWidget *parent, const char *name) : WdgPerformanceSettings(parent, name) { KisImageConfig cfg; const int totalRAM = cfg.totalRAM(); lblTotalMemory->setText(i18n("%1 MiB", totalRAM)); sliderMemoryLimit->setSuffix(" %"); sliderMemoryLimit->setRange(1, 100, 2); sliderMemoryLimit->setSingleStep(0.01); sliderPoolLimit->setSuffix(" %"); sliderPoolLimit->setRange(0, 20, 2); sliderMemoryLimit->setSingleStep(0.01); sliderUndoLimit->setSuffix(" %"); sliderUndoLimit->setRange(0, 50, 2); sliderMemoryLimit->setSingleStep(0.01); intMemoryLimit->setMinimumWidth(80); intPoolLimit->setMinimumWidth(80); intUndoLimit->setMinimumWidth(80); SliderAndSpinBoxSync *sync1 = new SliderAndSpinBoxSync(sliderMemoryLimit, intMemoryLimit, getTotalRAM); sync1->slotParentValueChanged(); m_syncs << sync1; SliderAndSpinBoxSync *sync2 = new SliderAndSpinBoxSync(sliderPoolLimit, intPoolLimit, boost::bind(&QSpinBox::value, intMemoryLimit)); connect(intMemoryLimit, SIGNAL(valueChanged(int)), sync2, SLOT(slotParentValueChanged())); sync2->slotParentValueChanged(); m_syncs << sync2; SliderAndSpinBoxSync *sync3 = new SliderAndSpinBoxSync(sliderUndoLimit, intUndoLimit, boost::bind(&PerformanceTab::realTilesRAM, this)); connect(intPoolLimit, SIGNAL(valueChanged(int)), sync3, SLOT(slotParentValueChanged())); sync3->slotParentValueChanged(); m_syncs << sync3; sliderSwapSize->setSuffix(i18n(" GiB")); sliderSwapSize->setRange(1, 64); intSwapSize->setRange(1, 64); KisAcyclicSignalConnector *swapSizeConnector = new KisAcyclicSignalConnector(this); swapSizeConnector->connectForwardInt(sliderSwapSize, SIGNAL(valueChanged(int)), intSwapSize, SLOT(setValue(int))); swapSizeConnector->connectBackwardInt(intSwapSize, SIGNAL(valueChanged(int)), sliderSwapSize, SLOT(setValue(int))); lblSwapFileLocation->setText(cfg.swapDir()); connect(bnSwapFile, SIGNAL(clicked()), SLOT(selectSwapDir())); load(false); } PerformanceTab::~PerformanceTab() { qDeleteAll(m_syncs); } void PerformanceTab::load(bool requestDefault) { KisImageConfig cfg; sliderMemoryLimit->setValue(cfg.memoryHardLimitPercent(requestDefault)); sliderPoolLimit->setValue(cfg.memoryPoolLimitPercent(requestDefault)); sliderUndoLimit->setValue(cfg.memorySoftLimitPercent(requestDefault)); chkPerformanceLogging->setChecked(cfg.enablePerfLog(requestDefault)); sliderSwapSize->setValue(cfg.maxSwapSize(requestDefault) / 1024); lblSwapFileLocation->setText(cfg.swapDir(requestDefault)); } void PerformanceTab::save() { KisImageConfig cfg; cfg.setMemoryHardLimitPercent(sliderMemoryLimit->value()); cfg.setMemorySoftLimitPercent(sliderUndoLimit->value()); cfg.setMemoryPoolLimitPercent(sliderPoolLimit->value()); cfg.setEnablePerfLog(chkPerformanceLogging->isChecked()); cfg.setMaxSwapSize(sliderSwapSize->value() * 1024); cfg.setSwapDir(lblSwapFileLocation->text()); } void PerformanceTab::selectSwapDir() { KisImageConfig cfg; QString swapDir = cfg.swapDir(); swapDir = QFileDialog::getExistingDirectory(0, i18nc("@title:window", "Select a swap directory"), swapDir); lblSwapFileLocation->setText(swapDir); } //--------------------------------------------------------------------------------------------------- #include "KoColor.h" #include "KoColorPopupAction.h" DisplaySettingsTab::DisplaySettingsTab(QWidget *parent, const char *name) : WdgDisplaySettings(parent, name) { KisConfig cfg; #ifdef HAVE_OPENGL if (!QGLFormat::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableDoubleBuffering->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL()); chkUseTextureBuffer->setEnabled(cfg.useOpenGL()); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer()); chkDisableDoubleBuffering->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableDoubleBuffering->setEnabled(cfg.useOpenGL()); chkDisableDoubleBuffering->setChecked(cfg.disableDoubleBuffering()); chkDisableVsync->setVisible(cfg.showAdvancedOpenGLSettings()); chkDisableVsync->setEnabled(cfg.useOpenGL()); chkDisableVsync->setChecked(cfg.disableVSync()); cmbFilterMode->setEnabled(cfg.useOpenGL()); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode()); // Don't show the high quality filtering mode if it's not available if (!KisOpenGL::supportsGLSL13()) { cmbFilterMode->removeItem(3); } } if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { grpOpenGL->setVisible(false); grpOpenGL->setMaximumHeight(0); } #else grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); #endif KoColor c; c.fromQColor(cfg.selectionOverlayMaskColor()); m_selectionOverlayColorAction = new KoColorPopupAction(this); m_selectionOverlayColorAction->setCurrentColor(c); - m_selectionOverlayColorAction->setIcon(koIcon("format-stroke-color")); + m_selectionOverlayColorAction->setIcon(KisIconUtils::loadIcon("format-stroke-color")); m_selectionOverlayColorAction->setToolTip(i18n("Change the background color of the image")); btnSelectionOverlayColor->setDefaultAction(m_selectionOverlayColorAction); intCheckSize->setValue(cfg.checkSize()); chkMoving->setChecked(cfg.scrollCheckers()); colorChecks1->setColor(cfg.checkersColor1()); colorChecks2->setColor(cfg.checkersColor2()); canvasBorder->setColor(cfg.canvasBorderColor()); hideScrollbars->setChecked(cfg.hideScrollbars()); chkCurveAntialiasing->setChecked(cfg.antialiasCurves()); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline()); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor()); chkHidePopups->setChecked(cfg.hidePopups()); connect(grpOpenGL, SIGNAL(toggled(bool)), SLOT(slotUseOpenGLToggled(bool))); } void DisplaySettingsTab::setDefault() { KisConfig cfg; #ifdef HAVE_OPENGL if (!QGLFormat::hasOpenGL()) { grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); chkUseTextureBuffer->setEnabled(false); chkDisableDoubleBuffering->setEnabled(false); chkDisableVsync->setEnabled(false); cmbFilterMode->setEnabled(false); } else { grpOpenGL->setEnabled(true); grpOpenGL->setChecked(cfg.useOpenGL(true)); chkUseTextureBuffer->setChecked(cfg.useOpenGLTextureBuffer(true)); chkUseTextureBuffer->setEnabled(true); chkDisableDoubleBuffering->setEnabled(true); chkDisableDoubleBuffering->setChecked(cfg.disableDoubleBuffering(true)); chkDisableVsync->setEnabled(true); chkDisableVsync->setChecked(cfg.disableVSync(true)); cmbFilterMode->setEnabled(true); cmbFilterMode->setCurrentIndex(cfg.openGLFilteringMode(true)); } #else grpOpenGL->setEnabled(false); grpOpenGL->setChecked(false); #endif chkMoving->setChecked(cfg.scrollCheckers(true)); intCheckSize->setValue(cfg.checkSize(true)); colorChecks1->setColor(cfg.checkersColor1(true)); colorChecks2->setColor(cfg.checkersColor2(true)); canvasBorder->setColor(cfg.canvasBorderColor(true)); hideScrollbars->setChecked(cfg.hideScrollbars(true)); chkCurveAntialiasing->setChecked(cfg.antialiasCurves(true)); chkSelectionOutlineAntialiasing->setChecked(cfg.antialiasSelectionOutline(true)); chkChannelsAsColor->setChecked(cfg.showSingleChannelAsColor(true)); chkHidePopups->setChecked(cfg.hidePopups(true)); } void DisplaySettingsTab::slotUseOpenGLToggled(bool isChecked) { #ifdef HAVE_OPENGL chkUseTextureBuffer->setEnabled(isChecked); chkDisableDoubleBuffering->setEnabled(isChecked); chkDisableVsync->setEnabled(isChecked); cmbFilterMode->setEnabled(isChecked); #else Q_UNUSED(isChecked); #endif } //--------------------------------------------------------------------------------------------------- GridSettingsTab::GridSettingsTab(QWidget* parent) : WdgGridSettingsBase(parent) { KisConfig cfg; selectMainStyle->setCurrentIndex(cfg.getGridMainStyle()); selectSubdivisionStyle->setCurrentIndex(cfg.getGridSubdivisionStyle()); colorMain->setColor(cfg.getGridMainColor()); colorSubdivision->setColor(cfg.getGridSubdivisionColor()); intHSpacing->setValue(cfg.getGridHSpacing()); intVSpacing->setValue(cfg.getGridVSpacing()); spacingAspectButton->setKeepAspectRatio(cfg.getGridSpacingAspect()); linkSpacingToggled(cfg.getGridSpacingAspect()); intSubdivision->setValue(cfg.getGridSubdivisions()); intXOffset->setValue(cfg.getGridOffsetX()); intYOffset->setValue(cfg.getGridOffsetY()); offsetAspectButton->setKeepAspectRatio(cfg.getGridOffsetAspect()); linkOffsetToggled(cfg.getGridOffsetAspect()); connect(spacingAspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(linkSpacingToggled(bool))); connect(offsetAspectButton, SIGNAL(keepAspectRatioChanged(bool)), this, SLOT(linkOffsetToggled(bool))); connect(intHSpacing, SIGNAL(valueChanged(int)), this, SLOT(spinBoxHSpacingChanged(int))); connect(intVSpacing, SIGNAL(valueChanged(int)), this, SLOT(spinBoxVSpacingChanged(int))); connect(intXOffset, SIGNAL(valueChanged(int)), this, SLOT(spinBoxXOffsetChanged(int))); connect(intYOffset, SIGNAL(valueChanged(int)), this, SLOT(spinBoxYOffsetChanged(int))); } void GridSettingsTab::setDefault() { KisConfig cfg; selectMainStyle->setCurrentIndex(cfg.getGridMainStyle(true)); selectSubdivisionStyle->setCurrentIndex(cfg.getGridSubdivisionStyle(true)); colorMain->setColor(cfg.getGridMainColor(true)); colorSubdivision->setColor(cfg.getGridSubdivisionColor(true)); intHSpacing->setValue(cfg.getGridHSpacing(true)); intVSpacing->setValue(cfg.getGridVSpacing(true)); linkSpacingToggled(cfg.getGridSpacingAspect(true)); intSubdivision->setValue(cfg.getGridSubdivisions(true)); intXOffset->setValue(cfg.getGridOffsetX(true)); intYOffset->setValue(cfg.getGridOffsetY()); linkOffsetToggled(cfg.getGridOffsetAspect(true)); } 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; if (m_linkSpacing) { intVSpacing->setValue(intHSpacing->value()); } } void GridSettingsTab::spinBoxXOffsetChanged(int v) { if (m_linkOffset) { intYOffset->setValue(v); } } void GridSettingsTab::spinBoxYOffsetChanged(int v) { if (m_linkOffset) { intXOffset->setValue(v); } } void GridSettingsTab::linkOffsetToggled(bool b) { m_linkOffset = b; if (m_linkOffset) { intYOffset->setValue(intXOffset->value()); } } //--------------------------------------------------------------------------------------------------- FullscreenSettingsTab::FullscreenSettingsTab(QWidget* parent) : WdgFullscreenSettingsBase(parent) { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen()); chkMenu->setChecked(cfg.hideMenuFullscreen()); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen()); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen()); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen()); chkToolbar->setChecked(cfg.hideToolbarFullscreen()); } void FullscreenSettingsTab::setDefault() { KisConfig cfg; chkDockers->setChecked(cfg.hideDockersFullscreen(true)); chkMenu->setChecked(cfg.hideMenuFullscreen(true)); chkScrollbars->setChecked(cfg.hideScrollbarsFullscreen(true)); chkStatusbar->setChecked(cfg.hideStatusbarFullscreen(true)); chkTitlebar->setChecked(cfg.hideTitlebarFullscreen(true)); chkToolbar->setChecked(cfg.hideToolbarFullscreen(true)); } //--------------------------------------------------------------------------------------------------- KisDlgPreferences::KisDlgPreferences(QWidget* parent, const char* name) : KPageDialog(parent) { Q_UNUSED(name); setCaption(i18n("Preferences")); setButtons(Ok | Cancel | Help | Default); setDefaultButton(Ok); showButtonSeparator(true); setFaceType(KPageDialog::List); // General KVBox *vbox = new KVBox(); KPageWidgetItem *page = new KPageWidgetItem(vbox, i18n("General")); page->setObjectName("general"); page->setHeader(i18n("General")); - page->setIcon(themedIcon("configure")); + page->setIcon(KisIconUtils::loadIcon("configure")); addPage(page); m_general = new GeneralTab(vbox); // Display vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Display")); page->setObjectName("display"); page->setHeader(i18n("Display")); - page->setIcon(themedIcon("preferences-desktop-display")); + page->setIcon(KisIconUtils::loadIcon("preferences-desktop-display")); addPage(page); m_displaySettings = new DisplaySettingsTab(vbox); // Color vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Color Management")); page->setObjectName("colormanagement"); page->setHeader(i18n("Color")); - page->setIcon(themedIcon("preferences-desktop-color")); + page->setIcon(KisIconUtils::loadIcon("preferences-desktop-color")); addPage(page); m_colorSettings = new ColorSettingsTab(vbox); // Performance vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Performance")); page->setObjectName("performance"); page->setHeader(i18n("Performance")); - page->setIcon(themedIcon("applications-system")); + page->setIcon(KisIconUtils::loadIcon("applications-system")); addPage(page); m_performanceSettings = new PerformanceTab(vbox); // Grid vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Grid")); page->setObjectName("grid"); page->setHeader(i18n("Grid")); - page->setIcon(themedIcon("view-grid")); + page->setIcon(KisIconUtils::loadIcon("view-grid")); addPage(page); m_gridSettings = new GridSettingsTab(vbox); // Tablet vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Tablet settings")); page->setObjectName("tablet"); page->setHeader(i18n("Tablet")); - page->setIcon(koIcon("input-tablet")); + page->setIcon(KisIconUtils::loadIcon("document-edit")); addPage(page); m_tabletSettings = new TabletSettingsTab(vbox); // full-screen mode vbox = new KVBox(); page = new KPageWidgetItem(vbox, i18n("Canvas-only settings")); page->setObjectName("canvasonly"); page->setHeader(i18n("Canvas-only")); - page->setIcon(themedIcon("folder-pictures")); + page->setIcon(KisIconUtils::loadIcon("folder-pictures")); addPage(page); m_fullscreenSettings = new FullscreenSettingsTab(vbox); // Author profiles m_authorPage = new KoConfigAuthorPage(); page = addPage(m_authorPage, i18nc("@title:tab Author page", "Author" )); page->setObjectName("author"); page->setHeader(i18n("Author")); - page->setIcon(themedIcon("im-user")); + page->setIcon(KisIconUtils::loadIcon("im-user")); // input settings m_inputConfiguration = new KisInputConfigurationPage(); page = addPage(m_inputConfiguration, i18n("Canvas Input Settings")); page->setHeader(i18n("Canvas Input")); page->setObjectName("canvasinput"); - page->setIcon(themedIcon("applications-system")); + page->setIcon(KisIconUtils::loadIcon("applications-system")); connect(this, SIGNAL(okClicked()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(applyClicked()), m_inputConfiguration, SLOT(saveChanges())); connect(this, SIGNAL(cancelClicked()), m_inputConfiguration, SLOT(revertChanges())); connect(this, SIGNAL(defaultClicked()), m_inputConfiguration, SLOT(setDefaults())); KisPreferenceSetRegistry *preferenceSetRegistry = KisPreferenceSetRegistry::instance(); foreach (KisAbstractPreferenceSetFactory *preferenceSetFactory, preferenceSetRegistry->values()) { KisPreferenceSet* preferenceSet = preferenceSetFactory->createPreferenceSet(); vbox = new KVBox(); page = new KPageWidgetItem(vbox, preferenceSet->name()); page->setHeader(preferenceSet->header()); page->setIcon(preferenceSet->icon()); addPage(page); preferenceSet->setParent(vbox); preferenceSet->loadPreferences(); connect(this, SIGNAL(defaultClicked()), preferenceSet, SLOT(loadDefaultPreferences()), Qt::UniqueConnection); connect(this, SIGNAL(okClicked()), preferenceSet, SLOT(savePreferences()), Qt::UniqueConnection); } connect(this, SIGNAL(defaultClicked()), this, SLOT(slotDefault())); } KisDlgPreferences::~KisDlgPreferences() { } void KisDlgPreferences::slotDefault() { if (currentPage()->objectName() == "default") { m_general->setDefault(); } else if (currentPage()->objectName() == "display") { m_displaySettings->setDefault(); } else if (currentPage()->objectName() == "colormanagement") { m_colorSettings->setDefault(); } else if (currentPage()->objectName() == "performance") { m_performanceSettings->load(true); } else if (currentPage()->objectName() == "grid") { m_gridSettings->setDefault(); } else if (currentPage()->objectName() == "tablet") { m_tabletSettings->setDefault(); } else if (currentPage()->objectName() == "canvasonly") { m_fullscreenSettings->setDefault(); } else if (currentPage()->objectName() == "canvasinput") { m_inputConfiguration->setDefaults(); } } bool KisDlgPreferences::editPreferences() { KisDlgPreferences* dialog; dialog = new KisDlgPreferences(); bool baccept = (dialog->exec() == Accepted); if (baccept) { // General settings KisConfig cfg; cfg.setNewCursorStyle(dialog->m_general->cursorStyle()); cfg.setNewOutlineStyle(dialog->m_general->outlineStyle()); cfg.setShowRootLayer(dialog->m_general->showRootLayer()); cfg.setShowOutlineWhilePainting(dialog->m_general->showOutlineWhilePainting()); cfg.setHideSplashScreen(dialog->m_general->hideSplashScreen()); cfg.writeEntry("mdi_viewmode", dialog->m_general->mdiMode()); cfg.setMDIBackgroundColor(dialog->m_general->m_mdiColor->color()); cfg.setMDIBackgroundImage(dialog->m_general->m_backgroundimage->text()); cfg.setAutoSaveInterval(dialog->m_general->autoSaveInterval()); cfg.setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); cfg.setShowCanvasMessages(dialog->m_general->showCanvasMessages()); cfg.setCompressKra(dialog->m_general->compressKra()); cfg.setToolOptionsInDocker(dialog->m_general->toolOptionsInDocker()); KisPart *part = KisPart::instance(); if (part) { foreach(QPointer doc, part->documents()) { if (doc) { doc->setAutoSave(dialog->m_general->autoSaveInterval()); doc->setBackupFile(dialog->m_general->m_backupFileCheckBox->isChecked()); doc->undoStack()->setUndoLimit(dialog->m_general->undoStackSize()); } } } cfg.setUndoStackLimit(dialog->m_general->undoStackSize()); cfg.setFavoritePresets(dialog->m_general->favoritePresets()); // Color settings cfg.setUseSystemMonitorProfile(dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); for (int i = 0; i < QApplication::desktop()->screenCount(); ++i) { if (dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()) { int currentIndex = dialog->m_colorSettings->m_monitorProfileWidgets[i]->currentIndex(); QString monitorid = dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemData(currentIndex).toString(); cfg.setMonitorForScreen(i, monitorid); } else { cfg.setMonitorProfile(i, dialog->m_colorSettings->m_monitorProfileWidgets[i]->itemHighlighted(), dialog->m_colorSettings->m_page->chkUseSystemMonitorProfile->isChecked()); } } cfg.setWorkingColorSpace(dialog->m_colorSettings->m_page->cmbWorkingColorSpace->currentItem().id()); cfg.setPrinterColorSpace(dialog->m_colorSettings->m_page->cmbPrintingColorSpace->currentItem().id()); cfg.setPrinterProfile(dialog->m_colorSettings->m_page->cmbPrintProfile->itemHighlighted()); cfg.setUseBlackPointCompensation(dialog->m_colorSettings->m_page->chkBlackpoint->isChecked()); cfg.setAllowLCMSOptimization(dialog->m_colorSettings->m_page->chkAllowLCMSOptimization->isChecked()); cfg.setPasteBehaviour(dialog->m_colorSettings->m_pasteBehaviourGroup.checkedId()); cfg.setRenderIntent(dialog->m_colorSettings->m_page->cmbMonitorIntent->currentIndex()); // Tablet settings cfg.setPressureTabletCurve( dialog->m_tabletSettings->m_page->pressureCurve->curve().toString() ); dialog->m_performanceSettings->save(); #ifdef HAVE_OPENGL if (!cfg.useOpenGL() && dialog->m_displaySettings->grpOpenGL->isChecked()) cfg.setCanvasState("TRY_OPENGL"); cfg.setUseOpenGL(dialog->m_displaySettings->grpOpenGL->isChecked()); cfg.setUseOpenGLTextureBuffer(dialog->m_displaySettings->chkUseTextureBuffer->isChecked()); cfg.setOpenGLFilteringMode(dialog->m_displaySettings->cmbFilterMode->currentIndex()); cfg.setDisableDoubleBuffering(dialog->m_displaySettings->chkDisableDoubleBuffering->isChecked()); cfg.setDisableVSync(dialog->m_displaySettings->chkDisableVsync->isChecked()); #endif cfg.setCheckSize(dialog->m_displaySettings->intCheckSize->value()); cfg.setScrollingCheckers(dialog->m_displaySettings->chkMoving->isChecked()); cfg.setCheckersColor1(dialog->m_displaySettings->colorChecks1->color()); cfg.setCheckersColor2(dialog->m_displaySettings->colorChecks2->color()); cfg.setCanvasBorderColor(dialog->m_displaySettings->canvasBorder->color()); cfg.setHideScrollbars(dialog->m_displaySettings->hideScrollbars->isChecked()); cfg.setSelectionOverlayMaskColor(dialog->m_displaySettings->m_selectionOverlayColorAction->currentKoColor().toQColor()); cfg.setAntialiasCurves(dialog->m_displaySettings->chkCurveAntialiasing->isChecked()); cfg.setAntialiasSelectionOutline(dialog->m_displaySettings->chkSelectionOutlineAntialiasing->isChecked()); cfg.setShowSingleChannelAsColor(dialog->m_displaySettings->chkChannelsAsColor->isChecked()); cfg.setHidePopups(dialog->m_displaySettings->chkHidePopups->isChecked()); // Grid settings cfg.setGridMainStyle(dialog->m_gridSettings->selectMainStyle->currentIndex()); cfg.setGridSubdivisionStyle(dialog->m_gridSettings->selectSubdivisionStyle->currentIndex()); 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.setGridSpacingAspect(dialog->m_gridSettings->spacingAspectButton->keepAspectRatio()); cfg.setGridSubdivisions(dialog->m_gridSettings->intSubdivision->value()); cfg.setGridOffsetX(dialog->m_gridSettings->intXOffset->value()); cfg.setGridOffsetY(dialog->m_gridSettings->intYOffset->value()); cfg.setGridOffsetAspect(dialog->m_gridSettings->offsetAspectButton->keepAspectRatio()); cfg.setHideDockersFullscreen(dialog->m_fullscreenSettings->chkDockers->checkState()); cfg.setHideMenuFullscreen(dialog->m_fullscreenSettings->chkMenu->checkState()); cfg.setHideScrollbarsFullscreen(dialog->m_fullscreenSettings->chkScrollbars->checkState()); cfg.setHideStatusbarFullscreen(dialog->m_fullscreenSettings->chkStatusbar->checkState()); cfg.setHideTitlebarFullscreen(dialog->m_fullscreenSettings->chkTitlebar->checkState()); cfg.setHideToolbarFullscreen(dialog->m_fullscreenSettings->chkToolbar->checkState()); dialog->m_authorPage->apply(); } delete dialog; return baccept; } #include "kis_dlg_preferences.moc" diff --git a/krita/ui/flake/kis_dummies_facade_base.h b/krita/ui/flake/kis_dummies_facade_base.h index a8b758902cf..86eba0b2a52 100644 --- a/krita/ui/flake/kis_dummies_facade_base.h +++ b/krita/ui/flake/kis_dummies_facade_base.h @@ -1,103 +1,103 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DUMMIES_FACADE_BASE_H #define __KIS_DUMMIES_FACADE_BASE_H #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" class KisNodeDummy; /** * Keeps track of the node stack and manages local (UI-wide) representation * of the node stack. It uses KisNodeDummy objects to represent the stack. * This is done to break synchronization tie between UI and Image threads, * caused by the fact that KisNodeModel must be synchronously notified * when a node is removed/deleted. */ class KRITAUI_EXPORT KisDummiesFacadeBase : public QObject { Q_OBJECT public: KisDummiesFacadeBase(QObject *parent = 0); virtual ~KisDummiesFacadeBase(); void setImage(KisImageWSP image); virtual bool hasDummyForNode(KisNodeSP node) const = 0; virtual KisNodeDummy* dummyForNode(KisNodeSP node) const = 0; virtual KisNodeDummy* rootDummy() const = 0; virtual int dummiesCount() const = 0; protected: KisImageWSP image() const; virtual void addNodeImpl(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis) = 0; virtual void removeNodeImpl(KisNodeSP node) = 0; Q_SIGNALS: void sigContinueAddNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void sigContinueRemoveNode(KisNodeSP node); /** * The signals for controlling the node model */ void sigBeginInsertDummy(KisNodeDummy *parent, int index, const QString &metaObjectType); void sigEndInsertDummy(KisNodeDummy *dummy); void sigBeginRemoveDummy(KisNodeDummy *dummy); void sigEndRemoveDummy(); void sigDummyChanged(KisNodeDummy *dummy); /** * This signal is emitted when the shape controller wants to request * the change of an active layer. E.g. when a new layer is added or * when the root layer of the image is changed. It should be forwarded * through a signal to allow queueing and synchronization of threads. */ void sigActivateNode(KisNodeSP node); private Q_SLOTS: void slotLayersChanged(); void slotNodeChanged(KisNodeSP node); void slotNodeActivationRequested(KisNodeSP node); void slotNodeAdded(KisNodeSP node); void slotRemoveNode(KisNodeSP node); void slotContinueAddNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void slotContinueRemoveNode(KisNodeSP node); private: static KisNodeSP findFirstLayer(KisNodeSP root); private: struct Private; Private * const m_d; }; #endif /* __KIS_DUMMIES_FACADE_BASE_H */ diff --git a/krita/ui/flake/kis_node_dummies_graph.h b/krita/ui/flake/kis_node_dummies_graph.h index 4303f5894f0..9b8ac596e10 100644 --- a/krita/ui/flake/kis_node_dummies_graph.h +++ b/krita/ui/flake/kis_node_dummies_graph.h @@ -1,145 +1,145 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_NODE_DUMMIES_GRAPH_H #define __KIS_NODE_DUMMIES_GRAPH_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_types.h" #include "kis_node.h" class KisNodeShape; /** * KisNodeDummy is a simplified representation of a node * in the node stack. It stores all the hierarchy information * about the node, so you needn't access from the node * directly (actually, you cannot do it usually, because UI * works in a different thread and race conditions are possible). * * The dummy stores a KisNodeShape which can store a pointer to * to node. You can access to the node data through it, but take * care -- not all the information is accessible in * multithreading environment. * * The ownership on the KisNodeShape is taken by the dummy. * The ownership on the children of the dummy is taken as well. */ class KRITAUI_EXPORT KisNodeDummy { public: /** * Take care tha KisNodeDummy does not take ownership over * the \p nodeShape since the handling of the removal of the * children of the shape is done by flake. So please handle it * manually. * * The children dummies of the dummy are still owned by the * dummy and are deleted automatically. */ KisNodeDummy(KisNodeShape *nodeShape, KisNodeSP node); ~KisNodeDummy(); KisNodeDummy* firstChild() const; KisNodeDummy* lastChild() const; KisNodeDummy* nextSibling() const; KisNodeDummy* prevSibling() const; KisNodeDummy* parent() const; KisNodeDummy* at(int index) const; int childCount() const; int indexOf(KisNodeDummy *child) const; KisNodeSP node() const; private: friend class KisNodeShapesGraph; // for ::nodeShape() method friend class KisNodeShapesGraphTest; KisNodeShape* nodeShape() const; friend class KisNodeDummiesGraph; KisNodeDummy *m_parent; QList m_children; KisNodeShape *m_nodeShape; KisNodeSP m_node; }; /** * KisNodeDummiesGraph manages the hierarchy of dummy objects * representing nodes in the UI environment. */ class KRITAUI_EXPORT KisNodeDummiesGraph { public: KisNodeDummiesGraph(); KisNodeDummy* rootDummy() const; KisNodeDummy* nodeToDummy(KisNodeSP node); bool containsNode(KisNodeSP node) const; int dummiesCount() const; /** * Adds a dummy \p node to the position specified * by \p parent and \p aboveThis. * * It is not expected that you would add a dummy twice. */ void addNode(KisNodeDummy *node, KisNodeDummy *parent, KisNodeDummy *aboveThis); /** * Moves a dummy \p node from its current position to * the position specified by \p parent and \p aboveThis. * * It is expected that the dummy \p node has been added * to the graph with addNode() before calling this function. */ void moveNode(KisNodeDummy *node, KisNodeDummy *parent, KisNodeDummy *aboveThis); /** * Removes the dummy \p node from the graph. * * WARNING: The dummy is only "unlinked" from the graph. Neither * deletion of the node nor deletion of its children happens. * The dummy keeps maintaining its children so after unlinking * it from the graph you can just type to free memory recursively: * \code * graph.removeNode(node); * delete node; * \endcode */ void removeNode(KisNodeDummy *node); private: void unmapDummyRecursively(KisNodeDummy *dummy); private: typedef QMap NodeMap; private: KisNodeDummy *m_rootDummy; NodeMap m_dummiesMap; }; #endif /* __KIS_NODE_DUMMIES_GRAPH_H */ diff --git a/krita/ui/flake/kis_node_shape.h b/krita/ui/flake/kis_node_shape.h index 28806d612ce..a145a5312ef 100644 --- a/krita/ui/flake/kis_node_shape.h +++ b/krita/ui/flake/kis_node_shape.h @@ -1,67 +1,67 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_NODE_SHAPE_H_ #define KIS_NODE_SHAPE_H_ #include #include -#include +#include #include class KoViewConverter; #define KIS_NODE_SHAPE_ID "KisNodeShape" /** * A KisNodeShape is a flake wrapper around Krita nodes. It is used * for dealing with currently active node for tools. */ class KRITAUI_EXPORT KisNodeShape : public QObject, public KoShapeLayer { Q_OBJECT public: KisNodeShape(KisNodeSP node); virtual ~KisNodeShape(); KisNodeSP node(); // Empty implementations as the node is not painted anywhere QSizeF size() const; QRectF boundingRect() const; void setPosition(const QPointF &); void paint(QPainter &painter, const KoViewConverter &converter, KoShapePaintingContext &paintcontext); void saveOdf(KoShapeSavingContext & context) const; bool loadOdf(const KoXmlElement & element, KoShapeLoadingContext &context); private Q_SLOTS: void setNodeVisible(bool); void editabilityChanged(); private: bool checkIfDescendant(KoShapeLayer *activeLayer); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/flake/kis_shape_layer.h b/krita/ui/flake/kis_shape_layer.h index 6bd2a747989..bbf52d52bb5 100644 --- a/krita/ui/flake/kis_shape_layer.h +++ b/krita/ui/flake/kis_shape_layer.h @@ -1,148 +1,148 @@ /* * Copyright (c) 2006 Boudewijn Rempt * Copyright (c) 2007 Thomas Zander * * 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_SHAPE_LAYER_H_ #define KIS_SHAPE_LAYER_H_ #include #include #include -#include +#include class QRect; class QIcon; class QRect; class QString; class KoShapeManager; class KoStore; class KoViewConverter; class KoShapeBasedDocumentBase; const QString KIS_SHAPE_LAYER_ID = "KisShapeLayer"; /** A KisShapeLayer contains any number of non-krita flakes, such as path shapes, text shapes and anything else people come up with. The KisShapeLayer has a shapemanager and a canvas of its own. The canvas paints onto the projection, and the projection is what we render in Krita. This means that no matter how many views you have, you cannot have a different view on your shapes per view. XXX: what about removing shapes? */ class KRITAUI_EXPORT KisShapeLayer : public KisExternalLayer, public KoShapeLayer { Q_OBJECT public: KisShapeLayer(KoShapeBasedDocumentBase* shapeController, KisImageWSP image, const QString &name, quint8 opacity); KisShapeLayer(const KisShapeLayer& _rhs); /** * Merge constructor. * * Creates a new layer as a merge of two existing layers. * * This is used by createMergedLayer() */ KisShapeLayer(const KisShapeLayer& _merge, const KisShapeLayer &_addShapes); virtual ~KisShapeLayer(); private: void initShapeLayer(KoShapeBasedDocumentBase* controller); public: KisNodeSP clone() const { return new KisShapeLayer(*this); } bool allowAsChild(KisNodeSP) const; virtual void setImage(KisImageWSP image); virtual KisLayerSP createMergedLayer(KisLayerSP prevLayer); public: // KoShape overrides bool isSelectable() const { return false; } void setParent(KoShapeContainer *parent); // KisExternalLayer implementation QIcon icon() const; void resetCache(); KisPaintDeviceSP original() const; KisPaintDeviceSP paintDevice() const; qint32 x() const; qint32 y() const; void setX(qint32); void setY(qint32); bool accept(KisNodeVisitor&); void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); KoShapeManager *shapeManager() const; bool saveLayer(KoStore * store) const; bool loadLayer(KoStore* store); KUndo2Command* crop(const QRect & rect); KUndo2Command* transform(const QTransform &transform); bool visible(bool recursive = false) const; void setVisible(bool visible, bool isLoading = false); protected: using KoShape::isVisible; friend class ShapeLayerContainerModel; KoViewConverter* converter() const; Q_SIGNALS: /** * These signals are forwarded from the local shape manager * This is done because we switch KoShapeManager and therefore * KoSelection in KisCanvas2, so we need to connect local managers * to the UI as well. * * \see comment in the constructor of KisCanvas2 */ void selectionChanged(); void currentLayerChanged(const KoShapeLayer *layer); Q_SIGNALS: /** * A signal + slot to synchronize UI and image * threads. Image thread emits the signal, UI * thread performes the action */ void sigMoveShapes(const QPointF &diff); private Q_SLOTS: void slotMoveShapes(const QPointF &diff); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/flake/kis_shape_selection.h b/krita/ui/flake/kis_shape_selection.h index d8fadce890f..6c26a8da202 100644 --- a/krita/ui/flake/kis_shape_selection.h +++ b/krita/ui/flake/kis_shape_selection.h @@ -1,128 +1,128 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SHAPE_SELECTION_H #define KIS_SHAPE_SELECTION_H #include #include #include #include #include #include -#include +#include class KoStore; class KoShapeManager; class KisShapeSelectionCanvas; class KisShapeSelectionModel; class KisImageViewConverter; class KUndo2Command; /** * The marker class. * It is added to the shape's user data to show this shape * is a part of a shape selection */ class KisShapeSelectionMarker : public KoShapeUserData { }; class KRITAUI_EXPORT KisShapeSelection : public KoShapeLayer, public KisSelectionComponent { KisShapeSelection(const KisShapeSelection& rhs); public: KisShapeSelection(KisImageWSP image, KisSelectionWSP selection); virtual ~KisShapeSelection(); KisShapeSelection(const KisShapeSelection& rhs, KisSelection* selection); KisSelectionComponent* clone(KisSelection* selection); bool saveSelection(KoStore * store) const; bool loadSelection(KoStore * store); /** * Renders the shapes to a selection. This method should only be called * by KisSelection to update it's projection. * * @param projection the target selection */ virtual void renderToProjection(KisPaintDeviceSP projection); virtual void renderToProjection(KisPaintDeviceSP projection, const QRect& r); KUndo2Command* resetToEmpty(); bool isEmpty() const; QPainterPath outlineCache() const; bool outlineCacheValid() const; void recalculateOutlineCache(); KoShapeManager *shapeManager() const; void moveX(qint32 x); void moveY(qint32 y); KUndo2Command* transform(const QTransform &transform); protected: virtual void paintComponent(QPainter& painter, const KoViewConverter& converter, KoShapePaintingContext &paintcontext); private: friend class KisTakeAllShapesCommand; void setUpdatesEnabled(bool enabled); bool updatesEnabled() const; private: void renderSelection(KisPaintDeviceSP projection, const QRect& r); KisImageWSP m_image; QPainterPath m_outline; KisImageViewConverter* m_converter; KisShapeSelectionCanvas* m_canvas; KisShapeSelectionModel* m_model; friend class KisShapeSelectionModel; }; class KRITAUI_EXPORT KisShapeSelectionFactory : public KoShapeFactoryBase { public: KisShapeSelectionFactory(); ~KisShapeSelectionFactory() {} virtual KoShape *createDefaultShape(KoDocumentResourceManager *documentResources = 0) const { Q_UNUSED(documentResources); return 0; } virtual bool supports(const KoXmlElement & e, KoShapeLoadingContext &context) const { Q_UNUSED(e); Q_UNUSED(context); return false; } }; #endif diff --git a/krita/ui/flake/kis_take_all_shapes_command.h b/krita/ui/flake/kis_take_all_shapes_command.h index e281fec5877..5a84758690b 100644 --- a/krita/ui/flake/kis_take_all_shapes_command.h +++ b/krita/ui/flake/kis_take_all_shapes_command.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TAKE_ALL_SHAPES_COMMAND_H #define __KIS_TAKE_ALL_SHAPES_COMMAND_H #include #include "kundo2command.h" -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_types.h" class KoShape; class KisShapeSelection; class KisTakeAllShapesCommand : public KUndo2Command { public: KisTakeAllShapesCommand(KisShapeSelection *shapeSelection, bool takeSilently); ~KisTakeAllShapesCommand(); void redo(); void undo(); private: KisShapeSelection *m_shapeSelection; QList m_shapes; bool m_takeSilently; }; #endif /* __KIS_TAKE_ALL_SHAPES_COMMAND_H */ diff --git a/krita/ui/input/kis_abstract_input_action.h b/krita/ui/input/kis_abstract_input_action.h index 18307823bea..fb30e3df29e 100644 --- a/krita/ui/input/kis_abstract_input_action.h +++ b/krita/ui/input/kis_abstract_input_action.h @@ -1,202 +1,202 @@ /* This file is part of the KDE project * Copyright (C) 2012 Arjen Hiemstra * * 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_ABSTRACT_INPUT_ACTION_H #define KIS_ABSTRACT_INPUT_ACTION_H #include -#include "krita_export.h" +#include "kritaui_export.h" class QPointF; class QEvent; class KisInputManager; /** * \brief Abstract base class for input actions. * * Input actions represent actions to be performed when interacting * with the canvas. They are managed by KisInputManager and activated * when KisKeyShortcut or KisStrokeShortcut detects it matches a certain * set of inputs. * * The begin() method uses an index for the type of behaviour to activate. * This index can be used to trigger behaviour when different events occur. * * The events can be of two types: * 1) Key events. The input manager calls begin() and end() sequentially * with an \p index parameter to begin() representing the type of * action that should be performed. The \p event parameter of both * calls in null. * 2) Stroke events. The input manager calls begin() and end() on the * corresponding mouse down and up events. The \p event parameter * will be of QMouseEvent type, representing the event happened. * All the mouse move events between begin() and end() will be * redirected to the inputEvent() method. * * You can fetch the QTabletEvent data for the current mouse event * with inputManager()->lastTabletEvent(). */ class KRITAUI_EXPORT KisAbstractInputAction { public: /** * Constructor. * * \param manager The InputManager this action belongs to. */ explicit KisAbstractInputAction(const QString &id); /** * Destructor. */ virtual ~KisAbstractInputAction(); /** * The method is called when the action is yet to be started, * that is, e.g. the user has pressed all the modifiers for the * action but hasn't started painting yet. This method is a right * place to show the user what is going to happen, e.g. change the * cursor. */ virtual void activate(int shortcut); /** * The method is called when the action is not a candidate for * the starting anymore. The action should revert everything that * was done in activate() method. * * \see activate() */ virtual void deactivate(int shortcut); /** * Begin the action. * * \param shortcut The index of the behaviour to trigger. * \param event The mouse event that has triggered this action. * Is null for keyboard-activated actions. */ virtual void begin(int shortcut, QEvent *event); /** * End the action. * \param event The mouse event that has finished this action. * Is null for keyboard-activated actions. */ virtual void end(QEvent *event); /** * Process an input event. * * By default handles MouseMove events and passes the data to * a convenience mouseMoved() method * * \param event An event to process. */ virtual void inputEvent(QEvent* event); /** * Returns true if the action can handle HiRes flow of move events * which is generated by the tablet. If the function returns * false, some of the events will be dropped or postponed. For * most of the actions in Krita (except of real painting) it is * perfectly acceptable, so 'false' is the default value. */ virtual bool supportsHiResInputEvents() const; /** * The indexes of shortcut behaviours available. */ virtual QHash shortcutIndexes() const; /** * The id of this action. */ virtual QString id() const; /** * The translated name of this action. */ virtual QString name() const; /** * A short description of this action. */ virtual QString description() const; /** * The priority for this action. * * Priority determines how "important" the action is and is used * to resolve conflicts when multiple actions can be activated. */ virtual int priority() const; /** * Returns true if an action can run with any modifiers pressed * (the shortcut's modifiers list must be empty for that). That is * used for making one type of actions default one. */ virtual bool canIgnoreModifiers() const; /** * Return true when the specified shortcut is required for basic * user interaction. This is used by the configuration system to * prevent basic actions like painting from being removed. * * \param shortcut The shortcut index to check. * \return True if the shortcut is required, false if not. */ virtual bool isShortcutRequired(int shortcut) const; protected: /** * The input manager this action belongs to. */ KisInputManager *inputManager() const; /** * Set the name of this action. * * \param name The new name. */ void setName(const QString &name); /** * Set the description of this action. * * \param description The new description. */ void setDescription(const QString &description); /** * Set the available indexes of shortcut behaviours. * * \param indexes The new indexes. */ void setShortcutIndexes(const QHash &indexes); /** * Convenience method for handling the mouse moves. It is * called by the default implementation of inputEvent */ virtual void mouseMoved(const QPointF &lastPos, const QPointF &pos); private: friend class KisInputManager; static void setInputManager(KisInputManager *manager); class Private; Private * const d; }; #endif // KIS_ABSTRACT_INPUT_ACTION_H diff --git a/krita/ui/input/kis_abstract_shortcut.h b/krita/ui/input/kis_abstract_shortcut.h index 12a8a85028e..29085d526f5 100644 --- a/krita/ui/input/kis_abstract_shortcut.h +++ b/krita/ui/input/kis_abstract_shortcut.h @@ -1,67 +1,67 @@ /* * Copyright (C) 2012 Arjen Hiemstra * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ABSTRACT_SHORTCUT_H #define __KIS_ABSTRACT_SHORTCUT_H #include #include -#include +#include class KisAbstractInputAction; class KRITAUI_EXPORT KisAbstractShortcut { public: KisAbstractShortcut(KisAbstractInputAction *action, int index); virtual ~KisAbstractShortcut(); /** * The priority of the shortcut. The shortcut with the * greatest value will be chosen for executution */ virtual int priority() const = 0; /** * The action associated with this shortcut. */ KisAbstractInputAction* action() const; /** * Set the action associated with this shortcut. */ void setAction(KisAbstractInputAction *action); /** * The index of the shortcut. * * \see KisAbstractInputAction::begin() */ int shortcutIndex() const; protected: bool compareKeys(const QList &keys1, const QList &keys2); private: class Private; Private * const m_d; }; #endif /* __KIS_ABSTRACT_SHORTCUT_H */ diff --git a/krita/ui/input/kis_input_manager.h b/krita/ui/input/kis_input_manager.h index e978d24c193..4c2b5e24633 100644 --- a/krita/ui/input/kis_input_manager.h +++ b/krita/ui/input/kis_input_manager.h @@ -1,131 +1,131 @@ /* This file is part of the KDE project * Copyright (C) 2012 Arjen Hiemstra * * 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_INPUTMANAGER_H #define KIS_INPUTMANAGER_H #include -#include +#include class QPointF; class QTabletEvent; class QTouchEvent; class KisToolProxy; class KisCanvas2; /** * \brief Central object to manage canvas input. * * The Input Manager class manages all canvas input. It is created * by KisCanvas2 and processes all events related to input sent to the * canvas. * * The Input Manager keeps track of a set of actions and a set of * shortcuts. The actions are pre-defined while the shortcuts are * set from configuration. * * For each event, it will try to determine if there is a shortcut that * matches the input. It will then activate this action and pass all * consecutive events on to this action. * * \sa KisAbstractInputAction * * \todo Implement shortcut configuration */ class KRITAUI_EXPORT KisInputManager : public QObject { Q_OBJECT public: /** * Constructor. */ KisInputManager(QObject *parent); /** * Destructor. */ ~KisInputManager(); void addTrackedCanvas(KisCanvas2 *canvas); void removeTrackedCanvas(KisCanvas2 *canvas); void toggleTabletLogger(); /** * Installs the input manager as an event filter for \p receiver. * Please note that KisInputManager is supposed to handle events * for a single receiver only. This is defined by the fact that it * resends some of the events back through the Qt's queue to the * reciever. That is why the input manager will assert when it gets * an event with wrong destination. */ void setupAsEventFilter(QObject *receiver); /** * Event filter method. Overridden from QObject. */ bool eventFilter(QObject* object, QEvent* event ); void attachPriorityEventFilter(QObject *filter); void detachPriorityEventFilter(QObject *filter); /** * Return the canvas this input manager is associated with. */ KisCanvas2 *canvas() const; /** * The tool proxy of the current application. */ KisToolProxy *toolProxy() const; /** * Returns the event object for the last tablet event * happened. Returns null if there was no tablet event recently */ QTabletEvent *lastTabletEvent() const; /** * Touch events are special, too. * * \return a touch event if there was one, otherwise 0 */ QTouchEvent *lastTouchEvent() const; /** * Convert a widget position to a document position. */ QPointF widgetToDocument(const QPointF &position); public Q_SLOTS: void stopIgnoringEvents(); void slotFocusOnEnter(bool value); private Q_SLOTS: void slotToolChanged(); void profileChanged(); void slotCompressedMoveEvent(); private: class Private; Private* const d; }; #endif // KIS_INPUTMANAGER_H diff --git a/krita/ui/input/kis_input_profile_manager.h b/krita/ui/input/kis_input_profile_manager.h index 198b992893c..e21f2addc2c 100644 --- a/krita/ui/input/kis_input_profile_manager.h +++ b/krita/ui/input/kis_input_profile_manager.h @@ -1,148 +1,148 @@ /* * This file is part of the KDE project * Copyright (C) 2013 Arjen Hiemstra * * 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 KISINPUTPROFILEMANAGER_H #define KISINPUTPROFILEMANAGER_H #include -#include "krita_export.h" +#include "kritaui_export.h" class KisAbstractInputAction; class KisInputProfile; /** * \brief A class to manage a list of profiles and actions. * * */ class KRITAUI_EXPORT KisInputProfileManager : public QObject { Q_OBJECT public: KisInputProfileManager(QObject *parent = 0); ~KisInputProfileManager(); Q_DISABLE_COPY(KisInputProfileManager) /** * Retrieve a profile by name. * * \param name The name of the profile to retrieve. * * \return The profile with the given name, or 0 if not found. */ KisInputProfile *profile(const QString &name) const; /** * \return A list of all profiles. */ QList profiles() const; /** * \return A list of the names of all profiles. */ QStringList profileNames() const; /** * \return The current active profile. */ KisInputProfile *currentProfile() const; /** * Set the current active profile. * * \param profile The profile to set as current. */ void setCurrentProfile(KisInputProfile *profile); /** * Add a profile. * * \param name The name of the new profile. * * \return The new, empty profile or the non-empty profile if it already exists. */ KisInputProfile *addProfile(const QString &name); /** * Remove a profile. * * This will remove the given profile from the list of profiles and delete it. * * \param name The profile to remove. */ void removeProfile(const QString &name); /** * Rename a profile. * * \param oldName The current name of the profile. * \param newName The new name of the profile. * * \return true if successful, false if not. */ bool renameProfile(const QString &oldName, const QString &newName); /** * Duplicate a profile. * * This creates a new profile with the given name and copies all * data from the old profile to the new profile. * * \param name The name of the profile to duplicate. * \param newName The name of the new profile. */ void duplicateProfile(const QString &name, const QString &newName); /** * \return The list of all available actions. */ QList< KisAbstractInputAction * > actions(); /** * Load all profiles from the configuration stored on disk. */ void loadProfiles(); /** * Save all profiles to configuration on disk. */ void saveProfiles(); /** * Reset all profiles to the default state. * * This will remove all custom profiles the user created and reset any changed profiles. */ void resetAll(); /** * \return The singleton instance of this class. */ static KisInputProfileManager *instance(); Q_SIGNALS: /** * Emitted when the list of profiles changes. */ void profilesChanged(); /** * Emitted when the current active profile changes. */ void currentProfileChanged(); private: class Private; Private *const d; }; #endif // KISINPUTPROFILEMANAGER_H diff --git a/krita/ui/input/wintab/kis_tablet_support_win.h b/krita/ui/input/wintab/kis_tablet_support_win.h index cc37c28a34c..9ab4ba43826 100644 --- a/krita/ui/input/wintab/kis_tablet_support_win.h +++ b/krita/ui/input/wintab/kis_tablet_support_win.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2013 Digia Plc and/or its subsidiary(-ies). * Copyright (c) 2013 Boudewijn Rempt * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TABLET_SUPPORT_WIN_H #define KIS_TABLET_SUPPORT_WIN_H #include -#include +#include #ifndef _WINDEF_ typedef unsigned long DWORD; #endif class KRITAUI_EXPORT KisTabletSupportWin { public: struct KRITAUI_EXPORT ButtonsConverter { virtual ~ButtonsConverter() {} virtual void convert(DWORD btnOld, DWORD btnNew, Qt::MouseButton *button, Qt::MouseButtons *buttons) = 0; }; public: static void init(); static void setButtonsConverter(ButtonsConverter *buttonsConverter); static bool eventFilter(void *message, long *result); }; #endif // KIS_TABLET_SUPPORT_WIN_H diff --git a/krita/ui/input/wintab/kis_tablet_support_x11.h b/krita/ui/input/wintab/kis_tablet_support_x11.h index d16f59dd942..0ff752c8e54 100644 --- a/krita/ui/input/wintab/kis_tablet_support_x11.h +++ b/krita/ui/input/wintab/kis_tablet_support_x11.h @@ -1,32 +1,32 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TABLET_SUPPORT_X11_H #define __KIS_TABLET_SUPPORT_X11_H -#include +#include class KRITAUI_EXPORT KisTabletSupportX11 { public: static void init(); static bool eventFilter(void *message, long *result); }; #endif /* __KIS_TABLET_SUPPORT_X11_H */ diff --git a/krita/ui/kis_abstract_perspective_grid.h b/krita/ui/kis_abstract_perspective_grid.h index ab1bf766e99..26d90359d2d 100644 --- a/krita/ui/kis_abstract_perspective_grid.h +++ b/krita/ui/kis_abstract_perspective_grid.h @@ -1,47 +1,47 @@ /* * This file is part of Krita * * Copyright (c) 2010 Geoffry Song * * 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_ABSTRACT_PERSPECTIVE_GRID_H #define KIS_ABSTRACT_PERSPECTIVE_GRID_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KRITAUI_EXPORT KisAbstractPerspectiveGrid : public QObject { Q_OBJECT public: KisAbstractPerspectiveGrid(QObject * parent = 0); virtual ~KisAbstractPerspectiveGrid() {} virtual bool contains(const QPointF& pt) const = 0; /** * Returns the reciprocal of the distance from the given point * to the 'observer', in the range [0, 1] where 0 = inifinite * distance and 1 = closest. */ virtual qreal distance(const QPointF& pt) const = 0; }; #endif diff --git a/krita/ui/kis_action.h b/krita/ui/kis_action.h index 0a469f26c3d..178cbc682ba 100644 --- a/krita/ui/kis_action.h +++ b/krita/ui/kis_action.h @@ -1,106 +1,106 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_ACTION_H #define KIS_ACTION_H #include -#include +#include #include class KisActionManager; class KRITAUI_EXPORT KisAction : public KAction { Q_OBJECT public: enum ActivationFlag { NONE = 0x0000, ///< Always activate ACTIVE_IMAGE = 0x0001, ///< Activate if there is at least one image MULTIPLE_IMAGES = 0x0002, ///< Activate if there is more than one image open CURRENT_IMAGE_MODIFIED = 0x0004, ///< Activate if the current image is modified ACTIVE_NODE = 0x0008, ///< Activate if there's an active node (layer or mask) ACTIVE_DEVICE = 0x0010, ///< Activate if the active node has a paint device, i.e. there are pixels to be modified ACTIVE_LAYER = 0x0020, ///< Activate if the current node is a layer (vector or pixel) ACTIVE_TRANSPARENCY_MASK = 0x0040, ///< Activate if the current node is a transparency mask ACTIVE_SHAPE_LAYER = 0x0080, ///< Activate if the current node is a vector layer PIXELS_SELECTED = 0x0100, ///< Activate if there is an active pixel selection SHAPES_SELECTED = 0x0200, ///< Activate if there is an active vector selection PIXEL_SELECTION_WITH_PIXELS = 0x0400, ///< ??? PIXELS_IN_CLIPBOARD = 0x0800, ///< Activate if the clipboard contains pixels SHAPES_IN_CLIPBOARD = 0x1000, ///< Activate if the clipboard contains vector data NEVER_ACTIVATE = 0x2000, ///< }; Q_DECLARE_FLAGS(ActivationFlags, ActivationFlag) enum ActivationCondition { NO_CONDITION = 0, ACTIVE_NODE_EDITABLE = 0x1, ACTIVE_NODE_EDITABLE_PAINT_DEVICE = 0x2, SELECTION_EDITABLE = 0x4 }; Q_DECLARE_FLAGS(ActivationConditions, ActivationCondition) explicit KisAction(QObject* parent = 0); KisAction(const QString& text, QObject* parent = 0); KisAction(const KIcon& icon, const QString& text, QObject* parent = 0); virtual ~KisAction(); void setActivationFlags(ActivationFlags flags); ActivationFlags activationFlags(); void setActivationConditions(ActivationConditions conditions); ActivationConditions activationConditions(); void setExcludedNodeTypes(const QStringList &nodeTypes); const QStringList& excludedNodeTypes() const; virtual void setActionEnabled(bool enabled); /** * Set operation id. This will used to run an operation in the KisActionManager */ void setOperationID(const QString& id); Q_SIGNALS: void sigEnableSlaves(bool value); private Q_SLOTS: void slotTriggered(); void slotChanged(); private: friend class KisActionManager; /** * Set the action manager. Only used by KisActionManager */ void setActionManager(KisActionManager* actionManager); class Private; Private* const d; }; Q_DECLARE_OPERATORS_FOR_FLAGS(KisAction::ActivationFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(KisAction::ActivationConditions) #endif // KIS_ACTION_H diff --git a/krita/ui/kis_action_manager.h b/krita/ui/kis_action_manager.h index a62e91b98dd..14e52b0d676 100644 --- a/krita/ui/kis_action_manager.h +++ b/krita/ui/kis_action_manager.h @@ -1,76 +1,76 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_ACTION_MANAGER_H #define KIS_ACTION_MANAGER_H -#include +#include #include #include "KisView.h" #include "kstandardaction.h" class KisViewManager; class KisAction; class KisOperationUIFactory; class KisOperation; class KisOperationConfiguration; /** * @brief The KisActionManager class keeps track of (nearly) all actions in krita, and enables * and disables the action depending on the state of the application. */ class KRITAUI_EXPORT KisActionManager { public: KisActionManager(KisViewManager* viewManager); virtual ~KisActionManager(); void setView(QPointer imageView); void addAction(const QString& name, KisAction* action); void takeAction(KisAction* action); KisAction *actionByName(const QString &name) const; void registerOperationUIFactory(KisOperationUIFactory* factory); void registerOperation(KisOperation* operation); void runOperation(const QString &id); void runOperationFromConfiguration(KisOperationConfiguration* config); void updateGUI(); /// Create a KisAction based on a KStandardAction. The KStandardAction is deleted. KisAction *createStandardAction(KStandardAction::StandardAction, const QObject *receiver, const char *member); private: void dumpActionFlags(); class Private; Private* const d; }; #endif // KIS_ACTION_MANAGER_H diff --git a/krita/ui/kis_asl_layer_style_serializer.h b/krita/ui/kis_asl_layer_style_serializer.h index 76be82df27c..13bd8dcfe5f 100644 --- a/krita/ui/kis_asl_layer_style_serializer.h +++ b/krita/ui/kis_asl_layer_style_serializer.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_ASL_LAYER_STYLE_SERIALIZER_H #define __KIS_ASL_LAYER_STYLE_SERIALIZER_H -#include "krita_export.h" +#include "kritaui_export.h" class QIODevice; class KoPattern; #include "kis_psd_layer_style.h" #include "asl/kis_asl_callback_object_catcher.h" class KRITAUI_EXPORT KisAslLayerStyleSerializer { public: KisAslLayerStyleSerializer(); ~KisAslLayerStyleSerializer(); void saveToDevice(QIODevice *device); void readFromDevice(QIODevice *device); QVector styles() const; void setStyles(const QVector &styles); void registerPSDPattern(const QDomDocument &doc); void readFromPSDXML(const QDomDocument &doc); QDomDocument formXmlDocument() const; QDomDocument formPsdXmlDocument() const; private: void registerPatternObject(const KoPattern *pattern); void assignPatternObject(const QString &patternUuid, const QString &patternName, boost::function setPattern); QVector fetchAllPatterns(KisPSDLayerStyle *style) const; void newStyleStarted(bool isPsdStructure); void connectCatcherToStyle(KisPSDLayerStyle *style, const QString &prefix); private: QHash m_patternsStore; KisAslCallbackObjectCatcher m_catcher; QVector m_stylesVector; }; #endif /* __KIS_ASL_LAYER_STYLE_SERIALIZER_H */ diff --git a/krita/ui/kis_bookmarked_configurations_editor.h b/krita/ui/kis_bookmarked_configurations_editor.h index 41389bdd536..86aebd1774a 100644 --- a/krita/ui/kis_bookmarked_configurations_editor.h +++ b/krita/ui/kis_bookmarked_configurations_editor.h @@ -1,53 +1,53 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_BOOKMARKED_CONFIGURATIONS_EDITOR_H_ #define _KIS_BOOKMARKED_CONFIGURATIONS_EDITOR_H_ #include -#include +#include class KisBookmarkedConfigurationsModel; class KisSerializableConfiguration; class QItemSelection; /** * This dialog is used to edit the content of a bookmark manager */ class KRITAUI_EXPORT KisBookmarkedConfigurationsEditor : public QDialog { Q_OBJECT public: /** * @param parent * @param manager the model representing the bookmark manager * @param currentConfig is used if the user choose to create a new configuration * entry or to replace an existing entry */ KisBookmarkedConfigurationsEditor(QWidget* parent, KisBookmarkedConfigurationsModel* manager, const KisSerializableConfiguration* currentConfig); ~KisBookmarkedConfigurationsEditor(); private Q_SLOTS: void currentConfigChanged(const QItemSelection& selected, const QItemSelection&); void addCurrentConfiguration(); void deleteConfiguration(); private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/kis_bookmarked_configurations_model.h b/krita/ui/kis_bookmarked_configurations_model.h index c950ae70467..866dcf9b5d1 100644 --- a/krita/ui/kis_bookmarked_configurations_model.h +++ b/krita/ui/kis_bookmarked_configurations_model.h @@ -1,91 +1,91 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_BOOKMARKED_CONFIGURATIONS_MODEL_H_ #define _KIS_BOOKMARKED_CONFIGURATIONS_MODEL_H_ #include -#include +#include class KLocalizedString; class KisBookmarkedConfigurationManager; class KisSerializableConfiguration; /** * This class provides the basic functionality for a model of a bookmark * of configurations. */ class KRITAUI_EXPORT KisBookmarkedConfigurationsModel : public QAbstractListModel { public: /** * Initialized thee model with the bookmarks manager */ KisBookmarkedConfigurationsModel(KisBookmarkedConfigurationManager*); ~KisBookmarkedConfigurationsModel(); /** * @return the bookmarked configuration manager associated with this model. */ KisBookmarkedConfigurationManager* bookmarkedConfigurationManager(); /** * @return the number of configurations (the minimum is always 2, the default * configuration and the last used configuration are always present) */ virtual int rowCount(const QModelIndex &parent = QModelIndex()) const; /** * When role == Qt::DisplayRole, this function will return the name of the * configuration. */ virtual QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; virtual bool setData(const QModelIndex & index, const QVariant & value, int role = Qt::EditRole); /** * @return the configuration at the given index */ KisSerializableConfiguration* configuration(const QModelIndex &index) const; /** * @return the index corresponding to the @p name . */ QModelIndex indexFor(const QString& name) const; /** * @return true if the configuration at the given index can be removed */ virtual bool isIndexDeletable(const QModelIndex &index) const; /** * @return the flags associated to the index */ Qt::ItemFlags flags(const QModelIndex & index) const; /** * Insert a new configuration. */ virtual void newConfiguration(KLocalizedString baseName, const KisSerializableConfiguration* config); /** * Save a configuration to the bookmark manager. */ virtual void saveConfiguration(const QString & name, const KisSerializableConfiguration* config); /** * Delete the configuration at the given index. (if possible) */ virtual void deleteIndex(const QModelIndex &index); private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/kis_canvas_controls_manager.h b/krita/ui/kis_canvas_controls_manager.h index f58c5db1554..5dc8d05fccc 100644 --- a/krita/ui/kis_canvas_controls_manager.h +++ b/krita/ui/kis_canvas_controls_manager.h @@ -1,57 +1,57 @@ /* * Copyright (c) 2003-2009 Boudewijn Rempt * Copyright (c) 2014 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CANVAS_CONTROLS_MANAGER_H #define KIS_CANVAS_CONTROLS_MANAGER_H #include #include -#include +#include class KisViewManager; class KisActionManager; class KisView; class KRITAUI_EXPORT KisCanvasControlsManager: public QObject { Q_OBJECT public: KisCanvasControlsManager(KisViewManager * view); virtual ~KisCanvasControlsManager(); void setup(KisActionManager *actionManager); void setView(QPointerimageView); private Q_SLOTS: void makeColorLighter(); void makeColorDarker(); void increaseOpacity(); void decreaseOpacity(); private: void transformColor(int step); void stepAlpha(float step); private: KisViewManager * m_view; }; #endif // KIS_CANVAS_CONTROLS_MANAGER_H diff --git a/krita/ui/kis_canvas_resource_provider.h b/krita/ui/kis_canvas_resource_provider.h index e0d65cfc442..3a0ee863daf 100644 --- a/krita/ui/kis_canvas_resource_provider.h +++ b/krita/ui/kis_canvas_resource_provider.h @@ -1,205 +1,205 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CANVAS_RESOURCE_PROVIDER_H_ #define KIS_CANVAS_RESOURCE_PROVIDER_H_ #include #include #include #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" class KisWorkspaceResource; class KoColorProfile; class KoAbstractGradient; class KoResource; class KoCanvasBase; class KisViewManager; class KoPattern; class KisFilterConfiguration; #include /** * KisCanvasResourceProvider contains the per-window current settings that * influence painting, like paintop, color, gradients and so on. */ class KRITAUI_EXPORT KisCanvasResourceProvider : public QObject { Q_OBJECT public: enum Resources { HdrExposure = KoCanvasResourceManager::KritaStart + 1, CurrentPattern, CurrentGradient, CurrentDisplayProfile, CurrentImage, CurrentKritaNode, CurrentPaintOpPreset, CurrentGeneratorConfiguration, CurrentCompositeOp, MirrorHorizontal, MirrorVertical, MirrorAxesCenter, Opacity, HdrGamma, GlobalAlphaLock, PreviousPaintOpPreset, EffectiveZoom ///<-Used only by painting tools for non-displaying purposes }; KisCanvasResourceProvider(KisViewManager * view); ~KisCanvasResourceProvider(); void setResourceManager(KoCanvasResourceManager *resourceManager); KoCanvasResourceManager* resourceManager(); KoCanvasBase * canvas() const; KoColor bgColor() const; void setBGColor(const KoColor& c); KoColor fgColor() const; void setFGColor(const KoColor& c); float HDRExposure() const; void setHDRExposure(float exposure); float HDRGamma() const; void setHDRGamma(float gamma); KoPattern *currentPattern() const; KoAbstractGradient *currentGradient() const; void resetDisplayProfile(int screen = -1); const KoColorProfile * currentDisplayProfile() const; KisImageWSP currentImage() const; KisNodeSP currentNode() const; KisPaintOpPresetSP currentPreset() const; void setPaintOpPreset(const KisPaintOpPresetSP preset); KisPaintOpPresetSP previousPreset() const; void setPreviousPaintOpPreset(const KisPaintOpPresetSP preset); KisFilterConfiguration* currentGeneratorConfiguration() const; void setCurrentCompositeOp(const QString& compositeOp); QString currentCompositeOp() const; QList > perspectiveGrids() const; void addPerspectiveGrid(KisAbstractPerspectiveGrid*); void removePerspectiveGrid(KisAbstractPerspectiveGrid*); void clearPerspectiveGrids(); void setMirrorHorizontal(bool mirrorHorizontal); bool mirrorHorizontal() const; void setMirrorVertical(bool mirrorVertical); bool mirrorVertical() const; void setOpacity(qreal opacity); qreal opacity() const; void setGlobalAlphaLock(bool lock); bool globalAlphaLock() const; ///Notify that the workspace is saved and settings should be saved to it void notifySavingWorkspace(KisWorkspaceResource* workspace); ///Notify that the workspace is loaded and settings can be read void notifyLoadingWorkspace(KisWorkspaceResource* workspace); public Q_SLOTS: void slotSetFGColor(const KoColor& c); void slotSetBGColor(const KoColor& c); void slotPatternActivated(KoResource *pattern); void slotGradientActivated(KoResource *gradient); void slotNodeActivated(const KisNodeSP node); void slotGeneratorConfigurationActivated(KisFilterConfiguration * generatorConfiguration); void slotPainting(); /** * Set the image size in pixels. The resource provider will store * the image size in postscript points. */ // FIXME: this slot doesn't catch the case when image resolution is changed void slotImageSizeChanged(); void slotSetDisplayProfile(const KoColorProfile * profile); void slotOnScreenResolutionChanged(); // This is a flag to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible void slotResetEnableFGChange(bool); private Q_SLOTS: void slotCanvasResourceChanged(int key, const QVariant & res); Q_SIGNALS: void sigFGColorChanged(const KoColor &); void sigBGColorChanged(const KoColor &); void sigGradientChanged(KoAbstractGradient *); void sigPatternChanged(KoPattern *); void sigNodeChanged(const KisNodeSP); void sigDisplayProfileChanged(const KoColorProfile *); void sigFGColorUsed(const KoColor&); void sigOnScreenResolutionChanged(qreal scaleX, qreal scaleY); void sigOpacityChanged(qreal); void sigSavingWorkspace(KisWorkspaceResource* workspace); void sigLoadingWorkspace(KisWorkspaceResource* workspace); void mirrorModeChanged(); private: KisViewManager * m_view; KoCanvasResourceManager *m_resourceManager; const KoColorProfile *m_displayProfile; bool m_fGChanged; QList > m_perspectiveGrids; // This is a flag to handle a bug: // If pop up palette is visible and a new colour is selected, the new colour // will be added when the user clicks on the canvas to hide the palette // In general, we want to be able to store recent color if the pop up palette // is not visible bool m_enablefGChange; }; #endif diff --git a/krita/ui/kis_categories_mapper.h b/krita/ui/kis_categories_mapper.h index 1aa25d131b0..fc4c2779ec0 100644 --- a/krita/ui/kis_categories_mapper.h +++ b/krita/ui/kis_categories_mapper.h @@ -1,334 +1,334 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_CATEGORIES_MAPPER_H #define __KIS_CATEGORIES_MAPPER_H #include #include -#include +#include /** * Templated classes cannot inherit QObject, so the signal handling is * moved to a separate class */ class KRITAUI_EXPORT __CategoriesSignalsBase : public QObject { Q_OBJECT Q_SIGNALS: void rowChanged(int row); void beginInsertRow(int row); void endInsertRow(); void beginRemoveRow(int row); void endRemoveRow(); }; template class KisCategoriesMapper : public __CategoriesSignalsBase { public: class DataItem { public: DataItem(const QString &categoryName, KisCategoriesMapper *parent) : m_name(categoryName), m_category(0), m_expanded(false), m_enabled(true), m_checkable(false), m_checked(false), m_locked(false), m_lockable(false), m_toggled(false), m_parent(parent) { } DataItem(const TEntry &entry, DataItem *category, KisCategoriesMapper *parent) : m_data(new TEntry(entry)), m_category(category), m_expanded(false), m_enabled(true), m_checkable(false), m_checked(false), m_locked(false), m_lockable(false), m_toggled(false), m_parent(parent) { Q_ASSERT(category); TEntryToQStringConverter converter; m_name = converter(entry); } TEntry* data() const { return m_data.data(); } QString name() const { return m_name; } bool isCategory() const { Q_ASSERT(static_cast(m_category) == static_cast(m_data)); return !m_category; } DataItem* parentCategory() const { return m_category; } bool isExpanded() const { return m_expanded; } void setExpanded(bool value) { Q_ASSERT(isCategory()); m_expanded = value; m_parent->notifyCategoryExpanded(this); } bool isEnabled() const { return m_enabled; } void setEnabled(bool value) { m_enabled = value; notifyItemChanged(); } bool isCheckable() const { return m_checkable; } void setCheckable(bool value) { m_checkable = value; notifyItemChanged(); } bool isChecked() const { return m_checked; } void setChecked(bool value) { setToggled(value!=m_checked); m_checked = value; notifyItemChanged(); } bool isLocked() const { return m_locked; } void setLocked(bool value){ m_locked = value; } bool isLockable() const { return m_lockable; } void setLockable(bool value){ m_lockable = value; } bool isToggled() const { return m_toggled; } void setToggled(bool value){ m_toggled = value; } private: void notifyItemChanged() { m_parent->notifyItemChanged(this); } private: QString m_name; QScopedPointer m_data; DataItem *m_category; bool m_expanded; bool m_enabled; bool m_checkable; bool m_checked; bool m_locked; bool m_lockable; bool m_toggled; KisCategoriesMapper *m_parent; }; public: KisCategoriesMapper() {} virtual ~KisCategoriesMapper() { qDeleteAll(m_items); } DataItem* addCategory(const QString &category) { if (fetchCategory(category)) return 0; DataItem *item = new DataItem(category, this); emit beginInsertRow(m_items.size()); m_items.append(item); emit endInsertRow(); return item; } void removeCategory(const QString &category) { QMutableListIterator it(m_items); DataItem *categoryItem = 0; int row = 0; while(it.hasNext()) { DataItem *item = it.next(); if (!item->isCategory() && item->parentCategory()->name() == category) { emit beginRemoveRow(row); it.remove(); delete item; emit endRemoveRow(); } else { if (item->isCategory() && item->name() == category) { Q_ASSERT(!categoryItem); categoryItem = item; } row++; } } if (categoryItem) { int row = m_items.indexOf(categoryItem); emit beginRemoveRow(row); delete m_items.takeAt(row); emit endRemoveRow(); } } DataItem* addEntry(const QString &category, const TEntry &entry) { DataItem *categoryItem = fetchCategory(category); if (!categoryItem) { categoryItem = addCategory(category); } DataItem *item = new DataItem(entry, categoryItem, this); emit beginInsertRow(m_items.size()); m_items.append(item); emit endInsertRow(); return item; } void removeEntry(const QString &category, const TEntry &entry) { DataItem *item = fetchEntry(category, entry); if (!item) return; int row = m_items.indexOf(item); emit beginRemoveRow(row); delete m_items.takeAt(row); emit endRemoveRow(); } DataItem* fetchCategory(const QString &category) const { foreach(DataItem *item, m_items) { if (item->isCategory() && item->name() == category) return item; } return 0; } DataItem* fetchEntry(const QString &category, const TEntry &entry) const { foreach(DataItem *item, m_items) { if (!item->isCategory() && *item->data() == entry && item->parentCategory()->name() == category) return item; } return 0; } DataItem* fetchOneEntry(const TEntry &entry) const { foreach(DataItem *item, m_items) { if (!item->isCategory() && *item->data() == entry) return item; } return 0; } QVector itemsForCategory(const QString &category) const { QVector filteredItems; foreach(DataItem *item, m_items) { if (!item->isCategory() && item->parentCategory()->name() == category) { filteredItems.append(item); } } return filteredItems; } void expandAllCategories() { foreach(DataItem *item, m_items) { if (item->isCategory()) { item->setExpanded(true); } } } DataItem* itemFromRow(int row) const { return m_items[row]; } int rowFromItem(DataItem *item) const { return m_items.indexOf(item); } int rowCount() const { return m_items.size(); } private: void notifyItemChanged(DataItem *item) { emit rowChanged(m_items.indexOf(item)); } void notifyCategoryExpanded(DataItem *categoryItem) { Q_ASSERT(categoryItem->isCategory()); notifyItemChanged(categoryItem); foreach(DataItem *item, m_items) { if (!item->isCategory() && item->parentCategory() == categoryItem) { notifyItemChanged(item); } } } protected: QList& testingGetItems() { return m_items; } private: QList m_items; }; #endif /* __KIS_CATEGORIES_MAPPER_H */ diff --git a/krita/ui/kis_categorized_item_delegate.h b/krita/ui/kis_categorized_item_delegate.h index 0d0ace05890..3185c2156b2 100644 --- a/krita/ui/kis_categorized_item_delegate.h +++ b/krita/ui/kis_categorized_item_delegate.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2009 Cyrille Berger * Copyright (c) 2011 Silvio Heinrich * Copyright (c) 2014 Mohit Goyal * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_CATEGORIZED_ITEM_DELEGATE_H_ #define _KIS_CATEGORIZED_ITEM_DELEGATE_H_ -#include +#include #include #include /** * This delegate draw categories using information from a \ref KCategorizedSortFilterProxyModel . */ class KRITAUI_EXPORT KisCategorizedItemDelegate: public QStyledItemDelegate { public: KisCategorizedItemDelegate(bool indicateError, QObject *parent); virtual void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const; virtual QSize sizeHint(const QStyleOptionViewItem& option, const QModelIndex& index) const; private: void paintTriangle(QPainter* painter, qint32 x, qint32 y, qint32 size, bool rotate) const; bool m_indicateError; mutable qint32 m_minimumItemHeight; }; #endif // _KIS_CATEGORIZED_ITEM_DELEGATE_H_ diff --git a/krita/ui/kis_clipboard.h b/krita/ui/kis_clipboard.h index abfd126fe55..e48574a4382 100644 --- a/krita/ui/kis_clipboard.h +++ b/krita/ui/kis_clipboard.h @@ -1,95 +1,95 @@ /* * kis_clipboard.h - part of Krayon * * Copyright (c) 2004 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_CLIPBOARD_H_ #define __KIS_CLIPBOARD_H_ #include #include #include "kis_types.h" -#include +#include class QImage; class QRect; enum enumPasteBehaviour { PASTE_ASSUME_WEB, PASTE_ASSUME_MONITOR, PASTE_ASK }; /** * The Krita clipboard is a clipboard that can store paint devices * instead of just qimage's. */ class KRITAUI_EXPORT KisClipboard : public QObject { Q_OBJECT Q_PROPERTY(bool clip READ hasClip NOTIFY clipChanged) 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. * * @param dev The paint device that will be stored on the clipboard * @param topLeft a hint about the place where the clip should be pasted by default */ void setClip(KisPaintDeviceSP dev, const QPoint& topLeft); /** * Get the contents of the clipboard in the form of a paint device. */ KisPaintDeviceSP clip(const QRect &imageBounds, bool showPopup); bool hasClip() const; QSize clipSize() const; Q_SIGNALS: void clipCreated(); private Q_SLOTS: void clipboardDataChanged(); private: KisClipboard(); KisClipboard(const KisClipboard &); KisClipboard operator=(const KisClipboard &); bool m_hasClip; bool m_pushedClipboard; Q_SIGNALS: void clipChanged(); }; #endif // __KIS_CLIPBOARD_H_ diff --git a/krita/ui/kis_config.cc b/krita/ui/kis_config.cc index d9ba199404c..c1c1950aa07 100644 --- a/krita/ui/kis_config.cc +++ b/krita/ui/kis_config.cc @@ -1,1587 +1,1597 @@ /* * Copyright (c) 2002 Patrick Julien * * 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_config.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas_resource_provider.h" #include "kis_global.h" #include "kis_config_notifier.h" #include #include KisConfig::KisConfig() : m_cfg(KGlobal::config()->group("")) { } KisConfig::~KisConfig() { if (qApp->thread() != QThread::currentThread()) { qDebug() << "WARNING: KisConfig: requested config synchronization from nonGUI thread! Skipping..."; return; } m_cfg.sync(); } bool KisConfig::disableTouchOnCanvas(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("disableTouchOnCanvas", false)); } void KisConfig::setDisableTouchOnCanvas(bool value) const { m_cfg.writeEntry("disableTouchOnCanvas", value); } bool KisConfig::useProjections(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useProjections", true)); } void KisConfig::setUseProjections(bool useProj) const { m_cfg.writeEntry("useProjections", useProj); } bool KisConfig::undoEnabled(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("undoEnabled", true)); } void KisConfig::setUndoEnabled(bool undo) const { m_cfg.writeEntry("undoEnabled", undo); } int KisConfig::undoStackLimit(bool defaultValue) const { return (defaultValue ? 30 : m_cfg.readEntry("undoStackLimit", 30)); } void KisConfig::setUndoStackLimit(int limit) const { m_cfg.writeEntry("undoStackLimit", limit); } bool KisConfig::useCumulativeUndoRedo(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useCumulativeUndoRedo",false)); } void KisConfig::setCumulativeUndoRedo(bool value) { m_cfg.writeEntry("useCumulativeUndoRedo", value); } double KisConfig::stackT1(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackT1",5)); } void KisConfig::setStackT1(int T1) { m_cfg.writeEntry("stackT1", T1); } double KisConfig::stackT2(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("stackT2",1)); } void KisConfig::setStackT2(int T2) { m_cfg.writeEntry("stackT2", T2); } int KisConfig::stackN(bool defaultValue) const { return (defaultValue ? 5 : m_cfg.readEntry("stackN",5)); } void KisConfig::setStackN(int N) { m_cfg.writeEntry("stackN", N); } qint32 KisConfig::defImageWidth(bool defaultValue) const { return (defaultValue ? 1600 : m_cfg.readEntry("imageWidthDef", 1600)); } qint32 KisConfig::defImageHeight(bool defaultValue) const { return (defaultValue ? 1200 : m_cfg.readEntry("imageHeightDef", 1200)); } double KisConfig::defImageResolution(bool defaultValue) const { return (defaultValue ? 100.0 : m_cfg.readEntry("imageResolutionDef", 100.0)) / 72.0; } QString KisConfig::defColorModel(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id() : m_cfg.readEntry("colorModelDef", KoColorSpaceRegistry::instance()->rgb8()->colorModelId().id())); } void KisConfig::defColorModel(const QString & model) const { m_cfg.writeEntry("colorModelDef", model); } QString KisConfig::defaultColorDepth(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id() : m_cfg.readEntry("colorDepthDef", KoColorSpaceRegistry::instance()->rgb8()->colorDepthId().id())); } void KisConfig::setDefaultColorDepth(const QString & depth) const { m_cfg.writeEntry("colorDepthDef", depth); } QString KisConfig::defColorProfile(bool defaultValue) const { return (defaultValue ? KoColorSpaceRegistry::instance()->rgb8()->profile()->name() : m_cfg.readEntry("colorProfileDef", KoColorSpaceRegistry::instance()->rgb8()->profile()->name())); } void KisConfig::defColorProfile(const QString & profile) const { m_cfg.writeEntry("colorProfileDef", profile); } void KisConfig::defImageWidth(qint32 width) const { m_cfg.writeEntry("imageWidthDef", width); } void KisConfig::defImageHeight(qint32 height) const { m_cfg.writeEntry("imageHeightDef", height); } void KisConfig::defImageResolution(double res) const { m_cfg.writeEntry("imageResolutionDef", res*72.0); } void cleanOldCursorStyleKeys(KConfigGroup &cfg) { if (cfg.hasKey("newCursorStyle") && cfg.hasKey("newOutlineStyle")) { cfg.deleteEntry("cursorStyleDef"); } } CursorStyle KisConfig::newCursorStyle(bool defaultValue) const { if (defaultValue) { return CURSOR_STYLE_NO_CURSOR; } int style = m_cfg.readEntry("newCursorStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: style = CURSOR_STYLE_TOOLICON; break; case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: style = CURSOR_STYLE_CROSSHAIR; break; case OLD_CURSOR_STYLE_POINTER: style = CURSOR_STYLE_POINTER; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_NO_CURSOR: style = CURSOR_STYLE_NO_CURSOR; break; case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: style = CURSOR_STYLE_SMALL_ROUND; break; case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: style = CURSOR_STYLE_TRIANGLE_RIGHTHANDED; break; case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = CURSOR_STYLE_TRIANGLE_LEFTHANDED; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_CURSOR_STYLE_SIZE) { style = CURSOR_STYLE_NO_CURSOR; } return (CursorStyle) style; } void KisConfig::setNewCursorStyle(CursorStyle style) { m_cfg.writeEntry("newCursorStyle", (int)style); } OutlineStyle KisConfig::newOutlineStyle(bool defaultValue) const { if (defaultValue) { return OUTLINE_FULL; } int style = m_cfg.readEntry("newOutlineStyle", int(-1)); if (style < 0) { // old style format style = m_cfg.readEntry("cursorStyleDef", int(OLD_CURSOR_STYLE_OUTLINE)); switch (style) { case OLD_CURSOR_STYLE_TOOLICON: case OLD_CURSOR_STYLE_CROSSHAIR: case OLD_CURSOR_STYLE_POINTER: case OLD_CURSOR_STYLE_NO_CURSOR: case OLD_CURSOR_STYLE_SMALL_ROUND: case OLD_CURSOR_STYLE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_TRIANGLE_LEFTHANDED: style = OUTLINE_NONE; break; case OLD_CURSOR_STYLE_OUTLINE: case OLD_CURSOR_STYLE_OUTLINE_CENTER_DOT: case OLD_CURSOR_STYLE_OUTLINE_CENTER_CROSS: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_RIGHTHANDED: case OLD_CURSOR_STYLE_OUTLINE_TRIANGLE_LEFTHANDED: style = OUTLINE_FULL; break; default: style = -1; } } cleanOldCursorStyleKeys(m_cfg); // compatibility with future versions if (style < 0 || style >= N_OUTLINE_STYLE_SIZE) { style = OUTLINE_FULL; } return (OutlineStyle) style; } void KisConfig::setNewOutlineStyle(OutlineStyle style) { m_cfg.writeEntry("newOutlineStyle", (int)style); } QRect KisConfig::colorPreviewRect() const { return m_cfg.readEntry("colorPreviewRect", QVariant(QRect(32, 32, 48, 48))).toRect(); } void KisConfig::setColorPreviewRect(const QRect &rect) { m_cfg.writeEntry("colorPreviewRect", QVariant(rect)); } bool KisConfig::useDirtyPresets(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useDirtyPresets",false)); } void KisConfig::setUseDirtyPresets(bool value) { m_cfg.writeEntry("useDirtyPresets",value); KisConfigNotifier::instance()->notifyConfigChanged(); } bool KisConfig::useEraserBrushSize(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useEraserBrushSize",false)); } void KisConfig::setUseEraserBrushSize(bool value) { m_cfg.writeEntry("useEraserBrushSize",value); KisConfigNotifier::instance()->notifyConfigChanged(); } QColor KisConfig::getMDIBackgroundColor(bool defaultValue) const { QColor col(77, 77, 77); return (defaultValue ? col : m_cfg.readEntry("mdiBackgroundColor", col)); } void KisConfig::setMDIBackgroundColor(const QColor &v) const { m_cfg.writeEntry("mdiBackgroundColor", v); } QString KisConfig::getMDIBackgroundImage(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("mdiBackgroundImage", "")); } void KisConfig::setMDIBackgroundImage(const QString &filename) const { m_cfg.writeEntry("mdiBackgroundImage", filename); } QString KisConfig::monitorProfile(int screen) const { // Note: keep this in sync with the default profile for the RGB colorspaces! QString profile = m_cfg.readEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), "sRGB-elle-V2-srgbtrc.icc"); //qDebug() << "KisConfig::monitorProfile()" << profile; return profile; } QString KisConfig::monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue) const { return (defaultValue ? defaultMonitor : m_cfg.readEntry(QString("monitor_for_screen_%1").arg(screen), defaultMonitor)); } void KisConfig::setMonitorForScreen(int screen, const QString& monitor) { m_cfg.writeEntry(QString("monitor_for_screen_%1").arg(screen), monitor); } void KisConfig::setMonitorProfile(int screen, const QString & monitorProfile, bool override) const { m_cfg.writeEntry("monitorProfile/OverrideX11", override); m_cfg.writeEntry("monitorProfile" + QString(screen == 0 ? "": QString("_%1").arg(screen)), monitorProfile); } const KoColorProfile *KisConfig::getScreenProfile(int screen) { KisConfig cfg; QString monitorId = cfg.monitorForScreen(screen, ""); if (monitorId.isEmpty()) { return 0; } QByteArray bytes = KisColorManager::instance()->displayProfile(monitorId); if (bytes.length() > 0) { const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(RGBAColorModelID.id(), Integer8BitsColorDepthID.id(), bytes); //qDebug() << "KisConfig::getScreenProfile for screen" << screen << profile->name(); return profile; } else { //qDebug() << "Could not get a system monitor profile"; return 0; } } const KoColorProfile *KisConfig::displayProfile(int screen) const { // if the user plays with the settings, they can override the display profile, in which case // we don't want the system setting. bool override = m_cfg.readEntry("monitorProfile/OverrideX11", false); //qDebug() << "KisConfig::displayProfile(). Override X11:" << override; const KoColorProfile *profile = 0; if (override) { //qDebug() << "\tGoing to get the screen profile"; profile = KisConfig::getScreenProfile(screen); } // if it fails. check the configuration if (!profile || !profile->isSuitableForDisplay()) { //ebug() << "\tGoing to get the monitor profile"; QString monitorProfileName = monitorProfile(screen); //qDebug() << "\t\tmonitorProfileName:" << monitorProfileName; if (!monitorProfileName.isEmpty()) { profile = KoColorSpaceRegistry::instance()->profileByName(monitorProfileName); } if (profile) { //qDebug() << "\t\tsuitable for display6" << profile->isSuitableForDisplay(); } else { //qDebug() << "\t\tstill no profile"; } } // if we still don't have a profile, or the profile isn't suitable for display, // we need to get a last-resort profile. the built-in sRGB is a good choice then. if (!profile || !profile->isSuitableForDisplay()) { //qDebug() << "\tnothing worked, going to get sRGB built-in"; profile = KoColorSpaceRegistry::instance()->profileByName("sRGB Built-in"); } if (profile) { //qDebug() << "\tKisConfig::displayProfile for screen" << screen << "is" << profile->name(); } else { //qDebug() << "\tCOuldn't get a display profile at all"; } return profile; } QString KisConfig::workingColorSpace(bool defaultValue) const { return (defaultValue ? "RGBA" : m_cfg.readEntry("workingColorSpace", "RGBA")); } void KisConfig::setWorkingColorSpace(const QString & workingColorSpace) const { m_cfg.writeEntry("workingColorSpace", workingColorSpace); } QString KisConfig::printerColorSpace(bool /*defaultValue*/) const { //TODO currently only rgb8 is supported //return (defaultValue ? "RGBA" : m_cfg.readEntry("printerColorSpace", "RGBA")); return QString("RGBA"); } void KisConfig::setPrinterColorSpace(const QString & printerColorSpace) const { m_cfg.writeEntry("printerColorSpace", printerColorSpace); } QString KisConfig::printerProfile(bool defaultValue) const { return (defaultValue ? "" : m_cfg.readEntry("printerProfile", "")); } void KisConfig::setPrinterProfile(const QString & printerProfile) const { m_cfg.writeEntry("printerProfile", printerProfile); } bool KisConfig::useBlackPointCompensation(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useBlackPointCompensation", true)); } void KisConfig::setUseBlackPointCompensation(bool useBlackPointCompensation) const { m_cfg.writeEntry("useBlackPointCompensation", useBlackPointCompensation); } bool KisConfig::allowLCMSOptimization(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("allowLCMSOptimization", true)); } void KisConfig::setAllowLCMSOptimization(bool allowLCMSOptimization) { m_cfg.writeEntry("allowLCMSOptimization", allowLCMSOptimization); } bool KisConfig::showRulers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showrulers", false)); } void KisConfig::setShowRulers(bool rulers) const { m_cfg.writeEntry("showrulers", rulers); } qint32 KisConfig::pasteBehaviour(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("pasteBehaviour", 2)); } void KisConfig::setPasteBehaviour(qint32 renderIntent) const { m_cfg.writeEntry("pasteBehaviour", renderIntent); } qint32 KisConfig::monitorRenderIntent(bool defaultValue) const { qint32 intent = m_cfg.readEntry("renderIntent", INTENT_PERCEPTUAL); if (intent > 3) intent = 3; if (intent < 0) intent = 0; return (defaultValue ? INTENT_PERCEPTUAL : intent); } void KisConfig::setRenderIntent(qint32 renderIntent) const { if (renderIntent > 3) renderIntent = 3; if (renderIntent < 0) renderIntent = 0; m_cfg.writeEntry("renderIntent", renderIntent); } bool KisConfig::useOpenGL(bool defaultValue) const { if (qApp->applicationName() == "krita") { if (defaultValue) { #ifdef Q_WS_MAC return false; #else return true; #endif } //qDebug() << "use opengl" << m_cfg.readEntry("useOpenGL", true) << "success" << m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); QString canvasState = m_cfg.readEntry("canvasState", "OPENGL_SUCCESS"); #ifdef Q_WS_MAC return (m_cfg.readEntry("useOpenGL", false) && (canvasState == "OPENGL_SUCCESS" || canvasState == "TRY_OPENGL")); #else return (m_cfg.readEntry("useOpenGL", true) && (canvasState == "OPENGL_SUCCESS" || canvasState == "TRY_OPENGL")); #endif } else if (qApp->applicationName() == "kritasketch" || qApp->applicationName() == "kritagemini") { return true; // for sketch and gemini } else { return false; } } void KisConfig::setUseOpenGL(bool useOpenGL) const { m_cfg.writeEntry("useOpenGL", useOpenGL); } int KisConfig::openGLFilteringMode(bool defaultValue) const { return (defaultValue ? 3 : m_cfg.readEntry("OpenGLFilterMode", 3)); } void KisConfig::setOpenGLFilteringMode(int filteringMode) { m_cfg.writeEntry("OpenGLFilterMode", filteringMode); } bool KisConfig::useOpenGLTextureBuffer(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("useOpenGLTextureBuffer", true)); } void KisConfig::setUseOpenGLTextureBuffer(bool useBuffer) { m_cfg.writeEntry("useOpenGLTextureBuffer", useBuffer); } int KisConfig::openGLTextureSize(bool defaultValue) const { return (defaultValue ? 256 : m_cfg.readEntry("textureSize", 256)); } bool KisConfig::disableDoubleBuffering(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("disableDoubleBuffering", true)); } void KisConfig::setDisableDoubleBuffering(bool disableDoubleBuffering) { m_cfg.writeEntry("disableDoubleBuffering", disableDoubleBuffering); } bool KisConfig::disableVSync(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("disableVSync", true)); } void KisConfig::setDisableVSync(bool disableVSync) { m_cfg.writeEntry("disableVSync", disableVSync); } bool KisConfig::showAdvancedOpenGLSettings(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showAdvancedOpenGLSettings", false)); } bool KisConfig::forceOpenGLFenceWorkaround(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("forceOpenGLFenceWorkaround", false)); } int KisConfig::numMipmapLevels(bool defaultValue) const { return (defaultValue ? 4 : m_cfg.readEntry("numMipmapLevels", 4)); } int KisConfig::textureOverlapBorder() const { return 1 << qMax(0, numMipmapLevels()); } qint32 KisConfig::maxNumberOfThreads(bool defaultValue) const { return (defaultValue ? QThread::idealThreadCount() : m_cfg.readEntry("maxthreads", QThread::idealThreadCount())); } void KisConfig::setMaxNumberOfThreads(qint32 maxThreads) { m_cfg.writeEntry("maxthreads", maxThreads); } quint32 KisConfig::getGridMainStyle(bool defaultValue) const { quint32 v = m_cfg.readEntry("gridmainstyle", 0); if (v > 2) v = 2; return (defaultValue ? 0 : v); } void KisConfig::setGridMainStyle(quint32 v) const { m_cfg.writeEntry("gridmainstyle", v); } quint32 KisConfig::getGridSubdivisionStyle(bool defaultValue) const { quint32 v = m_cfg.readEntry("gridsubdivisionstyle", 1); if (v > 2) v = 2; return (defaultValue ? 1 : v); } void KisConfig::setGridSubdivisionStyle(quint32 v) const { m_cfg.writeEntry("gridsubdivisionstyle", v); } QColor KisConfig::getGridMainColor(bool defaultValue) const { QColor col(99, 99, 99); return (defaultValue ? col : m_cfg.readEntry("gridmaincolor", col)); } void KisConfig::setGridMainColor(const QColor & v) const { m_cfg.writeEntry("gridmaincolor", v); } QColor KisConfig::getGridSubdivisionColor(bool defaultValue) const { QColor col(150, 150, 150); return (defaultValue ? col : m_cfg.readEntry("gridsubdivisioncolor", col)); } void KisConfig::setGridSubdivisionColor(const QColor & v) const { m_cfg.writeEntry("gridsubdivisioncolor", v); } quint32 KisConfig::getGridHSpacing(bool defaultValue) const { qint32 v = m_cfg.readEntry("gridhspacing", 10); return (defaultValue ? 10 : (quint32)qMax(1, v)); } void KisConfig::setGridHSpacing(quint32 v) const { m_cfg.writeEntry("gridhspacing", v); } quint32 KisConfig::getGridVSpacing(bool defaultValue) const { qint32 v = m_cfg.readEntry("gridvspacing", 10); return (defaultValue ? 10 : (quint32)qMax(1, v)); } void KisConfig::setGridVSpacing(quint32 v) const { m_cfg.writeEntry("gridvspacing", v); } bool KisConfig::getGridSpacingAspect(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("gridspacingaspect", false)); } void KisConfig::setGridSpacingAspect(bool v) const { m_cfg.writeEntry("gridspacingaspect", v); } quint32 KisConfig::getGridSubdivisions(bool defaultValue) const { qint32 v = m_cfg.readEntry("gridsubsivisons", 2); return (defaultValue ? 2 : (quint32)qMax(1, v)); } void KisConfig::setGridSubdivisions(quint32 v) const { m_cfg.writeEntry("gridsubsivisons", v); } quint32 KisConfig::getGridOffsetX(bool defaultValue) const { qint32 v = m_cfg.readEntry("gridoffsetx", 0); return (defaultValue ? 0 : (quint32)qMax(0, v)); } void KisConfig::setGridOffsetX(quint32 v) const { m_cfg.writeEntry("gridoffsetx", v); } quint32 KisConfig::getGridOffsetY(bool defaultValue) const { qint32 v = m_cfg.readEntry("gridoffsety", 0); return (defaultValue ? 0 : (quint32)qMax(0, v)); } void KisConfig::setGridOffsetY(quint32 v) const { m_cfg.writeEntry("gridoffsety", v); } bool KisConfig::getGridOffsetAspect(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("gridoffsetaspect", false)); } void KisConfig::setGridOffsetAspect(bool v) const { m_cfg.writeEntry("gridoffsetaspect", v); } qint32 KisConfig::checkSize(bool defaultValue) const { return (defaultValue ? 32 : m_cfg.readEntry("checksize", 32)); } void KisConfig::setCheckSize(qint32 checksize) const { m_cfg.writeEntry("checksize", checksize); } bool KisConfig::scrollCheckers(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("scrollingcheckers", false)); } void KisConfig::setScrollingCheckers(bool sc) const { m_cfg.writeEntry("scrollingcheckers", sc); } QColor KisConfig::canvasBorderColor(bool defaultValue) const { QColor color(QColor(128,128,128)); return (defaultValue ? color : m_cfg.readEntry("canvasBorderColor", color)); } void KisConfig::setCanvasBorderColor(const QColor& color) const { m_cfg.writeEntry("canvasBorderColor", color); } bool KisConfig::hideScrollbars(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hideScrollbars", false)); } void KisConfig::setHideScrollbars(bool value) const { m_cfg.writeEntry("hideScrollbars", value); } QColor KisConfig::checkersColor1(bool defaultValue) const { QColor col(220, 220, 220); return (defaultValue ? col : m_cfg.readEntry("checkerscolor", col)); } void KisConfig::setCheckersColor1(const QColor & v) const { m_cfg.writeEntry("checkerscolor", v); } QColor KisConfig::checkersColor2(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("checkerscolor2", QColor(Qt::white))); } void KisConfig::setCheckersColor2(const QColor & v) const { m_cfg.writeEntry("checkerscolor2", v); } bool KisConfig::antialiasCurves(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("antialiascurves", true)); } void KisConfig::setAntialiasCurves(bool v) const { m_cfg.writeEntry("antialiascurves", v); } QColor KisConfig::selectionOverlayMaskColor(bool defaultValue) const { QColor def(255, 0, 0, 220); return (defaultValue ? def : m_cfg.readEntry("selectionOverlayMaskColor", def)); } void KisConfig::setSelectionOverlayMaskColor(const QColor &color) { m_cfg.writeEntry("selectionOverlayMaskColor", color); } bool KisConfig::antialiasSelectionOutline(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("AntialiasSelectionOutline", false)); } void KisConfig::setAntialiasSelectionOutline(bool v) const { m_cfg.writeEntry("AntialiasSelectionOutline", v); } bool KisConfig::showRootLayer(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowRootLayer", false)); } void KisConfig::setShowRootLayer(bool showRootLayer) const { m_cfg.writeEntry("ShowRootLayer", showRootLayer); } bool KisConfig::showGlobalSelection(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ShowGlobalSelection", false)); } void KisConfig::setShowGlobalSelection(bool showGlobalSelection) const { m_cfg.writeEntry("ShowGlobalSelection", showGlobalSelection); } bool KisConfig::showOutlineWhilePainting(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ShowOutlineWhilePainting", true)); } void KisConfig::setShowOutlineWhilePainting(bool showOutlineWhilePainting) const { m_cfg.writeEntry("ShowOutlineWhilePainting", showOutlineWhilePainting); } bool KisConfig::hideSplashScreen(bool defaultValue) const { KConfigGroup cfg(KGlobal::config(), "SplashScreen"); return (defaultValue ? true : cfg.readEntry("HideSplashAfterStartup", true)); } void KisConfig::setHideSplashScreen(bool hideSplashScreen) const { KConfigGroup cfg(KGlobal::config(), "SplashScreen"); cfg.writeEntry("HideSplashAfterStartup", hideSplashScreen); } qreal KisConfig::outlineSizeMinimum(bool defaultValue) const { return (defaultValue ? 1.0 : m_cfg.readEntry("OutlineSizeMinimum", 1.0)); } void KisConfig::setOutlineSizeMinimum(qreal outlineSizeMinimum) const { m_cfg.writeEntry("OutlineSizeMinimum", outlineSizeMinimum); } int KisConfig::autoSaveInterval(bool defaultValue) const { return (defaultValue ? KisDocument::defaultAutoSave() : m_cfg.readEntry("AutoSaveInterval", KisDocument::defaultAutoSave())); } void KisConfig::setAutoSaveInterval(int seconds) const { return m_cfg.writeEntry("AutoSaveInterval", seconds); } bool KisConfig::backupFile(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("CreateBackupFile", true)); } void KisConfig::setBackupFile(bool backupFile) const { m_cfg.writeEntry("CreateBackupFile", backupFile); } bool KisConfig::showFilterGallery(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showFilterGallery", false)); } void KisConfig::setShowFilterGallery(bool showFilterGallery) const { m_cfg.writeEntry("showFilterGallery", showFilterGallery); } bool KisConfig::showFilterGalleryLayerMaskDialog(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showFilterGalleryLayerMaskDialog", true)); } void KisConfig::setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const { m_cfg.writeEntry("setShowFilterGalleryLayerMaskDialog", showFilterGallery); } QString KisConfig::canvasState(bool defaultValue) const { return (defaultValue ? "OPENGL_NOT_TRIED" : m_cfg.readEntry("canvasState", "OPENGL_NOT_TRIED")); } void KisConfig::setCanvasState(const QString& state) const { static QStringList acceptableStates; if (acceptableStates.isEmpty()) { acceptableStates << "OPENGL_SUCCESS" << "TRY_OPENGL" << "OPENGL_NOT_TRIED" << "OPENGL_FAILED"; } if (acceptableStates.contains(state)) { m_cfg.writeEntry("canvasState", state); m_cfg.sync(); } } bool KisConfig::toolOptionsPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ToolOptionsPopupDetached", false)); } void KisConfig::setToolOptionsPopupDetached(bool detached) const { m_cfg.writeEntry("ToolOptionsPopupDetached", detached); } bool KisConfig::paintopPopupDetached(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("PaintopPopupDetached", false)); } void KisConfig::setPaintopPopupDetached(bool detached) const { m_cfg.writeEntry("PaintopPopupDetached", detached); } QString KisConfig::pressureTabletCurve(bool defaultValue) const { return (defaultValue ? "0,0;1,1" : m_cfg.readEntry("tabletPressureCurve","0,0;1,1;")); } void KisConfig::setPressureTabletCurve(const QString& curveString) const { m_cfg.writeEntry("tabletPressureCurve", curveString); } qreal KisConfig::vastScrolling(bool defaultValue) const { return (defaultValue ? 0.9 : m_cfg.readEntry("vastScrolling", 0.9)); } void KisConfig::setVastScrolling(const qreal factor) const { m_cfg.writeEntry("vastScrolling", factor); } int KisConfig::presetChooserViewMode(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("presetChooserViewMode", 0)); } void KisConfig::setPresetChooserViewMode(const int mode) const { m_cfg.writeEntry("presetChooserViewMode", mode); } bool KisConfig::firstRun(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("firstRun", true)); } void KisConfig::setFirstRun(const bool first) const { m_cfg.writeEntry("firstRun", first); } int KisConfig::horizontalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("horizontalSplitLines", 1)); } void KisConfig::setHorizontalSplitLines(const int numberLines) const { m_cfg.writeEntry("horizontalSplitLines", numberLines); } int KisConfig::verticalSplitLines(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("verticalSplitLines", 1)); } void KisConfig::setVerticalSplitLines(const int numberLines) const { m_cfg.writeEntry("verticalSplitLines", numberLines); } bool KisConfig::clicklessSpacePan(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("clicklessSpacePan", true)); } void KisConfig::setClicklessSpacePan(const bool toggle) const { m_cfg.writeEntry("clicklessSpacePan", toggle); } bool KisConfig::hideDockersFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideDockersFullScreen", true)); } void KisConfig::setHideDockersFullscreen(const bool value) const { m_cfg.writeEntry("hideDockersFullScreen", value); } bool KisConfig::showDockerTitleBars(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showDockerTitleBars", true)); } void KisConfig::setShowDockerTitleBars(const bool value) const { m_cfg.writeEntry("showDockerTitleBars", value); } bool KisConfig::hideMenuFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideMenuFullScreen", true)); } void KisConfig::setHideMenuFullscreen(const bool value) const { m_cfg.writeEntry("hideMenuFullScreen", value); } bool KisConfig::hideScrollbarsFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideScrollbarsFullScreen", true)); } void KisConfig::setHideScrollbarsFullscreen(const bool value) const { m_cfg.writeEntry("hideScrollbarsFullScreen", value); } bool KisConfig::hideStatusbarFullscreen(bool defaultValue) const { return (defaultValue ? true: m_cfg.readEntry("hideStatusbarFullScreen", true)); } void KisConfig::setHideStatusbarFullscreen(const bool value) const { m_cfg.writeEntry("hideStatusbarFullScreen", value); } bool KisConfig::hideTitlebarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideTitleBarFullscreen", true)); } void KisConfig::setHideTitlebarFullscreen(const bool value) const { m_cfg.writeEntry("hideTitleBarFullscreen", value); } bool KisConfig::hideToolbarFullscreen(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("hideToolbarFullscreen", true)); } void KisConfig::setHideToolbarFullscreen(const bool value) const { m_cfg.writeEntry("hideToolbarFullscreen", value); } +bool KisConfig::fullscreenMode(bool defaultValue) const +{ + return (defaultValue ? true : m_cfg.readEntry("fullscreenMode", true)); +} + +void KisConfig::setFullscreenMode(const bool value) const +{ + m_cfg.writeEntry("fullscreenMode", value); +} + QStringList KisConfig::favoriteCompositeOps(bool defaultValue) const { return (defaultValue ? QStringList() : m_cfg.readEntry("favoriteCompositeOps", QStringList())); } void KisConfig::setFavoriteCompositeOps(const QStringList& compositeOps) const { m_cfg.writeEntry("favoriteCompositeOps", compositeOps); } QString KisConfig::exportConfiguration(const QString &filterId, bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("ExportConfiguration-" + filterId, QString())); } void KisConfig::setExportConfiguration(const QString &filterId, const KisPropertiesConfiguration &properties) const { QString exportConfig = properties.toXML(); m_cfg.writeEntry("ExportConfiguration-" + filterId, exportConfig); } bool KisConfig::useOcio(bool defaultValue) const { #ifdef HAVE_OCIO return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/UseOcio", false)); #else return false; #endif } void KisConfig::setUseOcio(bool useOCIO) const { m_cfg.writeEntry("Krita/Ocio/UseOcio", useOCIO); } int KisConfig::favoritePresets(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("numFavoritePresets", 10)); } void KisConfig::setFavoritePresets(const int value) { m_cfg.writeEntry("numFavoritePresets", value); } KisConfig::OcioColorManagementMode KisConfig::ocioColorManagementMode(bool defaultValue) const { return (OcioColorManagementMode)(defaultValue ? INTERNAL : m_cfg.readEntry("Krita/Ocio/OcioColorManagementMode", (int) INTERNAL)); } void KisConfig::setOcioColorManagementMode(OcioColorManagementMode mode) const { m_cfg.writeEntry("Krita/Ocio/OcioColorManagementMode", (int) mode); } QString KisConfig::ocioConfigurationPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioConfigPath", QString())); } void KisConfig::setOcioConfigurationPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioConfigPath", path); } QString KisConfig::ocioLutPath(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("Krita/Ocio/OcioLutPath", QString())); } void KisConfig::setOcioLutPath(const QString &path) const { m_cfg.writeEntry("Krita/Ocio/OcioLutPath", path); } int KisConfig::ocioLutEdgeSize(bool defaultValue) const { return (defaultValue ? 64 : m_cfg.readEntry("Krita/Ocio/LutEdgeSize", 64)); } void KisConfig::setOcioLutEdgeSize(int value) { m_cfg.writeEntry("Krita/Ocio/LutEdgeSize", value); } bool KisConfig::ocioLockColorVisualRepresentation(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("Krita/Ocio/OcioLockColorVisualRepresentation", false)); } void KisConfig::setOcioLockColorVisualRepresentation(bool value) { m_cfg.writeEntry("Krita/Ocio/OcioLockColorVisualRepresentation", value); } QString KisConfig::defaultPalette(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("defaultPalette", QString())); } void KisConfig::setDefaultPalette(const QString& name) const { m_cfg.writeEntry("defaultPalette", name); } QString KisConfig::toolbarSlider(int sliderNumber, bool defaultValue) const { QString def = "flow"; if (sliderNumber == 1) { def = "opacity"; } if (sliderNumber == 2) { def = "size"; } return (defaultValue ? def : m_cfg.readEntry(QString("toolbarslider_%1").arg(sliderNumber), def)); } void KisConfig::setToolbarSlider(int sliderNumber, const QString &slider) { m_cfg.writeEntry(QString("toolbarslider_%1").arg(sliderNumber), slider); } bool KisConfig::sliderLabels(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("sliderLabels", true)); } void KisConfig::setSliderLabels(bool enabled) { m_cfg.writeEntry("sliderLabels", enabled); } QString KisConfig::currentInputProfile(bool defaultValue) const { return (defaultValue ? QString() : m_cfg.readEntry("currentInputProfile", QString())); } void KisConfig::setCurrentInputProfile(const QString& name) { m_cfg.writeEntry("currentInputProfile", name); } bool KisConfig::useSystemMonitorProfile(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("ColorManagement/UseSystemMonitorProfile", false)); } void KisConfig::setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const { m_cfg.writeEntry("ColorManagement/UseSystemMonitorProfile", _useSystemMonitorProfile); } bool KisConfig::presetStripVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("presetStripVisible", true)); } void KisConfig::setPresetStripVisible(bool visible) { m_cfg.writeEntry("presetStripVisible", visible); } bool KisConfig::scratchpadVisible(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("scratchpadVisible", true)); } void KisConfig::setScratchpadVisible(bool visible) { m_cfg.writeEntry("scratchpadVisible", visible); } bool KisConfig::showSingleChannelAsColor(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("showSingleChannelAsColor", false)); } void KisConfig::setShowSingleChannelAsColor(bool asColor) { m_cfg.writeEntry("showSingleChannelAsColor", asColor); } bool KisConfig::hidePopups(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("hidePopups", false)); } void KisConfig::setHidePopups(bool hidepopups) { m_cfg.writeEntry("hidePopups", hidepopups); } int KisConfig::numDefaultLayers(bool defaultValue) const { return (defaultValue ? 2 : m_cfg.readEntry("NumberOfLayersForNewImage", 2)); } void KisConfig::setNumDefaultLayers(int num) { m_cfg.writeEntry("NumberOfLayersForNewImage", num); } quint8 KisConfig::defaultBackgroundOpacity(bool defaultValue) const { return (defaultValue ? (int)OPACITY_OPAQUE_U8 : m_cfg.readEntry("BackgroundOpacityForNewImage", (int)OPACITY_OPAQUE_U8)); } void KisConfig::setDefaultBackgroundOpacity(quint8 value) { m_cfg.writeEntry("BackgroundOpacityForNewImage", (int)value); } QColor KisConfig::defaultBackgroundColor(bool defaultValue) const { return (defaultValue ? QColor(Qt::white) : m_cfg.readEntry("BackgroundColorForNewImage", QColor(Qt::white))); } void KisConfig::setDefaultBackgroundColor(QColor value) { m_cfg.writeEntry("BackgroundColorForNewImage", value); } KisConfig::BackgroundStyle KisConfig::defaultBackgroundStyle(bool defaultValue) const { return (KisConfig::BackgroundStyle)(defaultValue ? LAYER : m_cfg.readEntry("BackgroundStyleForNewImage", (int)LAYER)); } void KisConfig::setDefaultBackgroundStyle(KisConfig::BackgroundStyle value) { m_cfg.writeEntry("BackgroundStyleForNewImage", (int)value); } int KisConfig::lineSmoothingType(bool defaultValue) const { return (defaultValue ? 1 : m_cfg.readEntry("LineSmoothingType", 1)); } void KisConfig::setLineSmoothingType(int value) { m_cfg.writeEntry("LineSmoothingType", value); } qreal KisConfig::lineSmoothingDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDistance", 50.0)); } void KisConfig::setLineSmoothingDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDistance", value); } qreal KisConfig::lineSmoothingTailAggressiveness(bool defaultValue) const { return (defaultValue ? 0.15 : m_cfg.readEntry("LineSmoothingTailAggressiveness", 0.15)); } void KisConfig::setLineSmoothingTailAggressiveness(qreal value) { m_cfg.writeEntry("LineSmoothingTailAggressiveness", value); } bool KisConfig::lineSmoothingSmoothPressure(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("LineSmoothingSmoothPressure", false)); } void KisConfig::setLineSmoothingSmoothPressure(bool value) { m_cfg.writeEntry("LineSmoothingSmoothPressure", value); } bool KisConfig::lineSmoothingScalableDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingScalableDistance", true)); } void KisConfig::setLineSmoothingScalableDistance(bool value) { m_cfg.writeEntry("LineSmoothingScalableDistance", value); } qreal KisConfig::lineSmoothingDelayDistance(bool defaultValue) const { return (defaultValue ? 50.0 : m_cfg.readEntry("LineSmoothingDelayDistance", 50.0)); } void KisConfig::setLineSmoothingDelayDistance(qreal value) { m_cfg.writeEntry("LineSmoothingDelayDistance", value); } bool KisConfig::lineSmoothingUseDelayDistance(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingUseDelayDistance", true)); } void KisConfig::setLineSmoothingUseDelayDistance(bool value) { m_cfg.writeEntry("LineSmoothingUseDelayDistance", value); } bool KisConfig::lineSmoothingFinishStabilizedCurve(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingFinishStabilizedCurve", true)); } void KisConfig::setLineSmoothingFinishStabilizedCurve(bool value) { m_cfg.writeEntry("LineSmoothingFinishStabilizedCurve", value); } bool KisConfig::lineSmoothingStabilizeSensors(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("LineSmoothingStabilizeSensors", true)); } void KisConfig::setLineSmoothingStabilizeSensors(bool value) { m_cfg.writeEntry("LineSmoothingStabilizeSensors", value); } int KisConfig::paletteDockerPaletteViewSectionSize(bool defaultValue) const { return (defaultValue ? 12 : m_cfg.readEntry("paletteDockerPaletteViewSectionSize", 12)); } void KisConfig::setPaletteDockerPaletteViewSectionSize(int value) const { m_cfg.writeEntry("paletteDockerPaletteViewSectionSize", value); } int KisConfig::tabletEventsDelay(bool defaultValue) const { return (defaultValue ? 10 : m_cfg.readEntry("tabletEventsDelay", 10)); } void KisConfig::setTabletEventsDelay(int value) { m_cfg.writeEntry("tabletEventsDelay", value); } bool KisConfig::testingAcceptCompressedTabletEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingAcceptCompressedTabletEvents", false)); } void KisConfig::setTestingAcceptCompressedTabletEvents(bool value) { m_cfg.writeEntry("testingAcceptCompressedTabletEvents", value); } bool KisConfig::testingCompressBrushEvents(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("testingCompressBrushEvents", false)); } void KisConfig::setTestingCompressBrushEvents(bool value) { m_cfg.writeEntry("testingCompressBrushEvents", value); } bool KisConfig::useVerboseOpenGLDebugOutput(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("useVerboseOpenGLDebugOutput", false)); } int KisConfig::workaroundX11SmoothPressureSteps(bool defaultValue) const { return (defaultValue ? 0 : m_cfg.readEntry("workaroundX11SmoothPressureSteps", 0)); } bool KisConfig::showCanvasMessages(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("showOnCanvasMessages", true)); } void KisConfig::setShowCanvasMessages(bool show) { m_cfg.writeEntry("showOnCanvasMessages", show); } bool KisConfig::compressKra(bool defaultValue) const { return (defaultValue ? false : m_cfg.readEntry("compressLayersInKra", false)); } void KisConfig::setCompressKra(bool compress) { m_cfg.writeEntry("compressLayersInKra", compress); } bool KisConfig::toolOptionsInDocker(bool defaultValue) const { return (defaultValue ? true : m_cfg.readEntry("ToolOptionsInDocker", true)); } void KisConfig::setToolOptionsInDocker(bool inDocker) { m_cfg.writeEntry("ToolOptionsInDocker", inDocker); } const KoColorSpace* KisConfig::customColorSelectorColorSpace(bool defaultValue) const { const KoColorSpace *cs = 0; KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); if (defaultValue || cfg.readEntry("useCustomColorSpace", true)) { KoColorSpaceRegistry* csr = KoColorSpaceRegistry::instance(); cs = csr->colorSpace(cfg.readEntry("customColorSpaceModel", "RGBA"), cfg.readEntry("customColorSpaceDepthID", "U8"), cfg.readEntry("customColorSpaceProfile", "sRGB built-in - (lcms internal)")); } return cs; } void KisConfig::setCustomColorSelectorColorSpace(const KoColorSpace *cs) { KConfigGroup cfg = KGlobal::config()->group("advancedColorSelector"); cfg.writeEntry("useCustomColorSpace", bool(cs)); if(cs) { cfg.writeEntry("customColorSpaceModel", cs->colorModelId().id()); cfg.writeEntry("customColorSpaceDepthID", cs->colorDepthId().id()); cfg.writeEntry("customColorSpaceProfile", cs->profile()->name()); } KisConfigNotifier::instance()->notifyConfigChanged(); } diff --git a/krita/ui/kis_config.h b/krita/ui/kis_config.h index c0ce02be773..1405bca3785 100644 --- a/krita/ui/kis_config.h +++ b/krita/ui/kis_config.h @@ -1,493 +1,496 @@ /* * Copyright (c) 2002 Patrick Julien * * 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 #include #include #include #include #include #include "kis_global.h" #include "kis_properties_configuration.h" -#include "krita_export.h" +#include "kritaui_export.h" class KoColorProfile; class KoColorSpace; class KRITAUI_EXPORT KisConfig { public: KisConfig(); ~KisConfig(); bool disableTouchOnCanvas(bool defaultValue = false) const; void setDisableTouchOnCanvas(bool value) const; bool useProjections(bool defaultValue = false) const; void setUseProjections(bool useProj) const; bool undoEnabled(bool defaultValue = false) const; void setUndoEnabled(bool undo) const; int undoStackLimit(bool defaultValue = false) const; void setUndoStackLimit(int limit) const; bool useCumulativeUndoRedo(bool defaultValue = false) const; void setCumulativeUndoRedo(bool value); double stackT1(bool defaultValue = false) const; void setStackT1(int T1); double stackT2(bool defaultValue = false) const; void setStackT2(int T2); int stackN(bool defaultValue = false) const; void setStackN(int N); qint32 defImageWidth(bool defaultValue = false) const; void defImageWidth(qint32 width) const; qint32 defImageHeight(bool defaultValue = false) const; void defImageHeight(qint32 height) const; double defImageResolution(bool defaultValue = false) const; void defImageResolution(double res) const; /** * @return the id of the default color model used for creating new images. */ QString defColorModel(bool defaultValue = false) const; /** * set the id of the default color model used for creating new images. */ void defColorModel(const QString & model) const; /** * @return the id of the default color depth used for creating new images. */ QString defaultColorDepth(bool defaultValue = false) const; /** * set the id of the default color depth used for creating new images. */ void setDefaultColorDepth(const QString & depth) const; /** * @return the id of the default color profile used for creating new images. */ QString defColorProfile(bool defaultValue = false) const; /** * set the id of the default color profile used for creating new images. */ void defColorProfile(const QString & depth) const; CursorStyle newCursorStyle(bool defaultValue = false) const; void setNewCursorStyle(CursorStyle style); OutlineStyle newOutlineStyle(bool defaultValue = false) const; void setNewOutlineStyle(OutlineStyle style); QRect colorPreviewRect() const; void setColorPreviewRect(const QRect &rect); /// get the profile the user has selected for the given screen QString monitorProfile(int screen) const; void setMonitorProfile(int screen, const QString & monitorProfile, bool override) const; QString monitorForScreen(int screen, const QString &defaultMonitor, bool defaultValue = true) const; void setMonitorForScreen(int screen, const QString& monitor); /// Get the actual profile to be used for the given screen, which is /// either the screen profile set by the color management system or /// the custom monitor profile set by the user, depending on the configuration const KoColorProfile *displayProfile(int screen) const; QString workingColorSpace(bool defaultValue = false) const; void setWorkingColorSpace(const QString & workingColorSpace) const; QString importProfile(bool defaultValue = false) const; void setImportProfile(const QString & importProfile) const; QString printerColorSpace(bool defaultValue = false) const; void setPrinterColorSpace(const QString & printerColorSpace) const; QString printerProfile(bool defaultValue = false) const; void setPrinterProfile(const QString & printerProfile) const; bool useBlackPointCompensation(bool defaultValue = false) const; void setUseBlackPointCompensation(bool useBlackPointCompensation) const; bool allowLCMSOptimization(bool defaultValue = false) const; void setAllowLCMSOptimization(bool allowLCMSOptimization); bool showRulers(bool defaultValue = false) const; void setShowRulers(bool rulers) const; qint32 pasteBehaviour(bool defaultValue = false) const; void setPasteBehaviour(qint32 behaviour) const; qint32 monitorRenderIntent(bool defaultValue = false) const; void setRenderIntent(qint32 monitorRenderIntent) const; bool useOpenGL(bool defaultValue = false) const; void setUseOpenGL(bool useOpenGL) const; int openGLFilteringMode(bool defaultValue = false) const; void setOpenGLFilteringMode(int filteringMode); bool useOpenGLTextureBuffer(bool defaultValue = false) const; void setUseOpenGLTextureBuffer(bool useBuffer); bool disableDoubleBuffering(bool defaultValue = false) const; void setDisableDoubleBuffering(bool disableDoubleBuffering); bool disableVSync(bool defaultValue = false) const; void setDisableVSync(bool disableVSync); bool showAdvancedOpenGLSettings(bool defaultValue = false) const; bool forceOpenGLFenceWorkaround(bool defaultValue = false) const; int numMipmapLevels(bool defaultValue = false) const; int openGLTextureSize(bool defaultValue = false) const; int textureOverlapBorder() const; qint32 maxNumberOfThreads(bool defaultValue = false) const; void setMaxNumberOfThreads(qint32 numberOfThreads); quint32 getGridMainStyle(bool defaultValue = false) const; void setGridMainStyle(quint32 v) const; quint32 getGridSubdivisionStyle(bool defaultValue = false) const; void setGridSubdivisionStyle(quint32 v) const; QColor getGridMainColor(bool defaultValue = false) const; void setGridMainColor(const QColor & v) const; QColor getGridSubdivisionColor(bool defaultValue = false) const; void setGridSubdivisionColor(const QColor & v) const; quint32 getGridHSpacing(bool defaultValue = false) const; void setGridHSpacing(quint32 v) const; quint32 getGridVSpacing(bool defaultValue = false) const; void setGridVSpacing(quint32 v) const; bool getGridSpacingAspect(bool defaultValue = false) const; void setGridSpacingAspect(bool v) const; quint32 getGridSubdivisions(bool defaultValue = false) const; void setGridSubdivisions(quint32 v) const; quint32 getGridOffsetX(bool defaultValue = false) const; void setGridOffsetX(quint32 v) const; quint32 getGridOffsetY(bool defaultValue = false) const; void setGridOffsetY(quint32 v) const; bool getGridOffsetAspect(bool defaultValue = false) const; void setGridOffsetAspect(bool v) const; qint32 checkSize(bool defaultValue = false) const; void setCheckSize(qint32 checkSize) const; bool scrollCheckers(bool defaultValue = false) const; void setScrollingCheckers(bool scollCheckers) const; QColor checkersColor1(bool defaultValue = false) const; void setCheckersColor1(const QColor & v) const; QColor checkersColor2(bool defaultValue = false) const; void setCheckersColor2(const QColor & v) const; QColor canvasBorderColor(bool defaultValue = false) const; void setCanvasBorderColor(const QColor &color) const; bool hideScrollbars(bool defaultValue = false) const; void setHideScrollbars(bool value) const; bool antialiasCurves(bool defaultValue = false) const; void setAntialiasCurves(bool v) const; QColor selectionOverlayMaskColor(bool defaultValue = false) const; void setSelectionOverlayMaskColor(const QColor &color); bool antialiasSelectionOutline(bool defaultValue = false) const; void setAntialiasSelectionOutline(bool v) const; bool showRootLayer(bool defaultValue = false) const; void setShowRootLayer(bool showRootLayer) const; bool showGlobalSelection(bool defaultValue = false) const; void setShowGlobalSelection(bool showGlobalSelection) const; bool showOutlineWhilePainting(bool defaultValue = false) const; void setShowOutlineWhilePainting(bool showOutlineWhilePainting) const; bool hideSplashScreen(bool defaultValue = false) const; void setHideSplashScreen(bool hideSplashScreen) const; qreal outlineSizeMinimum(bool defaultValue = false) const; void setOutlineSizeMinimum(qreal outlineSizeMinimum) const; int autoSaveInterval(bool defaultValue = false) const; void setAutoSaveInterval(int seconds) const; bool backupFile(bool defaultValue = false) const; void setBackupFile(bool backupFile) const; bool showFilterGallery(bool defaultValue = false) const; void setShowFilterGallery(bool showFilterGallery) const; bool showFilterGalleryLayerMaskDialog(bool defaultValue = false) const; void setShowFilterGalleryLayerMaskDialog(bool showFilterGallery) const; // OPENGL_SUCCESS, TRY_OPENGL, OPENGL_NOT_TRIED, OPENGL_FAILED QString canvasState(bool defaultValue = false) const; void setCanvasState(const QString& state) const; bool toolOptionsPopupDetached(bool defaultValue = false) const; void setToolOptionsPopupDetached(bool detached) const; bool paintopPopupDetached(bool defaultValue = false) const; void setPaintopPopupDetached(bool detached) const; QString pressureTabletCurve(bool defaultValue = false) const; void setPressureTabletCurve(const QString& curveString) const; qreal vastScrolling(bool defaultValue = false) const; void setVastScrolling(const qreal factor) const; int presetChooserViewMode(bool defaultValue = false) const; void setPresetChooserViewMode(const int mode) const; bool firstRun(bool defaultValue = false) const; void setFirstRun(const bool firstRun) const; bool clicklessSpacePan(bool defaultValue = false) const; void setClicklessSpacePan(const bool toggle) const; int horizontalSplitLines(bool defaultValue = false) const; void setHorizontalSplitLines(const int numberLines) const; int verticalSplitLines(bool defaultValue = false) const; void setVerticalSplitLines(const int numberLines) const; bool hideDockersFullscreen(bool defaultValue = false) const; void setHideDockersFullscreen(const bool value) const; bool showDockerTitleBars(bool defaultValue = false) const; void setShowDockerTitleBars(const bool value) const; bool hideMenuFullscreen(bool defaultValue = false) const; void setHideMenuFullscreen(const bool value) const; bool hideScrollbarsFullscreen(bool defaultValue = false) const; void setHideScrollbarsFullscreen(const bool value) const; bool hideStatusbarFullscreen(bool defaultValue = false) const; void setHideStatusbarFullscreen(const bool value) const; bool hideTitlebarFullscreen(bool defaultValue = false) const; void setHideTitlebarFullscreen(const bool value) const; bool hideToolbarFullscreen(bool defaultValue = false) const; void setHideToolbarFullscreen(const bool value) const; + bool fullscreenMode(bool defaultValue = false) const; + void setFullscreenMode(const bool value) const; + QStringList favoriteCompositeOps(bool defaultValue = false) const; void setFavoriteCompositeOps(const QStringList& compositeOps) const; QString exportConfiguration(const QString &filterId, bool defaultValue = false) const; void setExportConfiguration(const QString &filterId, const KisPropertiesConfiguration &properties) const; bool useOcio(bool defaultValue = false) const; void setUseOcio(bool useOCIO) const; int favoritePresets(bool defaultValue = false) const; void setFavoritePresets(const int value); enum OcioColorManagementMode { INTERNAL = 0, OCIO_CONFIG, OCIO_ENVIRONMENT }; OcioColorManagementMode ocioColorManagementMode(bool defaultValue = false) const; void setOcioColorManagementMode(OcioColorManagementMode mode) const; QString ocioConfigurationPath(bool defaultValue = false) const; void setOcioConfigurationPath(const QString &path) const; QString ocioLutPath(bool defaultValue = false) const; void setOcioLutPath(const QString &path) const; int ocioLutEdgeSize(bool defaultValue = false) const; void setOcioLutEdgeSize(int value); bool ocioLockColorVisualRepresentation(bool defaultValue = false) const; void setOcioLockColorVisualRepresentation(bool value); bool useSystemMonitorProfile(bool defaultValue = false) const; void setUseSystemMonitorProfile(bool _useSystemMonitorProfile) const; QString defaultPalette(bool defaultValue = false) const; void setDefaultPalette(const QString& name) const; QString toolbarSlider(int sliderNumber, bool defaultValue = false) const; void setToolbarSlider(int sliderNumber, const QString &slider); bool sliderLabels(bool defaultValue = false) const; void setSliderLabels(bool enabled); QString currentInputProfile(bool defaultValue = false) const; void setCurrentInputProfile(const QString& name); bool presetStripVisible(bool defaultValue = false) const; void setPresetStripVisible(bool visible); bool scratchpadVisible(bool defaultValue = false) const; void setScratchpadVisible(bool visible); bool showSingleChannelAsColor(bool defaultValue = false) const; void setShowSingleChannelAsColor(bool asColor); bool hidePopups(bool defaultValue = false) const; void setHidePopups(bool hidepopups); int numDefaultLayers(bool defaultValue = false) const; void setNumDefaultLayers(int num); quint8 defaultBackgroundOpacity(bool defaultValue = false) const; void setDefaultBackgroundOpacity(quint8 value); QColor defaultBackgroundColor(bool defaultValue = false) const; void setDefaultBackgroundColor(QColor value); enum BackgroundStyle { LAYER = 0, PROJECTION = 1 }; BackgroundStyle defaultBackgroundStyle(bool defaultValue = false) const; void setDefaultBackgroundStyle(BackgroundStyle value); int lineSmoothingType(bool defaultValue = false) const; void setLineSmoothingType(int value); qreal lineSmoothingDistance(bool defaultValue = false) const; void setLineSmoothingDistance(qreal value); qreal lineSmoothingTailAggressiveness(bool defaultValue = false) const; void setLineSmoothingTailAggressiveness(qreal value); bool lineSmoothingSmoothPressure(bool defaultValue = false) const; void setLineSmoothingSmoothPressure(bool value); bool lineSmoothingScalableDistance(bool defaultValue = false) const; void setLineSmoothingScalableDistance(bool value); qreal lineSmoothingDelayDistance(bool defaultValue = false) const; void setLineSmoothingDelayDistance(qreal value); bool lineSmoothingUseDelayDistance(bool defaultValue = false) const; void setLineSmoothingUseDelayDistance(bool value); bool lineSmoothingFinishStabilizedCurve(bool defaultValue = false) const; void setLineSmoothingFinishStabilizedCurve(bool value); bool lineSmoothingStabilizeSensors(bool defaultValue = false) const; void setLineSmoothingStabilizeSensors(bool value); int paletteDockerPaletteViewSectionSize(bool defaultValue = false) const; void setPaletteDockerPaletteViewSectionSize(int value) const; int tabletEventsDelay(bool defaultValue = false) const; void setTabletEventsDelay(int value); bool testingAcceptCompressedTabletEvents(bool defaultValue = false) const; void setTestingAcceptCompressedTabletEvents(bool value); bool testingCompressBrushEvents(bool defaultValue = false) const; void setTestingCompressBrushEvents(bool value); const KoColorSpace* customColorSelectorColorSpace(bool defaultValue = false) const; void setCustomColorSelectorColorSpace(const KoColorSpace *cs); bool useDirtyPresets(bool defaultValue = false) const; void setUseDirtyPresets(bool value); bool useEraserBrushSize(bool defaultValue = false) const; void setUseEraserBrushSize(bool value); QColor getMDIBackgroundColor(bool defaultValue = false) const; void setMDIBackgroundColor(const QColor & v) const; QString getMDIBackgroundImage(bool defaultValue = false) const; void setMDIBackgroundImage(const QString & fileName) const; bool useVerboseOpenGLDebugOutput(bool defaultValue = false) const; int workaroundX11SmoothPressureSteps(bool defaultValue = false) const; bool showCanvasMessages(bool defaultValue = false) const; void setShowCanvasMessages(bool show); bool compressKra(bool defaultValue = false) const; void setCompressKra(bool compress); bool toolOptionsInDocker(bool defaultValue = false) const; void setToolOptionsInDocker(bool inDocker); template void writeEntry(const QString& name, const T& value) { m_cfg.writeEntry(name, value); } template void writeList(const QString& name, const QList& value) { m_cfg.writeEntry(name, value); } template T readEntry(const QString& name, const T& defaultValue=T()) { return m_cfg.readEntry(name, defaultValue); } template QList readList(const QString& name, const QList& defaultValue=QList()) { return m_cfg.readEntry(name, defaultValue); } private: KisConfig(const KisConfig&); KisConfig& operator=(const KisConfig&) const; /// get the profile the color managment system has stored for the given screen static const KoColorProfile* getScreenProfile(int screen); private: mutable KConfigGroup m_cfg; }; #endif // KIS_CONFIG_H_ diff --git a/krita/ui/kis_config_notifier.h b/krita/ui/kis_config_notifier.h index 91823f7f6b4..96151089008 100644 --- a/krita/ui/kis_config_notifier.h +++ b/krita/ui/kis_config_notifier.h @@ -1,57 +1,57 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CONFIG_NOTIFIER_H_ #define KIS_CONFIG_NOTIFIER_H_ #include -#include "krita_export.h" +#include "kritaui_export.h" /** * An object that emits a signal to inform interested parties that the * configuration settings have changed. */ class KRITAUI_EXPORT KisConfigNotifier : public QObject { Q_OBJECT public: /** * @return the KisConfigNotifier singleton */ static KisConfigNotifier *instance(); /** * Notify that the configuration has changed. This will cause the * configChanged() signal to be emitted. */ void notifyConfigChanged(void); Q_SIGNALS: /** * This signal is emitted whenever notifyConfigChanged() is called. */ void configChanged(void); private: KisConfigNotifier(); ~KisConfigNotifier(); KisConfigNotifier(const KisConfigNotifier&); KisConfigNotifier operator=(const KisConfigNotifier&); }; #endif // KIS_CONFIG_NOTIFIER_H_ diff --git a/krita/ui/kis_cursor.h b/krita/ui/kis_cursor.h index 78bc1ee5c65..fe60875261c 100644 --- a/krita/ui/kis_cursor.h +++ b/krita/ui/kis_cursor.h @@ -1,92 +1,92 @@ /* * kis_cursor.h - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2004 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_cursor_h__ #define __kis_cursor_h__ -#include +#include #include class KRITAUI_EXPORT KisCursor { public: KisCursor(); // Predefined Qt cursors. static QCursor arrowCursor(); // standard arrow cursor static QCursor upArrowCursor(); // upwards arrow static QCursor crossCursor(); // crosshair static QCursor roundCursor(); // small open circle 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(); // horizontal splitting static QCursor pointingHandCursor(); // a pointing hand static QCursor zoomSmoothCursor(); static QCursor zoomDiscreteCursor(); static QCursor rotateCanvasSmoothCursor(); static QCursor rotateCanvasDiscreteCursor(); static QCursor pickerImageForegroundCursor(); static QCursor pickerImageBackgroundCursor(); static QCursor pickerLayerForegroundCursor(); static QCursor pickerLayerBackgroundCursor(); static QCursor changeExposureCursor(); static QCursor changeGammaCursor(); static QCursor triangleLeftHandedCursor(); static QCursor triangleRightHandedCursor(); // 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 pickLayerCursor(); // pick layer cursor static QCursor colorChangerCursor(); // color changer tool cursor static QCursor selectCursor(); // select 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 // Makes a 32x32 bitmap that is compatible with different platforms static QBitmap bitmapFromData(const QSize& size, const unsigned char* data); // 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_document_undo_store.h b/krita/ui/kis_document_undo_store.h index 9222d358a04..97515886f80 100644 --- a/krita/ui/kis_document_undo_store.h +++ b/krita/ui/kis_document_undo_store.h @@ -1,42 +1,43 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DOCUMENT_UNDO_STORE_H #define __KIS_DOCUMENT_UNDO_STORE_H #include "kis_undo_store.h" +#include "kritaui_export.h" class KisDocument; class KRITAUI_EXPORT KisDocumentUndoStore : public KisUndoStore { public: KisDocumentUndoStore(KisDocument *doc); const KUndo2Command* presentCommand(); void undoLastCommand(); void addCommand(KUndo2Command *cmd); void beginMacro(const KUndo2MagicString& macroName); void endMacro(); void purgeRedoState(); private: KisDocument* m_doc; }; #endif /* __KIS_DOCUMENT_UNDO_STORES_H */ diff --git a/krita/ui/kis_factory2.cc b/krita/ui/kis_factory2.cc index 6e2fd9df86f..d778bdde101 100644 --- a/krita/ui/kis_factory2.cc +++ b/krita/ui/kis_factory2.cc @@ -1,93 +1,98 @@ /* * kis_factory.cc - part of Krayon * * Copyright (c) 1999 Matthias Elter * * 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 _MSC_VER // this removes KDEWIN extensions to stdint.h: required by exiv2 //#define KDEWIN_STDINT_H //#endif #include "kis_factory2.h" #include #include #include #include #include #include +#include + #include #include "kis_aboutdata.h" #include "KisPart.h" +#include "kis_md5_generator.h" + KAboutData* KisFactory::s_aboutData = 0; KComponentData* KisFactory::s_componentData = 0; KisFactory::KisFactory() { (void)componentData(); + KoHashGeneratorProvider::instance()->setGenerator("MD5", new KisMD5Generator()); } KisFactory::~KisFactory() { delete s_aboutData; s_aboutData = 0; delete s_componentData; s_componentData = 0; } KAboutData* KisFactory::aboutData() { if (!s_aboutData) { s_aboutData = newKritaAboutData(); } return s_aboutData; } const KComponentData &KisFactory::componentData() { if (!s_componentData) { s_componentData = new KComponentData(aboutData()); Q_CHECK_PTR(s_componentData); // for cursors s_componentData->dirs()->addResourceType("kis_pics", "data", "krita/pics/"); // for images in the paintop box s_componentData->dirs()->addResourceType("kis_images", "data", "krita/images/"); s_componentData->dirs()->addResourceType("icc_profiles", "data", "krita/profiles/"); // Tell the iconloader about share/apps/calligra/icons KIconLoader::global()->addAppDir("calligra"); KGlobal::locale()->insertCatalog(s_componentData->catalogName()); } return *s_componentData; } const QString KisFactory::componentName() { return "krita"; } diff --git a/krita/ui/kis_factory2.h b/krita/ui/kis_factory2.h index 6873d1e013b..ea91d96b255 100644 --- a/krita/ui/kis_factory2.h +++ b/krita/ui/kis_factory2.h @@ -1,47 +1,47 @@ /* * kis_factory2.h - part of Krayon * * Copyright (c) 1999 Matthias Elter * * 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_2_H_ #define KIS_FACTORY_2_H_ #include -#include +#include #include #include class KRITAUI_EXPORT KisFactory { public: KisFactory(); ~KisFactory(); static KAboutData *aboutData(); static const KComponentData &componentData(); static const QString componentName(); private: static KComponentData *s_componentData; static KAboutData *s_aboutData; }; #endif diff --git a/krita/ui/kis_file_layer.h b/krita/ui/kis_file_layer.h index 204291c42e2..d00f51145cc 100644 --- a/krita/ui/kis_file_layer.h +++ b/krita/ui/kis_file_layer.h @@ -1,81 +1,81 @@ /* * Copyright (c) 2013 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_FILE_LAYER_H #define KIS_FILE_LAYER_H -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_external_layer_iface.h" #include "kis_safe_document_loader.h" /** * @brief The KisFileLayer class loads a particular file as a layer into the layer stack. */ class KRITAUI_EXPORT KisFileLayer : public KisExternalLayer { Q_OBJECT public: enum ScalingMethod { None, ToImageSize, ToImagePPI }; explicit KisFileLayer(KisImageWSP image, const QString& basePath, const QString &filename, ScalingMethod scalingMethod, const QString &name, quint8 opacity); ~KisFileLayer(); KisFileLayer(const KisFileLayer& rhs); void resetCache(); virtual const KoColorSpace *colorSpace() const; KisPaintDeviceSP original() const; KisPaintDeviceSP paintDevice() const; KisDocumentSectionModel::PropertyList sectionModelProperties() const; void setFileName(const QString &basePath, const QString &filename); QString fileName() const; QString path() const; ScalingMethod scalingMethod() const; KisNodeSP clone() const; bool allowAsChild(KisNodeSP) const; bool accept(KisNodeVisitor&); void accept(KisProcessingVisitor &visitor, KisUndoAdapter *undoAdapter); KUndo2Command* crop(const QRect & rect); KUndo2Command* transform(const QTransform &transform); public Q_SLOTS: void slotLoadingFinished(KisImageSP importedImage); private: QString m_basePath; QString m_filename; ScalingMethod m_scalingMethod; KisPaintDeviceSP m_image; KisSafeDocumentLoader m_loader; }; #endif // KIS_FILE_LAYER_H diff --git a/krita/ui/kis_filter_manager.h b/krita/ui/kis_filter_manager.h index 072b758fac8..3a6d69e3465 100644 --- a/krita/ui/kis_filter_manager.h +++ b/krita/ui/kis_filter_manager.h @@ -1,68 +1,68 @@ /* * Copyright (c) 2005 Boudewijn Rempt * Copyright (c) 2007 Cyrille Berger * * 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 -#include +#include #include class KisViewManager; class KActionCollection; class KisActionManager; class KisView; /** * Create all the filter actions for the specified view and implement re-apply filter */ class KRITAUI_EXPORT KisFilterManager : public QObject { Q_OBJECT public: KisFilterManager(KisViewManager * parent); ~KisFilterManager(); void setView(QPointerimageView); void setup(KActionCollection * ac, KisActionManager *actionManager); void updateGUI(); void apply(KisSafeFilterConfigurationSP filterConfig); void finish(); void cancel(); bool isStrokeRunning() const; private Q_SLOTS: void insertFilter(const QString &name); void showFilterDialog(const QString &filterId); void reapplyLastFilter(); void slotStrokeEndRequested(); void slotStrokeCancelRequested(); private: struct Private; Private * const d; }; #endif diff --git a/krita/ui/kis_histogram_view.h b/krita/ui/kis_histogram_view.h index 4ec43e5746a..c2151f25fd5 100644 --- a/krita/ui/kis_histogram_view.h +++ b/krita/ui/kis_histogram_view.h @@ -1,133 +1,133 @@ /* * Copyright (c) 2005 Bart Coppens * * 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 #include #include #include #include #include "kis_types.h" #include "KoHistogramProducer.h" #include "kis_histogram.h" -#include +#include class KoChannelInfo; /** * 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. * * XXX: make beautiful, for instance by using alpha and a bit of a * gradient! **/ class KRITAUI_EXPORT KisHistogramView : public QLabel { Q_OBJECT public: KisHistogramView(QWidget *parent = 0, const char *name = 0, Qt::WFlags f = 0); virtual ~KisHistogramView(); void setPaintDevice(KisPaintDeviceSP dev, const QRect &bounds); void setHistogram(KisHistogramSP histogram); void setView(double from, double size); KoHistogramProducerSP currentProducer(); QStringList channelStrings(); /** Lists all producers currently available */ QList producers(); /** Sets the currently displayed channels to channels of the producer with producerID as ID*/ void setCurrentChannels(const KoID& producerID, QList channels); /** Be careful, producer will be modified */ void setCurrentChannels(KoHistogramProducerSP producer, QList channels); bool hasColor(); void setColor(bool set); public Q_SLOTS: void setActiveChannel(int channel); void setHistogramType(enumHistogramType type); void updateHistogram(); Q_SIGNALS: void rightClicked(const QPoint& pos); protected: virtual void mousePressEvent(QMouseEvent * e); private: void setChannels(); void addProducerChannels(KoHistogramProducerSP producer); typedef struct { bool isProducer; KoHistogramProducerSP producer; KoChannelInfo * channel; } ComboboxInfo; QVector m_comboInfo; QPixmap m_pix; KisHistogramSP m_histogram; const KoColorSpace* m_cs; KoHistogramProducerSP m_currentProducer; QList m_channels; // Maps the channels in m_channels to a real channel offset in the producer->channels() QVector 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_utils.cpp b/krita/ui/kis_icon_utils.cpp new file mode 100644 index 00000000000..a0fa1d97c6c --- /dev/null +++ b/krita/ui/kis_icon_utils.cpp @@ -0,0 +1,138 @@ +/* + * Copyright (c) 2015 Dmitry Kazakov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#include "kis_icon_utils.h" + +#include "kis_debug.h" + +#include +#include +#include +#include + +#include "KoIcon.h" + + +namespace KisIconUtils +{ + +KIcon loadIcon(const QString &name) { + + static bool firstUse = true; + if (firstUse) { + // workaround for some kde-related crash + bool _unused = KIconLoader::global()->iconPath(name, KIconLoader::NoGroup, true).isEmpty(); + Q_UNUSED(_unused); + firstUse = false; + } + + QString realName; + + // try load themed icon + QColor background = qApp->palette().background().color(); + bool useDarkIcons = background.value() > 100; + const char * const prefix = useDarkIcons ? "dark_" : "light_"; + + realName = QLatin1String(prefix) + name; + + bool absent = KIconLoader::global()->iconPath(realName, KIconLoader::User, true).isEmpty(); + if (absent) { + realName = name; + } + + KIcon icon(realName); + + // fallback + if (icon.isNull()) { + icon = KIcon(name); + } + + return icon; +} + +bool adjustIcon(QIcon *icon) +{ + bool result = false; + + QString iconName = icon->name(); + if (iconName.isNull()) return result; + + QString realIconName = iconName; + + if (iconName.startsWith("dark_")) { + realIconName = iconName.mid(5); + } + + if (iconName.startsWith("light_")) { + realIconName = iconName.mid(6); + } + + if (!realIconName.isNull()) { + *icon = loadIcon(realIconName); + result = !icon->isNull(); + } + + return result; +} + +void updateIconCommon(QObject *object) +{ + QAbstractButton* button = dynamic_cast(object); + if (button) { + updateIcon(button); + } + + QComboBox* comboBox = dynamic_cast(object); + if (comboBox) { + updateIcon(comboBox); + } + + QAction* action = dynamic_cast(object); + if (action) { + updateIcon(action); + } +} + +void updateIcon(QAbstractButton *button) +{ + QIcon icon = button->icon(); + + if (adjustIcon(&icon)) { + button->setIcon(icon); + } +} + +void updateIcon(QComboBox *comboBox) +{ + for (int i = 0; i < comboBox->count(); i++) { + QIcon icon = comboBox->itemIcon(i); + if (adjustIcon(&icon)) { + comboBox->setItemIcon(i, icon); + } + } +} + +void updateIcon(QAction *action) +{ + QIcon icon = action->icon(); + + if (adjustIcon(&icon)) { + action->setIcon(icon); + } +} +} diff --git a/krita/ui/kis_icon_utils.h b/krita/ui/kis_icon_utils.h new file mode 100644 index 00000000000..8650afe2cb1 --- /dev/null +++ b/krita/ui/kis_icon_utils.h @@ -0,0 +1,61 @@ +/* + * Copyright (c) 2015 Dmitry Kazakov + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +#ifndef __KIS_ICON_UTILS_H +#define __KIS_ICON_UTILS_H + +#include "kritaui_export.h" + +class QIcon; +class QAbstractButton; +class QComboBox; +class QAction; +class QObject; +class KIcon; + +namespace KisIconUtils +{ + /** + * Load a themed icon using its base name. Use it in + * Kirta instead of previous themedIcon() + */ + KRITAUI_EXPORT KIcon loadIcon(const QString &name); + + /** + * This function updates an icon of \p object depending on its + * type. See updateIcon() overrides to see the supported types + */ + KRITAUI_EXPORT void updateIconCommon(QObject *object); + + /** + * Update an icon of \p button according to the current theme + */ + KRITAUI_EXPORT void updateIcon(QAbstractButton *button); + + /** + * Update an icon of \p comboBox according to the current theme + */ + KRITAUI_EXPORT void updateIcon(QComboBox *comboBox); + + /** + * Update an icon of \p action according to the current theme + */ + KRITAUI_EXPORT void updateIcon(QAction *action); +} + +#endif /* __KIS_ICON_UTILS_H */ diff --git a/krita/ui/kis_image_manager.h b/krita/ui/kis_image_manager.h index e08e2c7c319..8eb870ee490 100644 --- a/krita/ui/kis_image_manager.h +++ b/krita/ui/kis_image_manager.h @@ -1,75 +1,75 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2006 * * 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_IMAGE_MANAGER #define KIS_IMAGE_MANAGER #include #include #include -#include +#include class KisViewManager; class KisFilterStrategy; class KisActionManager; class KisView; class KRITAUI_EXPORT KisImageManager : public QObject { Q_OBJECT public: KisImageManager(KisViewManager * view); ~KisImageManager() {} void setView(QPointerimageView); void setup(KisActionManager *actionManager); public Q_SLOTS: void slotImportLayerFromFile(); void slotImportLayerAsTransparencyMask(); void slotImportLayerAsFilterMask(); void slotImportLayerAsSelectionMask(); /** * 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 */ qint32 importImage(const KUrl& url, const QString &layerType = "KisPaintLayer"); void resizeCurrentImage(qint32 w, qint32 h, qint32 xOffset, qint32 yOffset); void scaleCurrentImage(const QSize &size, qreal xres, qreal yres, KisFilterStrategy *filterStrategy); void rotateCurrentImage(double radians); void shearCurrentImage(double angleX, double angleY); void slotImageProperties(); void slotImageColor(); private: KisViewManager * m_view; }; #endif // KIS_IMAGE_MANAGER diff --git a/krita/ui/kis_image_view_converter.h b/krita/ui/kis_image_view_converter.h index 50b5b76d417..d0cb6bb154f 100644 --- a/krita/ui/kis_image_view_converter.h +++ b/krita/ui/kis_image_view_converter.h @@ -1,69 +1,69 @@ /* * Copyright (c) 2007 Thomas Zander * * 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_IMAGE_VIEW_CONVERTER_H #define KIS_IMAGE_VIEW_CONVERTER_H -#include +#include #include "kis_image.h" #include "kis_types.h" #include class QTransform; /** * ViewConverter to convert from flake-internal points to * krita-internal pixels and back. You can use this class whereever * the flake tools or shapes come in contact with the krita-image. * * For usage remember that the document here is the flake-points. And * the view is the krita-pixels. */ class KRITAUI_EXPORT KisImageViewConverter : public KoViewConverter { public: /** * constructor * @param image the image this viewConverter works for. */ KisImageViewConverter(const KisImageWSP image); QTransform documentToView() const; QTransform viewToDocument() const; using KoViewConverter::documentToView; using KoViewConverter::viewToDocument; /// reimplemented from superclass void zoom(qreal *zoomX, qreal *zoomY) const; qreal documentToViewX(qreal documentX) const; qreal documentToViewY(qreal documentY) const; qreal viewToDocumentX(qreal viewX) const; qreal viewToDocumentY(qreal viewY) const; // This method shouldn't be used for image qreal zoom() const; private: const KisImageWSP m_image; }; #endif diff --git a/krita/ui/kis_layer_manager.cc b/krita/ui/kis_layer_manager.cc index c0e29733424..b85f1ef6c0d 100644 --- a/krita/ui/kis_layer_manager.cc +++ b/krita/ui/kis_layer_manager.cc @@ -1,979 +1,1007 @@ /* * Copyright (C) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_layer_manager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisView.h" #include "kis_config.h" #include "kis_cursor.h" #include "dialogs/kis_dlg_adj_layer_props.h" #include "dialogs/kis_dlg_adjustment_layer.h" #include "dialogs/kis_dlg_layer_properties.h" #include "dialogs/kis_dlg_generator_layer.h" #include "dialogs/kis_dlg_file_layer.h" #include "dialogs/kis_dlg_layer_style.h" #include "KisDocument.h" #include "kis_filter_manager.h" #include "kis_node_visitor.h" #include "kis_paint_layer.h" #include "commands/kis_image_commands.h" #include "commands/kis_layer_commands.h" #include "commands/kis_node_commands.h" #include "kis_canvas_resource_provider.h" #include "kis_selection_manager.h" #include "kis_statusbar.h" #include "KisViewManager.h" #include "kis_zoom_manager.h" #include "canvas/kis_canvas2.h" #include "widgets/kis_meta_data_merge_strategy_chooser_widget.h" #include "widgets/kis_wdg_generator.h" #include "kis_progress_widget.h" #include "kis_node_commands_adapter.h" #include "kis_node_manager.h" #include "kis_action.h" #include "kis_action_manager.h" #include "KisPart.h" #include "kis_signal_compressor_with_param.h" #include "kis_abstract_projection_plane.h" #include "commands_new/kis_set_layer_style_command.h" #include "kis_post_execution_undo_adapter.h" - +#include "kis_selection_mask.h" class KisSaveGroupVisitor : public KisNodeVisitor { public: KisSaveGroupVisitor(KisImageWSP image, bool saveInvisible, bool saveTopLevelOnly, const KUrl &url, const QString &baseName, const QString &extension, const QString &mimeFilter) : m_image(image) , m_saveInvisible(saveInvisible) , m_saveTopLevelOnly(saveTopLevelOnly) , m_url(url) , m_baseName(baseName) , m_extension(extension) , m_mimeFilter(mimeFilter) { } virtual ~KisSaveGroupVisitor() { } public: bool visit(KisNode* ) { return true; } bool visit(KisPaintLayer *) { return true; } bool visit(KisAdjustmentLayer *) { return true; } bool visit(KisExternalLayer *) { return true; } bool visit(KisCloneLayer *) { return true; } bool visit(KisFilterMask *) { return true; } bool visit(KisTransformMask *) { return true; } bool visit(KisTransparencyMask *) { return true; } bool visit(KisGeneratorLayer * ) { return true; } bool visit(KisSelectionMask* ) { return true; } bool visit(KisGroupLayer *layer) { if (layer == m_image->rootLayer()) { KisLayerSP child = dynamic_cast(layer->firstChild().data()); while (child) { child->accept(*this); child = dynamic_cast(child->nextSibling().data()); } } else if (layer->visible() || m_saveInvisible) { QRect r = m_image->bounds(); KisDocument *d = KisPart::instance()->createDocument(); d->prepareForImport(); KisImageWSP dst = new KisImage(d->createUndoStore(), r.width(), r.height(), m_image->colorSpace(), layer->name()); dst->setResolution(m_image->xRes(), m_image->yRes()); d->setCurrentImage(dst); KisPaintLayer* paintLayer = new KisPaintLayer(dst, "projection", layer->opacity()); KisPainter gc(paintLayer->paintDevice()); gc.bitBlt(QPoint(0, 0), layer->projection(), r); dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0)); dst->refreshGraph(); d->setOutputMimeType(m_mimeFilter.toLatin1()); d->setSaveInBatchMode(true); KUrl url = m_url; url.adjustPath(KUrl::AddTrailingSlash); url.setFileName(m_baseName + '_' + layer->name().replace(' ', '_') + '.' + m_extension); d->exportDocument(url); if (!m_saveTopLevelOnly) { KisGroupLayerSP child = dynamic_cast(layer->firstChild().data()); while (child) { child->accept(*this); child = dynamic_cast(child->nextSibling().data()); } } delete d; } return true; } private: KisImageWSP m_image; bool m_saveInvisible; bool m_saveTopLevelOnly; KUrl m_url; QString m_baseName; QString m_extension; QString m_mimeFilter; }; KisLayerManager::KisLayerManager(KisViewManager * view) : m_view(view) , m_imageView(0) , m_imageFlatten(0) , m_imageMergeLayer(0) , m_groupLayersSave(0) , m_imageResizeToLayer(0) , m_flattenLayer(0) , m_rasterizeLayer(0) , m_commandsAdapter(new KisNodeCommandsAdapter(m_view)) , m_layerStyle(0) { } KisLayerManager::~KisLayerManager() { delete m_commandsAdapter; } void KisLayerManager::setView(QPointerview) { m_imageView = view; } KisLayerSP KisLayerManager::activeLayer() { if (m_imageView) { return m_imageView->currentLayer(); } return 0; } KisPaintDeviceSP KisLayerManager::activeDevice() { if (activeLayer()) { return activeLayer()->paintDevice(); } return 0; } void KisLayerManager::activateLayer(KisLayerSP layer) { if (m_imageView) { emit sigLayerActivated(layer); layersUpdated(); if (layer) { m_view->resourceProvider()->slotNodeActivated(layer.data()); } } } void KisLayerManager::setup(KisActionManager* actionManager) { m_imageFlatten = new KisAction(i18n("&Flatten image"), this); m_imageFlatten->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("flatten_image", m_imageFlatten); m_imageFlatten->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_E)); connect(m_imageFlatten, SIGNAL(triggered()), this, SLOT(flattenImage())); m_imageMergeLayer = new KisAction(i18n("&Merge with Layer Below"), this); m_imageMergeLayer->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("merge_layer", m_imageMergeLayer); m_imageMergeLayer->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_E)); connect(m_imageMergeLayer, SIGNAL(triggered()), this, SLOT(mergeLayer())); m_flattenLayer = new KisAction(i18n("&Flatten Layer"), this); m_flattenLayer->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("flatten_layer", m_flattenLayer); connect(m_flattenLayer, SIGNAL(triggered()), this, SLOT(flattenLayer())); KisAction * action = new KisAction(i18n("Rename current layer"), this); action->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("RenameCurrentLayer", action); action->setShortcut(KShortcut(Qt::Key_F2)); connect(action, SIGNAL(triggered()), this, SLOT(layerProperties())); m_rasterizeLayer = new KisAction(i18n("Rasterize Layer"), this); m_rasterizeLayer->setActivationFlags(KisAction::ACTIVE_SHAPE_LAYER); m_rasterizeLayer->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("rasterize_layer", m_rasterizeLayer); connect(m_rasterizeLayer, SIGNAL(triggered()), this, SLOT(rasterizeLayer())); m_groupLayersSave = new KisAction(themedIcon("document-save"), i18n("Save Group Layers..."), this); m_groupLayersSave->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("save_groups_as_images", m_groupLayersSave); connect(m_groupLayersSave, SIGNAL(triggered()), this, SLOT(saveGroupLayers())); m_imageResizeToLayer = new KisAction(i18n("Trim to Current Layer"), this); m_imageResizeToLayer->setActivationFlags(KisAction::ACTIVE_LAYER); actionManager->addAction("resizeimagetolayer", m_imageResizeToLayer); connect(m_imageResizeToLayer, SIGNAL(triggered()), this, SLOT(imageResizeToActiveLayer())); KisAction *trimToImage = new KisAction(themedIcon("trim-to-image"), i18n("Trim to Image Size"), this); trimToImage->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager->addAction("trim_to_image", trimToImage); connect(trimToImage, SIGNAL(triggered()), this, SLOT(trimToImage())); m_layerStyle = new KisAction(i18n("Layer Style..."), this); m_layerStyle->setActivationFlags(KisAction::ACTIVE_LAYER); m_layerStyle->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("layer_style", m_layerStyle); connect(m_layerStyle, SIGNAL(triggered()), this, SLOT(layerStyle())); } void KisLayerManager::updateGUI() { KisImageWSP image = m_view->image(); KisLayerSP layer; qint32 nlayers = 0; if (image) { layer = activeLayer(); nlayers = image->nlayers(); } // XXX these should be named layer instead of image m_imageFlatten->setEnabled(nlayers > 1); m_imageMergeLayer->setEnabled(nlayers > 1 && layer && layer->prevSibling()); m_flattenLayer->setEnabled(nlayers > 1 && layer && layer->firstChild()); if (m_view->statusBar()) m_view->statusBar()->setProfile(image); } void KisLayerManager::imageResizeToActiveLayer() { KisLayerSP layer; KisImageWSP image = m_view->image(); if (image && (layer = activeLayer())) { QRect cropRect = layer->projection()->nonDefaultPixelArea(); if (!cropRect.isEmpty()) { image->cropImage(cropRect); } else { m_view->showFloatingMessage( i18nc("floating message in layer manager", "Layer is empty "), QIcon(), 2000, KisFloatingMessage::Low); } } } void KisLayerManager::trimToImage() { KisImageWSP image = m_view->image(); if (image) { image->cropImage(image->bounds()); } } void KisLayerManager::layerProperties() { if (!m_view) return; if (!m_view->document()) return; KisLayerSP layer = activeLayer(); if (!layer) return; if (KisAdjustmentLayerSP alayer = KisAdjustmentLayerSP(dynamic_cast(layer.data()))) { KisPaintDeviceSP dev = alayer->projection(); KisDlgAdjLayerProps dlg(alayer, alayer.data(), dev, m_view, alayer->filter().data(), alayer->name(), i18n("Filter Layer Properties"), m_view->mainWindow(), "dlgadjlayerprops"); dlg.resize(dlg.minimumSizeHint()); KisSafeFilterConfigurationSP configBefore(alayer->filter()); KIS_ASSERT_RECOVER_RETURN(configBefore); QString xmlBefore = configBefore->toXML(); if (dlg.exec() == QDialog::Accepted) { alayer->setName(dlg.layerName()); KisSafeFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); if(xmlBefore != xmlAfter) { KisChangeFilterCmd *cmd = new KisChangeFilterCmd(alayer, configBefore->name(), xmlBefore, configAfter->name(), xmlAfter, false); // FIXME: check whether is needed cmd->redo(); m_view->undoAdapter()->addCommand(cmd); m_view->document()->setModified(true); } } else { KisSafeFilterConfigurationSP configAfter(dlg.filterConfiguration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); if(xmlBefore != xmlAfter) { alayer->setFilter(KisFilterRegistry::instance()->cloneConfiguration(configBefore.data())); alayer->setDirty(); } } } else if (KisGeneratorLayerSP alayer = KisGeneratorLayerSP(dynamic_cast(layer.data()))) { KisDlgGeneratorLayer dlg(alayer->name(), m_view, m_view->mainWindow()); dlg.setCaption(i18n("Fill Layer Properties")); KisSafeFilterConfigurationSP configBefore(alayer->filter()); Q_ASSERT(configBefore); QString xmlBefore = configBefore->toXML(); dlg.setConfiguration(configBefore.data()); dlg.resize(dlg.minimumSizeHint()); if (dlg.exec() == QDialog::Accepted) { alayer->setName(dlg.layerName()); KisSafeFilterConfigurationSP configAfter(dlg.configuration()); Q_ASSERT(configAfter); QString xmlAfter = configAfter->toXML(); if(xmlBefore != xmlAfter) { KisChangeFilterCmd *cmd = new KisChangeFilterCmd(alayer, configBefore->name(), xmlBefore, configAfter->name(), xmlAfter, true); // FIXME: check whether is needed cmd->redo(); m_view->undoAdapter()->addCommand(cmd); m_view->document()->setModified(true); } } } else { // If layer == normal painting layer, vector layer, or group layer KisDlgLayerProperties *dialog = new KisDlgLayerProperties(layer, m_view, m_view->document()); dialog->resize(dialog->minimumSizeHint()); dialog->setAttribute(Qt::WA_DeleteOnClose); Qt::WindowFlags flags = dialog->windowFlags(); dialog->setWindowFlags(flags | Qt::WindowStaysOnTopHint | Qt::Dialog); dialog->show(); } } void KisLayerManager::convertNodeToPaintLayer(KisNodeSP source) { KisImageWSP image = m_view->image(); if (!image) return; KisPaintDeviceSP srcDevice = source->paintDevice() ? source->projection() : source->original(); if (!srcDevice) return; KisPaintDeviceSP clone; if (!(*srcDevice->colorSpace() == *srcDevice->compositionSourceColorSpace())) { clone = new KisPaintDevice(srcDevice->compositionSourceColorSpace()); QRect rc(srcDevice->extent()); KisPainter::copyAreaOptimized(rc.topLeft(), srcDevice, clone, rc); } else { clone = new KisPaintDevice(*srcDevice); } KisLayerSP layer = new KisPaintLayer(image, source->name(), source->opacity(), clone); layer->setCompositeOp(source->compositeOpId()); KisNodeSP parent = source->parent(); KisNodeSP above = source; while (parent && !parent->allowAsChild(layer)) { above = above->parent(); parent = above ? above->parent() : 0; } m_commandsAdapter->beginMacro(kundo2_i18n("Convert to a Paint Layer")); m_commandsAdapter->addNode(layer, parent, above); m_commandsAdapter->removeNode(source); m_commandsAdapter->endMacro(); } void KisLayerManager::adjustLayerPosition(KisNodeSP node, KisNodeSP activeNode, KisNodeSP &parent, KisNodeSP &above) { Q_ASSERT(activeNode); parent = activeNode; above = parent->lastChild(); - while (parent && !parent->allowAsChild(node)) { + while (parent && + (!parent->allowAsChild(node) || parent->userLocked())) { + above = parent; parent = parent->parent(); } if (!parent) { qWarning() << "KisLayerManager::adjustLayerPosition:" << "No node accepted newly created node"; parent = m_view->image()->root(); above = parent->lastChild(); } } void KisLayerManager::addLayerCommon(KisNodeSP activeNode, KisLayerSP layer) { KisNodeSP parent; KisNodeSP above; adjustLayerPosition(layer, activeNode, parent, above); m_commandsAdapter->addNode(layer, parent, above); } void KisLayerManager::addLayer(KisNodeSP activeNode) { KisImageWSP image = m_view->image(); addLayerCommon(activeNode, new KisPaintLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8, image->colorSpace())); } void KisLayerManager::addGroupLayer(KisNodeSP activeNode) { KisImageWSP image = m_view->image(); addLayerCommon(activeNode, new KisGroupLayer(image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8)); } void KisLayerManager::addCloneLayer(KisNodeSP activeNode) { KisImageWSP image = m_view->image(); addLayerCommon(activeNode, new KisCloneLayer(activeLayer(), image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8)); } void KisLayerManager::addShapeLayer(KisNodeSP activeNode) { if (!m_view) return; if (!m_view->document()) return; KisImageWSP image = m_view->image(); KisShapeLayerSP layer = new KisShapeLayer(m_view->document()->shapeController(), image.data(), image->nextLayerName(), OPACITY_OPAQUE_U8); addLayerCommon(activeNode, layer); } void KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode) { KisImageWSP image = m_view->image(); KisSelectionSP selection = m_view->selection(); KisAdjustmentLayerSP adjl = addAdjustmentLayer(activeNode, QString(), 0, selection); image->refreshGraph(); KisPaintDeviceSP previewDevice = new KisPaintDevice(*adjl->original()); KisDlgAdjustmentLayer dlg(adjl, adjl.data(), previewDevice, image->nextLayerName(), i18n("New Filter Layer"), m_view); dlg.resize(dlg.minimumSizeHint()); // ensure that the device may be free'd by the dialog // when it is not needed anymore previewDevice = 0; if (dlg.exec() != QDialog::Accepted || adjl->filter().isNull()) { // XXX: add messagebox warning if there's no filter set! m_commandsAdapter->undoLastCommand(); } else { adjl->setName(dlg.layerName()); } } KisAdjustmentLayerSP KisLayerManager::addAdjustmentLayer(KisNodeSP activeNode, const QString & name, KisFilterConfiguration * filter, KisSelectionSP selection) { KisImageWSP image = m_view->image(); KisAdjustmentLayerSP layer = new KisAdjustmentLayer(image, name, filter, selection); addLayerCommon(activeNode, layer); return layer; } void KisLayerManager::addGeneratorLayer(KisNodeSP activeNode) { KisImageWSP image = m_view->image(); KisDlgGeneratorLayer dlg(image->nextLayerName(), m_view, m_view->mainWindow()); dlg.resize(dlg.minimumSizeHint()); if (dlg.exec() == QDialog::Accepted) { KisSelectionSP selection = m_view->selection(); KisFilterConfiguration * generator = dlg.configuration(); QString name = dlg.layerName(); addLayerCommon(activeNode, new KisGeneratorLayer(image, name, generator, selection)); } } void KisLayerManager::layerDuplicate() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP active = activeLayer(); if (!active) return; KisLayerSP dup = dynamic_cast(active->clone().data()); m_commandsAdapter->addNode(dup.data(), active->parent(), active.data()); if (dup) { activateLayer(dup); } else { QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("Could not add layer to image.")); } } void KisLayerManager::layerRaise() { KisImageWSP image = m_view->image(); KisLayerSP layer; if (!image) return; layer = activeLayer(); m_commandsAdapter->raise(layer); layer->parent()->setDirty(); } void KisLayerManager::layerLower() { KisImageWSP image = m_view->image(); KisLayerSP layer; if (!image) return; layer = activeLayer(); m_commandsAdapter->lower(layer); layer->parent()->setDirty(); } void KisLayerManager::layerFront() { KisImageWSP image = m_view->image(); KisLayerSP layer; if (!image) return; layer = activeLayer(); m_commandsAdapter->toTop(layer); layer->parent()->setDirty(); } void KisLayerManager::layerBack() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer; layer = activeLayer(); m_commandsAdapter->toBottom(layer); layer->parent()->setDirty(); } void KisLayerManager::rotateLayer(double radians) { if (!m_view->image()) return; KisLayerSP layer = activeLayer(); if (!layer) return; m_view->image()->rotateNode(layer, radians); } void KisLayerManager::shearLayer(double angleX, double angleY) { if (!m_view->image()) return; KisLayerSP layer = activeLayer(); if (!layer) return; m_view->image()->shearNode(layer, angleX, angleY); } void KisLayerManager::flattenImage() { KisImageWSP image = m_view->image(); if (image) { bool doIt = true; if (image->nHiddenLayers() > 0) { int answer = QMessageBox::warning(m_view->mainWindow(), i18nc("@title:window", "Flatten Image"), i18n("The image contains hidden layers that will be lost. Do you want to flatten the image?"), QMessageBox::Yes | QMessageBox::No, QMessageBox::No); if (answer != QMessageBox::Yes) { doIt = false; } } if (doIt) { image->flatten(); } } } +inline bool isSelectionMask(KisNodeSP node) { + return dynamic_cast(node.data()); +} + +bool tryMergeSelectionMasks(KisNodeSP currentNode, KisImageSP image) +{ + bool result = false; + + KisNodeSP prevNode = currentNode->prevSibling(); + if (isSelectionMask(currentNode) && + prevNode && isSelectionMask(prevNode)) { + + QList mergedNodes; + mergedNodes.append(currentNode); + mergedNodes.append(prevNode); + + image->mergeMultipleLayers(mergedNodes, currentNode); + + result = true; + } + + return result; +} + void KisLayerManager::mergeLayer() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = activeLayer(); if (!layer) return; QList selectedNodes = m_view->nodeManager()->selectedNodes(); if (selectedNodes.size() > 1) { image->mergeMultipleLayers(selectedNodes, layer); - } else { + + } else if (!tryMergeSelectionMasks(m_view->activeNode(), image)) { + if (!layer->prevSibling()) return; KisLayer *prevLayer = dynamic_cast(layer->prevSibling().data()); if (!prevLayer) return; if (layer->metaData()->isEmpty() && prevLayer->metaData()->isEmpty()) { image->mergeDown(layer, KisMetaData::MergeStrategyRegistry::instance()->get("Drop")); } else { const KisMetaData::MergeStrategy* strategy = KisMetaDataMergeStrategyChooserWidget::showDialog(m_view->mainWindow()); if (!strategy) return; image->mergeDown(layer, strategy); } } m_view->updateGUI(); } void KisLayerManager::flattenLayer() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = activeLayer(); if (!layer) return; KisLayerSP newLayer = image->flattenLayer(layer); if (newLayer) { newLayer->setDirty(); } m_view->updateGUI(); } void KisLayerManager::rasterizeLayer() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = activeLayer(); if (!layer) return; KisPaintLayerSP paintLayer = new KisPaintLayer(image, layer->name(), layer->opacity()); KisPainter gc(paintLayer->paintDevice()); QRect rc = layer->projection()->exactBounds(); gc.bitBlt(rc.topLeft(), layer->projection(), rc); m_commandsAdapter->beginMacro(kundo2_i18n("Rasterize Layer")); m_commandsAdapter->addNode(paintLayer.data(), layer->parent().data(), layer.data()); int childCount = layer->childCount(); for (int i = 0; i < childCount; i++) { m_commandsAdapter->moveNode(layer->firstChild(), paintLayer, paintLayer->lastChild()); } m_commandsAdapter->removeNode(layer); m_commandsAdapter->endMacro(); updateGUI(); } void KisLayerManager::layersUpdated() { KisLayerSP layer = activeLayer(); if (!layer) return; m_view->updateGUI(); } void KisLayerManager::saveGroupLayers() { QStringList listMimeFilter = KisImportExportManager::mimeFilter("application/x-krita", KisImportExportManager::Export); KDialog dlg; QWidget *page = new QWidget(&dlg); dlg.setMainWidget(page); QBoxLayout *layout = new QVBoxLayout(page); KFileWidget *fd = new KFileWidget(m_view->document()->url().path(), page); fd->setUrl(m_view->document()->url()); fd->setMimeFilter(listMimeFilter); fd->setOperationMode(KAbstractFileWidget::Saving); layout->addWidget(fd); QCheckBox *chkInvisible = new QCheckBox(i18n("Convert Invisible Groups"), page); chkInvisible->setChecked(false); layout->addWidget(chkInvisible); QCheckBox *chkDepth = new QCheckBox(i18n("Export Only Toplevel Groups"), page); chkDepth->setChecked(true); layout->addWidget(chkDepth); if (!dlg.exec()) return; // selectedUrl()( does not return the expected result. So, build up the KUrl the more complicated way //return m_fileWidget->selectedUrl(); KUrl url = fd->dirOperator()->url(); url.adjustPath(KUrl::AddTrailingSlash); QString path = fd->locationEdit()->currentText(); QFileInfo f(path); QString extension = f.completeSuffix(); QString basename = f.baseName(); QString mimefilter = fd->currentMimeFilter(); if (mimefilter.isEmpty()) { KMimeType::Ptr mime = KMimeType::findByUrl(url); mimefilter = mime->name(); extension = mime->extractKnownExtension(path); } if (url.isEmpty()) return; KisImageWSP image = m_view->image(); if (!image) return; KisSaveGroupVisitor v(image, chkInvisible->isChecked(), chkDepth->isChecked(), url, basename, extension, mimefilter); image->rootLayer()->accept(v); } bool KisLayerManager::activeLayerHasSelection() { return (activeLayer()->selection() != 0); } void KisLayerManager::addFileLayer(KisNodeSP activeNode) { QString basePath; KUrl url = m_view->document()->url(); if (url.isLocalFile()) { basePath = QFileInfo(url.toLocalFile()).absolutePath(); } KisImageWSP image = m_view->image(); KisDlgFileLayer dlg(basePath, image->nextLayerName(), m_view->mainWindow()); dlg.resize(dlg.minimumSizeHint()); if (dlg.exec() == QDialog::Accepted) { QString name = dlg.layerName(); QString fileName = dlg.fileName(); if(fileName.isEmpty()){ QMessageBox::critical(m_view->mainWindow(), i18nc("@title:window", "Krita"), i18n("No file name specified")); return; } KisFileLayer::ScalingMethod scalingMethod = dlg.scaleToImageResolution(); addLayerCommon(activeNode, new KisFileLayer(image, basePath, fileName, scalingMethod, name, OPACITY_OPAQUE_U8)); } } void updateLayerStyles(KisLayerSP layer, KisDlgLayerStyle *dlg) { KisSetLayerStyleCommand::updateLayerStyle(layer, dlg->style()->clone()); } void KisLayerManager::layerStyle() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = activeLayer(); if (!layer) return; KisPSDLayerStyleSP oldStyle; if (layer->layerStyle()) { oldStyle = layer->layerStyle()->clone(); } else { oldStyle = toQShared(new KisPSDLayerStyle()); } KisDlgLayerStyle dlg(oldStyle->clone(), m_view->resourceProvider()); boost::function updateCall(boost::bind(updateLayerStyles, layer, &dlg)); SignalToFunctionProxy proxy(updateCall); connect(&dlg, SIGNAL(configChanged()), &proxy, SLOT(start())); if (dlg.exec() == QDialog::Accepted) { KisPSDLayerStyleSP newStyle = dlg.style(); KUndo2CommandSP command = toQShared( new KisSetLayerStyleCommand(layer, oldStyle, newStyle)); image->postExecutionUndoAdapter()->addCommand(command); } } #include "kis_layer_manager.moc" diff --git a/krita/ui/kis_mainwindow_observer.h b/krita/ui/kis_mainwindow_observer.h index 1e860eca611..b904d5864ed 100644 --- a/krita/ui/kis_mainwindow_observer.h +++ b/krita/ui/kis_mainwindow_observer.h @@ -1,19 +1,19 @@ #ifndef KIS_MAINWINDOW_OBSERVER_H #define KIS_MAINWINDOW_OBSERVER_H #include -#include +#include class KisViewManager; class KRITAUI_EXPORT KisMainwindowObserver : public KoCanvasObserverBase { public: KisMainwindowObserver(); virtual ~KisMainwindowObserver(); virtual void setMainWindow(KisViewManager* kisview) = 0; }; #endif // KIS_MAINWINDOW_OBSERVER_H diff --git a/krita/ui/kis_md5_generator.cpp b/krita/ui/kis_md5_generator.cpp new file mode 100644 index 00000000000..329122a3079 --- /dev/null +++ b/krita/ui/kis_md5_generator.cpp @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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_md5_generator.h" + +#include +#include + +KisMD5Generator::KisMD5Generator() +{ + +} + +KisMD5Generator::~KisMD5Generator() +{ + +} + +QByteArray KisMD5Generator::generateHash(QString filename) +{ + QByteArray ba; + if(filename.startsWith("bundle://")) { + QString bn = filename.mid(9); + QString fn = bn.mid(bn.indexOf(":") + 1); + bn = bn.left(bn.indexOf(":")); + + QScopedPointer resourceStore(KoStore::createStore(bn, KoStore::Read, "application/x-krita-resourcebundle", KoStore::Zip)); + if (!resourceStore || resourceStore->bad()) { + qWarning() << "Could not open store on bundle" << bn; + return ba; + } + + if (resourceStore->isOpen()) resourceStore->close(); + + if (!resourceStore->open(fn)) { + qWarning() << "Could not open preset" << fn << "in bundle" << bn; + return ba; + } + + ba = resourceStore->device()->readAll(); + + resourceStore->close(); + return KoMD5Generator::generateHash(ba); + + } + + return KoMD5Generator::generateHash(filename); +} diff --git a/krita/ui/kis_md5_generator.h b/krita/ui/kis_md5_generator.h new file mode 100644 index 00000000000..3542f29fa95 --- /dev/null +++ b/krita/ui/kis_md5_generator.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 + +class KisMD5Generator : public KoMD5Generator +{ +public: + KisMD5Generator(); + ~KisMD5Generator(); + + QByteArray generateHash(QString filename); +}; diff --git a/krita/ui/kis_mimedata.h b/krita/ui/kis_mimedata.h index ea56934be4e..77704aa1cf7 100644 --- a/krita/ui/kis_mimedata.h +++ b/krita/ui/kis_mimedata.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2011 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this library; 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_MIMEDATA_H #define KIS_MIMEDATA_H #include #include -#include +#include class KisShapeController; /** * KisMimeData implements delayed retrieval of nodes for d&d and copy/paste. * * TODO: implement support for the ora format. */ class KRITAUI_EXPORT KisMimeData : public QMimeData { Q_OBJECT public: KisMimeData(QList nodes); /// return the node set on this mimedata object -- for internal use QList nodes() const; /** * KisMimeData provides the following formats if a node has been set: *
    *
  • application/x-krita-node: requests a whole serialized node. For d&d between instances of Krita. *
  • application/x-qt-image: fallback for other applications, returns a QImage of the * current node's paintdevice *
  • application/zip: allows drop targets that can handle zip files to open the data *
*/ QStringList formats() const; /** * Try load the node, which belongs to the same Krita instance, * that is can be fetched without serialization */ static QList tryLoadInternalNodes(const QMimeData *data, KisImageWSP image, KisShapeController *shapeController, bool /* IN-OUT */ ©Node); /** * Loads a node from a mime container * Supports application/x-krita-node and image types. */ static QList loadNodes(const QMimeData *data, const QRect &imageBounds, const QPoint &preferredCenter, bool forceRecenter, KisImageWSP image, KisShapeController *shapeController); protected: QVariant retrieveData(const QString &mimetype, QVariant::Type preferredType) const; private: static void initializeExternalNode(KisNodeSP &nodes, KisImageWSP image, KisShapeController *shapeController); private: QList m_nodes; }; #endif // KIS_MIMEDATA_H diff --git a/krita/ui/kis_model_index_converter_base.h b/krita/ui/kis_model_index_converter_base.h index 6ac69021f79..92ceef18846 100644 --- a/krita/ui/kis_model_index_converter_base.h +++ b/krita/ui/kis_model_index_converter_base.h @@ -1,78 +1,78 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_MODEL_INDEX_CONVERTER_BASE_H #define __KIS_MODEL_INDEX_CONVERTER_BASE_H #include -#include "krita_export.h" +#include "kritaui_export.h" class KisNodeDummy; /** * The base class for converting objects to/from QModelIndex used * in KisNodeModel and KisNodeDummy used in KisDummiesFacadeBase * (KisShapeController). * * This is not a trivial task, because the indexing of nodes is * reversed in KisNodeModel. */ class KRITAUI_EXPORT KisModelIndexConverterBase { public: virtual ~KisModelIndexConverterBase(); /** * Returns the dummy staying in the specified \p row of a \p parent * May return null in case of incosistency */ virtual KisNodeDummy* dummyFromRow(int row, QModelIndex parent) = 0; /** * Returns the dummy associated with the \p index * WARNING: \p index must be valid * NOTE: cannot return null */ virtual KisNodeDummy* dummyFromIndex(QModelIndex index) = 0; /** * Returns the index corresponding to the position of the \p dummy * in the model. Will return invalid index if the dummy should be hidden */ virtual QModelIndex indexFromDummy(KisNodeDummy *dummy) = 0; /** * Calculates the parent and the position in the model for newly created dummy * \param newNodeMetaObjectType is a class name of a newly added node * This name is got from Qt's meta object system so you must * compare this value against a corresponding staticMetaObject * object only. * We do not pass a pointer to a real node to limit the access to * real nodes. * Return whether the new dummy will be shown in the model */ virtual bool indexFromAddedDummy(KisNodeDummy *parentDummy, int index, const QString &newNodeMetaObjectType, QModelIndex &parentIndex, int &row) = 0; /** * Returns the number of children of the given index of the model */ virtual int rowCount(QModelIndex parent) = 0; }; #endif /* __KIS_MODEL_INDEX_CONVERTER_BASE_H */ diff --git a/krita/ui/kis_node_commands_adapter.h b/krita/ui/kis_node_commands_adapter.h index 64632e1a083..e30d13ffb4d 100644 --- a/krita/ui/kis_node_commands_adapter.h +++ b/krita/ui/kis_node_commands_adapter.h @@ -1,63 +1,63 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_NODE_COMMANDS_ADAPTER_H #define KIS_NODE_COMMANDS_ADAPTER_H class KisViewManager; class KoCompositeOp; class KUndo2MagicString; #include -#include +#include #include /** * This class allows the manipulation of nodes in a KisImage * and creates commands as needed. */ class KRITAUI_EXPORT KisNodeCommandsAdapter : public QObject { Q_OBJECT public: KisNodeCommandsAdapter(KisViewManager * view); virtual ~KisNodeCommandsAdapter(); public: void beginMacro(const KUndo2MagicString& macroName); void addExtraCommand(KUndo2Command *command); void endMacro(); void addNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void addNode(KisNodeSP node, KisNodeSP parent, quint32 index); void moveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void moveNode(KisNodeSP node, KisNodeSP parent, quint32 indexaboveThis); void removeNode(KisNodeSP node); void lower(KisNodeSP node); void raise(KisNodeSP node); void toBottom(KisNodeSP node); void toTop(KisNodeSP node); void setOpacity(KisNodeSP node, qint32 opacity); void setCompositeOp(KisNodeSP node, const KoCompositeOp* compositeOp); void undoLastCommand(); private: KisViewManager* m_view; }; #endif // KIS_NODE_COMMANDS_ADAPTER_H diff --git a/krita/ui/kis_node_manager.cpp b/krita/ui/kis_node_manager.cpp index dcd01532454..e8dc2311450 100644 --- a/krita/ui/kis_node_manager.cpp +++ b/krita/ui/kis_node_manager.cpp @@ -1,1148 +1,1150 @@ /* * Copyright (C) 2007 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_node_manager.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "KisPart.h" #include "canvas/kis_canvas2.h" #include "kis_shape_controller.h" #include "kis_canvas_resource_provider.h" #include "KisViewManager.h" #include "KisDocument.h" #include "kis_mask_manager.h" #include "kis_group_layer.h" #include "kis_layer_manager.h" #include "kis_selection_manager.h" #include "kis_node_commands_adapter.h" #include "kis_action.h" #include "kis_action_manager.h" #include "kis_processing_applicator.h" #include "kis_sequential_iterator.h" #include "kis_transaction.h" #include "processing/kis_mirror_processing_visitor.h" #include "KisView.h" struct KisNodeManager::Private { Private(KisNodeManager *_q) : q(_q) , view(0) , imageView(0) , layerManager(0) , maskManager(0) , self(0) , commandsAdapter(0) { } ~Private() { delete layerManager; delete maskManager; } KisNodeManager *q; KisViewManager * view; QPointerimageView; KisLayerManager * layerManager; KisMaskManager * maskManager; KisNodeManager* self; KisNodeCommandsAdapter* commandsAdapter; QList selectedNodes; bool activateNodeImpl(KisNodeSP node); QSignalMapper nodeCreationSignalMapper; QSignalMapper nodeConversionSignalMapper; void saveDeviceAsImage(KisPaintDeviceSP device, const QString &defaultName, const QRect &bounds, qreal xRes, qreal yRes, quint8 opacity); void mergeTransparencyMaskAsAlpha(bool writeToLayers); }; bool KisNodeManager::Private::activateNodeImpl(KisNodeSP node) { Q_ASSERT(view); Q_ASSERT(view->canvasBase()); Q_ASSERT(view->canvasBase()->globalShapeManager()); Q_ASSERT(imageView); if (node && node == self->activeNode()) { return false; } // Set the selection on the shape manager to the active layer // and set call KoSelection::setActiveLayer( KoShapeLayer* layer ) // with the parent of the active layer. KoSelection *selection = view->canvasBase()->globalShapeManager()->selection(); Q_ASSERT(selection); selection->deselectAll(); if (!node) { selection->setActiveLayer(0); imageView->setCurrentNode(0); maskManager->activateMask(0); layerManager->activateLayer(0); } else { KoShape * shape = view->document()->shapeForNode(node); Q_ASSERT(shape); selection->select(shape); KoShapeLayer * shapeLayer = dynamic_cast(shape); Q_ASSERT(shapeLayer); // shapeLayer->setGeometryProtected(node->userLocked()); // shapeLayer->setVisible(node->visible()); selection->setActiveLayer(shapeLayer); imageView->setCurrentNode(node); if (KisLayerSP layer = dynamic_cast(node.data())) { maskManager->activateMask(0); layerManager->activateLayer(layer); } else if (KisMaskSP mask = dynamic_cast(node.data())) { maskManager->activateMask(mask); // XXX_NODE: for now, masks cannot be nested. layerManager->activateLayer(static_cast(node->parent().data())); } } return true; } KisNodeManager::KisNodeManager(KisViewManager *view) : m_d(new Private(this)) { m_d->view = view; m_d->layerManager = new KisLayerManager(view); m_d->maskManager = new KisMaskManager(view); m_d->self = this; m_d->commandsAdapter = new KisNodeCommandsAdapter(view); connect(m_d->layerManager, SIGNAL(sigLayerActivated(KisLayerSP)), SIGNAL(sigLayerActivated(KisLayerSP))); } KisNodeManager::~KisNodeManager() { delete m_d->commandsAdapter; delete m_d; } void KisNodeManager::setView(QPointerimageView) { m_d->maskManager->setView(imageView); m_d->layerManager->setView(imageView); if (m_d->imageView) { KisShapeController *shapeController = dynamic_cast(m_d->imageView->document()->shapeController()); Q_ASSERT(shapeController); shapeController->disconnect(SIGNAL(sigActivateNode(KisNodeSP)), this); m_d->imageView->image()->disconnect(this); } m_d->imageView = imageView; if (m_d->imageView) { KisShapeController *shapeController = dynamic_cast(m_d->imageView->document()->shapeController()); Q_ASSERT(shapeController); connect(shapeController, SIGNAL(sigActivateNode(KisNodeSP)), SLOT(slotNonUiActivatedNode(KisNodeSP))); connect(m_d->imageView->image(), SIGNAL(sigIsolatedModeChanged()),this, SLOT(slotUpdateIsolateModeAction())); m_d->imageView->resourceProvider()->slotNodeActivated(m_d->imageView->currentNode()); } } #define NEW_LAYER_ACTION(id, text, layerType, icon) \ { \ action = new KisAction(icon, text, this); \ action->setActivationFlags(KisAction::ACTIVE_NODE); \ actionManager->addAction(id, action); \ m_d->nodeCreationSignalMapper.setMapping(action, layerType); \ connect(action, SIGNAL(triggered()), \ &m_d->nodeCreationSignalMapper, SLOT(map())); \ } #define NEW_LAYER_ACTION_KEY(id, text, layerType, icon, shortcut) \ { \ NEW_LAYER_ACTION(id, text, layerType, icon); \ action->setShortcut(KShortcut(shortcut)); \ } #define NEW_MASK_ACTION(id, text, layerType, icon) \ { \ NEW_LAYER_ACTION(id, text, layerType, icon); \ action->setActivationFlags(KisAction::ACTIVE_LAYER); \ } #define CONVERT_NODE_ACTION(id, text, layerType, icon) \ { \ action = new KisAction(icon, text, this); \ action->setActivationFlags(KisAction::ACTIVE_NODE); \ action->setExcludedNodeTypes(QStringList(layerType)); \ actionManager->addAction(id, action); \ m_d->nodeConversionSignalMapper.setMapping(action, layerType); \ connect(action, SIGNAL(triggered()), \ &m_d->nodeConversionSignalMapper, SLOT(map())); \ } void KisNodeManager::setup(KActionCollection * actionCollection, KisActionManager* actionManager) { m_d->layerManager->setup(actionManager); m_d->maskManager->setup(actionCollection, actionManager); KisAction * action = new KisAction(themedIcon("symmetry-horizontal"), i18n("Mirror Layer Horizontally"), this); action->setActivationFlags(KisAction::ACTIVE_NODE); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("mirrorNodeX", action); connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeX())); action = new KisAction(themedIcon("symmetry-vertical"), i18n("Mirror Layer Vertically"), this); action->setActivationFlags(KisAction::ACTIVE_NODE); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("mirrorNodeY", action); connect(action, SIGNAL(triggered()), this, SLOT(mirrorNodeY())); action = new KisAction(i18n("Activate next layer"), this); action->setActivationFlags(KisAction::ACTIVE_LAYER); action->setShortcut(KShortcut(Qt::Key_PageUp)); actionManager->addAction("activateNextLayer", action); connect(action, SIGNAL(triggered()), this, SLOT(activateNextNode())); action = new KisAction(i18n("Activate previous layer"), this); action->setActivationFlags(KisAction::ACTIVE_LAYER); action->setShortcut(KShortcut(Qt::Key_PageDown)); actionManager->addAction("activatePreviousLayer", action); connect(action, SIGNAL(triggered()), this, SLOT(activatePreviousNode())); action = new KisAction(themedIcon("document-save"), i18n("Save Layer/Mask..."), this); action->setActivationFlags(KisAction::ACTIVE_NODE); actionManager->addAction("save_node_as_image", action); connect(action, SIGNAL(triggered()), this, SLOT(saveNodeAsImage())); action = new KisAction(themedIcon("edit-copy"), i18n("&Duplicate Layer or Mask"), this); action->setActivationFlags(KisAction::ACTIVE_NODE); action->setShortcut(KShortcut(Qt::ControlModifier + Qt::Key_J)); actionManager->addAction("duplicatelayer", action); connect(action, SIGNAL(triggered()), this, SLOT(duplicateActiveNode())); NEW_LAYER_ACTION_KEY("add_new_paint_layer", i18n("&Paint Layer"), "KisPaintLayer", themedIcon("document-new"), Qt::Key_Insert); NEW_LAYER_ACTION_KEY("add_new_group_layer", i18n("&Group Layer"), "KisGroupLayer", themedIcon("folder"), Qt::ControlModifier + Qt::Key_G); NEW_LAYER_ACTION("add_new_clone_layer", i18n("&Clone Layer"), "KisCloneLayer", themedIcon("edit-copy")); NEW_LAYER_ACTION("add_new_shape_layer", i18n("&Vector Layer"), "KisShapeLayer", themedIcon("bookmarks")); NEW_LAYER_ACTION("add_new_adjustment_layer", i18n("&Filter Layer..."), "KisAdjustmentLayer", themedIcon("view-filter")); NEW_LAYER_ACTION("add_new_fill_layer", i18n("&Fill Layer..."), "KisGeneratorLayer", themedIcon("krita_tool_color_fill")); NEW_LAYER_ACTION("add_new_file_layer", i18n("&File Layer..."), "KisFileLayer", themedIcon("document-open")); NEW_MASK_ACTION("add_new_transparency_mask", i18n("&Transparency Mask"), "KisTransparencyMask", themedIcon("edit-copy")); NEW_MASK_ACTION("add_new_filter_mask", i18n("&Filter Mask..."), "KisFilterMask", themedIcon("view-filter")); NEW_MASK_ACTION("add_new_transform_mask", i18n("&Transform Mask..."), "KisTransformMask", themedIcon("bookmarks")); NEW_MASK_ACTION("add_new_selection_mask", i18n("&Local Selection"), "KisSelectionMask", themedIcon("edit-paste")); connect(&m_d->nodeCreationSignalMapper, SIGNAL(mapped(const QString &)), this, SLOT(createNode(const QString &))); CONVERT_NODE_ACTION("convert_to_paint_layer", i18n("to &Paint Layer"), "KisPaintLayer", themedIcon("document-new")); CONVERT_NODE_ACTION("convert_to_selection_mask", i18n("to &Selection Mask"), "KisSelectionMask", themedIcon("edit-paste")); CONVERT_NODE_ACTION("convert_to_filter_mask", i18n("to &Filter Mask..."), "KisFilterMask", themedIcon("view-filter")); CONVERT_NODE_ACTION("convert_to_transparency_mask", i18n("to &Transparency Mask"), "KisTransparencyMask", themedIcon("edit-copy")); connect(&m_d->nodeConversionSignalMapper, SIGNAL(mapped(const QString &)), this, SLOT(convertNode(const QString &))); action = new KisAction(themedIcon("layer-visible-off"), i18n("&Isolate Layer"), this); action->setCheckable(true); action->setActivationFlags(KisAction::ACTIVE_NODE); actionManager->addAction("isolate_layer", action); connect(action, SIGNAL(triggered(bool)), this, SLOT(toggleIsolateMode(bool))); action = new KisAction(themedIcon("edit-copy"), i18n("Alpha into Mask"), this); action->setActivationFlags(KisAction::ACTIVE_LAYER); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE_PAINT_DEVICE); actionManager->addAction("split_alpha_into_mask", action); connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaIntoMask())); action = new KisAction(themedIcon("transparency-enabled"), i18n("Write as Alpha"), this); action->setActivationFlags(KisAction::ACTIVE_TRANSPARENCY_MASK); action->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("split_alpha_write", action); connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaWrite())); action = new KisAction(themedIcon("document-save"), i18n("Save Merged..."), this); action->setActivationFlags(KisAction::ACTIVE_TRANSPARENCY_MASK); // HINT: we can save even when the nodes are not editable actionManager->addAction("split_alpha_save_merged", action); connect(action, SIGNAL(triggered()), this, SLOT(slotSplitAlphaSaveMerged())); connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotUpdateIsolateModeAction())); connect(this, SIGNAL(sigNodeActivated(KisNodeSP)), SLOT(slotTryFinishIsolatedMode())); } void KisNodeManager::updateGUI() { // enable/disable all relevant actions m_d->layerManager->updateGUI(); m_d->maskManager->updateGUI(); } KisNodeSP KisNodeManager::activeNode() { if (m_d->imageView) { return m_d->imageView->currentNode(); } return 0; } KisLayerSP KisNodeManager::activeLayer() { return m_d->layerManager->activeLayer(); } const KoColorSpace* KisNodeManager::activeColorSpace() { Q_ASSERT(m_d->maskManager); if (m_d->maskManager->activeDevice()) { // Q_ASSERT(m_d->maskManager->activeDevice()); return m_d->maskManager->activeDevice()->colorSpace(); } else { Q_ASSERT(m_d->layerManager); Q_ASSERT(m_d->layerManager->activeLayer()); if (m_d->layerManager->activeLayer()->parentLayer()) return m_d->layerManager->activeLayer()->parentLayer()->colorSpace(); else return m_d->view->image()->colorSpace(); } } void KisNodeManager::moveNodeAt(KisNodeSP node, KisNodeSP parent, int index) { if (parent->allowAsChild(node)) { if (node->inherits("KisSelectionMask") && parent->inherits("KisLayer")) { KisSelectionMask *m = dynamic_cast(node.data()); KisLayer *l = dynamic_cast(parent.data()); KisSelectionMaskSP selMask = l->selectionMask(); if (m && m->active() && l && l->selectionMask()) selMask->setActive(false); } m_d->commandsAdapter->moveNode(node, parent, index); } } void KisNodeManager::addNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis) { Q_ASSERT(parent->allowAsChild(node)); m_d->commandsAdapter->addNode(node, parent, aboveThis); } void KisNodeManager::moveNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis) { Q_ASSERT(parent->allowAsChild(node)); m_d->commandsAdapter->moveNode(node, parent, aboveThis); } void KisNodeManager::toggleIsolateActiveNode() { KisImageWSP image = m_d->view->image(); KisNodeSP activeNode = this->activeNode(); KIS_ASSERT_RECOVER_RETURN(activeNode); if (activeNode == image->isolatedModeRoot()) { toggleIsolateMode(false); } else { toggleIsolateMode(true); } } void KisNodeManager::toggleIsolateMode(bool checked) { KisImageWSP image = m_d->view->image(); if (checked) { KisNodeSP activeNode = this->activeNode(); // Transform masks don't have pixel data... if (activeNode->inherits("KisTransformMask")) return; KIS_ASSERT_RECOVER_RETURN(activeNode); - - image->startIsolatedMode(activeNode); + if (!image->startIsolatedMode(activeNode)) { + KisAction *action = m_d->view->actionManager()->actionByName("isolate_layer"); + action->setChecked(false); + } } else { image->stopIsolatedMode(); } } void KisNodeManager::slotUpdateIsolateModeAction() { KisAction *action = m_d->view->actionManager()->actionByName("isolate_layer"); Q_ASSERT(action); KisNodeSP activeNode = this->activeNode(); KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot(); action->setChecked(isolatedRootNode && isolatedRootNode == activeNode); } void KisNodeManager::slotTryFinishIsolatedMode() { KisNodeSP isolatedRootNode = m_d->view->image()->isolatedModeRoot(); if (!isolatedRootNode) return; bool belongsToIsolatedGroup = false; KisNodeSP node = this->activeNode(); while(node) { if (node == isolatedRootNode) { belongsToIsolatedGroup = true; break; } node = node->parent(); } if (!belongsToIsolatedGroup) { m_d->view->image()->stopIsolatedMode(); } } void KisNodeManager::createNode(const QString & nodeType, bool quiet, KisPaintDeviceSP copyFrom) { KisNodeSP activeNode = this->activeNode(); if (!activeNode) { activeNode = m_d->view->image()->root(); } KIS_ASSERT_RECOVER_RETURN(activeNode); if (activeNode->systemLocked()) { return; } // XXX: make factories for this kind of stuff, // with a registry if (nodeType == "KisPaintLayer") { m_d->layerManager->addLayer(activeNode); } else if (nodeType == "KisGroupLayer") { m_d->layerManager->addGroupLayer(activeNode); } else if (nodeType == "KisAdjustmentLayer") { m_d->layerManager->addAdjustmentLayer(activeNode); } else if (nodeType == "KisGeneratorLayer") { m_d->layerManager->addGeneratorLayer(activeNode); } else if (nodeType == "KisShapeLayer") { m_d->layerManager->addShapeLayer(activeNode); } else if (nodeType == "KisCloneLayer") { m_d->layerManager->addCloneLayer(activeNode); } else if (nodeType == "KisTransparencyMask") { m_d->maskManager->createTransparencyMask(activeNode, copyFrom, false); } else if (nodeType == "KisFilterMask") { m_d->maskManager->createFilterMask(activeNode, copyFrom, quiet, false); } else if (nodeType == "KisTransformMask") { m_d->maskManager->createTransformMask(activeNode); } else if (nodeType == "KisSelectionMask") { m_d->maskManager->createSelectionMask(activeNode, copyFrom, false); } else if (nodeType == "KisFileLayer") { m_d->layerManager->addFileLayer(activeNode); } } void KisNodeManager::convertNode(const QString &nodeType) { KisNodeSP activeNode = this->activeNode(); if (!activeNode) return; if (nodeType == "KisPaintLayer") { m_d->layerManager->convertNodeToPaintLayer(activeNode); } else if (nodeType == "KisSelectionMask" || nodeType == "KisFilterMask" || nodeType == "KisTransparencyMask") { KisPaintDeviceSP copyFrom = activeNode->paintDevice() ? activeNode->paintDevice() : activeNode->projection(); m_d->commandsAdapter->beginMacro(kundo2_i18n("Convert to a Selection Mask")); if (nodeType == "KisSelectionMask") { m_d->maskManager->createSelectionMask(activeNode, copyFrom, true); } else if (nodeType == "KisFilterMask") { m_d->maskManager->createFilterMask(activeNode, copyFrom, false, true); } else if (nodeType == "KisTransparencyMask") { m_d->maskManager->createTransparencyMask(activeNode, copyFrom, true); } m_d->commandsAdapter->removeNode(activeNode); m_d->commandsAdapter->endMacro(); } else { qWarning() << "Unsupported node conversion type:" << nodeType; } } void KisNodeManager::slotNonUiActivatedNode(KisNodeSP node) { if (m_d->activateNodeImpl(node)) { emit sigUiNeedChangeActiveNode(node); emit sigNodeActivated(node); nodesUpdated(); if (node) { bool toggled = m_d->view->actionCollection()->action("view_show_just_the_canvas")->isChecked(); if (toggled) { m_d->view->showFloatingMessage( activeLayer()->name(), QIcon(), 1600, KisFloatingMessage::Medium, Qt::TextSingleLine); } } } } void KisNodeManager::slotUiActivatedNode(KisNodeSP node) { if (m_d->activateNodeImpl(node)) { emit sigNodeActivated(node); nodesUpdated(); } if (node) { QStringList vectorTools = QStringList() << "InteractionTool" << "KarbonPatternTool" << "KarbonGradientTool" << "KarbonCalligraphyTool" << "CreateShapesTool" << "PathToolFactoryId"; QStringList pixelTools = QStringList() << "KritaShape/KisToolBrush" << "KritaShape/KisToolDyna" << "KritaShape/KisToolMultiBrush" << "KritaFill/KisToolFill" << "KritaFill/KisToolGradient"; if (node->inherits("KisShapeLayer")) { if (pixelTools.contains(KoToolManager::instance()->activeToolId())) { KoToolManager::instance()->switchToolRequested("InteractionTool"); } } else { if (vectorTools.contains(KoToolManager::instance()->activeToolId())) { KoToolManager::instance()->switchToolRequested("KritaShape/KisToolBrush"); } } } } void KisNodeManager::nodesUpdated() { KisNodeSP node = activeNode(); if (!node) return; m_d->layerManager->layersUpdated(); m_d->maskManager->masksUpdated(); m_d->view->updateGUI(); m_d->view->selectionManager()->selectionChanged(); } KisPaintDeviceSP KisNodeManager::activePaintDevice() { return m_d->maskManager->activeMask() ? m_d->maskManager->activeDevice() : m_d->layerManager->activeDevice(); } void KisNodeManager::nodeProperties(KisNodeSP node) { if (node->inherits("KisLayer")) { m_d->layerManager->layerProperties(); } else if (node->inherits("KisMask")) { m_d->maskManager->maskProperties(); } } qint32 KisNodeManager::convertOpacityToInt(qreal opacity) { /** * Scales opacity from the range 0...100 * to the integer range 0...255 */ return qMin(255, int(opacity * 2.55 + 0.5)); } void KisNodeManager::setNodeOpacity(KisNodeSP node, qint32 opacity, bool finalChange) { if (!node) return; if (node->opacity() == opacity) return; if (!finalChange) { node->setOpacity(opacity); node->setDirty(); } else { m_d->commandsAdapter->setOpacity(node, opacity); } } void KisNodeManager::setNodeCompositeOp(KisNodeSP node, const KoCompositeOp* compositeOp) { if (!node) return; if (node->compositeOp() == compositeOp) return; m_d->commandsAdapter->setCompositeOp(node, compositeOp); } void KisNodeManager::setSelectedNodes(QList nodes) { m_d->selectedNodes = nodes; } QList KisNodeManager::selectedNodes() { return m_d->selectedNodes; } void KisNodeManager::nodeOpacityChanged(qreal opacity, bool finalChange) { KisNodeSP node = activeNode(); setNodeOpacity(node, convertOpacityToInt(opacity), finalChange); } void KisNodeManager::nodeCompositeOpChanged(const KoCompositeOp* op) { KisNodeSP node = activeNode(); setNodeCompositeOp(node, op); } void KisNodeManager::duplicateActiveNode() { KisNodeSP node = activeNode(); // FIXME: can't imagine how it may happen Q_ASSERT(node); if (node->inherits("KisLayer")) { m_d->layerManager->layerDuplicate(); } else if (node->inherits("KisMask")) { m_d->maskManager->duplicateMask(); } } void KisNodeManager::raiseNode() { // The user sees the layer stack topsy-turvy, as a tree with the // root at the bottom instead of on top. KisNodeSP node = activeNode(); if (node->inherits("KisLayer")) { m_d->layerManager->layerLower(); } else if (node->inherits("KisMask")) { m_d->maskManager->lowerMask(); } } void KisNodeManager::lowerNode() { // The user sees the layer stack topsy-turvy, as a tree with the // root at the bottom instead of on top. KisNodeSP node = activeNode(); if (node->inherits("KisLayer")) { m_d->layerManager->layerRaise(); } else if (node->inherits("KisMask")) { m_d->maskManager->raiseMask(); } } void KisNodeManager::nodeToTop() { KisNodeSP node = activeNode(); if (node->inherits("KisLayer")) { m_d->layerManager->layerBack(); } else if (node->inherits("KisMask")) { m_d->maskManager->maskToBottom(); } } void KisNodeManager::nodeToBottom() { KisNodeSP node = activeNode(); if (node->inherits("KisLayer")) { m_d->layerManager->layerLower(); } else if (node->inherits("KisMask")) { m_d->maskManager->maskToTop(); } } bool scanForLastLayer(KisImageWSP image, KisNodeSP nodeToRemove) { if (!dynamic_cast(nodeToRemove.data())) { return false; } bool lastLayer = true; KisNodeSP node = image->root()->firstChild(); while (node) { if (node != nodeToRemove && dynamic_cast(node.data())) { lastLayer = false; break; } node = node->nextSibling(); } return lastLayer; } /// Scan whether the node has a parent in the list of nodes bool scanForParent(QList nodeList, KisNodeSP node) { KisNodeSP parent = node->parent(); while (parent) { if (nodeList.contains(parent)) { return true; } parent = parent->parent(); } return false; } void KisNodeManager::removeSingleNode(KisNodeSP node) { if (!node || !node->parent()) { return; } if (scanForLastLayer(m_d->view->image(), node)) { m_d->commandsAdapter->beginMacro(kundo2_i18n("Remove Last Layer")); m_d->commandsAdapter->removeNode(node); // An oddity, but this is required as for some reason, we can end up in a situation // where our active node is still set to one of the layers removed above. activeNode().clear(); createNode("KisPaintLayer"); m_d->commandsAdapter->endMacro(); } else { m_d->commandsAdapter->removeNode(node); } } void KisNodeManager::removeSelectedNodes(QList selectedNodes) { m_d->commandsAdapter->beginMacro(kundo2_i18n("Remove Multiple Layers and Masks")); foreach(KisNodeSP node, selectedNodes) { if (!scanForParent(selectedNodes, node)) { removeSingleNode(node); } } m_d->commandsAdapter->endMacro(); } void KisNodeManager::removeNode() { //do not delete root layer if (m_d->selectedNodes.count() > 1) { removeSelectedNodes(m_d->selectedNodes); } else { removeSingleNode(activeNode()); } } void KisNodeManager::mirrorNodeX() { KisNodeSP node = activeNode(); KUndo2MagicString commandName; if (node->inherits("KisLayer")) { commandName = kundo2_i18n("Mirror Layer X"); } else if (node->inherits("KisMask")) { commandName = kundo2_i18n("Mirror Mask X"); } mirrorNode(node, commandName, Qt::Horizontal); } void KisNodeManager::mirrorNodeY() { KisNodeSP node = activeNode(); KUndo2MagicString commandName; if (node->inherits("KisLayer")) { commandName = kundo2_i18n("Mirror Layer Y"); } else if (node->inherits("KisMask")) { commandName = kundo2_i18n("Mirror Mask Y"); } mirrorNode(node, commandName, Qt::Vertical); } inline bool checkForGlobalSelection(KisNodeSP node) { return dynamic_cast(node.data()) && node->parent() && !node->parent()->parent(); } void KisNodeManager::activateNextNode() { KisNodeSP activeNode = this->activeNode(); if (!activeNode) return; KisNodeSP node = activeNode->nextSibling(); if (!node && activeNode->parent() && activeNode->parent()->parent()) { node = activeNode->parent(); } while(node && checkForGlobalSelection(node)) { node = node->nextSibling(); } if (node) { slotNonUiActivatedNode(node); } } void KisNodeManager::activatePreviousNode() { KisNodeSP activeNode = this->activeNode(); if (!activeNode) return; KisNodeSP node = activeNode->prevSibling(); if (!node && activeNode->parent()) { node = activeNode->parent()->prevSibling(); } while(node && checkForGlobalSelection(node)) { node = node->prevSibling(); } if (node) { slotNonUiActivatedNode(node); } } void KisNodeManager::mergeLayer() { m_d->layerManager->mergeLayer(); } void KisNodeManager::rotate(double radians) { // XXX: implement rotation for masks as well m_d->layerManager->rotateLayer(radians); } void KisNodeManager::rotate180() { rotate(M_PI); } void KisNodeManager::rotateLeft90() { rotate(-M_PI / 2); } void KisNodeManager::rotateRight90() { rotate(M_PI / 2); } void KisNodeManager::shear(double angleX, double angleY) { // XXX: implement shear for masks as well m_d->layerManager->shearLayer(angleX, angleY); } void KisNodeManager::scale(double sx, double sy, KisFilterStrategy *filterStrategy) { KisNodeSP node = activeNode(); KIS_ASSERT_RECOVER_RETURN(node); m_d->view->image()->scaleNode(node, sx, sy, filterStrategy); nodesUpdated(); } void KisNodeManager::mirrorNode(KisNodeSP node, const KUndo2MagicString& actionName, Qt::Orientation orientation) { KisImageSignalVector emitSignals; emitSignals << ModifiedSignal; KisProcessingApplicator applicator(m_d->view->image(), node, KisProcessingApplicator::RECURSIVE, emitSignals, actionName); KisProcessingVisitorSP visitor = new KisMirrorProcessingVisitor(m_d->view->image()->bounds(), orientation); applicator.applyVisitor(visitor, KisStrokeJobData::CONCURRENT); applicator.end(); nodesUpdated(); } void KisNodeManager::Private::saveDeviceAsImage(KisPaintDeviceSP device, const QString &defaultName, const QRect &bounds, qreal xRes, qreal yRes, quint8 opacity) { KoFileDialog dialog(view->mainWindow(), KoFileDialog::SaveFile, "krita/savenodeasimage"); dialog.setCaption(i18n("Export \"%1\"", defaultName)); dialog.setDefaultDir(QDesktopServices::storageLocation(QDesktopServices::PicturesLocation)); dialog.setMimeTypeFilters(KisImportExportManager::mimeFilter("application/x-krita", KisImportExportManager::Export)); QString filename = dialog.url(); if (filename.isEmpty()) return; KUrl url = KUrl::fromLocalFile(filename); if (url.isEmpty()) return; KMimeType::Ptr mime = KMimeType::findByUrl(url); QString mimefilter = mime->name(); QScopedPointer d(KisPart::instance()->createDocument()); d->prepareForImport(); KisImageSP dst = new KisImage(d->createUndoStore(), bounds.width(), bounds.height(), device->compositionSourceColorSpace(), defaultName); dst->setResolution(xRes, yRes); d->setCurrentImage(dst); KisPaintLayer* paintLayer = new KisPaintLayer(dst, "paint device", opacity); paintLayer->paintDevice()->makeCloneFrom(device, bounds); dst->addNode(paintLayer, dst->rootLayer(), KisLayerSP(0)); dst->initialRefreshGraph(); d->setOutputMimeType(mimefilter.toLatin1()); d->exportDocument(url); } void KisNodeManager::saveNodeAsImage() { KisNodeSP node = activeNode(); if (!node) { qWarning() << "BUG: Save Node As Image was called without any node selected"; return; } KisImageWSP image = m_d->view->image(); QRect saveRect = image->bounds() | node->exactBounds(); KisPaintDeviceSP device = node->paintDevice(); if (!device) { device = node->projection(); } m_d->saveDeviceAsImage(device, node->name(), saveRect, image->xRes(), image->yRes(), node->opacity()); } void KisNodeManager::slotSplitAlphaIntoMask() { KisNodeSP node = activeNode(); // guaranteed by KisActionManager KIS_ASSERT_RECOVER_RETURN(node->hasEditablePaintDevice()); KisPaintDeviceSP srcDevice = node->paintDevice(); const KoColorSpace *srcCS = srcDevice->colorSpace(); const QRect processRect = srcDevice->exactBounds() | srcDevice->defaultBounds()->bounds(); KisPaintDeviceSP selectionDevice = new KisPaintDevice(KoColorSpaceRegistry::instance()->alpha8()); m_d->commandsAdapter->beginMacro(kundo2_i18n("Split Alpha into a Mask")); KisTransaction transaction(kundo2_noi18n("__split_alpha_channel__"), srcDevice); KisSequentialIterator srcIt(srcDevice, processRect); KisSequentialIterator dstIt(selectionDevice, processRect); do { quint8 *srcPtr = srcIt.rawData(); quint8 *alpha8Ptr = dstIt.rawData(); *alpha8Ptr = srcCS->opacityU8(srcPtr); srcCS->setOpacity(srcPtr, OPACITY_OPAQUE_U8, 1); } while (srcIt.nextPixel() && dstIt.nextPixel()); m_d->commandsAdapter->addExtraCommand(transaction.endAndTake()); createNode("KisTransparencyMask", false, selectionDevice); m_d->commandsAdapter->endMacro(); } void KisNodeManager::Private::mergeTransparencyMaskAsAlpha(bool writeToLayers) { KisNodeSP node = q->activeNode(); KisNodeSP parentNode = node->parent(); // guaranteed by KisActionManager KIS_ASSERT_RECOVER_RETURN(node->inherits("KisTransparencyMask")); if (writeToLayers && !parentNode->hasEditablePaintDevice()) { QMessageBox::information(view->mainWindow(), i18nc("@title:window", "Layer %1 is not editable").arg(parentNode->name()), i18n("Cannot write alpha channel of " "the parent layer \"%1\".\n" "The operation will be cancelled.").arg(parentNode->name())); return; } KisPaintDeviceSP dstDevice; if (writeToLayers) { KIS_ASSERT_RECOVER_RETURN(parentNode->paintDevice()); dstDevice = parentNode->paintDevice(); } else { KisPaintDeviceSP copyDevice = parentNode->paintDevice(); if (!copyDevice) { copyDevice = parentNode->original(); } dstDevice = new KisPaintDevice(*copyDevice); } const KoColorSpace *dstCS = dstDevice->colorSpace(); KisPaintDeviceSP selectionDevice = node->paintDevice(); KIS_ASSERT_RECOVER_RETURN(selectionDevice->colorSpace()->pixelSize() == 1); const QRect processRect = selectionDevice->exactBounds() | dstDevice->exactBounds() | selectionDevice->defaultBounds()->bounds(); QScopedPointer transaction; if (writeToLayers) { commandsAdapter->beginMacro(kundo2_i18n("Write Alpha into a Layer")); transaction.reset(new KisTransaction(kundo2_noi18n("__write_alpha_channel__"), dstDevice)); } KisSequentialIterator srcIt(selectionDevice, processRect); KisSequentialIterator dstIt(dstDevice, processRect); do { quint8 *alpha8Ptr = srcIt.rawData(); quint8 *dstPtr = dstIt.rawData(); dstCS->setOpacity(dstPtr, *alpha8Ptr, 1); } while (srcIt.nextPixel() && dstIt.nextPixel()); if (writeToLayers) { commandsAdapter->addExtraCommand(transaction->endAndTake()); commandsAdapter->removeNode(node); commandsAdapter->endMacro(); } else { KisImageWSP image = view->image(); QRect saveRect = image->bounds(); saveDeviceAsImage(dstDevice, parentNode->name(), saveRect, image->xRes(), image->yRes(), OPACITY_OPAQUE_U8); } } void KisNodeManager::slotSplitAlphaWrite() { m_d->mergeTransparencyMaskAsAlpha(true); } void KisNodeManager::slotSplitAlphaSaveMerged() { m_d->mergeTransparencyMaskAsAlpha(false); } #include "kis_node_manager.moc" diff --git a/krita/ui/kis_node_manager.h b/krita/ui/kis_node_manager.h index cf345661d92..6f10d76290d 100644 --- a/krita/ui/kis_node_manager.h +++ b/krita/ui/kis_node_manager.h @@ -1,224 +1,224 @@ /* * Copyright (C) 2007 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_NODE_MANAGER #define KIS_NODE_MANAGER #include #include #include "kis_types.h" -#include +#include class KActionCollection; class KoCompositeOp; class KoColorSpace; class KUndo2MagicString; class KisFilterStrategy; class KisViewManager; class KisActionManager; class KisView; /** * The node manager passes requests for new layers or masks on to the mask and layer * managers. */ class KRITAUI_EXPORT KisNodeManager : public QObject { Q_OBJECT public: KisNodeManager(KisViewManager * view); ~KisNodeManager(); void setView(QPointerimageView); Q_SIGNALS: /// emitted whenever a node is selected. void sigNodeActivated(KisNodeSP node); /// emitted whenever a different layer is selected. void sigLayerActivated(KisLayerSP layer); /// for the layer box: this sets the current node in the layerbox /// without telling the node manager that the node is activated, /// preventing loops (I think...) void sigUiNeedChangeActiveNode(KisNodeSP node); public: void setup(KActionCollection * collection, KisActionManager* actionManager); void updateGUI(); /// Convenience function to get the active layer or mask KisNodeSP activeNode(); /// convenience function to get the active layer. If a mask is /// active, it's parent layer is the active layer. KisLayerSP activeLayer(); /// Get the paint device the user wants to paint on now KisPaintDeviceSP activePaintDevice(); /** * @return the active color space used for composition, meaning the color space * of the active mask, or the color space of the parent of the active layer */ const KoColorSpace* activeColorSpace(); /** * Sets opacity for the node in a universal way (masks/layers) */ void setNodeOpacity(KisNodeSP node, qint32 opacity, bool finalChange); /** * Sets compositeOp for the node in a universal way (masks/layers) */ void setNodeCompositeOp(KisNodeSP node, const KoCompositeOp* compositeOp); /** * @brief setSelectedNodes set the list of nodes selected in the layerbox. Selected nodes are not necessarily active nodes. * @param nodes the selected nodes */ void setSelectedNodes(QList nodes); QList selectedNodes(); public Q_SLOTS: /** * Explicitly activates \p node * The UI will be noticed that active node has been changed. * Both sigNodeActivated and sigUiNeedChangeActiveNode are emitted. * * WARNING: normally you needn't call this method manually. It is * automatically called when a node is added to the graph. If you * have some special cases when you need to activate a node, consider * adding them to KisDummiesFacadeBase instead. Calling this method * directly should be the last resort. * * \see slotUiActivatedNode for comparison */ void slotNonUiActivatedNode(KisNodeSP node); /** * Activates \p node. * All non-ui listeners are notified with sigNodeActivated, * sigUiNeedChangeActiveNode is *not* emitted. * * \see activateNode */ void slotUiActivatedNode(KisNodeSP node); /** * Adds a node without searching appropriate position for it. * You *must* ensure that the node is allowed to be added to * the parent, otherwise you'll get an assert. */ void addNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); /** * Moves a node without searching appropriate position for it. * You *must* ensure that the node is allowed to be added to * the parent, otherwise you'll get an assert. */ void moveNodeDirect(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void toggleIsolateActiveNode(); void toggleIsolateMode(bool checked); void slotUpdateIsolateModeAction(); void slotTryFinishIsolatedMode(); void moveNodeAt(KisNodeSP node, KisNodeSP parent, int index); void createNode(const QString& nodeType, bool quiet = false, KisPaintDeviceSP copyFrom = 0); void convertNode(const QString &nodeType); void nodesUpdated(); void nodeProperties(KisNodeSP node); void nodeOpacityChanged(qreal opacity, bool finalChange); void nodeCompositeOpChanged(const KoCompositeOp* op); void duplicateActiveNode(); void removeNode(); void mirrorNodeX(); void mirrorNodeY(); void mirrorNode(KisNodeSP node, const KUndo2MagicString& commandName, Qt::Orientation orientation); void activateNextNode(); void activatePreviousNode(); /** * move the active node up the nodestack. */ void raiseNode(); /** * move the active node down the nodestack */ void lowerNode(); /** * move the activenode to the top-most position of the nodestack * If the node is a mask, the stack is limited to the set of masks * belonging to the current layer. */ void nodeToTop(); /** * move the activenode to the bottom-most position of the nodestack * If the node is a mask, the stack is limited to the set of masks * belonging to the current layer. */ void nodeToBottom(); void rotate(double radians); void rotate180(); void rotateLeft90(); void rotateRight90(); void saveNodeAsImage(); // merges the active layer with the layer below it. void mergeLayer(); void slotSplitAlphaIntoMask(); void slotSplitAlphaWrite(); void slotSplitAlphaSaveMerged(); public: void shear(double angleX, double angleY); void scale(double sx, double sy, KisFilterStrategy *filterStrategy); private: /** * Scales opacity from the range 0...1 * to the integer range 0...255 */ qint32 convertOpacityToInt(qreal opacity); void removeSelectedNodes(QList selectedNodes); void removeSingleNode(KisNodeSP node); struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/kis_node_model.h b/krita/ui/kis_node_model.h index 820e552b095..fd2c15853d8 100644 --- a/krita/ui/kis_node_model.h +++ b/krita/ui/kis_node_model.h @@ -1,117 +1,117 @@ /* * Copyright (c) 2007 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_NODE_MODEL #define KIS_NODE_MODEL #include -#include "krita_export.h" +#include "kritaui_export.h" #include class KisDummiesFacadeBase; class KisNodeDummy; class KisShapeController; /** * KisNodeModel offers a Qt model-view compatible view on the node * hierarchy. * * Note that there's a discrepancy between the krita node tree model * and the model Qt wants to see: we hide the root node from Qt. * * The node model shows an inverse view on the layer tree: we want the * first layer to show up at the bottom. */ class KRITAUI_EXPORT KisNodeModel : public KisDocumentSectionModel { Q_OBJECT public: // from QAbstractItemModel KisNodeModel(QObject * parent); ~KisNodeModel(); void setDummiesFacade(KisDummiesFacadeBase *dummiesFacade, KisImageWSP image, KisShapeController *shapeController); KisNodeSP nodeFromIndex(const QModelIndex &index) const; QModelIndex indexFromNode(KisNodeSP node) const; bool showGlobalSelection() const; public Q_SLOTS: void setShowGlobalSelection(bool value); public: int rowCount(const QModelIndex &parent = QModelIndex()) const; int columnCount(const QModelIndex &parent = QModelIndex()) const; QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const; QModelIndex parent(const QModelIndex &index) const; QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const; Qt::ItemFlags flags(const QModelIndex &index) const; bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole); QStringList mimeTypes() const; QMimeData* mimeData(const QModelIndexList & indexes) const; bool dropMimeData(const QMimeData * data, Qt::DropAction action, int row, int column, const QModelIndex & parent); Qt::DropActions supportedDragActions() const; Qt::DropActions supportedDropActions() const; bool hasDummiesFacade(); Q_SIGNALS: void nodeActivated(KisNodeSP); void toggleIsolateActiveNode(); void requestAddNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); void requestMoveNode(KisNodeSP node, KisNodeSP parent, KisNodeSP aboveThis); private Q_SLOTS: void slotBeginInsertDummy(KisNodeDummy *parent, int index, const QString &metaObjectType); void slotEndInsertDummy(KisNodeDummy *dummy); void slotBeginRemoveDummy(KisNodeDummy *dummy); void slotEndRemoveDummy(); void slotDummyChanged(KisNodeDummy *dummy); void slotIsolatedModeChanged(); void updateSettings(); void processUpdateQueue(); void progressPercentageChanged(int, const KisNodeSP); private: friend class KisModelIndexConverter; friend class KisModelIndexConverterShowAll; void connectDummy(KisNodeDummy *dummy, bool needConnect); void connectDummies(KisNodeDummy *dummy, bool needConnect); void resetIndexConverter(); bool correctNewNodeLocation(KisNodeSP node, KisNodeDummy* &parentDummy, KisNodeDummy* &aboveThisDummy); void regenerateItems(KisNodeDummy *dummy); bool belongsToIsolatedGroup(KisNodeSP node) const; private: struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/kis_paint_ops_model.h b/krita/ui/kis_paint_ops_model.h index ada430caaf9..60cdeb58c60 100644 --- a/krita/ui/kis_paint_ops_model.h +++ b/krita/ui/kis_paint_ops_model.h @@ -1,91 +1,91 @@ /* * Copyright (c) 2009 Cyrille Berger * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2011 Silvio Heinrich * * 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_LIST_MODEL_H_ #define _KIS_PAINTOP_LIST_MODEL_H_ #include #include -#include +#include #include "kis_categorized_list_model.h" #include "kis_paintop_factory.h" class KisPaintOpFactory; struct KRITAUI_EXPORT KisPaintOpInfo { KisPaintOpInfo() { } KisPaintOpInfo(const QString& _id, const QString& _name, const QString& _category, const QPixmap& _icon, qint32 _priority): id(_id), name(_name), category(_category), icon(_icon), priority(_priority) { } KisPaintOpInfo(const QString& _id): id(_id) { } bool operator==(const KisPaintOpInfo info) const{ return (info.id == id); } QString id; QString name; QString category; QPixmap icon; qint32 priority; }; struct PaintOpInfoToQStringConverter { QString operator() (const KisPaintOpInfo &info) { return info.name; } }; typedef KisCategorizedListModel BasePaintOpCategorizedListModel; class KRITAUI_EXPORT KisPaintOpListModel : public BasePaintOpCategorizedListModel { public: KisPaintOpListModel(QObject *parent); virtual QVariant data(const QModelIndex& idx, int role = Qt::DisplayRole) const; void fill(const QList& list); }; class KRITAUI_EXPORT KisSortedPaintOpListModel : public KisSortedCategorizedListModel { public: KisSortedPaintOpListModel(QObject *parent) : KisSortedCategorizedListModel(parent), m_model(new KisPaintOpListModel(this)) { initializeModel(m_model); } void fill(const QList &list) { m_model->fill(list); } protected: bool lessThan(const QModelIndex &left, const QModelIndex &right) const { return lessThanPriority(left, right, KisPaintOpFactory::categoryStable()); } private: KisPaintOpListModel *m_model; }; #endif //_KIS_PAINTOP_LIST_MODEL_H_ diff --git a/krita/ui/kis_painting_assistant.h b/krita/ui/kis_painting_assistant.h index 5650aacfc14..67b19c1fea2 100644 --- a/krita/ui/kis_painting_assistant.h +++ b/krita/ui/kis_painting_assistant.h @@ -1,174 +1,174 @@ /* * Copyright (c) 2008 Cyrille Berger * * 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_PAINTING_ASSISTANT_H_ #define _KIS_PAINTING_ASSISTANT_H_ #include #include #include #include #include #include -#include +#include #include #include class QPainter; class QRect; class QRectF; class KoStore; class KisCoordinatesConverter; class KisDocument; #include #include class KisPaintingAssistantHandle; typedef KisSharedPtr KisPaintingAssistantHandleSP; class KisPaintingAssistant; class QPainterPath; /** * Represent an handle of the assistant, used to edit the parameters * of an assistants. Handles can be shared between assistants. */ class KRITAUI_EXPORT KisPaintingAssistantHandle : public QPointF, public KisShared { friend class KisPaintingAssistant; public: KisPaintingAssistantHandle(double x, double y); explicit KisPaintingAssistantHandle(QPointF p); KisPaintingAssistantHandle(const KisPaintingAssistantHandle&); ~KisPaintingAssistantHandle(); void mergeWith(KisPaintingAssistantHandleSP); QList split(); void uncache(); KisPaintingAssistantHandle& operator=(const QPointF&); void setType(char type); char handleType(); private: void registerAssistant(KisPaintingAssistant*); void unregisterAssistant(KisPaintingAssistant*); bool containsAssistant(KisPaintingAssistant*); private: struct Private; Private* const d; }; /** * A KisPaintingAssistant is an object that assist the drawing on the canvas. * With this class you can implement virtual equivalent to ruler or compas. */ class KRITAUI_EXPORT KisPaintingAssistant { public: KisPaintingAssistant(const QString& id, const QString& name); virtual ~KisPaintingAssistant(); const QString& id() const; const QString& name() const; bool snapping() const;//this returns whether or not the snapping is/should be active. void setSnapping(bool set); bool outline() const;//this returns whether or not the preview is/should be active. void setOutline(bool set); /** * Adjust the position given in parameter. * @param point the coordinates in point in the document reference * @param strokeBegin the coordinates of the beginning of the stroke */ virtual QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin) = 0; virtual void endStroke() { } virtual QPointF buttonPosition() const = 0; virtual int numHandles() const = 0; void replaceHandle(KisPaintingAssistantHandleSP _handle, KisPaintingAssistantHandleSP _with); void addHandle(KisPaintingAssistantHandleSP handle); void addSideHandle(KisPaintingAssistantHandleSP handle); virtual void drawAssistant(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter, bool cached = true,KisCanvas2 *canvas=0, bool assistantVisible=true, bool previewVisible=true); void uncache(); const QList& handles() const; QList handles(); const QList& sideHandles() const; QList sideHandles(); QByteArray saveXml( QMap &handleMap); void loadXml(KoStore *store, QMap &handleMap, QString path); void saveXmlList(QDomDocument& doc, QDomElement& ssistantsElement, int count); void findHandleLocation(); KisPaintingAssistantHandleSP oppHandleOne(); /** * Get the topLeft, bottomLeft, topRight and BottomRight corners of the assistant */ const KisPaintingAssistantHandleSP topLeft() const; KisPaintingAssistantHandleSP topLeft(); const KisPaintingAssistantHandleSP topRight() const; KisPaintingAssistantHandleSP topRight(); const KisPaintingAssistantHandleSP bottomLeft() const; KisPaintingAssistantHandleSP bottomLeft(); const KisPaintingAssistantHandleSP bottomRight() const; KisPaintingAssistantHandleSP bottomRight(); const KisPaintingAssistantHandleSP topMiddle() const; KisPaintingAssistantHandleSP topMiddle(); const KisPaintingAssistantHandleSP rightMiddle() const; KisPaintingAssistantHandleSP rightMiddle(); const KisPaintingAssistantHandleSP leftMiddle() const; KisPaintingAssistantHandleSP leftMiddle(); const KisPaintingAssistantHandleSP bottomMiddle() const; KisPaintingAssistantHandleSP bottomMiddle(); public: /** * This will paint a path using a white and black colors. */ static void drawPath(QPainter& painter, const QPainterPath& path, bool drawActive=true); static void drawPreview(QPainter& painter, const QPainterPath& path); protected: virtual QRect boundingRect() const; virtual void drawCache(QPainter& gc, const KisCoordinatesConverter *converter, bool assistantVisible=true) = 0; void initHandles(QList _handles); QList m_handles; private: struct Private; Private* const d; }; /** * Allow to create a painting assistant. */ class KRITAUI_EXPORT KisPaintingAssistantFactory { public: KisPaintingAssistantFactory(); virtual ~KisPaintingAssistantFactory(); virtual QString id() const = 0; virtual QString name() const = 0; virtual KisPaintingAssistant* createPaintingAssistant() const = 0; }; class KRITAUI_EXPORT KisPaintingAssistantFactoryRegistry : public KoGenericRegistry { KisPaintingAssistantFactoryRegistry(); ~KisPaintingAssistantFactoryRegistry(); public: static KisPaintingAssistantFactoryRegistry* instance(); }; #endif diff --git a/krita/ui/kis_painting_assistants_decoration.h b/krita/ui/kis_painting_assistants_decoration.h index bff00ffd60d..78ebfed05ff 100644 --- a/krita/ui/kis_painting_assistants_decoration.h +++ b/krita/ui/kis_painting_assistants_decoration.h @@ -1,70 +1,70 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_PAINTING_ASSISTANTS_MANAGER_H_ #define _KIS_PAINTING_ASSISTANTS_MANAGER_H_ #include #include "canvas/kis_canvas_decoration.h" #include "kis_painting_assistant.h" -#include +#include class KisView; /** * This class hold a list of painting assistants. */ class KRITAUI_EXPORT KisPaintingAssistantsDecoration : public KisCanvasDecoration { Q_OBJECT public: KisPaintingAssistantsDecoration(QPointer parent); ~KisPaintingAssistantsDecoration(); void addAssistant(KisPaintingAssistant* assistant); void removeAssistant(KisPaintingAssistant* assistant); void removeAll(); QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin); void endStroke(); QList handles(); QList assistants(); /*sets whether the main assistant is visible*/ void setAssistantVisible(bool set); /*sets whether the preview is visible*/ void setOutlineVisible(bool set); /*returns assistant visibility*/ bool assistantVisibility(); /*returns preview visibility*/ bool outlineVisibility(); /*uncache all assistants*/ void uncache(); Q_SIGNALS: void assistantChanged(); public Q_SLOTS: void toggleAssistantVisible(); void toggleOutlineVisible(); protected: void drawDecoration(QPainter& gc, const QRectF& updateRect, const KisCoordinatesConverter *converter,KisCanvas2* canvas); private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/kis_paintop_box.cc b/krita/ui/kis_paintop_box.cc index d64e9dc99f1..1a3afcfcd42 100644 --- a/krita/ui/kis_paintop_box.cc +++ b/krita/ui/kis_paintop_box.cc @@ -1,1163 +1,1161 @@ /* * kis_paintop_box.cc - part of KImageShop/Krayon/Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2009-2011 Sven Langkamp (sven.langkamp@gmail.com) * Copyright (c) 2010 Lukáš Tvrdý * Copyright (C) 2011 Silvio Heinrich * Copyright (C) 2011 Srikanth Tiyyagura * Copyright (c) 2014 Mohit Goyal * * 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_paintop_box.h" #include #include #include #include #include #include #include #include -#include +#include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_canvas2.h" #include "kis_node_manager.h" #include "KisViewManager.h" #include "kis_factory2.h" #include "kis_canvas_resource_provider.h" #include "kis_resource_server_provider.h" #include "kis_favorite_resource_manager.h" #include "kis_config.h" #include "widgets/kis_popup_button.h" #include "widgets/kis_tool_options_popup.h" #include "widgets/kis_paintop_presets_popup.h" #include "widgets/kis_tool_options_popup.h" #include "widgets/kis_paintop_presets_chooser_popup.h" #include "widgets/kis_workspace_chooser.h" #include "widgets/kis_paintop_list_widget.h" #include "widgets/kis_slider_spin_box.h" #include "widgets/kis_cmb_composite.h" #include "widgets/kis_widget_chooser.h" #include "tool/kis_tool.h" #include "kis_signals_blocker.h" - - typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; KisPaintopBox::KisPaintopBox(KisViewManager *view, QWidget *parent, const char *name) : QWidget(parent) , m_resourceProvider(view->resourceProvider()) , m_optionWidget(0) , m_toolOptionsPopupButton(0) , m_brushEditorPopupButton(0) , m_presetSelectorPopupButton(0) , m_toolOptionsPopup(0) , m_viewManager(view) , m_previousNode(0) , m_currTabletToolID(KoInputDevice::invalid()) , m_presetsEnabled(true) , m_blockUpdate(false) , m_dirtyPresetsEnabled(false) , m_eraserBrushSizeEnabled(false) { Q_ASSERT(view != 0); KGlobal::mainComponent().dirs()->addResourceType("kis_defaultpresets", "data", "krita/defaultpresets/"); setObjectName(name); KisConfig cfg; m_dirtyPresetsEnabled = cfg.useDirtyPresets(); m_eraserBrushSizeEnabled = cfg.useEraserBrushSize(); KAcceleratorManager::setNoAccel(this); setWindowTitle(i18n("Painter's Toolchest")); KConfigGroup grp = KGlobal::config()->group("krita").group("Toolbar BrushesAndStuff"); int iconsize = grp.readEntry("IconSize", 32); if (!cfg.toolOptionsInDocker()) { m_toolOptionsPopupButton = new KisPopupButton(this); - m_toolOptionsPopupButton->setIcon(themedIcon("configure")); + m_toolOptionsPopupButton->setIcon(KisIconUtils::loadIcon("configure")); m_toolOptionsPopupButton->setToolTip(i18n("Tool Settings")); m_toolOptionsPopupButton->setFixedSize(iconsize, iconsize); } m_brushEditorPopupButton = new KisPopupButton(this); - m_brushEditorPopupButton->setIcon(koIcon("paintop_settings_02")); + m_brushEditorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_02")); m_brushEditorPopupButton->setToolTip(i18n("Edit brush settings")); m_brushEditorPopupButton->setFixedSize(iconsize, iconsize); m_presetSelectorPopupButton = new KisPopupButton(this); - m_presetSelectorPopupButton->setIcon(koIcon("paintop_settings_01")); + m_presetSelectorPopupButton->setIcon(KisIconUtils::loadIcon("paintop_settings_01")); m_presetSelectorPopupButton->setToolTip(i18n("Choose brush preset")); m_presetSelectorPopupButton->setFixedSize(iconsize, iconsize); m_eraseModeButton = new QToolButton(this); m_eraseModeButton->setFixedSize(iconsize, iconsize); m_eraseModeButton->setCheckable(true); KisAction* eraseAction = new KisAction(i18n("Set eraser mode"), m_eraseModeButton); eraseAction->setActivationFlags(KisAction::ACTIVE_DEVICE); - eraseAction->setIcon(themedIcon("draw-eraser")); + eraseAction->setIcon(KisIconUtils::loadIcon("draw-eraser")); eraseAction->setShortcut(Qt::Key_E); eraseAction->setCheckable(true); m_eraseModeButton->setDefaultAction(eraseAction); m_viewManager->actionCollection()->addAction("erase_action", eraseAction); eraserBrushSize = 0; // brush size changed when using erase mode m_reloadButton = new QToolButton(this); m_reloadButton->setFixedSize(iconsize, iconsize); m_reloadButton->setCheckable(true); KisAction* reloadAction = new KisAction(i18n("Reload Original Preset"), m_reloadButton); reloadAction->setActivationFlags(KisAction::ACTIVE_DEVICE); - reloadAction->setIcon(themedIcon("view-refresh")); + reloadAction->setIcon(KisIconUtils::loadIcon("view-refresh")); m_reloadButton->setDefaultAction(reloadAction); m_viewManager->actionCollection()->addAction("reload_preset_action", reloadAction); m_alphaLockButton = new QToolButton(this); m_alphaLockButton->setFixedSize(iconsize, iconsize); m_alphaLockButton->setCheckable(true); KisAction* alphaLockAction = new KisAction(i18n("Preserve Alpha"), m_alphaLockButton); alphaLockAction->setActivationFlags(KisAction::ACTIVE_DEVICE); - alphaLockAction->setIcon(koIcon("transparency-unlocked")); + alphaLockAction->setIcon(KisIconUtils::loadIcon("transparency-unlocked")); alphaLockAction->setCheckable(true); m_alphaLockButton->setDefaultAction(alphaLockAction); m_viewManager->actionCollection()->addAction("preserve_alpha", alphaLockAction); m_hMirrorButton = new QToolButton(this); m_hMirrorButton->setFixedSize(iconsize, iconsize); m_hMirrorButton->setCheckable(true); m_hMirrorAction = new KisAction(i18n("Set horizontal mirror mode"), m_hMirrorButton); - m_hMirrorAction->setIcon(themedIcon("symmetry-horizontal")); + m_hMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-horizontal")); m_hMirrorAction->setActivationFlags(KisAction::ACTIVE_DEVICE); m_hMirrorAction->setCheckable(true); m_hMirrorButton->setDefaultAction(m_hMirrorAction); m_viewManager->actionCollection()->addAction("hmirror_action", m_hMirrorAction); m_vMirrorButton = new QToolButton(this); m_vMirrorButton->setFixedSize(iconsize, iconsize); m_vMirrorButton->setCheckable(true); m_vMirrorAction = new KisAction(i18n("Set vertical mirror mode"), m_vMirrorButton); m_vMirrorAction->setActivationFlags(KisAction::ACTIVE_DEVICE); - m_vMirrorAction->setIcon(themedIcon("symmetry-vertical")); + m_vMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-vertical")); m_vMirrorAction->setCheckable(true); m_vMirrorButton->setDefaultAction(m_vMirrorAction); m_viewManager->actionCollection()->addAction("vmirror_action", m_vMirrorAction); const bool sliderLabels = cfg.sliderLabels(); int sliderWidth; if (sliderLabels) { sliderWidth = 150 * logicalDpiX() / 96; } else { sliderWidth = 120 * logicalDpiX() / 96; } for (int i = 0; i < 3; ++i) { m_sliderChooser[i] = new KisWidgetChooser(i + 1); KisDoubleSliderSpinBox* slOpacity; KisDoubleSliderSpinBox* slFlow; KisDoubleSliderSpinBox* slSize; if (sliderLabels) { slOpacity = m_sliderChooser[i]->addWidget("opacity"); slFlow = m_sliderChooser[i]->addWidget("flow"); slSize = m_sliderChooser[i]->addWidget("size"); slOpacity->setPrefix(QString("%1 ").arg(i18n("Opacity:"))); slFlow->setPrefix(QString("%1 ").arg(i18n("Flow:"))); slSize->setPrefix(QString("%1 ").arg(i18n("Size:"))); } else { slOpacity = m_sliderChooser[i]->addWidget("opacity", i18n("Opacity:")); slFlow = m_sliderChooser[i]->addWidget("flow", i18n("Flow:")); slSize = m_sliderChooser[i]->addWidget("size", i18n("Size:")); } slOpacity->setRange(0.0, 1.0, 2); slOpacity->setValue(1.0); slOpacity->setSingleStep(0.05); slOpacity->setMinimumWidth(qMax(sliderWidth, slOpacity->sizeHint().width())); slOpacity->setFixedHeight(iconsize); slOpacity->setBlockUpdateSignalOnDrag(true); slFlow->setRange(0.0, 1.0, 2); slFlow->setValue(1.0); slFlow->setSingleStep(0.05); slFlow->setMinimumWidth(qMax(sliderWidth, slFlow->sizeHint().width())); slFlow->setFixedHeight(iconsize); slFlow->setBlockUpdateSignalOnDrag(true); slSize->setRange(0, 1000, 2); slSize->setValue(100); slSize->setSingleStep(1); slSize->setExponentRatio(3.0); slSize->setSuffix(" px"); slSize->setMinimumWidth(qMax(sliderWidth, slSize->sizeHint().width())); slSize->setFixedHeight(iconsize); slSize->setBlockUpdateSignalOnDrag(true); m_sliderChooser[i]->chooseWidget(cfg.toolbarSlider(i + 1)); } m_cmbCompositeOp = new KisCompositeOpComboBox(); m_cmbCompositeOp->setFixedHeight(iconsize); foreach(KAction * a, m_cmbCompositeOp->blendmodeActions()) { m_viewManager->actionCollection()->addAction(a->text(), a); } m_workspaceWidget = new KisPopupButton(this); - m_workspaceWidget->setIcon(themedIcon("view-choose")); + m_workspaceWidget->setIcon(KisIconUtils::loadIcon("view-choose")); m_workspaceWidget->setToolTip(i18n("Choose workspace")); m_workspaceWidget->setFixedSize(iconsize, iconsize); m_workspaceWidget->setPopupWidget(new KisWorkspaceChooser(view)); QHBoxLayout* baseLayout = new QHBoxLayout(this); m_paintopWidget = new QWidget(this); baseLayout->addWidget(m_paintopWidget); baseLayout->setSpacing(4); baseLayout->setContentsMargins(0, 0, 0, 0); m_layout = new QHBoxLayout(m_paintopWidget); if (!cfg.toolOptionsInDocker()) { m_layout->addWidget(m_toolOptionsPopupButton); } m_layout->addWidget(m_brushEditorPopupButton); m_layout->addWidget(m_presetSelectorPopupButton); m_layout->setSpacing(4); m_layout->setContentsMargins(0, 0, 0, 0); QWidget* compositeActions = new QWidget(this); QHBoxLayout* compositeLayout = new QHBoxLayout(compositeActions); compositeLayout->addWidget(m_cmbCompositeOp); compositeLayout->addWidget(m_eraseModeButton); compositeLayout->addWidget(m_alphaLockButton); compositeLayout->setSpacing(4); compositeLayout->setContentsMargins(0, 0, 0, 0); compositeLayout->addWidget(m_reloadButton); KAction* action; action = new KAction(i18n("Brush composite"), this); view->actionCollection()->addAction("composite_actions", action); action->setDefaultWidget(compositeActions); action = new KAction(i18n("Brush option slider 1"), this); view->actionCollection()->addAction("brushslider1", action); action->setDefaultWidget(m_sliderChooser[0]); connect(action, SIGNAL(triggered()), m_sliderChooser[0], SLOT(showPopupWidget())); action = new KAction(i18n("Brush option slider 2"), this); view->actionCollection()->addAction("brushslider2", action); action->setDefaultWidget(m_sliderChooser[1]); connect(action, SIGNAL(triggered()), m_sliderChooser[1], SLOT(showPopupWidget())); action = new KAction(i18n("Brush option slider 3"), this); view->actionCollection()->addAction("brushslider3", action); action->setDefaultWidget(m_sliderChooser[2]); connect(action, SIGNAL(triggered()), m_sliderChooser[2], SLOT(showPopupWidget())); action = new KAction(i18n("Next Favourite Preset"), this); view->actionCollection()->addAction("next_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Comma)); connect(action, SIGNAL(triggered()), this, SLOT(slotNextFavoritePreset())); action = new KAction(i18n("Previous Favourite Preset"), this); view->actionCollection()->addAction("previous_favorite_preset", action); action->setShortcut(KShortcut(Qt::Key_Period)); connect(action, SIGNAL(triggered()), this, SLOT(slotPreviousFavoritePreset())); action = new KAction(i18n("Switch to Previous Preset"), this); view->actionCollection()->addAction("previous_preset", action); action->setShortcut(KShortcut(Qt::Key_Slash)); connect(action, SIGNAL(triggered()), this, SLOT(slotSwitchToPreviousPreset())); if (!cfg.toolOptionsInDocker()) { action = new KAction(i18n("Show Tool Options"), this); view->actionCollection()->addAction("show_tool_options", action); action->setShortcut(Qt::Key_Backslash); connect(action, SIGNAL(triggered()), m_toolOptionsPopupButton, SLOT(showPopupWidget())); } action = new KAction(i18n("Show Brush Editor"), this); view->actionCollection()->addAction("show_brush_editor", action); action->setShortcut(Qt::Key_F5); connect(action, SIGNAL(triggered()), m_brushEditorPopupButton, SLOT(showPopupWidget())); action = new KAction(i18n("Show Brush Presets"), this); view->actionCollection()->addAction("show_brush_presets", action); action->setShortcut(Qt::Key_F6); connect(action, SIGNAL(triggered()), m_presetSelectorPopupButton, SLOT(showPopupWidget())); QWidget* mirrorActions = new QWidget(this); QHBoxLayout* mirrorLayout = new QHBoxLayout(mirrorActions); mirrorLayout->addWidget(m_hMirrorButton); mirrorLayout->addWidget(m_vMirrorButton); mirrorLayout->setSpacing(4); mirrorLayout->setContentsMargins(0, 0, 0, 0); action = new KAction(i18n("Mirror"), this); view->actionCollection()->addAction("mirror_actions", action); action->setDefaultWidget(mirrorActions); action = new KAction(i18n("Workspaces"), this); view->actionCollection()->addAction("workspaces", action); action->setDefaultWidget(m_workspaceWidget); if (!cfg.toolOptionsInDocker()) { m_toolOptionsPopup = new KisToolOptionsPopup(); m_toolOptionsPopupButton->setPopupWidget(m_toolOptionsPopup); m_toolOptionsPopup->switchDetached(false); } m_presetsPopup = new KisPaintOpPresetsPopup(m_resourceProvider); m_brushEditorPopupButton->setPopupWidget(m_presetsPopup); m_presetsPopup->switchDetached(false); m_presetsChooserPopup = new KisPaintOpPresetsChooserPopup(); m_presetsChooserPopup->setFixedSize(500, 600); m_presetSelectorPopupButton->setPopupWidget(m_presetsChooserPopup); m_prevCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); m_currCompositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); slotNodeChanged(view->activeNode()); // Get all the paintops QList keys = KisPaintOpRegistry::instance()->keys(); QList factoryList; foreach(const QString & paintopId, keys) { factoryList.append(KisPaintOpRegistry::instance()->get(paintopId)); } m_presetsPopup->setPaintOpList(factoryList); connect(m_presetsPopup , SIGNAL(paintopActivated(QString)) , SLOT(slotSetPaintop(QString))); connect(m_presetsPopup , SIGNAL(savePresetClicked()) , SLOT(slotSaveActivePreset())); connect(m_presetsPopup , SIGNAL(defaultPresetClicked()) , SLOT(slotSetupDefaultPreset())); connect(m_presetsPopup , SIGNAL(signalResourceSelected(KoResource*)), SLOT(resourceSelected(KoResource*))); connect(m_presetsPopup , SIGNAL(reloadPresetClicked()) , SLOT(slotReloadPreset())); connect(m_presetsPopup , SIGNAL(dirtyPresetToggled(bool)) , SLOT(slotDirtyPresetToggled(bool))); connect(m_presetsPopup , SIGNAL(eraserBrushSizeToggled(bool)) , SLOT(slotEraserBrushSizeToggled(bool))); connect(m_presetsChooserPopup, SIGNAL(resourceSelected(KoResource*)) , SLOT(resourceSelected(KoResource*))); connect(m_resourceProvider , SIGNAL(sigNodeChanged(const KisNodeSP)) , SLOT(slotNodeChanged(const KisNodeSP))); connect(m_cmbCompositeOp , SIGNAL(currentIndexChanged(int)) , SLOT(slotSetCompositeMode(int))); connect(eraseAction , SIGNAL(triggered(bool)) , SLOT(slotToggleEraseMode(bool))); connect(alphaLockAction , SIGNAL(triggered(bool)) , SLOT(slotToggleAlphaLockMode(bool))); connect(m_hMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotHorizontalMirrorChanged(bool))); connect(m_vMirrorAction , SIGNAL(triggered(bool)) , SLOT(slotVerticalMirrorChanged(bool))); connect(reloadAction , SIGNAL(triggered()) , SLOT(slotReloadPreset())); connect(m_sliderChooser[0]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[0]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider1Changed())); connect(m_sliderChooser[1]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[1]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider2Changed())); connect(m_sliderChooser[2]->getWidget("opacity"), SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("flow") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); connect(m_sliderChooser[2]->getWidget("size") , SIGNAL(valueChanged(qreal)), SLOT(slotSlider3Changed())); //Needed to connect canvas to favorite resource manager connect(m_viewManager->resourceProvider(), SIGNAL(sigOpacityChanged(qreal)), SLOT(slotOpacityChanged(qreal))); connect(m_viewManager->resourceProvider(), SIGNAL(sigFGColorChanged(KoColor)), SLOT(slotUnsetEraseMode())); m_favoriteResourceManager = new KisFavoriteResourceManager(this); connect(m_resourceProvider, SIGNAL(sigFGColorUsed(KoColor)), m_favoriteResourceManager, SLOT(slotAddRecentColor(KoColor))); connect(m_resourceProvider, SIGNAL(sigFGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotChangeFGColorSelector(KoColor))); connect(m_resourceProvider, SIGNAL(sigBGColorChanged(KoColor)), m_favoriteResourceManager, SLOT(slotSetBGColor(KoColor))); // cold initialization m_favoriteResourceManager->slotChangeFGColorSelector(m_resourceProvider->fgColor()); m_favoriteResourceManager->slotSetBGColor(m_resourceProvider->bgColor()); connect(m_favoriteResourceManager, SIGNAL(sigSetFGColor(KoColor)), m_resourceProvider, SLOT(slotSetFGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigSetBGColor(KoColor)), m_resourceProvider, SLOT(slotSetBGColor(KoColor))); connect(m_favoriteResourceManager, SIGNAL(sigEnableChangeColor(bool)), m_resourceProvider, SLOT(slotResetEnableFGChange(bool))); connect(view->mainWindow(), SIGNAL(themeChanged()), this, SLOT(slotUpdateSelectionIcon())); slotInputDeviceChanged(KoToolManager::instance()->currentInputDevice()); } KisPaintopBox::~KisPaintopBox() { KisConfig cfg; QMapIterator iter(m_tabletToolMap); while (iter.hasNext()) { iter.next(); if ((iter.key().pointer) == QTabletEvent::Eraser) { cfg.writeEntry(QString("LastEraser_%1").arg(iter.key().uniqueID) , iter.value().preset->name()); } else { cfg.writeEntry(QString("LastPreset_%1").arg(iter.key().uniqueID) , iter.value().preset->name()); } } // Do not delete the widget, since it it is global to the application, not owned by the view m_presetsPopup->setPaintOpSettingsWidget(0); qDeleteAll(m_paintopOptionWidgets); delete m_favoriteResourceManager; } void KisPaintopBox::restoreResource(KoResource* resource) { KisPaintOpPreset* preset = dynamic_cast(resource); if (preset) { setCurrentPaintop(preset->paintOp(), preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } void KisPaintopBox::newOptionWidgets(const QList > &optionWidgetList) { if (m_toolOptionsPopup) { m_toolOptionsPopup->newOptionWidgets(optionWidgetList); } } void KisPaintopBox::resourceSelected(KoResource* resource) { KisPaintOpPreset* preset = dynamic_cast(resource); if (preset) { if (!preset->settings()->isLoadable()) return; setCurrentPaintopAndReload(preset->paintOp(), preset); m_presetsPopup->setPresetImage(preset->image()); m_presetsPopup->resourceSelected(resource); } } QPixmap KisPaintopBox::paintopPixmap(const KoID& paintop) { QString pixmapName = KisPaintOpRegistry::instance()->pixmap(paintop); if (pixmapName.isEmpty()) return QPixmap(); return QPixmap(KisFactory::componentData().dirs()->findResource("kis_images", pixmapName)); } KoID KisPaintopBox::currentPaintop() { return m_resourceProvider->currentPreset()->paintOp(); } void KisPaintopBox::setCurrentPaintopAndReload(const KoID& paintop, KisPaintOpPresetSP preset) { if (!m_dirtyPresetsEnabled) { KisSignalsBlocker blocker(m_optionWidget); if (!preset->load()) { qWarning() << "failed to load the preset."; } } setCurrentPaintop(paintop, preset); } void KisPaintopBox::setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset) { if (m_resourceProvider->currentPreset()) { m_resourceProvider->setPreviousPaintOpPreset(m_resourceProvider->currentPreset()); if (m_optionWidget) { m_optionWidget->disconnect(this); m_optionWidget->hide(); } m_paintOpPresetMap[m_resourceProvider->currentPreset()->paintOp()] = m_resourceProvider->currentPreset(); m_tabletToolMap[m_currTabletToolID].preset = m_resourceProvider->currentPreset(); m_tabletToolMap[m_currTabletToolID].paintOpID = m_resourceProvider->currentPreset()->paintOp(); } preset = (!preset) ? activePreset(paintop) : preset; Q_ASSERT(preset && preset->settings()); if (!m_paintopOptionWidgets.contains(paintop)) m_paintopOptionWidgets[paintop] = KisPaintOpRegistry::instance()->get(paintop.id())->createConfigWidget(this); m_optionWidget = m_paintopOptionWidgets[paintop]; preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setImage(m_viewManager->image()); m_optionWidget->setNode(m_viewManager->activeNode()); m_optionWidget->setConfiguration(preset->settings()); m_presetsPopup->setPaintOpSettingsWidget(m_optionWidget); Q_ASSERT(m_optionWidget && m_presetSelectorPopupButton); connect(m_optionWidget, SIGNAL(sigConfigurationUpdated()), this, SLOT(slotUpdatePreset())); connect(m_optionWidget, SIGNAL(sigSaveLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotSaveLockedOptionToPreset(KisPropertiesConfiguration*))); connect(m_optionWidget, SIGNAL(sigDropLockedConfig(KisPropertiesConfiguration*)), this, SLOT(slotDropLockedOption(KisPropertiesConfiguration*))); connect(m_optionWidget, SIGNAL(sigConfigurationItemChanged()), this, SLOT(slotConfigurationItemChanged())); KisPaintOpFactory* paintOp = KisPaintOpRegistry::instance()->get(paintop.id()); QString pixFilename = KisFactory::componentData().dirs()->findResource("kis_images", paintOp->pixmap()); m_brushEditorPopupButton->setIcon(QIcon(pixFilename)); m_resourceProvider->setPaintOpPreset(preset); m_presetsPopup->setCurrentPaintOp(paintop.id()); if (m_presetsPopup->currentPaintOp() != paintop.id()) { // Must change the paintop as the current one is not supported // by the new colorspace. kWarning() << "current paintop " << paintop.name() << " was not set, not supported by colorspace"; } /** * We will get more update signals from the configuration widgets * but they might be delayed by some internal deferring timers, * so just call the slot directly */ slotUpdatePreset(); } KoID KisPaintopBox::defaultPaintOp() { return KoID("paintbrush"); } KisPaintOpPresetSP KisPaintopBox::defaultPreset(const KoID& paintOp) { QString defaultName = paintOp.id() + ".kpp"; QString path = KGlobal::mainComponent().dirs()->findResource("kis_defaultpresets", defaultName); KisPaintOpPresetSP preset = new KisPaintOpPreset(path); if (!preset->load()) { preset = KisPaintOpRegistry::instance()->defaultPreset(paintOp); } Q_ASSERT(preset); Q_ASSERT(preset->valid()); return preset; } KisPaintOpPresetSP KisPaintopBox::activePreset(const KoID& paintOp) { if (m_paintOpPresetMap[paintOp] == 0) { m_paintOpPresetMap[paintOp] = defaultPreset(paintOp); } return m_paintOpPresetMap[paintOp]; } void KisPaintopBox::updateCompositeOp(QString compositeOpID, bool localUpdate) { if (!m_optionWidget) return; KisSignalsBlocker blocker(m_optionWidget); KisNodeSP node = m_resourceProvider->currentNode(); if (node && node->paintDevice()) { if (!node->paintDevice()->colorSpace()->hasCompositeOp(compositeOpID)) compositeOpID = KoCompositeOpRegistry::instance().getDefaultCompositeOp().id(); m_cmbCompositeOp->blockSignals(true); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOpID)); m_cmbCompositeOp->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(true); m_eraseModeButton->blockSignals(true); m_eraseModeButton->setChecked(compositeOpID == COMPOSITE_ERASE); m_eraseModeButton->defaultAction()->setChecked(compositeOpID == COMPOSITE_ERASE); m_eraseModeButton->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(false); if (compositeOpID != m_currCompositeOpID) { m_resourceProvider->currentPreset()->settings()->setPaintOpCompositeOp(compositeOpID); m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); if (!localUpdate) m_resourceProvider->setCurrentCompositeOp(compositeOpID); m_prevCompositeOpID = m_currCompositeOpID; m_currCompositeOpID = compositeOpID; } } } void KisPaintopBox::setWidgetState(int flags) { if (flags & (ENABLE_COMPOSITEOP | DISABLE_COMPOSITEOP)) { m_cmbCompositeOp->setEnabled(flags & ENABLE_COMPOSITEOP); m_eraseModeButton->setEnabled(flags & ENABLE_COMPOSITEOP); } if (flags & (ENABLE_PRESETS | DISABLE_PRESETS)) { m_presetSelectorPopupButton->setEnabled(flags & ENABLE_PRESETS); m_brushEditorPopupButton->setEnabled(flags & ENABLE_PRESETS); } for (int i = 0; i < 3; ++i) { if (flags & (ENABLE_OPACITY | DISABLE_OPACITY)) m_sliderChooser[i]->getWidget("opacity")->setEnabled(flags & ENABLE_OPACITY); if (flags & (ENABLE_FLOW | DISABLE_FLOW)) m_sliderChooser[i]->getWidget("flow")->setEnabled(flags & ENABLE_FLOW); if (flags & (ENABLE_SIZE | DISABLE_SIZE)) m_sliderChooser[i]->getWidget("size")->setEnabled(flags & ENABLE_SIZE); } } void KisPaintopBox::setSliderValue(const QString& sliderID, qreal value) { for (int i = 0; i < 3; ++i) { KisDoubleSliderSpinBox* slider = m_sliderChooser[i]->getWidget(sliderID); slider->blockSignals(true); slider->setValue(value); slider->blockSignals(false); } } void KisPaintopBox::slotSetPaintop(const QString& paintOpId) { if (KisPaintOpRegistry::instance()->get(paintOpId) != 0) { KoID id(paintOpId, KisPaintOpRegistry::instance()->get(paintOpId)->name()); setCurrentPaintop(id); } } void KisPaintopBox::slotInputDeviceChanged(const KoInputDevice& inputDevice) { TabletToolMap::iterator toolData = m_tabletToolMap.find(inputDevice); if (toolData == m_tabletToolMap.end()) { KisConfig cfg; KisPaintOpPresetResourceServer *rserver = KisResourceServerProvider::instance()->paintOpPresetServer(false); KisPaintOpPresetSP preset; if (inputDevice.pointer() == QTabletEvent::Eraser) { preset = rserver->resourceByName(cfg.readEntry(QString("LastEraser_%1").arg(inputDevice.uniqueTabletId()), "Eraser_circle")); } else { preset = rserver->resourceByName(cfg.readEntry(QString("LastPreset_%1").arg(inputDevice.uniqueTabletId()), "Basic_tip_default")); } if (!preset) { preset = rserver->resourceByName("Basic_tip_default"); } if (preset) { setCurrentPaintop(preset->paintOp(), preset); } } else { setCurrentPaintop(toolData->paintOpID, toolData->preset); } m_currTabletToolID = TabletToolID(inputDevice); } void KisPaintopBox::slotCanvasResourceChanged(int /*key*/, const QVariant& /*v*/) { if (m_viewManager) { sender()->blockSignals(true); KisPaintOpPresetSP preset = m_viewManager->resourceProvider()->resourceManager()->resource(KisCanvasResourceProvider::CurrentPaintOpPreset).value(); if (preset && m_resourceProvider->currentPreset()->name() != preset->name()) { QString compositeOp = preset->settings()->getString("CompositeOp"); updateCompositeOp(compositeOp); resourceSelected(preset.data()); } m_presetsChooserPopup->canvasResourceChanged(preset.data(), preset); if (m_resourceProvider->currentCompositeOp() != m_currCompositeOpID) { QString compositeOp = m_resourceProvider->currentCompositeOp(); m_cmbCompositeOp->blockSignals(true); m_cmbCompositeOp->selectCompositeOp(KoID(compositeOp)); m_cmbCompositeOp->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(true); m_eraseModeButton->blockSignals(true); m_eraseModeButton->setChecked(compositeOp == COMPOSITE_ERASE); m_eraseModeButton->defaultAction()->setChecked(compositeOp == COMPOSITE_ERASE); m_eraseModeButton->blockSignals(false); m_eraseModeButton->defaultAction()->blockSignals(false); } sender()->blockSignals(false); } } void KisPaintopBox::slotSaveActivePreset() { KisPaintOpPresetSP curPreset = m_resourceProvider->currentPreset(); if (!curPreset) return; m_favoriteResourceManager->setBlockUpdates(true); KisPaintOpPresetSP newPreset = curPreset->clone(); KisPaintOpPresetResourceServer * rServer = KisResourceServerProvider::instance()->paintOpPresetServer(); QString saveLocation = rServer->saveLocation(); QString presetName = m_presetsPopup->getPresetName(); QString presetFilename = saveLocation + presetName + newPreset->defaultFileExtension(); QStringList tags; KisPaintOpPresetSP resource = rServer->resourceByName(presetName); if (resource) { tags = rServer->assignedTagsList(resource.data()); rServer->removeResourceAndBlacklist(resource); } newPreset->setImage(m_presetsPopup->cutOutOverlay()); newPreset->setFilename(presetFilename); newPreset->setName(presetName); newPreset->setPresetDirty(false); rServer->addResource(newPreset); foreach(const QString & tag, tags) { rServer->addTag(newPreset.data(), tag); } // HACK ALERT! the server does not notify the observers // automatically, so we need to call theupdate manually! rServer->tagCategoryMembersChanged(); restoreResource(newPreset.data()); m_favoriteResourceManager->setBlockUpdates(false); } void KisPaintopBox::slotUpdatePreset() { if (!m_resourceProvider->currentPreset()) return; // block updates of avoid some over updating of the option widget m_blockUpdate = true; setSliderValue("size", m_resourceProvider->currentPreset()->settings()->paintOpSize().width()); { qreal opacity = m_resourceProvider->currentPreset()->settings()->paintOpOpacity(); m_resourceProvider->setOpacity(opacity); setSliderValue("opacity", opacity); setWidgetState(ENABLE_OPACITY); } { setSliderValue("flow", m_resourceProvider->currentPreset()->settings()->paintOpFlow()); setWidgetState(ENABLE_FLOW); } { updateCompositeOp(m_resourceProvider->currentPreset()->settings()->paintOpCompositeOp()); setWidgetState(ENABLE_COMPOSITEOP); } m_blockUpdate = false; } void KisPaintopBox::slotSetupDefaultPreset() { KisPaintOpPresetSP preset = defaultPreset(m_resourceProvider->currentPreset()->paintOp()); preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setConfiguration(preset->settings()); m_optionWidget->writeConfiguration(const_cast(preset->settings().data())); } void KisPaintopBox::slotNodeChanged(const KisNodeSP node) { if (m_previousNode.isValid() && m_previousNode->paintDevice()) disconnect(m_previousNode->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); // Reconnect colorspace change of node if (node && node->paintDevice()) { connect(node->paintDevice().data(), SIGNAL(colorSpaceChanged(const KoColorSpace*)), this, SLOT(slotColorSpaceChanged(const KoColorSpace*))); m_resourceProvider->setCurrentCompositeOp(m_currCompositeOpID); m_previousNode = node; slotColorSpaceChanged(node->colorSpace()); } if (m_optionWidget) { m_optionWidget->setNode(node); } } void KisPaintopBox::slotColorSpaceChanged(const KoColorSpace* colorSpace) { m_cmbCompositeOp->validate(colorSpace); } void KisPaintopBox::slotToggleEraseMode(bool checked) { if (checked) { updateCompositeOp(COMPOSITE_ERASE); //add an option to enable eraser brush size if (m_eraserBrushSizeEnabled==true) { // remember brush size. set the eraser size to the normal brush size if not set normalBrushSize = m_sliderChooser[0]->getWidget("size")->value(); - if (!eraserBrushSize) + if (qFuzzyIsNull(eraserBrushSize)) eraserBrushSize = normalBrushSize; } else { normalBrushSize = eraserBrushSize; eraserBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } } else { updateCompositeOp(m_prevCompositeOpID); if (m_eraserBrushSizeEnabled==true) { // save eraser brush size as eraserBrushSize (they are all the same, so just grab the first one) eraserBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } else { normalBrushSize = m_sliderChooser[0]->getWidget("size")->value(); } } //update value in UI (this is the main place the value is 'stored' in memory) - int updateSize = checked ? eraserBrushSize : normalBrushSize; + qreal updateSize = checked ? eraserBrushSize : normalBrushSize; m_sliderChooser[0]->getWidget("size")->setValue(updateSize); m_sliderChooser[1]->getWidget("size")->setValue(updateSize); m_sliderChooser[2]->getWidget("size")->setValue(updateSize); toggleHighlightedButton(m_eraseModeButton); } void KisPaintopBox::slotSetCompositeMode(int index) { Q_UNUSED(index); if (m_resourceProvider->currentPreset()->settings()->hasProperty("CompositeOp")) { QString compositeOp = m_cmbCompositeOp->selectedCompositeOp().id(); updateCompositeOp(compositeOp); } } void KisPaintopBox::slotHorizontalMirrorChanged(bool value) { m_resourceProvider->setMirrorHorizontal(value); toggleHighlightedButton(m_hMirrorButton); } void KisPaintopBox::slotVerticalMirrorChanged(bool value) { m_resourceProvider->setMirrorVertical(value); toggleHighlightedButton(m_vMirrorButton); } void KisPaintopBox::sliderChanged(int n) { if (!m_optionWidget) // widget will not exist if the are no documents open return; KisSignalsBlocker blocker(m_optionWidget); m_optionWidget->writeConfiguration(const_cast(m_resourceProvider->currentPreset()->settings().data())); qreal opacity = m_sliderChooser[n]->getWidget("opacity")->value(); qreal flow = m_sliderChooser[n]->getWidget("flow")->value(); qreal size = m_sliderChooser[n]->getWidget("size")->value(); setSliderValue("opacity", opacity); setSliderValue("flow" , flow); setSliderValue("size" , size); if (m_presetsEnabled) { // IMPORTANT: set the PaintOp size before setting the other properties // it wont work the other way qreal sizeDiff = size - m_resourceProvider->currentPreset()->settings()->paintOpSize().width(); m_resourceProvider->currentPreset()->settings()->changePaintOpSize(sizeDiff, 0); m_resourceProvider->currentPreset()->settings()->setPaintOpOpacity(opacity); m_resourceProvider->currentPreset()->settings()->setPaintOpFlow(flow); KisLockedPropertiesProxy *propertiesProxy = KisLockedPropertiesServer::instance()->createLockedPropertiesProxy(m_resourceProvider->currentPreset()->settings()); propertiesProxy->setProperty("OpacityValue", opacity); propertiesProxy->setProperty("FlowValue", flow); delete propertiesProxy; m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); } m_resourceProvider->setOpacity(opacity); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); } void KisPaintopBox::slotSlider1Changed() { sliderChanged(0); } void KisPaintopBox::slotSlider2Changed() { sliderChanged(1); } void KisPaintopBox::slotSlider3Changed() { sliderChanged(2); } void KisPaintopBox::slotToolChanged(KoCanvasController* canvas, int toolId) { Q_UNUSED(canvas); Q_UNUSED(toolId); if (!m_viewManager->canvasBase()) return; QString id = KoToolManager::instance()->activeToolId(); KisTool* tool = dynamic_cast(KoToolManager::instance()->toolById(m_viewManager->canvasBase(), id)); if (tool) { int flags = tool->flags(); if (flags & KisTool::FLAG_USES_CUSTOM_COMPOSITEOP) { setWidgetState(ENABLE_COMPOSITEOP | ENABLE_OPACITY); } else { setWidgetState(DISABLE_COMPOSITEOP | DISABLE_OPACITY); } if (flags & KisTool::FLAG_USES_CUSTOM_PRESET) { setWidgetState(ENABLE_PRESETS | ENABLE_SIZE | ENABLE_FLOW); slotUpdatePreset(); m_presetsEnabled = true; } else { setWidgetState(DISABLE_PRESETS | DISABLE_SIZE | DISABLE_FLOW); m_presetsEnabled = false; } } else setWidgetState(DISABLE_ALL); } void KisPaintopBox::slotOpacityChanged(qreal opacity) { if (m_blockUpdate) { return; } m_blockUpdate = true; for (int i = 0; i < 3; ++i) { KisDoubleSliderSpinBox *opacitySlider = m_sliderChooser[i]->getWidget("opacity"); opacitySlider->blockSignals(true); opacitySlider->setValue(opacity); opacitySlider->blockSignals(false); } if (m_presetsEnabled) { m_resourceProvider->currentPreset()->settings()->setPaintOpOpacity(opacity); m_optionWidget->setConfiguration(m_resourceProvider->currentPreset()->settings().data()); } m_blockUpdate = false; } void KisPaintopBox::slotPreviousFavoritePreset() { if (!m_favoriteResourceManager) return; int i = 0; foreach (KisPaintOpPresetSP preset, m_favoriteResourceManager->favoritePresetList()) { if (m_resourceProvider->currentPreset() && m_resourceProvider->currentPreset()->name() == preset->name()) { if (i > 0) { m_favoriteResourceManager->slotChangeActivePaintop(i - 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(m_favoriteResourceManager->numFavoritePresets() - 1); } return; } i++; } } void KisPaintopBox::slotNextFavoritePreset() { if (!m_favoriteResourceManager) return; int i = 0; foreach (KisPaintOpPresetSP preset, m_favoriteResourceManager->favoritePresetList()) { if (m_resourceProvider->currentPreset()->name() == preset->name()) { if (i < m_favoriteResourceManager->numFavoritePresets() - 1) { m_favoriteResourceManager->slotChangeActivePaintop(i + 1); } else { m_favoriteResourceManager->slotChangeActivePaintop(0); } return; } i++; } } void KisPaintopBox::slotSwitchToPreviousPreset() { if (m_resourceProvider->previousPreset()) { setCurrentPaintop(m_resourceProvider->previousPreset()->paintOp(), m_resourceProvider->previousPreset()); } } void KisPaintopBox::slotUnsetEraseMode() { if (m_currCompositeOpID == COMPOSITE_ERASE) { updateCompositeOp(m_prevCompositeOpID); } } void KisPaintopBox::slotToggleAlphaLockMode(bool checked) { if (checked) { - m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-locked")); + m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("transparency-locked")); } else { - m_alphaLockButton->actions()[0]->setIcon(koIcon("transparency-unlocked")); + m_alphaLockButton->actions()[0]->setIcon(KisIconUtils::loadIcon("transparency-unlocked")); } toggleHighlightedButton(m_alphaLockButton); m_resourceProvider->setGlobalAlphaLock(checked); } void KisPaintopBox::toggleHighlightedButton(QToolButton* m_tool) { QPalette p = palette(); if (m_tool->isChecked()) { QPalette palette_highlight(p); palette_highlight.setColor(QPalette::Button, p.color(QPalette::Highlight)); m_tool->setPalette(palette_highlight); } else { m_tool->setPalette(p); } } void KisPaintopBox::slotReloadPreset() { KisSignalsBlocker blocker(m_optionWidget); //Here using the name and fetching the preset from the server was the only way the load was working. Otherwise it was not loading. KisPaintOpPresetResourceServer * rserver = KisResourceServerProvider::instance()->paintOpPresetServer(); KisPaintOpPresetSP preset = rserver->resourceByName(m_resourceProvider->currentPreset()->name()); if (preset) { preset->load(); preset->settings()->setOptionsWidget(m_optionWidget); m_optionWidget->setConfiguration(preset->settings()); m_presetsPopup->resourceSelected(preset.data()); } slotUpdatePreset(); } void KisPaintopBox::slotConfigurationItemChanged() // Called only when UI is changed and not when preset is changed { m_optionWidget->writeConfiguration(const_cast(m_resourceProvider->currentPreset()->settings().data())); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); m_presetsPopup->updateViewSettings(); } void KisPaintopBox::slotSaveLockedOptionToPreset(KisPropertiesConfiguration* p) { QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); m_resourceProvider->currentPreset()->settings()->setProperty(i.key(), QVariant(i.value())); if (m_resourceProvider->currentPreset()->settings()->hasProperty(i.key() + "_previous")) { m_resourceProvider->currentPreset()->settings()->removeProperty(i.key() + "_previous"); } } slotConfigurationItemChanged(); } void KisPaintopBox::slotDropLockedOption(KisPropertiesConfiguration* p) { KisSignalsBlocker blocker(m_optionWidget); KisPaintOpPresetSP preset = m_resourceProvider->currentPreset(); { KisPaintOpPreset::DirtyStateSaver dirtySaver(preset.data()); QMapIterator i(p->getProperties()); while (i.hasNext()) { i.next(); if (preset->settings()->hasProperty(i.key() + "_previous")) { preset->settings()->setProperty(i.key(), preset->settings()->getProperty(i.key() + "_previous")); preset->settings()->removeProperty(i.key() + "_previous"); } } m_optionWidget->setConfiguration(preset->settings()); } slotUpdatePreset(); } void KisPaintopBox::slotDirtyPresetToggled(bool value) { if (!value) { slotReloadPreset(); m_presetsPopup->resourceSelected(m_resourceProvider->currentPreset().data()); m_presetsPopup->updateViewSettings(); } m_dirtyPresetsEnabled = value; KisConfig cfg; cfg.setUseDirtyPresets(m_dirtyPresetsEnabled); } void KisPaintopBox::slotEraserBrushSizeToggled(bool value) { m_eraserBrushSizeEnabled = value; KisConfig cfg; cfg.setUseEraserBrushSize(m_eraserBrushSizeEnabled); } void KisPaintopBox::slotUpdateSelectionIcon() { - m_hMirrorAction->setIcon(themedIcon("symmetry-horizontal")); - m_vMirrorAction->setIcon(themedIcon("symmetry-vertical")); + m_hMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-horizontal")); + m_vMirrorAction->setIcon(KisIconUtils::loadIcon("symmetry-vertical")); } diff --git a/krita/ui/kis_paintop_box.h b/krita/ui/kis_paintop_box.h index 5eb3f01899e..fcddd6c04e9 100644 --- a/krita/ui/kis_paintop_box.h +++ b/krita/ui/kis_paintop_box.h @@ -1,249 +1,249 @@ /* * kis_paintop_box.h - part of KImageShop/Krayon/Krita * * Copyright (c) 2004-2008 Boudewijn Rempt (boud@valdyas.org) * Copyright (C) 2011 Silvio Heinrich * * 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 #include #include #include #include #include #include #include "kis_locked_properties_proxy.h" #include "kis_locked_properties_server.h" #include "kis_locked_properties.h" #include "kis_config.h" -#include "krita_export.h" +#include "kritaui_export.h" class QToolButton; class QString; class QHBoxLayout; class KoColorSpace; class KoResource; class KoCanvasController; class KisViewManager; class KisCanvasResourceProvider; class KisPopupButton; class KisToolOptionsPopup; class KisPaintOpPresetsPopup; class KisPaintOpPresetsChooserPopup; class KisPaintOpConfigWidget; class KisCompositeOpComboBox; class KisWidgetChooser; class KisFavoriteResourceManager; class KisLockedProperties; class KisAction; /** * 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. * * To incorporate the dirty preset functionality and locked settings * the following slots are added * void slotReloadPreset(); void slotConfigurationItemChanged(); void slotSaveLockedOptionToPreset(KisPropertiesConfiguration* p); void slotDropLockedOption(KisPropertiesConfiguration* p); void slotDirtyPresetToggled(bool); Everytime a value is changed in a preset, the preset is made dirty through the onChange() function. For Locked Settings however, a changed Locked Setting will not cause a preset to become dirty. That is becuase it borrows its values from the KisLockedPropertiesServer. Hence the dirty state of the Preset is kept consistent before and after a writeConfiguration operation in most cases. * 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 KRITAUI_EXPORT KisPaintopBox : public QWidget { Q_OBJECT enum { ENABLE_PRESETS = 0x0001, DISABLE_PRESETS = 0x0002, ENABLE_COMPOSITEOP = 0x0004, DISABLE_COMPOSITEOP = 0x0008, ENABLE_OPACITY = 0x0010, DISABLE_OPACITY = 0x0020, ENABLE_FLOW = 0x0040, DISABLE_FLOW = 0x0080, ENABLE_SIZE = 0x0100, DISABLE_SIZE = 0x0200, ENABLE_ALL = 0x5555, DISABLE_ALL = 0xAAAA }; public: KisPaintopBox(KisViewManager* view, QWidget* parent, const char* name); ~KisPaintopBox(); void restoreResource(KoResource* resource); /** * Update the option widgets to the argument ones, removing the currently set widgets. */ void newOptionWidgets(const QList > & optionWidgetList); public Q_SLOTS: void slotColorSpaceChanged(const KoColorSpace* colorSpace); void slotInputDeviceChanged(const KoInputDevice & inputDevice); void slotCanvasResourceChanged(int key, const QVariant& v); void resourceSelected(KoResource* resource); KisFavoriteResourceManager *favoriteResourcesManager() { return m_favoriteResourceManager; } private: KoID currentPaintop(); void setCurrentPaintop(const KoID& paintop, KisPaintOpPresetSP preset = 0); void setCurrentPaintopAndReload(const KoID& paintop, KisPaintOpPresetSP preset); QPixmap paintopPixmap(const KoID& paintop); KoID defaultPaintOp(); KisPaintOpPresetSP defaultPreset(const KoID& paintOp); KisPaintOpPresetSP activePreset(const KoID& paintOp); void updateCompositeOp(QString compositeOpID, bool localUpdate = false); void setWidgetState(int flags); void setSliderValue(const QString& sliderID, qreal value); void sliderChanged(int n); private Q_SLOTS: void slotSaveActivePreset(); void slotUpdatePreset(); void slotSetupDefaultPreset(); void slotNodeChanged(const KisNodeSP node); void slotToggleEraseMode(bool checked); void slotSetCompositeMode(int index); void slotSetPaintop(const QString& paintOpId); void slotHorizontalMirrorChanged(bool value); void slotVerticalMirrorChanged(bool value); void slotSlider1Changed(); void slotSlider2Changed(); void slotSlider3Changed(); void slotToolChanged(KoCanvasController* canvas, int toolId); void slotOpacityChanged(qreal); void slotPreviousFavoritePreset(); void slotNextFavoritePreset(); void slotSwitchToPreviousPreset(); void slotUnsetEraseMode(); void slotToggleAlphaLockMode(bool); void toggleHighlightedButton(QToolButton* m_tool); void slotReloadPreset(); void slotConfigurationItemChanged(); void slotSaveLockedOptionToPreset(KisPropertiesConfiguration* p); void slotDropLockedOption(KisPropertiesConfiguration* p); void slotDirtyPresetToggled(bool); void slotEraserBrushSizeToggled(bool); void slotUpdateSelectionIcon(); private: KisCanvasResourceProvider* m_resourceProvider; QHBoxLayout* m_layout; QWidget* m_paintopWidget; KisPaintOpConfigWidget* m_optionWidget; KisPopupButton* m_toolOptionsPopupButton; KisPopupButton* m_brushEditorPopupButton; KisPopupButton* m_presetSelectorPopupButton; KisCompositeOpComboBox* m_cmbCompositeOp; QToolButton* m_eraseModeButton; QToolButton* m_alphaLockButton; QToolButton* m_hMirrorButton; QToolButton* m_vMirrorButton; KisToolOptionsPopup* m_toolOptionsPopup; KisPaintOpPresetsPopup* m_presetsPopup; KisPaintOpPresetsChooserPopup* m_presetsChooserPopup; KisViewManager* m_viewManager; KisPopupButton* m_workspaceWidget; KisWidgetChooser* m_sliderChooser[3]; QMap m_paintopOptionWidgets; KisFavoriteResourceManager* m_favoriteResourceManager; QToolButton* m_reloadButton; QString m_prevCompositeOpID; QString m_currCompositeOpID; KisNodeWSP m_previousNode; - int normalBrushSize; // when toggling between eraser mode - int eraserBrushSize; + qreal normalBrushSize; // when toggling between eraser mode + qreal eraserBrushSize; KisAction* m_hMirrorAction; KisAction* m_vMirrorAction; struct TabletToolID { TabletToolID(const KoInputDevice& dev) { uniqueID = dev.uniqueTabletId(); // Only the eraser is special, and we don't look at Cursor pointer = QTabletEvent::Pen; if (dev.pointer() == QTabletEvent::Eraser) { pointer = QTabletEvent::Eraser; } } bool operator == (const TabletToolID& id) const { return pointer == id.pointer && uniqueID == id.uniqueID; } bool operator < (const TabletToolID& id) const { if (uniqueID == id.uniqueID) return pointer < id.pointer; return uniqueID < id.uniqueID; } QTabletEvent::PointerType pointer; qint64 uniqueID; }; struct TabletToolData { KoID paintOpID; KisPaintOpPresetSP preset; }; typedef QMap TabletToolMap; typedef QMap PaintOpPresetMap; TabletToolMap m_tabletToolMap; PaintOpPresetMap m_paintOpPresetMap; TabletToolID m_currTabletToolID; bool m_presetsEnabled; bool m_blockUpdate; bool m_dirtyPresetsEnabled; bool m_eraserBrushSizeEnabled; }; #endif //KIS_PAINTOP_BOX_H_ diff --git a/krita/ui/kis_paintop_option.h b/krita/ui/kis_paintop_option.h index b3f32194409..fa524266ea6 100644 --- a/krita/ui/kis_paintop_option.h +++ b/krita/ui/kis_paintop_option.h @@ -1,115 +1,115 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PAINTOP_OPTION_H #define KIS_PAINTOP_OPTION_H #include -#include +#include #include #include class QWidget; class QString; /** * Base interface for paintop options. A paintop option * can be enabled/disabled, has a configuration page * (for example, a curve), a user-visible name and can * be serialized and deserialized into KisPaintOpPresets * * Options are disabled by default. */ class KRITAUI_EXPORT KisPaintOpOption : public QObject { Q_OBJECT public: enum PaintopCategory { GENERAL, COLOR, TEXTURE, FILTER }; KisPaintOpOption(KisPaintOpOption::PaintopCategory category, bool checked); virtual ~KisPaintOpOption(); KisPaintOpOption::PaintopCategory category() const; virtual bool isCheckable() const; virtual bool isChecked() const; virtual void setChecked(bool checked); void setLocked(bool value); bool isLocked() const; /** * Reimplement this to use the image in the option widget */ virtual void setImage(KisImageWSP image); virtual void setNode(KisNodeWSP node); void startReadOptionSetting(const KisPropertiesConfiguration* setting); void startWriteOptionSetting(KisPropertiesConfiguration* setting) const; QWidget* configurationPage() const; protected: void setConfigurationPage(QWidget * page); protected: /** * Re-implement this to save the configuration to the paint configuration. */ virtual void writeOptionSetting(KisPropertiesConfiguration* setting) const { Q_UNUSED(setting); } /** * Re-implement this to set te widgets with the values in @param setting. */ virtual void readOptionSetting(const KisPropertiesConfiguration* setting) { Q_UNUSED(setting); } protected Q_SLOTS: void emitSettingChanged(); Q_SIGNALS: /** * emit this whenever a setting has changed. It will update the preview */ void sigSettingChanged(); protected: bool m_checkable; bool m_locked; private: struct Private; Private* const m_d; }; #endif diff --git a/krita/ui/kis_paintop_options_model.h b/krita/ui/kis_paintop_options_model.h index 9938e61d2e7..00c97919a59 100644 --- a/krita/ui/kis_paintop_options_model.h +++ b/krita/ui/kis_paintop_options_model.h @@ -1,76 +1,76 @@ /* This file is part of the KDE project * Copyright (c) 2010 Cyrille Berger * Copyright (c) 2011 Silvio Heinrich * * 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_PAINTOP_OPTION_LIST_MODEL_H_ #define _KIS_PAINTOP_OPTION_LIST_MODEL_H_ #include #include -#include +#include #include struct KRITAUI_EXPORT KisOptionInfo { KisOptionInfo() : option(0) {} KisOptionInfo(KisPaintOpOption* o, int i, const QString &label) : label(label) , option(o) , index(i) {} KisOptionInfo(const KisOptionInfo& info) : label(info.label) , option(info.option) , index(info.index) {} QString label; KisPaintOpOption *option; int index; }; KRITAUI_EXPORT bool operator==(const KisOptionInfo& a, const KisOptionInfo& b); struct KRITAUI_EXPORT OptionInfoToQStringConverter { QString operator() (const KisOptionInfo &info) { return info.label; } }; typedef KisCategorizedListModel BaseOptionCategorizedListModel; /** * This model can be use to show a list of visible composite op in a list view. */ class KRITAUI_EXPORT KisPaintOpOptionListModel : public BaseOptionCategorizedListModel { public: KisPaintOpOptionListModel(QObject *parent); void addPaintOpOption(KisPaintOpOption* option, int widgetIndex, const QString &label); QVariant data(const QModelIndex& idx, int role = Qt::DisplayRole) const; bool setData(const QModelIndex& idx, const QVariant& value, int role=Qt::EditRole); void signalDataChanged(const QModelIndex& index); }; #endif // _KIS_PAINTOP_OPTION_LIST_MODEL_H_ diff --git a/krita/ui/kis_paintop_settings_widget.h b/krita/ui/kis_paintop_settings_widget.h index 3b199acb504..9f0739cefc5 100644 --- a/krita/ui/kis_paintop_settings_widget.h +++ b/krita/ui/kis_paintop_settings_widget.h @@ -1,77 +1,77 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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_PAINTOP_SETTINGS_WIDGET_H #define KIS_PAINTOP_SETTINGS_WIDGET_H -#include +#include #include class KisPaintOpOption; class KisPropertiesConfiguration; class KisPaintOpConfigWidget; /** * A common widget for enabling/disabling and determining * the effect of tablet pressure, tilt and rotation and * other paintop settings. */ class KRITAUI_EXPORT KisPaintOpSettingsWidget : public KisPaintOpConfigWidget { Q_OBJECT public: KisPaintOpSettingsWidget(QWidget * parent = 0); ~KisPaintOpSettingsWidget(); void addPaintOpOption(KisPaintOpOption * option, const QString &label); /// Reimplemented virtual void setConfiguration(const KisPropertiesConfiguration * config); /// Reimplemented virtual void writeConfiguration(KisPropertiesConfiguration *config) const; ///Reimplemented, sets image on option widgets virtual void setImage(KisImageWSP image); ///Reimplemented, sets node on option widgets virtual void setNode(KisNodeWSP node); private Q_SLOTS: void changePage(const QModelIndex&); void lockProperties(const QModelIndex& index); void slotLockPropertiesDrop(); void slotLockPropertiesSave(); void slotEntryChecked(const QModelIndex &index); protected: virtual void notifyPageChanged(); private: struct Private; Private* const m_d; bool m_saveLockedOption; }; #endif diff --git a/krita/ui/kis_png_converter.h b/krita/ui/kis_png_converter.h index e896befb7c1..73f7d17c350 100644 --- a/krita/ui/kis_png_converter.h +++ b/krita/ui/kis_png_converter.h @@ -1,150 +1,150 @@ /* * Copyright (c) 2005, 2007 Cyrille Berger * * 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_PNG_CONVERTER_H_ #define _KIS_PNG_CONVERTER_H_ #include #include #include #include "kis_types.h" #include "kis_global.h" #include "kis_annotation.h" -#include +#include class KoStore; class KisDocument; namespace KisMetaData { class Filter; class Store; } struct KisPNGOptions { KisPNGOptions() : compression(0) , interlace(false) , alpha(true) , exif(true) , iptc(true) , xmp(true) , tryToSaveAsIndexed(true) , saveSRGBProfile(false) , forceSRGB(false) , transparencyFillColor(Qt::white) {} int compression; bool interlace; bool alpha; bool exif; bool iptc; bool xmp; bool tryToSaveAsIndexed; bool saveSRGBProfile; bool forceSRGB; QList filters; QColor transparencyFillColor; }; /** * Image import/export plugins can use these results to report about success or failure. */ enum KisImageBuilder_Result { KisImageBuilder_RESULT_FAILURE = -400, KisImageBuilder_RESULT_NOT_EXIST = -300, KisImageBuilder_RESULT_NOT_LOCAL = -200, KisImageBuilder_RESULT_BAD_FETCH = -100, KisImageBuilder_RESULT_INVALID_ARG = -50, KisImageBuilder_RESULT_OK = 0, KisImageBuilder_RESULT_PROGRESS = 1, KisImageBuilder_RESULT_EMPTY = 100, KisImageBuilder_RESULT_BUSY = 150, KisImageBuilder_RESULT_NO_URI = 200, KisImageBuilder_RESULT_UNSUPPORTED = 300, KisImageBuilder_RESULT_INTR = 400, KisImageBuilder_RESULT_PATH = 500, KisImageBuilder_RESULT_UNSUPPORTED_COLORSPACE = 600 }; /** * This class allows to import/export a PNG from either a file or a QIODevice. */ // XXX_PROGRESS (pass KoUpdater to the png converter) class KRITAUI_EXPORT KisPNGConverter : public QObject { Q_OBJECT public: /** * Initialize the converter. * @param doc the KisDocument related to the image, can be null if you don't have a KisDocument * @param adapter the undo adapter to be used by the image, can be null if you don't want to use an undo adapter */ KisPNGConverter(KisDocument *doc, bool batchMode = false); virtual ~KisPNGConverter(); public: /** * Load an image from an URL. If the image is not on a local drive, the image is first downloaded to a * temporary location. * @param uri the url of the image */ KisImageBuilder_Result buildImage(const KUrl& uri); /** * Load an image from a QIODevice. * @param iod device to access the data */ KisImageBuilder_Result buildImage(QIODevice* iod); /** * Save a layer to a PNG * @param uri the url of the destination file * @param device the paint device to save * @param annotationsStart an iterator on the first annotation * @param annotationsEnd an iterator on the last annotation * @param compression a number between 0 and 9 to specify the compression rate (9 is most compressed) * @param interlace set to true if you want to generate an interlaced png * @param alpha set to true if you want to save the alpha channel */ KisImageBuilder_Result buildFile(const KUrl& uri, KisImageWSP image, KisPaintDeviceSP device, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisPNGOptions options, KisMetaData::Store* metaData); KisImageBuilder_Result buildFile(QIODevice*, KisImageWSP image, KisPaintDeviceSP device, vKisAnnotationSP_it annotationsStart, vKisAnnotationSP_it annotationsEnd, KisPNGOptions options, KisMetaData::Store* metaData); /** * Retrieve the constructed image */ KisImageWSP image(); static bool saveDeviceToStore(const QString &filename, KisImageWSP image, KisPaintDeviceSP dev, KoStore *store, KisMetaData::Store* metaData = 0); public Q_SLOTS: virtual void cancel(); private: void progress(png_structp png_ptr, png_uint_32 row_number, int pass); private: png_uint_32 m_max_row; KisImageWSP m_image; KisDocument *m_doc; bool m_stop; bool m_batchMode; QString m_path; }; #endif diff --git a/krita/ui/kis_preference_set_registry.h b/krita/ui/kis_preference_set_registry.h index d2c4f8842eb..31ae07aa13c 100644 --- a/krita/ui/kis_preference_set_registry.h +++ b/krita/ui/kis_preference_set_registry.h @@ -1,75 +1,75 @@ /* * Copyright (c) 2010 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_PREFERENCE_SET_REGISTRY_H_ #define KIS_PREFERENCE_SET_REGISTRY_H_ #include #include #include #include "KoGenericRegistry.h" #include "kis_types.h" -#include +#include class KIcon; /** * Implement this abstract class to provide a preferences pane for the preferences dialog. */ class KRITAUI_EXPORT KisPreferenceSet : public QWidget { Q_OBJECT public: KisPreferenceSet(QWidget* parent=0) : QWidget(parent) {} virtual QString id() = 0; virtual QString name() = 0; virtual QString header() = 0; virtual KIcon icon() = 0; public Q_SLOTS: virtual void savePreferences() const = 0; virtual void loadPreferences() = 0; virtual void loadDefaultPreferences() = 0; }; class KRITAUI_EXPORT KisAbstractPreferenceSetFactory { public: virtual ~KisAbstractPreferenceSetFactory() {} virtual KisPreferenceSet* createPreferenceSet() = 0; virtual QString id() const = 0; }; /** * This registry does not load the plugins itself: plugins with preferences panes should * add those panes when they are loaded themselves. */ class KRITAUI_EXPORT KisPreferenceSetRegistry : public QObject, public KoGenericRegistry { public: virtual ~KisPreferenceSetRegistry(); static KisPreferenceSetRegistry * instance(); private: KisPreferenceSetRegistry(); Q_DISABLE_COPY(KisPreferenceSetRegistry) }; #endif // KIS_PREFERENCE_SETSPACE_REGISTRY_H_ diff --git a/krita/ui/kis_psd_layer_style_resource.h b/krita/ui/kis_psd_layer_style_resource.h index e2e92f1b003..24fbac6ad6a 100644 --- a/krita/ui/kis_psd_layer_style_resource.h +++ b/krita/ui/kis_psd_layer_style_resource.h @@ -1,63 +1,63 @@ /* * Copyright (c) 2014 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_PSD_LAYER_STYLE_RESOURCE_H #define KIS_PSD_LAYER_STYLE_RESOURCE_H #include #include -#include +#include #include "kis_psd_layer_style.h" /** * @brief The KisPSDLayerStyleResource class represents an ASL file type resource. */ class KRITAUI_EXPORT KisPSDLayerStyleCollectionResource : public KoResource { public: typedef QVector StylesVector; public: explicit KisPSDLayerStyleCollectionResource(const QString &filename); virtual ~KisPSDLayerStyleCollectionResource(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice *dev) const; virtual QString defaultFileExtension() const; StylesVector layerStyles() const; void setLayerStyles(StylesVector styles); void collectAllLayerStyles(KisNodeSP root); void assignAllLayerStyles(KisNodeSP root); protected: virtual QByteArray generateMD5() const; private: StylesVector m_layerStyles; }; #endif // KIS_PSD_LAYER_STYLE_RESOURCE_H diff --git a/krita/ui/kis_resource_server_provider.h b/krita/ui/kis_resource_server_provider.h index a4660c563c8..038b2344387 100644 --- a/krita/ui/kis_resource_server_provider.h +++ b/krita/ui/kis_resource_server_provider.h @@ -1,76 +1,76 @@ /* * kis_resource_server_provider.h - part of KImageShop * * Copyright (c) 1999 Matthias Elter * Copyright (c) 2003 Patrick Julien * Copyright (c) 2005 Sven Langkamp * Copyright (c) 2003-2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_RESOURCESERVERPROVIDER_H_ #define KIS_RESOURCESERVERPROVIDER_H_ #include #include #include -#include +#include "kritaui_export.h" class KoResourceLoaderThread; class KisWorkspaceResource; class KisPSDLayerStyleCollectionResource; typedef KoResourceServerSimpleConstruction > KisPaintOpPresetResourceServer; typedef KoResourceServerAdapter > KisPaintOpPresetResourceServerAdapter; class KRITAUI_EXPORT KisResourceServerProvider : public QObject { Q_OBJECT public: virtual ~KisResourceServerProvider(); static KisResourceServerProvider* instance(); KisPaintOpPresetResourceServer* paintOpPresetServer(bool block = true); KoResourceServer* workspaceServer(bool block = true); KoResourceServer* layerStyleCollectionServer(bool block = true); void brushBlacklistCleanup(); Q_SIGNALS: void notifyBrushBlacklistCleanup(); private: KisResourceServerProvider(); KisResourceServerProvider(const KisResourceServerProvider&); KisResourceServerProvider operator=(const KisResourceServerProvider&); KisPaintOpPresetResourceServer* m_paintOpPresetServer; KoResourceServer* m_workspaceServer; KoResourceServer* m_layerStyleCollectionServer; private: KoResourceLoaderThread *m_paintOpPresetThread; KoResourceLoaderThread *m_workspaceThread; KoResourceLoaderThread *m_layerStyleCollectionThread; }; #endif // KIS_RESOURCESERVERPROVIDER_H_ diff --git a/krita/ui/kis_safe_document_loader.cpp b/krita/ui/kis_safe_document_loader.cpp index 42f51fa157c..cfeec1f3071 100644 --- a/krita/ui/kis_safe_document_loader.cpp +++ b/krita/ui/kis_safe_document_loader.cpp @@ -1,172 +1,173 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_safe_document_loader.h" #include #include #include #include #include "KisDocument.h" #include "kis_image.h" #include "kis_signal_compressor.h" #include "KisPart.h" struct KisSafeDocumentLoader::Private { Private() : fileChangedSignalCompressor(500 /* ms */, KisSignalCompressor::POSTPONE), isLoading(false), fileChangedFlag(false) { } QScopedPointer doc; QFileSystemWatcher fileWatcher; KisSignalCompressor fileChangedSignalCompressor; QTimer delayedLoadTimer; bool isLoading; bool fileChangedFlag; QString path; QString temporaryPath; qint64 initialFileSize; QDateTime initialFileTimeStamp; }; KisSafeDocumentLoader::KisSafeDocumentLoader(const QString &path, QObject *parent) : QObject(parent), m_d(new Private()) { connect(&m_d->fileWatcher, SIGNAL(fileChanged(QString)), SLOT(fileChanged())); connect(&m_d->fileWatcher, SIGNAL(fileChanged(QString)), &m_d->fileChangedSignalCompressor, SLOT(start())); connect(&m_d->fileChangedSignalCompressor, SIGNAL(timeout()), SLOT(fileChangedCompressed())); connect(&m_d->delayedLoadTimer, SIGNAL(timeout()), SLOT(delayedLoadStart())); m_d->delayedLoadTimer.setSingleShot(true); m_d->delayedLoadTimer.setInterval(100 /* ms */); setPath(path); } KisSafeDocumentLoader::~KisSafeDocumentLoader() { delete m_d; } void KisSafeDocumentLoader::setPath(const QString &path) { if (path.isEmpty()) return; if (!m_d->path.isEmpty()) { m_d->fileWatcher.removePath(m_d->path); } m_d->path = path; m_d->fileWatcher.addPath(m_d->path); } void KisSafeDocumentLoader::reloadImage() { fileChangedCompressed(true); } void KisSafeDocumentLoader::fileChanged() { m_d->fileChangedFlag = true; } void KisSafeDocumentLoader::fileChangedCompressed(bool sync) { if (m_d->isLoading) return; QFileInfo initialFileInfo(m_d->path); m_d->initialFileSize = initialFileInfo.size(); m_d->initialFileTimeStamp = initialFileInfo.lastModified(); // it may happen when the file is flushed by // so other application if (!m_d->initialFileSize) return; m_d->isLoading = true; m_d->fileChangedFlag = false; m_d->temporaryPath = QDir::tempPath() + QDir::separator() + QString("krita_file_layer_copy_%1_%2.%3") .arg(QApplication::applicationPid()) .arg(qrand()) .arg(initialFileInfo.suffix()); QFile::copy(m_d->path, m_d->temporaryPath); if (!sync) { m_d->delayedLoadTimer.start(); } else { QApplication::processEvents(); delayedLoadStart(); } } void KisSafeDocumentLoader::delayedLoadStart() { QFileInfo originalInfo(m_d->path); QFileInfo tempInfo(m_d->temporaryPath); bool successfullyLoaded = false; if (!m_d->fileChangedFlag && originalInfo.size() == m_d->initialFileSize && originalInfo.lastModified() == m_d->initialFileTimeStamp && tempInfo.size() == m_d->initialFileSize) { m_d->doc.reset(KisPart::instance()->createDocument()); - successfullyLoaded = m_d->doc->openUrl(m_d->temporaryPath); + successfullyLoaded = m_d->doc->openUrl(m_d->temporaryPath, + KisDocument::OPEN_URL_FLAG_DO_NOT_ADD_TO_RECENT_FILES); } else { qDebug() << "File was modified externally. Restarting."; qDebug() << ppVar(m_d->fileChangedFlag); qDebug() << ppVar(m_d->initialFileSize); qDebug() << ppVar(m_d->initialFileTimeStamp); qDebug() << ppVar(originalInfo.size()); qDebug() << ppVar(originalInfo.lastModified()); qDebug() << ppVar(tempInfo.size()); } QFile::remove(m_d->temporaryPath); m_d->isLoading = false; if (!successfullyLoaded) { // Restart the attempt m_d->fileChangedSignalCompressor.start(); } else { emit loadingFinished(m_d->doc->image()); } m_d->doc.reset(); } diff --git a/krita/ui/kis_selection_manager.cc b/krita/ui/kis_selection_manager.cc index 657a367eaf2..4b100e39757 100644 --- a/krita/ui/kis_selection_manager.cc +++ b/krita/ui/kis_selection_manager.cc @@ -1,620 +1,658 @@ /* * Copyright (c) 2004 Boudewijn Rempt * Copyright (c) 2007 Sven Langkamp * * The outline algorith uses the limn algorithm of fontutils by * Karl Berry and Kathryn Hargreaves * * 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_selection_manager.h" #include #include #include #include #include #include #include #include #include #include "KoCanvasController.h" #include "KoChannelInfo.h" #include "KoIntegerMaths.h" #include #include #include #include #include #include #include #include #include #include #include #include "kis_adjustment_layer.h" #include "kis_node_manager.h" #include "canvas/kis_canvas2.h" #include "kis_config.h" #include "kis_convolution_painter.h" #include "kis_convolution_kernel.h" #include "kis_debug.h" #include "KisDocument.h" #include "kis_fill_painter.h" #include "kis_group_layer.h" #include "kis_image.h" #include "kis_layer.h" #include "kis_statusbar.h" #include "kis_paint_device.h" #include "kis_paint_layer.h" #include "kis_painter.h" #include "kis_transaction.h" #include "kis_selection.h" #include "kis_types.h" #include "kis_canvas_resource_provider.h" #include "kis_undo_adapter.h" #include "kis_pixel_selection.h" #include "flake/kis_shape_selection.h" #include "commands/kis_selection_commands.h" #include "kis_selection_mask.h" #include "flake/kis_shape_layer.h" #include "kis_selection_decoration.h" #include "canvas/kis_canvas_decoration.h" #include "kis_node_commands_adapter.h" #include "kis_iterator_ng.h" #include "kis_clipboard.h" #include "KisViewManager.h" #include "kis_selection_filters.h" #include "kis_figure_painting_tool_helper.h" #include "KisView.h" #include "actions/kis_selection_action_factories.h" #include "kis_action.h" #include "kis_action_manager.h" #include "operations/kis_operation_configuration.h" KisSelectionManager::KisSelectionManager(KisViewManager * view) : m_view(view), m_doc(0), m_imageView(0), m_adapter(new KisNodeCommandsAdapter(view)), m_copy(0), m_copyMerged(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_copyToNewLayer(0), m_fillForegroundColor(0), m_fillBackgroundColor(0), m_fillPattern(0), m_imageResizeToSelection(0), m_selectionDecoration(0) { m_clipboard = KisClipboard::instance(); } KisSelectionManager::~KisSelectionManager() { } void KisSelectionManager::setup(KisActionManager* actionManager) { m_cut = actionManager->createStandardAction(KStandardAction::Cut, this, SLOT(cut())); m_copy = actionManager->createStandardAction(KStandardAction::Copy, this, SLOT(copy())); m_paste = actionManager->createStandardAction(KStandardAction::Paste, this, SLOT(paste())); KisAction *copySharp = new KisAction(i18n("Copy (sharp)"), this); copySharp->setActivationFlags(KisAction::PIXELS_SELECTED); actionManager->addAction("copy_sharp", copySharp); connect(copySharp, SIGNAL(triggered()), this, SLOT(copySharp())); KisAction *cutSharp = new KisAction(i18n("Cut (sharp)"), this); cutSharp->setActivationFlags(KisAction::PIXELS_SELECTED); actionManager->addAction("cut_sharp", cutSharp); connect(cutSharp, SIGNAL(triggered()), this, SLOT(cutSharp())); m_pasteNew = new KisAction(i18n("Paste into &New Image"), this); actionManager->addAction("paste_new", m_pasteNew); m_pasteNew->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_N)); connect(m_pasteNew, SIGNAL(triggered()), this, SLOT(pasteNew())); m_pasteAt = new KisAction(i18n("Paste at cursor"), this); actionManager->addAction("paste_at", m_pasteAt); connect(m_pasteAt, SIGNAL(triggered()), this, SLOT(pasteAt())); m_copyMerged = new KisAction(i18n("Copy merged"), this); m_copyMerged->setActivationFlags(KisAction::PIXELS_SELECTED); actionManager->addAction("copy_merged", m_copyMerged); m_copyMerged->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_C)); connect(m_copyMerged, SIGNAL(triggered()), this, SLOT(copyMerged())); m_selectAll = new KisAction(themedIcon("select-all"), i18n("Select &All"), this); actionManager->addAction("select_all", m_selectAll); m_selectAll->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_A)); connect(m_selectAll, SIGNAL(triggered()), this, SLOT(selectAll())); - m_deselect = new KisAction(themedIcon("select-all"), i18n("Deselect"), this); + m_deselect = new KisAction(themedIcon("select-clear"), i18n("Deselect"), this); m_deselect->setActivationFlags(KisAction::PIXELS_SELECTED | KisAction::SHAPES_SELECTED); actionManager->addAction("deselect", m_deselect); m_deselect->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_A)); connect(m_deselect, SIGNAL(triggered()), this, SLOT(deselect())); m_clear = new KisAction(themedIcon("select-clear"), i18n("Clear"), this); m_clear->setActivationFlags(KisAction::ACTIVE_IMAGE); actionManager->addAction("clear", m_clear); m_clear->setShortcut(QKeySequence((Qt::Key_Delete))); connect(m_clear, SIGNAL(triggered()), SLOT(clear())); m_reselect = new KisAction(i18n("&Reselect"), this); actionManager->addAction("reselect", m_reselect); m_reselect->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_D)); connect(m_reselect, SIGNAL(triggered()), this, SLOT(reselect())); m_invert = new KisAction(i18n("&Invert Selection"), this); m_invert->setActivationFlags(KisAction::PIXEL_SELECTION_WITH_PIXELS); m_invert->setActivationConditions(KisAction::SELECTION_EDITABLE); m_invert->setOperationID("invertselection"); m_invert->setToolTip("foo"); actionManager->addAction("invert", m_invert); m_invert->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_I)); actionManager->registerOperation(new KisInvertSelectionOperaton); m_copyToNewLayer = new KisAction(i18n("Copy Selection to New Layer"), this); m_copyToNewLayer->setActivationFlags(KisAction::PIXELS_SELECTED); actionManager->addAction("copy_selection_to_new_layer", m_copyToNewLayer); m_copyToNewLayer->setShortcut(QKeySequence(Qt::CTRL + Qt::ALT + Qt::Key_J)); connect(m_copyToNewLayer, SIGNAL(triggered()), this, SLOT(copySelectionToNewLayer())); m_cutToNewLayer = new KisAction(i18n("Cut Selection to New Layer"), this); m_cutToNewLayer->setActivationFlags(KisAction::PIXELS_SELECTED); m_cutToNewLayer->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("cut_selection_to_new_layer", m_cutToNewLayer); m_cutToNewLayer->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_J)); connect(m_cutToNewLayer, SIGNAL(triggered()), this, SLOT(cutToNewLayer())); m_fillForegroundColor = new KisAction(i18n("Fill with Foreground Color"), this); m_fillForegroundColor->setActivationFlags(KisAction::ACTIVE_DEVICE); m_fillForegroundColor->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("fill_selection_foreground_color", m_fillForegroundColor); - m_fillForegroundColor->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Backspace)); + m_fillForegroundColor->setShortcut(QKeySequence(Qt::SHIFT + Qt::Key_Backspace)); connect(m_fillForegroundColor, SIGNAL(triggered()), this, SLOT(fillForegroundColor())); m_fillBackgroundColor = new KisAction(i18n("Fill with Background Color"), this); m_fillBackgroundColor->setActivationFlags(KisAction::ACTIVE_DEVICE); m_fillBackgroundColor->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("fill_selection_background_color", m_fillBackgroundColor); m_fillBackgroundColor->setShortcut(QKeySequence(Qt::Key_Backspace)); connect(m_fillBackgroundColor, SIGNAL(triggered()), this, SLOT(fillBackgroundColor())); m_fillPattern = new KisAction(i18n("Fill with Pattern"), this); m_fillPattern->setActivationFlags(KisAction::ACTIVE_DEVICE); m_fillPattern->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); actionManager->addAction("fill_selection_pattern", m_fillPattern); connect(m_fillPattern, SIGNAL(triggered()), this, SLOT(fillPattern())); + m_fillForegroundColorOpacity = new KisAction(i18n("Fill with Foreground Color (Opacity)"), this); + m_fillForegroundColorOpacity->setActivationFlags(KisAction::ACTIVE_DEVICE); + m_fillForegroundColorOpacity->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); + actionManager->addAction("fill_selection_foreground_color_opacity", m_fillForegroundColorOpacity); + m_fillForegroundColorOpacity->setShortcut(QKeySequence(Qt::CTRL + Qt::SHIFT + Qt::Key_Backspace)); + connect(m_fillForegroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillForegroundColorOpacity())); + + m_fillBackgroundColorOpacity = new KisAction(i18n("Fill with Background Color (Opacity)"), this); + m_fillBackgroundColorOpacity->setActivationFlags(KisAction::ACTIVE_DEVICE); + m_fillBackgroundColorOpacity->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); + actionManager->addAction("fill_selection_background_color_opacity", m_fillBackgroundColorOpacity); + m_fillBackgroundColorOpacity->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_Backspace)); + connect(m_fillBackgroundColorOpacity, SIGNAL(triggered()), this, SLOT(fillBackgroundColorOpacity())); + + m_fillPatternOpacity = new KisAction(i18n("Fill with Pattern (Opacity)"), this); + m_fillPatternOpacity->setActivationFlags(KisAction::ACTIVE_DEVICE); + m_fillPatternOpacity->setActivationConditions(KisAction::ACTIVE_NODE_EDITABLE); + actionManager->addAction("fill_selection_pattern_opacioty", m_fillPatternOpacity); + connect(m_fillPatternOpacity, SIGNAL(triggered()), this, SLOT(fillPatternOpacity())); + m_strokeShapes = new KisAction(i18nc("@action:inmenu", "Stro&ke selected shapes"), this); m_strokeShapes->setActivationFlags(KisAction::SHAPES_SELECTED); actionManager->addAction("stroke_shapes", m_strokeShapes); connect(m_strokeShapes, SIGNAL(triggered()), this, SLOT(paintSelectedShapes())); m_toggleDisplaySelection = new KisAction(i18n("Display Selection"), this); m_toggleDisplaySelection->setCheckable(true); m_toggleDisplaySelection->setActivationFlags(KisAction::ACTIVE_NODE); actionManager->addAction("toggle_display_selection", m_toggleDisplaySelection); m_toggleDisplaySelection->setShortcut(QKeySequence(Qt::CTRL + Qt::Key_H)); connect(m_toggleDisplaySelection, SIGNAL(triggered()), this, SLOT(toggleDisplaySelection())); m_toggleDisplaySelection->setChecked(true); m_imageResizeToSelection = new KisAction(i18n("Trim to Selection"), this); m_imageResizeToSelection->setActivationFlags(KisAction::PIXELS_SELECTED); actionManager->addAction("resizeimagetoselection", m_imageResizeToSelection); connect(m_imageResizeToSelection, SIGNAL(triggered()), this, SLOT(imageResizeToSelection())); KisAction *action = new KisAction(i18nc("@action:inmenu", "&Convert to Vector Selection"), this); action->setActivationFlags(KisAction::PIXEL_SELECTION_WITH_PIXELS); actionManager->addAction("convert_to_vector_selection", action); connect(action, SIGNAL(triggered()), SLOT(convertToVectorSelection())); action = new KisAction(i18nc("@action:inmenu", "Convert &Shapes to Vector Selection"), this); action->setActivationFlags(KisAction::SHAPES_SELECTED); actionManager->addAction("convert_shapes_to_vector_selection", action); connect(action, SIGNAL(triggered()), SLOT(convertShapesToVectorSelection())); action = new KisAction(i18nc("@action:inmenu", "&Convert to Shape"), this); action->setActivationFlags(KisAction::PIXEL_SELECTION_WITH_PIXELS); actionManager->addAction("convert_selection_to_shape", action); connect(action, SIGNAL(triggered()), SLOT(convertToShape())); m_toggleSelectionOverlayMode = new KisAction(i18nc("@action:inmenu", "&Toggle Selection Display Mode"), this); actionManager->addAction("toggle-selection-overlay-mode", m_toggleSelectionOverlayMode); connect(m_toggleSelectionOverlayMode, SIGNAL(triggered()), SLOT(slotToggleSelectionDecoration())); QClipboard *cb = QApplication::clipboard(); connect(cb, SIGNAL(dataChanged()), SLOT(clipboardDataChanged())); } void KisSelectionManager::setView(QPointerimageView) { if (m_imageView && m_imageView->canvasBase()) { disconnect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(const QString&)), this, SLOT(clipboardDataChanged())); KoSelection *selection = m_imageView->canvasBase()->globalShapeManager()->selection(); selection->disconnect(this, SLOT(shapeSelectionChanged())); KisSelectionDecoration *decoration = qobject_cast(m_imageView->canvasBase()->decoration("selection")); if (decoration) { disconnect(SIGNAL(currentSelectionChanged()), decoration); } m_imageView->image()->undoAdapter()->disconnect(this); m_selectionDecoration = 0; } m_imageView = imageView; if (m_imageView) { KoSelection * selection = m_imageView->canvasBase()->globalShapeManager()->selection(); Q_ASSERT(selection); connect(selection, SIGNAL(selectionChanged()), this, SLOT(shapeSelectionChanged())); KisSelectionDecoration* decoration = qobject_cast(m_imageView->canvasBase()->decoration("selection")); if (!decoration) { decoration = new KisSelectionDecoration(m_imageView); decoration->setVisible(true); m_imageView->canvasBase()->addDecoration(decoration); } m_selectionDecoration = decoration; connect(this, SIGNAL(currentSelectionChanged()), decoration, SLOT(selectionChanged())); connect(m_imageView->image()->undoAdapter(), SIGNAL(selectionChanged()), SLOT(selectionChanged())); connect(m_imageView->canvasBase()->toolProxy(), SIGNAL(toolChanged(const QString&)), SLOT(clipboardDataChanged())); } } void KisSelectionManager::clipboardDataChanged() { m_view->updateGUI(); } bool KisSelectionManager::havePixelsSelected() { KisSelectionSP activeSelection = m_view->selection(); return activeSelection && !activeSelection->selectedRect().isEmpty(); } bool KisSelectionManager::havePixelsInClipboard() { return m_clipboard->hasClip(); } bool KisSelectionManager::haveShapesSelected() { if (m_view && m_view->canvasBase() && m_view->canvasBase()->shapeManager() && m_view->canvasBase()->shapeManager()->selection()->count()) { return m_view->canvasBase()->shapeManager()->selection()->count() > 0; } return false; } bool KisSelectionManager::haveShapesInClipboard() { KisShapeLayer *shapeLayer = dynamic_cast(m_view->activeLayer().data()); if (shapeLayer) { const QMimeData* data = QApplication::clipboard()->mimeData(); if (data) { QStringList mimeTypes = m_view->canvasBase()->toolProxy()->supportedPasteMimeTypes(); foreach(const QString & mimeType, mimeTypes) { if (data->hasFormat(mimeType)) { return true; } } } } return false; } bool KisSelectionManager::havePixelSelectionWithPixels() { KisSelectionSP selection = m_view->selection(); if (selection && selection->hasPixelSelection()) { return !selection->pixelSelection()->selectedRect().isEmpty(); } return false; } void KisSelectionManager::updateGUI() { Q_ASSERT(m_view); Q_ASSERT(m_clipboard); if (!m_view || !m_clipboard) return; bool havePixelsSelected = this->havePixelsSelected(); bool havePixelsInClipboard = this->havePixelsInClipboard(); bool haveShapesSelected = this->haveShapesSelected(); bool haveShapesInClipboard = this->haveShapesInClipboard(); bool haveDevice = m_view->activeDevice(); KisLayerSP activeLayer = m_view->activeLayer(); KisImageWSP image = activeLayer ? activeLayer->image() : 0; bool canReselect = image && image->canReselectGlobalSelection(); bool canDeselect = image && image->globalSelection(); m_clear->setEnabled(haveDevice || havePixelsSelected || haveShapesSelected); m_cut->setEnabled(havePixelsSelected || haveShapesSelected); m_copy->setEnabled(havePixelsSelected || haveShapesSelected); m_paste->setEnabled(havePixelsInClipboard || haveShapesInClipboard); m_pasteAt->setEnabled(havePixelsInClipboard || haveShapesInClipboard); // FIXME: how about pasting shapes? m_pasteNew->setEnabled(havePixelsInClipboard); m_selectAll->setEnabled(true); m_deselect->setEnabled(canDeselect); m_reselect->setEnabled(canReselect); // m_load->setEnabled(true); // m_save->setEnabled(havePixelsSelected); updateStatusBar(); emit signalUpdateGUI(); } void KisSelectionManager::updateStatusBar() { if (m_view && m_view->statusBar()) { m_view->statusBar()->setSelection(m_view->image()); } } void KisSelectionManager::selectionChanged() { m_view->updateGUI(); emit currentSelectionChanged(); } void KisSelectionManager::cut() { KisCutCopyActionFactory factory; factory.run(true, false, m_view); } void KisSelectionManager::copy() { KisCutCopyActionFactory factory; factory.run(false, false, m_view); } void KisSelectionManager::cutSharp() { KisCutCopyActionFactory factory; factory.run(true, true, m_view); } void KisSelectionManager::copySharp() { KisCutCopyActionFactory factory; factory.run(false, true, m_view); } void KisSelectionManager::copyMerged() { KisCopyMergedActionFactory factory; factory.run(m_view); } void KisSelectionManager::paste() { KisPasteActionFactory factory; factory.run(m_view); } void KisSelectionManager::pasteAt() { //XXX } void KisSelectionManager::pasteNew() { KisPasteNewActionFactory factory; factory.run(m_view); } void KisSelectionManager::selectAll() { KisSelectAllActionFactory factory; factory.run(m_view); } void KisSelectionManager::deselect() { KisDeselectActionFactory factory; factory.run(m_view); } void KisSelectionManager::invert() { if(m_invert) m_invert->trigger(); } void KisSelectionManager::reselect() { KisReselectActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertToVectorSelection() { KisSelectionToVectorActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertShapesToVectorSelection() { KisShapesToVectorSelectionActionFactory factory; factory.run(m_view); } void KisSelectionManager::convertToShape() { KisSelectionToShapeActionFactory factory; factory.run(m_view); } void KisSelectionManager::clear() { KisClearActionFactory factory; factory.run(m_view); } void KisSelectionManager::fillForegroundColor() { KisFillActionFactory factory; factory.run("fg", m_view); } void KisSelectionManager::fillBackgroundColor() { KisFillActionFactory factory; factory.run("bg", m_view); } void KisSelectionManager::fillPattern() { KisFillActionFactory factory; factory.run("pattern", m_view); } +void KisSelectionManager::fillForegroundColorOpacity() +{ + KisFillActionFactory factory; + factory.run("fg_opacity", m_view); +} + +void KisSelectionManager::fillBackgroundColorOpacity() +{ + KisFillActionFactory factory; + factory.run("bg_opacity", m_view); +} + +void KisSelectionManager::fillPatternOpacity() +{ + KisFillActionFactory factory; + factory.run("pattern_opacity", m_view); +} + void KisSelectionManager::copySelectionToNewLayer() { copy(); paste(); } void KisSelectionManager::cutToNewLayer() { cut(); paste(); } void KisSelectionManager::toggleDisplaySelection() { KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration); m_selectionDecoration->toggleVisibility(); m_toggleDisplaySelection->blockSignals(true); m_toggleDisplaySelection->setChecked(m_selectionDecoration->visible()); m_toggleDisplaySelection->blockSignals(false); emit displaySelectionChanged(); } bool KisSelectionManager::displaySelection() { return m_toggleDisplaySelection->isChecked(); } void KisSelectionManager::shapeSelectionChanged() { KoShapeManager* shapeManager = m_view->canvasBase()->globalShapeManager(); KoSelection * selection = shapeManager->selection(); QList selectedShapes = selection->selectedShapes(); KoShapeStroke* border = new KoShapeStroke(0, Qt::lightGray); foreach(KoShape* shape, shapeManager->shapes()) { if (dynamic_cast(shape->parent())) { if (selectedShapes.contains(shape)) shape->setStroke(border); else shape->setStroke(0); } } m_view->updateGUI(); } void KisSelectionManager::imageResizeToSelection() { KisImageResizeToSelectionActionFactory factory; factory.run(m_view); } void KisSelectionManager::paintSelectedShapes() { KisImageWSP image = m_view->image(); if (!image) return; KisLayerSP layer = m_view->activeLayer(); if (!layer) return; QList shapes = m_view->canvasBase()->shapeManager()->selection()->selectedShapes(); KisPaintLayerSP paintLayer = new KisPaintLayer(image, i18n("Stroked Shapes"), OPACITY_OPAQUE_U8); KUndo2MagicString actionName = kundo2_i18n("Stroke Shapes"); m_adapter->beginMacro(actionName); m_adapter->addNode(paintLayer.data(), layer->parent().data(), layer.data()); KisFigurePaintingToolHelper helper(actionName, image, paintLayer.data(), m_view->resourceProvider()->resourceManager(), KisPainter::StrokeStyleBrush, KisPainter::FillStyleNone); foreach(KoShape* shape, shapes) { QTransform matrix = shape->absoluteTransformation(0) * QTransform::fromScale(image->xRes(), image->yRes()); QPainterPath mapedOutline = matrix.map(shape->outline()); helper.paintPainterPath(mapedOutline); } m_adapter->endMacro(); } void KisSelectionManager::slotToggleSelectionDecoration() { KIS_ASSERT_RECOVER_RETURN(m_selectionDecoration); KisSelectionDecoration::Mode mode = m_selectionDecoration->mode() ? KisSelectionDecoration::Ants : KisSelectionDecoration::Mask; m_selectionDecoration->setMode(mode); emit displaySelectionChanged(); } bool KisSelectionManager::showSelectionAsMask() const { if (m_selectionDecoration) { return m_selectionDecoration->mode() == KisSelectionDecoration::Mask; } return false; } #include "kis_selection_manager.moc" diff --git a/krita/ui/kis_selection_manager.h b/krita/ui/kis_selection_manager.h index bac1a655ca3..229c8788d2d 100644 --- a/krita/ui/kis_selection_manager.h +++ b/krita/ui/kis_selection_manager.h @@ -1,170 +1,176 @@ /* * Copyright (c) 2004 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_SELECTION_MANAGER_ #define KIS_SELECTION_MANAGER_ #include #include #include # #include "KisDocument.h" -#include +#include class KisActionManager; class KisAction; class KAction; class KoViewConverter; class KisViewManager; class KisDoc; class KisClipboard; class KisNodeCommandsAdapter; class KisView; class KisSelectionFilter; class KisSelectionDecoration; /** * The selection manager is responsible selections * and the clipboard. */ class KRITAUI_EXPORT KisSelectionManager : public QObject { Q_OBJECT Q_PROPERTY(bool displaySelection READ displaySelection NOTIFY displaySelectionChanged); Q_PROPERTY(bool havePixelsSelected READ havePixelsSelected NOTIFY currentSelectionChanged); public: KisSelectionManager(KisViewManager * view); virtual ~KisSelectionManager(); void setup(KisActionManager* actionManager); void setView(QPointerimageView); public: /** * This function return if the selection should be displayed */ bool displaySelection(); bool showSelectionAsMask() const; public Q_SLOTS: void updateGUI(); void selectionChanged(); void clipboardDataChanged(); void cut(); void copy(); void cutSharp(); void copySharp(); void copyMerged(); void paste(); void pasteNew(); void pasteAt(); void cutToNewLayer(); void selectAll(); void deselect(); void invert(); void clear(); void fillForegroundColor(); void fillBackgroundColor(); void fillPattern(); + void fillForegroundColorOpacity(); + void fillBackgroundColorOpacity(); + void fillPatternOpacity(); void reselect(); void convertToVectorSelection(); void convertShapesToVectorSelection(); void convertToShape(); void copySelectionToNewLayer(); void toggleDisplaySelection(); void shapeSelectionChanged(); void imageResizeToSelection(); void paintSelectedShapes(); void slotToggleSelectionDecoration(); Q_SIGNALS: void currentSelectionChanged(); void signalUpdateGUI(); void displaySelectionChanged(); public: bool havePixelsSelected(); bool havePixelsInClipboard(); bool haveShapesSelected(); bool haveShapesInClipboard(); /// Checks if the current selection is editabl and has some pixels selected in the pixel selection bool havePixelSelectionWithPixels(); // the following functions are needed for the siox tool // they might be also useful on its own void erode(); void dilate(); void paint(QPainter& gc, const KoViewConverter &converter); private: void fill(const KoColor& color, bool fillWithPattern, const QString& transactionText); void updateStatusBar(); void copyFromDevice(KisPaintDeviceSP device); void applySelectionFilter(KisSelectionFilter *filter); KisViewManager * m_view; KisDocument * m_doc; QPointerm_imageView; KisClipboard * m_clipboard; KisNodeCommandsAdapter* m_adapter; KisAction *m_copy; KisAction *m_copyMerged; KisAction *m_cut; KisAction *m_paste; KisAction *m_pasteAt; KisAction *m_pasteNew; KisAction *m_cutToNewLayer; KisAction *m_selectAll; KisAction *m_deselect; KisAction *m_clear; KisAction *m_reselect; KisAction *m_invert; KisAction *m_copyToNewLayer; KisAction *m_fillForegroundColor; KisAction *m_fillBackgroundColor; KisAction *m_fillPattern; + KisAction *m_fillForegroundColorOpacity; + KisAction *m_fillBackgroundColorOpacity; + KisAction *m_fillPatternOpacity; KisAction *m_imageResizeToSelection; KisAction *m_strokeShapes; KisAction *m_toggleDisplaySelection; KisAction *m_toggleSelectionOverlayMode; QList m_pluginActions; KisSelectionDecoration *m_selectionDecoration; }; #endif // KIS_SELECTION_MANAGER_ diff --git a/krita/ui/kis_splash_screen.h b/krita/ui/kis_splash_screen.h index f6f91634c44..4094b01b23a 100644 --- a/krita/ui/kis_splash_screen.h +++ b/krita/ui/kis_splash_screen.h @@ -1,46 +1,46 @@ /* * Copyright (c) 2014 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_SPLASH_SCREEN_H #define KIS_SPLASH_SCREEN_H #include #include "ui_wdgsplash.h" class QPixmap; -#include "krita_export.h" +#include "kritaui_export.h" class KRITAUI_EXPORT KisSplashScreen : public QWidget, public Ui::WdgSplash { Q_OBJECT public: explicit KisSplashScreen(const QString &m_version, const QPixmap &m_pixmap, bool themed = false, QWidget *parent = 0, Qt::WindowFlags f = 0); void repaint(); void show(); private Q_SLOTS: void toggleShowAtStartup(bool toggle); void linkClicked(const QString &link); }; #endif // KIS_SPLASH_SCREEN_H diff --git a/krita/ui/kis_statusbar.h b/krita/ui/kis_statusbar.h index 92a34af21b3..389cdd05f4e 100644 --- a/krita/ui/kis_statusbar.h +++ b/krita/ui/kis_statusbar.h @@ -1,87 +1,87 @@ /* This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 2003-200^ 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_STATUSBAR_H #define KIS_STATUSBAR_H #include #include #include #include #include "KisView.h" class QLabel; class QToolButton; class QPushButton; class KSqueezedTextLabel; class KisViewManager; class KisProgressWidget; -#include "krita_export.h" +#include "kritaui_export.h" class KRITAUI_EXPORT KisStatusBar : public QObject { Q_OBJECT public: KisStatusBar(KisViewManager * view); ~KisStatusBar(); void setView(QPointer imageView); KisProgressWidget *progress(); public Q_SLOTS: void documentMousePositionChanged(const QPointF &p); void imageSizeChanged(); void setSelection(KisImageWSP image); void setProfile(KisImageWSP image); void setHelp(const QString &t); void updateStatusBarProfileLabel(); void updateSelectionToolTip(); private Q_SLOTS: void updateSelectionIcon(); void showMemoryInfoToolTip(); private: void updateMemoryStatus(); private: KisViewManager * m_view; QPointer m_imageView; KisProgressWidget * m_progress; QToolButton *m_selectionStatus; QPushButton *m_memoryReportBox; QLabel *m_pointerPositionLabel; KSqueezedTextLabel *m_statusBarStatusLabel; KSqueezedTextLabel *m_statusBarProfileLabel; QString m_shortMemoryTag; QString m_longMemoryTag; QIcon m_memoryStatusIcon; }; #endif diff --git a/krita/ui/kis_transaction_based_command.h b/krita/ui/kis_transaction_based_command.h index 1c5cd845d98..7584f153516 100644 --- a/krita/ui/kis_transaction_based_command.h +++ b/krita/ui/kis_transaction_based_command.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TRANSACTION_BASED_COMMAND_H #define KIS_TRANSACTION_BASED_COMMAND_H -#include +#include #include class KRITAUI_EXPORT KisTransactionBasedCommand : public KUndo2Command { public: KisTransactionBasedCommand(const KUndo2MagicString &text = KUndo2MagicString(), KUndo2Command *parent = 0); ~KisTransactionBasedCommand(); void redo(); void undo(); protected: virtual KUndo2Command* paint() = 0; private: KUndo2Command *m_transactionData; }; #endif // KIS_TRANSACTION_BASED_COMMAND_H diff --git a/krita/ui/kis_view_plugin.h b/krita/ui/kis_view_plugin.h index 306c5ca8d71..4821c75ac45 100644 --- a/krita/ui/kis_view_plugin.h +++ b/krita/ui/kis_view_plugin.h @@ -1,55 +1,55 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_VIEW_PLUGIN_H #define KIS_VIEW_PLUGIN_H -#include +#include #include "operations/kis_operation_ui_factory.h" class KisOperation; class KisAction; class KisViewManager; /** * KisViewPlugin is the base for plugins which add actions to the view */ class KRITAUI_EXPORT KisViewPlugin : public QObject { Q_OBJECT public: KisViewPlugin(QObject* parent = 0); virtual ~KisViewPlugin(); protected: /** * adds an action to UI and action manager * @param name name of the action in the krita.rc file * @param action the action that should be added */ void addAction(const QString& name, KisAction* action); void addUIFactory(KisOperationUIFactory* factory); void addOperation(KisOperation* operation); KisViewManager* m_view; }; #endif // KIS_VIEW_PLUGIN_H diff --git a/krita/ui/kis_workspace_resource.cpp b/krita/ui/kis_workspace_resource.cpp index b71dc49ed59..eec1d018d17 100644 --- a/krita/ui/kis_workspace_resource.cpp +++ b/krita/ui/kis_workspace_resource.cpp @@ -1,139 +1,129 @@ /* This file is part of the KDE project * Copyright (C) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "kis_workspace_resource.h" #include #include #include -#include #define WORKSPACE_VERSION 1 KisWorkspaceResource::KisWorkspaceResource(const QString& filename): KoResource(filename) { } KisWorkspaceResource::~KisWorkspaceResource() { } bool KisWorkspaceResource::save() { if (filename().isEmpty()) return false; QFile file(filename()); file.open(QIODevice::WriteOnly); bool res = saveToDevice(&file); file.close(); return res; } bool KisWorkspaceResource::saveToDevice(QIODevice *dev) const { QDomDocument doc; QDomElement root = doc.createElement("Workspace"); root.setAttribute("name", name() ); root.setAttribute("version", WORKSPACE_VERSION); QDomElement state = doc.createElement("state"); state.appendChild(doc.createCDATASection(m_dockerState.toBase64())); root.appendChild(state); // Save KisPropertiesConfiguration settings QDomElement settings = doc.createElement("settings"); KisPropertiesConfiguration::toXML(doc, settings); root.appendChild(settings); doc.appendChild(root); QTextStream textStream(dev); doc.save(textStream, 4); + KoResource::saveToDevice(dev); + return true; } bool KisWorkspaceResource::load() { if (filename().isEmpty()) return false; QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { warnKrita << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KisWorkspaceResource::loadFromDevice(QIODevice *dev) { QDomDocument doc; if (!doc.setContent(dev)) { return false; } QDomElement element = doc.documentElement(); setName(element.attribute("name")); QDomElement state = element.firstChildElement("state"); if (!state.isNull()) { m_dockerState = QByteArray::fromBase64(state.text().toLatin1()); } QDomElement settings = element.firstChildElement("settings"); if (!settings.isNull()) { KisPropertiesConfiguration::fromXML(settings); } setValid(true); return true; } QString KisWorkspaceResource::defaultFileExtension() const { return QString(".kws"); } void KisWorkspaceResource::setDockerState(const QByteArray& state) { m_dockerState = state; } QByteArray KisWorkspaceResource::dockerState() { return m_dockerState; } - -QByteArray KisWorkspaceResource::generateMD5() const -{ - if (!m_dockerState.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(m_dockerState); - return md5.result(); - } - - return m_dockerState; -} diff --git a/krita/ui/kis_workspace_resource.h b/krita/ui/kis_workspace_resource.h index aefc57c7820..d2b53c0d60c 100644 --- a/krita/ui/kis_workspace_resource.h +++ b/krita/ui/kis_workspace_resource.h @@ -1,51 +1,47 @@ /* This file is part of the KDE project * Copyright (C) 2011 Sven Langkamp * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KIS_WORKSPACE_RESOURCE_H #define KIS_WORKSPACE_RESOURCE_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" /// Resource for storing of workspaces class KRITAUI_EXPORT KisWorkspaceResource : public KoResource , public KisPropertiesConfiguration { public: KisWorkspaceResource(const QString& filename); virtual ~KisWorkspaceResource(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; virtual QString defaultFileExtension() const; void setDockerState(const QByteArray& state); QByteArray dockerState(); -protected: - - virtual QByteArray generateMD5() const; - private: QByteArray m_dockerState; }; #endif // KIS_WORKSPACE_RESOURCE_H diff --git a/krita/ui/kisexiv2/kis_exiv2.h b/krita/ui/kisexiv2/kis_exiv2.h index 6c54a49a93f..070f0cb71d0 100644 --- a/krita/ui/kisexiv2/kis_exiv2.h +++ b/krita/ui/kisexiv2/kis_exiv2.h @@ -1,44 +1,44 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or * (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _KIS_EXIV2_H_ #define _KIS_EXIV2_H_ #include #include -#include "krita_export.h" +#include "kritaui_export.h" /// Convert an exiv value to a KisMetaData value KisMetaData::Value exivValueToKMDValue(const Exiv2::Value::AutoPtr value, bool forceSeq, KisMetaData::Value::ValueType arrayType = KisMetaData::Value::UnorderedArray); /// Convert a KisMetaData to an Exiv value Exiv2::Value* kmdValueToExivValue(const KisMetaData::Value& value, Exiv2::TypeId type); /** * Convert a KisMetaData to an Exiv value, without knowing the targeted Exiv2::TypeId * This function should be used for saving to XMP. */ Exiv2::Value* kmdValueToExivXmpValue(const KisMetaData::Value& value); struct KRITAUI_EXPORT KisExiv2 { static void initialize(); }; #endif diff --git a/krita/ui/kra/kis_kra_load_visitor.cpp b/krita/ui/kra/kis_kra_load_visitor.cpp index 72231790ec2..72d0489b03d 100644 --- a/krita/ui/kra/kis_kra_load_visitor.cpp +++ b/krita/ui/kra/kis_kra_load_visitor.cpp @@ -1,489 +1,488 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * * 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 "kra/kis_kra_load_visitor.h" #include "kis_kra_tags.h" #include "flake/kis_shape_layer.h" #include #include #include #include #include #include #include // kritaimage #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_transform_mask_params_factory_registry.h" #include #include #include "kis_shape_selection.h" #include "kis_dom_utils.h" using namespace KRA; QString expandEncodedDirectory(const QString& _intern) { QString intern = _intern; QString result; int pos; while ((pos = intern.indexOf('/')) != -1) { if (QChar(intern.at(0)).isDigit()) result += "part"; result += intern.left(pos + 1); // copy numbers (or "pictures") + "/" intern = intern.mid(pos + 1); // remove the dir we just processed } if (!intern.isEmpty() && QChar(intern.at(0)).isDigit()) result += "part"; result += intern; return result; } KisKraLoadVisitor::KisKraLoadVisitor(KisImageWSP image, KoStore *store, QMap &layerFilenames, const QString & name, int syntaxVersion) : KisNodeVisitor(), m_layerFilenames(layerFilenames) { m_external = false; m_image = image; m_store = store; m_name = name; m_store->pushDirectory(); if (m_name.startsWith("/")) { m_name.remove(0, 1); } if (!m_store->enterDirectory(m_name)) { dbgFile << "Could not enter directory" << m_name << ", probably an old-style file with 'part' added."; m_name = expandEncodedDirectory(m_name); } else { m_store->popDirectory(); } m_syntaxVersion = syntaxVersion; } void KisKraLoadVisitor::setExternalUri(const QString &uri) { m_external = true; m_uri = uri; } bool KisKraLoadVisitor::visit(KisExternalLayer * layer) { bool result = false; if (KisShapeLayer* shapeLayer = dynamic_cast(layer)) { if (!loadMetaData(layer)) { return false; } m_store->pushDirectory(); m_store->enterDirectory(getLocation(layer, DOT_SHAPE_LAYER)) ; result = shapeLayer->loadLayer(m_store); m_store->popDirectory(); } result = visitAll(layer) && result; return result; } bool KisKraLoadVisitor::visit(KisPaintLayer *layer) { dbgFile << "Visit: " << layer->name() << " colorSpace: " << layer->colorSpace()->id(); if (!loadPaintDevice(layer->paintDevice(), getLocation(layer))) { return false; } if (!loadProfile(layer->paintDevice(), getLocation(layer, DOT_ICC))) { return false; } if (!loadMetaData(layer)) { return false; } if (m_syntaxVersion == 1) { // Check whether there is a file with a .mask extension in the // layer directory, if so, it's an old-style transparency mask // that should be converted. QString location = getLocation(layer, ".mask"); if (m_store->open(location)) { KisSelectionSP selection = KisSelectionSP(new KisSelection()); KisPixelSelectionSP pixelSelection = selection->pixelSelection(); if (!pixelSelection->read(m_store->device())) { pixelSelection->disconnect(); } else { KisTransparencyMask* mask = new KisTransparencyMask(); mask->setSelection(selection); m_image->addNode(mask, layer, layer->firstChild()); } m_store->close(); } } bool result = visitAll(layer); return result; } bool KisKraLoadVisitor::visit(KisGroupLayer *layer) { if (!loadMetaData(layer)) { return false; } bool result = visitAll(layer); return result; } bool KisKraLoadVisitor::visit(KisAdjustmentLayer* layer) { // Adjustmentlayers are tricky: there's the 1.x style and the 2.x // style, which has selections with selection components bool result = true; if (m_syntaxVersion == 1) { KisSelectionSP selection = new KisSelection(); KisPixelSelectionSP pixelSelection = selection->pixelSelection(); result = loadPaintDevice(pixelSelection, getLocation(layer, ".selection")); layer->setInternalSelection(selection); } else if (m_syntaxVersion == 2) { result = loadSelection(getLocation(layer), layer->internalSelection()); } else { // We use the default, empty selection } if (!loadMetaData(layer)) { return false; } loadFilterConfiguration(layer->filter().data(), getLocation(layer, DOT_FILTERCONFIG)); result = visitAll(layer); return result; } bool KisKraLoadVisitor::visit(KisGeneratorLayer* layer) { if (!loadMetaData(layer)) { return false; } bool result = true; result = loadSelection(getLocation(layer), layer->internalSelection()); result = loadFilterConfiguration(layer->filter().data(), getLocation(layer, DOT_FILTERCONFIG)); layer->update(); result = visitAll(layer); return result; } bool KisKraLoadVisitor::visit(KisCloneLayer *layer) { if (!loadMetaData(layer)) { return false; } // the layer might have already been lazily initialized // from the mask loading code if (layer->copyFrom()) { return true; } KisNodeSP srcNode = layer->copyFromInfo().findNode(m_image->rootLayer()); KisLayerSP srcLayer = dynamic_cast(srcNode.data()); Q_ASSERT(srcLayer); layer->setCopyFrom(srcLayer); // Clone layers have no data except for their masks bool result = visitAll(layer); return result; } void KisKraLoadVisitor::initSelectionForMask(KisMask *mask) { KisLayer *cloneLayer = dynamic_cast(mask->parent().data()); if (cloneLayer) { // the clone layers should be initialized out of order // and lazily, because their original() is still not // initialized cloneLayer->accept(*this); } KisLayer *parentLayer = dynamic_cast(mask->parent().data()); // the KisKraLoader must have already set the parent for us Q_ASSERT(parentLayer); mask->initSelection(parentLayer); } bool KisKraLoadVisitor::visit(KisFilterMask *mask) { initSelectionForMask(mask); bool result = true; result = loadSelection(getLocation(mask), mask->selection()); result = loadFilterConfiguration(mask->filter().data(), getLocation(mask, DOT_FILTERCONFIG)); return result; } bool KisKraLoadVisitor::visit(KisTransformMask *mask) { QString location = getLocation(mask, DOT_TRANSFORMCONFIG); if (m_store->hasFile(location)) { QByteArray data; m_store->open(location); data = m_store->read(m_store->size()); m_store->close(); if (!data.isEmpty()) { QDomDocument doc; doc.setContent(data); QDomElement rootElement = doc.documentElement(); QDomElement main; if (!KisDomUtils::findOnlyElement(rootElement, "main", &main/*, &m_errorMessages*/)) { return false; } QString id = main.attribute("id", "not-valid"); if (id == "not-valid") { m_errorMessages << i18n("Could not load \"id\" of the transform mask"); return false; } QDomElement data; if (!KisDomUtils::findOnlyElement(rootElement, "data", &data, &m_errorMessages)) { return false; } KisTransformMaskParamsInterfaceSP params = KisTransformMaskParamsFactoryRegistry::instance()->createParams(id, data); if (!params) { m_errorMessages << i18n("Could not create transform mask params"); return false; } mask->setTransformParams(params); return true; } } return false; } bool KisKraLoadVisitor::visit(KisTransparencyMask *mask) { initSelectionForMask(mask); return loadSelection(getLocation(mask), mask->selection()); } bool KisKraLoadVisitor::visit(KisSelectionMask *mask) { initSelectionForMask(mask); return loadSelection(getLocation(mask), mask->selection()); } QStringList KisKraLoadVisitor::errorMessages() const { return m_errorMessages; } bool KisKraLoadVisitor::loadPaintDevice(KisPaintDeviceSP device, const QString& location) { // Layer data if (m_store->open(location)) { if (!device->read(m_store->device())) { m_errorMessages << i18n("Could not read pixel data: %1.", location); device->disconnect(); m_store->close(); return false; } m_store->close(); } else { m_errorMessages << i18n("Could not load pixel data: %1.", location); return false; } if (m_store->open(location + ".defaultpixel")) { int pixelSize = device->colorSpace()->pixelSize(); if (m_store->size() == pixelSize) { quint8 *defPixel = new quint8[pixelSize]; m_store->read((char*)defPixel, pixelSize); device->setDefaultPixel(defPixel); delete[] defPixel; } m_store->close(); } return true; } bool KisKraLoadVisitor::loadProfile(KisPaintDeviceSP device, const QString& location) { if (m_store->hasFile(location)) { m_store->open(location); QByteArray data; data.resize(m_store->size()); dbgFile << "Data to load: " << m_store->size() << " from " << location << " with color space " << device->colorSpace()->id(); int read = m_store->read(data.data(), m_store->size()); dbgFile << "Profile size: " << data.size() << " " << m_store->atEnd() << " " << m_store->device()->bytesAvailable() << " " << read; m_store->close(); // Create a colorspace with the embedded profile const KoColorProfile *profile = KoColorSpaceRegistry::instance()->createColorProfile(device->colorSpace()->colorModelId().id(), device->colorSpace()->colorDepthId().id(), data); const KoColorSpace *cs = KoColorSpaceRegistry::instance()->colorSpace(device->colorSpace()->colorModelId().id(), device->colorSpace()->colorDepthId().id(), profile); // replace the old colorspace if (cs) { device->setDataManager(device->dataManager(), cs); return true; } } m_errorMessages << i18n("Could not load profile %1.", location); return false; } bool KisKraLoadVisitor::loadFilterConfiguration(KisFilterConfiguration* kfc, const QString& location) { if (m_store->hasFile(location)) { QByteArray data; m_store->open(location); data = m_store->read(m_store->size()); m_store->close(); if (!data.isEmpty()) { QString xml(data); QDomDocument doc; doc.setContent(data); QDomElement e = doc.documentElement(); if (e.tagName() == "filterconfig") { kfc->fromLegacyXML(e); } else { kfc->fromXML(e); } return true; } } m_errorMessages << i18n("Could not filter configuration %1.", location); return false; } bool KisKraLoadVisitor::loadMetaData(KisNode* node) { dbgFile << "Load metadata for " << node->name(); KisLayer* layer = qobject_cast(node); if (!layer) return true; bool result = true; KisMetaData::IOBackend* backend = KisMetaData::IOBackendRegistry::instance()->get("xmp"); if (!backend || !backend->supportLoading()) { if (backend) dbgFile << "Backend " << backend->id() << " does not support loading."; else dbgFile << "Could not load the XMP backenda t all"; return true; } QString location = getLocation(node, QString(".") + backend->id() + DOT_METADATA); dbgFile << "going to load " << backend->id() << ", " << backend->name() << " from " << location; if (m_store->hasFile(location)) { QByteArray data; m_store->open(location); data = m_store->read(m_store->size()); m_store->close(); QBuffer buffer(&data); if (!backend->loadFrom(layer->metaData(), &buffer)) { m_errorMessages << i18n("Could not load metadata for layer %1.", layer->name()); result = false; } } return result; } bool KisKraLoadVisitor::loadSelection(const QString& location, KisSelectionSP dstSelection) { // Pixel selection bool result = true; QString pixelSelectionLocation = location + DOT_PIXEL_SELECTION; if (m_store->hasFile(pixelSelectionLocation)) { KisPixelSelectionSP pixelSelection = dstSelection->pixelSelection(); result = loadPaintDevice(pixelSelection, pixelSelectionLocation); if (!result) { m_errorMessages << i18n("Could not load raster selection %1.", location); } - + pixelSelection->invalidateOutlineCache(); } // Shape selection QString shapeSelectionLocation = location + DOT_SHAPE_SELECTION; if (m_store->hasFile(shapeSelectionLocation + "/content.xml")) { m_store->pushDirectory(); m_store->enterDirectory(shapeSelectionLocation) ; KisShapeSelection* shapeSelection = new KisShapeSelection(m_image, dstSelection); dstSelection->setShapeSelection(shapeSelection); result = shapeSelection->loadSelection(m_store); m_store->popDirectory(); if (!result) { m_errorMessages << i18n("Could not load vector selection %1.", location); } - } return result; } QString KisKraLoadVisitor::getLocation(KisNode* node, const QString& suffix) { QString location = m_external ? QString() : m_uri; location += m_name + LAYER_PATH + m_layerFilenames[node] + suffix; return location; } diff --git a/krita/ui/kra/kis_kra_loader.h b/krita/ui/kra/kis_kra_loader.h index c23a5e150be..57f7b9b2b83 100644 --- a/krita/ui/kra/kis_kra_loader.h +++ b/krita/ui/kra/kis_kra_loader.h @@ -1,106 +1,106 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2007 * * 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_KRA_LOADER_H #define KIS_KRA_LOADER_H class QString; class QStringList; #include "KoXmlReaderForward.h" class KoStore; class KisDocument; class KisNode; class KoColorSpace; class KisPaintingAssistant; #include -#include +#include /** * Load old-style 1.x .kra files. Updated for 2.0, let's try to stay * compatible. But 2.0 won't be able to save 1.x .kra files unless we * implement an export filter. */ class KRITAUI_EXPORT KisKraLoader { public: KisKraLoader(KisDocument * document, int syntaxVersion); ~KisKraLoader(); /** * Loading is done in two steps: first all xml is loaded, then, in finishLoading, * the actual layer data is loaded. */ KisImageWSP loadXML(const KoXmlElement& elem); void loadBinaryData(KoStore* store, KisImageWSP image, const QString & uri, bool external); vKisNodeSP selectedNodes() const; // it's neater to follow the same design as with selectedNodes, so let's have a getter here QList assistants() const; /// if empty, loading didn't fail... QStringList errorMessages() const; private: // this needs to be private, for neatness sake void loadAssistants(KoStore* store, const QString & uri, bool external); KisNodeSP loadNodes(const KoXmlElement& element, KisImageWSP image, KisNodeSP parent); KisNodeSP loadNode(const KoXmlElement& elem, KisImageWSP image, KisNodeSP parent); KisNodeSP loadPaintLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadGroupLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadAdjustmentLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadShapeLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadGeneratorLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadCloneLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, const KoColorSpace* cs, quint32 opacity); KisNodeSP loadFilterMask(const KoXmlElement& elem, KisNodeSP parent); KisNodeSP loadTransformMask(const KoXmlElement& elem, KisNodeSP parent); KisNodeSP loadTransparencyMask(const KoXmlElement& elem, KisNodeSP parent); KisNodeSP loadSelectionMask(KisImageWSP image, const KoXmlElement& elem, KisNodeSP parent); KisNodeSP loadFileLayer(const KoXmlElement& elem, KisImageWSP image, const QString& name, quint32 opacity); void loadCompositions(const KoXmlElement& elem, KisImageWSP image); void loadAssistantsList(const KoXmlElement& elem); private: struct Private; Private * const m_d; }; #endif diff --git a/krita/ui/kra/kis_kra_savexml_visitor.cpp b/krita/ui/kra/kis_kra_savexml_visitor.cpp index a19c9d65052..29736f7887b 100644 --- a/krita/ui/kra/kis_kra_savexml_visitor.cpp +++ b/krita/ui/kra/kis_kra_savexml_visitor.cpp @@ -1,400 +1,400 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * * 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 "kra/kis_kra_savexml_visitor.h" #include "kis_kra_tags.h" #include "kis_kra_utils.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include using namespace KRA; KisSaveXmlVisitor::KisSaveXmlVisitor(QDomDocument doc, const QDomElement & element, quint32 &count, const QString &url, bool root) : KisNodeVisitor() , m_doc(doc) , m_count(count) , m_url(url) , m_root(root) { Q_ASSERT(!element.isNull()); m_elem = element; } void KisSaveXmlVisitor::setSelectedNodes(vKisNodeSP selectedNodes) { m_selectedNodes = selectedNodes; } QStringList KisSaveXmlVisitor::errorMessages() const { return m_errorMessages; } bool KisSaveXmlVisitor::visit(KisExternalLayer * layer) { if (layer->inherits("KisShapeLayer")) { QDomElement layerElement = m_doc.createElement(LAYER); saveLayer(layerElement, SHAPE_LAYER, layer); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } else if (layer->inherits("KisFileLayer")) { QDomElement layerElement = m_doc.createElement(LAYER); saveLayer(layerElement, FILE_LAYER, layer); KisFileLayer *fileLayer = dynamic_cast(layer); QString path = fileLayer->path(); QDir d(QFileInfo(m_url).absolutePath()); layerElement.setAttribute("source", d.relativeFilePath(path)); if (fileLayer->scalingMethod() == KisFileLayer::ToImagePPI) { layerElement.setAttribute("scale", "true"); } else { layerElement.setAttribute("scale", "false"); } layerElement.setAttribute("scalingmethod", (int)fileLayer->scalingMethod()); layerElement.setAttribute(COLORSPACE_NAME, layer->original()->colorSpace()->id()); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } return false; } QDomElement KisSaveXmlVisitor::savePaintLayerAttributes(KisPaintLayer *layer, QDomDocument &doc) { QDomElement element = doc.createElement(LAYER); saveLayer(element, PAINT_LAYER, layer); element.setAttribute(CHANNEL_LOCK_FLAGS, flagsToString(layer->channelLockFlags())); element.setAttribute(COLORSPACE_NAME, layer->paintDevice()->colorSpace()->id()); return element; } void KisSaveXmlVisitor::loadPaintLayerAttributes(const QDomElement &el, KisPaintLayer *layer) { loadLayerAttributes(el, layer); if (el.hasAttribute(CHANNEL_LOCK_FLAGS)) { layer->setChannelLockFlags(stringToFlags(el.attribute(CHANNEL_LOCK_FLAGS))); } } bool KisSaveXmlVisitor::visit(KisPaintLayer *layer) { QDomElement layerElement = savePaintLayerAttributes(layer, m_doc); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } bool KisSaveXmlVisitor::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); saveLayer(layerElement, GROUP_LAYER, layer); layerElement.setAttribute(PASS_THROUGH_MODE, layer->passThroughMode()); m_elem.appendChild(layerElement); } QDomElement elem = m_doc.createElement(LAYERS); Q_ASSERT(!layerElement.isNull()); layerElement.appendChild(elem); KisSaveXmlVisitor visitor(m_doc, elem, m_count, m_url, false); visitor.setSelectedNodes(m_selectedNodes); m_count++; bool success = visitor.visitAllInverse(layer); m_errorMessages.append(visitor.errorMessages()); if (!m_errorMessages.isEmpty()) { return false; } QMapIterator i(visitor.nodeFileNames()); while (i.hasNext()) { i.next(); m_nodeFileNames[i.key()] = i.value(); } return success; } bool KisSaveXmlVisitor::visit(KisAdjustmentLayer* layer) { if (!layer->filter()) { return false; } QDomElement layerElement = m_doc.createElement(LAYER); saveLayer(layerElement, ADJUSTMENT_LAYER, layer); layerElement.setAttribute(FILTER_NAME, layer->filter()->name()); layerElement.setAttribute(FILTER_VERSION, layer->filter()->version()); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } bool KisSaveXmlVisitor::visit(KisGeneratorLayer *layer) { QDomElement layerElement = m_doc.createElement(LAYER); saveLayer(layerElement, GENERATOR_LAYER, layer); layerElement.setAttribute(GENERATOR_NAME, layer->filter()->name()); layerElement.setAttribute(GENERATOR_VERSION, layer->filter()->version()); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } bool KisSaveXmlVisitor::visit(KisCloneLayer *layer) { QDomElement layerElement = m_doc.createElement(LAYER); saveLayer(layerElement, CLONE_LAYER, layer); layerElement.setAttribute(CLONE_FROM, layer->copyFromInfo().name()); layerElement.setAttribute(CLONE_FROM_UUID, layer->copyFromInfo().uuid().toString()); layerElement.setAttribute(CLONE_TYPE, layer->copyType()); m_elem.appendChild(layerElement); m_count++; return saveMasks(layer, layerElement); } bool KisSaveXmlVisitor::visit(KisFilterMask *mask) { Q_ASSERT(mask); if (!mask->filter()) { return false; } QDomElement el = m_doc.createElement(MASK); saveMask(el, FILTER_MASK, mask); el.setAttribute(FILTER_NAME, mask->filter()->name()); el.setAttribute(FILTER_VERSION, mask->filter()->version()); m_elem.appendChild(el); m_count++; return true; } bool KisSaveXmlVisitor::visit(KisTransformMask *mask) { Q_ASSERT(mask); QDomElement el = m_doc.createElement(MASK); saveMask(el, TRANSFORM_MASK, mask); m_elem.appendChild(el); m_count++; return true; } bool KisSaveXmlVisitor::visit(KisTransparencyMask *mask) { Q_ASSERT(mask); QDomElement el = m_doc.createElement(MASK); saveMask(el, TRANSPARENCY_MASK, mask); m_elem.appendChild(el); m_count++; return true; } bool KisSaveXmlVisitor::visit(KisSelectionMask *mask) { Q_ASSERT(mask); QDomElement el = m_doc.createElement(MASK); saveMask(el, SELECTION_MASK, mask); m_elem.appendChild(el); m_count++; return true; } void KisSaveXmlVisitor::loadLayerAttributes(const QDomElement &el, KisLayer *layer) { if (el.hasAttribute(NAME)) { QString layerName = el.attribute(NAME); KIS_ASSERT_RECOVER_RETURN(layerName == layer->name()); } if (el.hasAttribute(CHANNEL_FLAGS)) { layer->setChannelFlags(stringToFlags(el.attribute(CHANNEL_FLAGS))); } if (el.hasAttribute(OPACITY)) { layer->setOpacity(el.attribute(OPACITY).toInt()); } if (el.hasAttribute(COMPOSITE_OP)) { layer->setCompositeOp(el.attribute(COMPOSITE_OP)); } if (el.hasAttribute(VISIBLE)) { layer->setVisible(el.attribute(VISIBLE).toInt()); } if (el.hasAttribute(LOCKED)) { layer->setUserLocked(el.attribute(LOCKED).toInt()); } if (el.hasAttribute(X)) { layer->setX(el.attribute(X).toInt()); } if (el.hasAttribute(Y)) { layer->setY(el.attribute(Y).toInt()); } if (el.hasAttribute(UUID)) { layer->setUuid(el.attribute(UUID)); } if (el.hasAttribute(COLLAPSED)) { layer->setCollapsed(el.attribute(COLLAPSED).toInt()); } if (el.hasAttribute(LAYER_STYLE_UUID)) { QString uuidString = el.attribute(LAYER_STYLE_UUID); QUuid uuid(uuidString); if (!uuid.isNull()) { KisPSDLayerStyleSP dumbLayerStyle(new KisPSDLayerStyle()); dumbLayerStyle->setUuid(uuid); layer->setLayerStyle(dumbLayerStyle); } else { qWarning() << "WARNING: Layer style for layer" << layer->name() << "contains invalid UUID" << uuidString; } } } void KisSaveXmlVisitor::saveLayer(QDomElement & el, const QString & layerType, const KisLayer * layer) { el.setAttribute(CHANNEL_FLAGS, flagsToString(layer->channelFlags())); el.setAttribute(NAME, layer->name()); el.setAttribute(OPACITY, layer->opacity()); el.setAttribute(COMPOSITE_OP, layer->compositeOp()->id()); el.setAttribute(VISIBLE, layer->visible()); el.setAttribute(LOCKED, layer->userLocked()); el.setAttribute(NODE_TYPE, layerType); el.setAttribute(FILE_NAME, LAYER + QString::number(m_count)); el.setAttribute(X, layer->x()); el.setAttribute(Y, layer->y()); el.setAttribute(UUID, layer->uuid().toString()); el.setAttribute(COLLAPSED, layer->collapsed()); if (layer->layerStyle()) { el.setAttribute(LAYER_STYLE_UUID, layer->layerStyle()->uuid().toString()); } foreach (KisNodeSP node, m_selectedNodes) { if (node.data() == layer) { el.setAttribute("selected", "true"); break; } } m_nodeFileNames[layer] = LAYER + QString::number(m_count); dbgFile << "Saved layer " << layer->name() << " of type " << layerType << " with filename " << LAYER + QString::number(m_count); } void KisSaveXmlVisitor::saveMask(QDomElement & el, const QString & maskType, const KisMask * mask) { el.setAttribute(NAME, mask->name()); el.setAttribute(VISIBLE, mask->visible()); el.setAttribute(LOCKED, mask->userLocked()); el.setAttribute(NODE_TYPE, maskType); el.setAttribute(FILE_NAME, MASK + QString::number(m_count)); el.setAttribute(X, mask->x()); el.setAttribute(Y, mask->y()); el.setAttribute(UUID, mask->uuid().toString()); if (maskType == SELECTION_MASK) { - el.setAttribute(ACTIVE, mask->nodeProperties().boolProperty("visible")); + el.setAttribute(ACTIVE, mask->nodeProperties().boolProperty("active")); } m_nodeFileNames[mask] = MASK + QString::number(m_count); dbgFile << "Saved mask " << mask->name() << " of type " << maskType << " with filename " << MASK + QString::number(m_count); } bool KisSaveXmlVisitor::saveMasks(KisNode * node, QDomElement & layerElement) { if (node->childCount() > 0) { QDomElement elem = m_doc.createElement(MASKS); Q_ASSERT(!layerElement.isNull()); layerElement.appendChild(elem); KisSaveXmlVisitor visitor(m_doc, elem, m_count, m_url, false); visitor.setSelectedNodes(m_selectedNodes); bool success = visitor.visitAllInverse(node); m_errorMessages.append(visitor.errorMessages()); if (!m_errorMessages.isEmpty()) { return false; } QMapIterator i(visitor.nodeFileNames()); while (i.hasNext()) { i.next(); m_nodeFileNames[i.key()] = i.value(); } return success; } return true; } diff --git a/krita/ui/kra/kis_kra_savexml_visitor.h b/krita/ui/kra/kis_kra_savexml_visitor.h index 9c80fb55e7e..0922ea94f78 100644 --- a/krita/ui/kra/kis_kra_savexml_visitor.h +++ b/krita/ui/kra/kis_kra_savexml_visitor.h @@ -1,89 +1,89 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (c) 2005 C. Boemann * * 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_KRA_SAVEXML_VISITOR_H_ #define KIS_KRA_SAVEXML_VISITOR_H_ #include #include #include #include "kis_node_visitor.h" #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" class KRITAUI_EXPORT KisSaveXmlVisitor : public KisNodeVisitor { public: KisSaveXmlVisitor(QDomDocument doc, const QDomElement & element, quint32 &count, const QString &url, bool root); void setSelectedNodes(vKisNodeSP selectedNodes); using KisNodeVisitor::visit; QStringList errorMessages() const; public: bool visit(KisNode*) { return true; } bool visit(KisExternalLayer *); bool visit(KisPaintLayer *layer); bool visit(KisGroupLayer *layer); bool visit(KisAdjustmentLayer* layer); bool visit(KisGeneratorLayer *layer); bool visit(KisCloneLayer *layer); bool visit(KisFilterMask *mask); bool visit(KisTransformMask *mask); bool visit(KisTransparencyMask *mask); bool visit(KisSelectionMask *mask); QMap nodeFileNames() { return m_nodeFileNames; } public: QDomElement savePaintLayerAttributes(KisPaintLayer *layer, QDomDocument &doc); // used by EXR to save properties of Krita layers inside .exr static void loadPaintLayerAttributes(const QDomElement &el, KisPaintLayer *layer); private: static void loadLayerAttributes(const QDomElement &el, KisLayer *layer); private: void saveLayer(QDomElement & el, const QString & layerType, const KisLayer * layer); void saveMask(QDomElement & el, const QString & maskType, const KisMask * mask); bool saveMasks(KisNode * node, QDomElement & layerElement); friend class KisKraSaveXmlVisitorTest; vKisNodeSP m_selectedNodes; QMap m_nodeFileNames; QDomDocument m_doc; QDomElement m_elem; quint32 &m_count; QString m_url; bool m_root; QStringList m_errorMessages; }; #endif diff --git a/krita/image/krita_export.h b/krita/ui/kritaui_export.h similarity index 59% rename from krita/image/krita_export.h rename to krita/ui/kritaui_export.h index 586d01fc6b2..0325b38dfc1 100644 --- a/krita/image/krita_export.h +++ b/krita/ui/kritaui_export.h @@ -1,99 +1,58 @@ /* This file is part of krita Copyright (c) 2008 Boudewijn Rempt - Copyright (c) 2008 Thomas Zander 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 KRITA_EXPORT_H -#define KRITA_EXPORT_H +#ifndef KRITAUI_EXPORT_H +#define KRITAUI_EXPORT_H #include /* We use _WIN32/_WIN64 instead of Q_OS_WIN so that this header can be used from C files too */ #if defined(_WIN32) || defined(_WIN64) -#ifndef KRITASKETCH_EXPORT -# ifdef MAKE_KRITASKETCHLIB_LIB -# define KRITASKETCH_EXPORT KDE_EXPORT -# else -# define KRITASKETCH_EXPORT KDE_IMPORT -# endif -#endif - #ifndef KRITAUI_EXPORT # ifdef MAKE_KRITAUI_LIB # define KRITAUI_EXPORT KDE_EXPORT # else # define KRITAUI_EXPORT KDE_IMPORT # endif #endif -#ifndef KRITAIMAGE_EXPORT -# ifdef MAKE_KRITAIMAGE_LIB -# define KRITAIMAGE_EXPORT KDE_EXPORT -# else -# define KRITAIMAGE_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef PAINTOP_EXPORT -# ifdef MAKE_KRITALIBPAINTOP_LIB -# define PAINTOP_EXPORT KDE_EXPORT -# else -# define PAINTOP_EXPORT KDE_IMPORT -# endif -#endif - -#ifndef BRUSH_EXPORT -# ifdef MAKE_KRITALIBBRUSH_LIB -# define BRUSH_EXPORT KDE_EXPORT -# else -# define BRUSH_EXPORT KDE_IMPORT -# endif -#endif - #else // not windows -#define KRITASKETCH_EXPORT KDE_EXPORT #define KRITAUI_EXPORT KDE_EXPORT -#define KRITAIMAGE_EXPORT KDE_EXPORT -#define PAINTOP_EXPORT KDE_EXPORT -#define BRUSH_EXPORT KDE_EXPORT #endif /* not windows */ /* Now the same for Krita*_TEST_EXPORT, if compiling with unit tests enabled */ #ifdef COMPILING_TESTS # if defined _WIN32 || defined _WIN64 -# if defined(MAKE_KRITAUI_LIB) || defined(MAKE_KRITAIMAGE_LIB) -# define KRITAIMAGE_TEST_EXPORT KDE_EXPORT +# if defined(MAKE_KRITAUI_LIB) # define KRITAUI_TEST_EXPORT KDE_EXPORT # else -# define KRITAIMAGE_TEST_EXPORT KDE_IMPORT # define KRITAUI_TEST_EXPORT KDE_IMPORT # endif # else /* not windows */ -# define KRITAIMAGE_TEST_EXPORT KDE_EXPORT # define KRITAUI_TEST_EXPORT KDE_EXPORT # endif #else /* not compiling tests */ -# define KRITAIMAGE_TEST_EXPORT # define KRITAUI_TEST_EXPORT #endif -#endif /* KRITA_EXPORT_H */ +#endif /* KRITAUI_EXPORT_H */ diff --git a/krita/ui/opengl/kis_opengl.h b/krita/ui/opengl/kis_opengl.h index 890ea9258ad..895cb4ed2cb 100644 --- a/krita/ui/opengl/kis_opengl.h +++ b/krita/ui/opengl/kis_opengl.h @@ -1,123 +1,123 @@ /* * Copyright (c) 2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_H_ #define KIS_OPENGL_H_ /** @file */ #include #ifdef HAVE_OPENGL #include #if defined(_WIN32) || defined(_WIN64) #include #endif #ifdef HAVE_GLEW #include #endif #include #ifdef Q_WS_MAC #include #else #include #endif -#include "krita_export.h" +#include "kritaui_export.h" class QGLWidget; /** * This class manages a shared OpenGL context and provides utility * functions for checking capabilities and error reporting. */ class KRITAUI_EXPORT KisOpenGL { public: /** * Returns the QGLWidget that uses the shared OpenGL context. * You should pass this as the shareWidget parameter to the * QGLWidget constructor. */ static QGLWidget *sharedContextWidget(); /** * Make the shared OpenGL context the current context. You should * make the context current before creating textures, display lists, * shader objects, etc, that are to be shared by multiple QGLWidgets. */ static void makeSharedContextCurrent(); /** * Make the context of the widget current. You should * make the context current before creating textures, display lists, * shader objects, etc, that are to be shared by multiple QGLWidgets. */ static void makeContextCurrent(QGLWidget *widget); /** * Print any error messages waiting to be read from glGetError(). Use * the helper macro KIS_OPENGL_PRINT_ERROR() to generate the source * file and line number to identify the location the error is reported * from. */ static void printError(const char *file = 0, int line = -1); /** * Clear any error codes waiting to be read from glGetError(). */ static void clearError(); /** * @brief supportsGLSL13 * @return true if we have a modern opengl capable of high-quality filtering */ static bool supportsGLSL13(); /** * Returns true if we have a driver that has bugged support to sync objects (a fence) * and false otherwise. */ static bool needsFenceWorkaround(); private: KisOpenGL(); static void createContext(); }; /** * Helper macro to print out any OpenGL error messages waiting to be * read. This will also print the source file and line number where * the print is performed. */ #define KIS_OPENGL_PRINT_ERROR() KisOpenGL::printError(__FILE__, __LINE__) /** * Helper macro to clear out any OpenGL error messages waiting to be * read. */ #define KIS_OPENGL_CLEAR_ERROR() KisOpenGL::clearError() #endif // HAVE_OPENGL #endif // KIS_OPENGL_H_ diff --git a/krita/ui/opengl/kis_opengl_canvas2.h b/krita/ui/opengl/kis_opengl_canvas2.h index 77bcbe94da5..6804b5a841c 100644 --- a/krita/ui/opengl/kis_opengl_canvas2.h +++ b/krita/ui/opengl/kis_opengl_canvas2.h @@ -1,113 +1,113 @@ /* * Copyright (C) Boudewijn Rempt , (C) 2006 * * 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_2_H #define KIS_OPENGL_CANVAS_2_H #include #ifdef HAVE_OPENGL #include #include #include "canvas/kis_canvas_widget_base.h" #include "opengl/kis_opengl_image_textures.h" -#include "krita_export.h" +#include "kritaui_export.h" class QWidget; class QPaintEvent; class KisCanvas2; /** * KisOpenGLCanvas is the widget that shows the actual image using OpenGL * * NOTE: if you change something in the event handling here, also change it * in the qpainter canvas. * */ class KRITAUI_EXPORT KisOpenGLCanvas2 : public QGLWidget, public KisCanvasWidgetBase { Q_OBJECT public: KisOpenGLCanvas2(KisCanvas2 * canvas, KisCoordinatesConverter *coordinatesConverter, QWidget * parent, KisOpenGLImageTexturesSP imageTextures); virtual ~KisOpenGLCanvas2(); void setDisplayFilter(KisDisplayFilter* displayFilter); void setWrapAroundViewingMode(bool value); public: // QWidget virtual QVariant inputMethodQuery(Qt::InputMethodQuery query) const; virtual void inputMethodEvent(QInputMethodEvent *event); virtual void paintEvent(QPaintEvent* event); public: bool isBusy() const; void initializeCheckerShader(); void initializeDisplayShader(); void renderCanvasGL() const; void renderDecorations(QPainter *painter); private Q_SLOTS: void slotConfigChanged(); public: void resizeGL(int width, int height); void initializeGL(); void paintGL(); public: QWidget *widget() { return this; } protected: // KisCanvasWidgetBase virtual bool callFocusNextPrevChild(bool next); private: void reportShaderLinkFailedAndExit(bool result, const QString &context, const QString &log); private: struct Private; Private * const d; void drawImage() const; void drawCheckers() const; QByteArray buildFragmentShader() const; }; #endif // HAVE_OPENGL #endif // KIS_OPENGL_CANVAS_2_H diff --git a/krita/ui/opengl/kis_opengl_image_textures.h b/krita/ui/opengl/kis_opengl_image_textures.h index a153e529a60..6133eddda8c 100644 --- a/krita/ui/opengl/kis_opengl_image_textures.h +++ b/krita/ui/opengl/kis_opengl_image_textures.h @@ -1,196 +1,196 @@ /* * Copyright (c) 2005-2007 Adrian Page * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPENGL_IMAGE_TEXTURES_H_ #define KIS_OPENGL_IMAGE_TEXTURES_H_ #include #ifdef HAVE_OPENGL #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_shared.h" #include "canvas/kis_update_info.h" #include "opengl/kis_texture_tile.h" class KisOpenGLImageTextures; typedef KisSharedPtr KisOpenGLImageTexturesSP; class KoColorProfile; /** * A set of OpenGL textures that contains the projection of a KisImage. */ class KRITAUI_EXPORT KisOpenGLImageTextures : public QObject, public KisShared { Q_OBJECT public: /** * Obtain a KisOpenGLImageTextures object for the given image. * @param image The image * @param monitorProfile The profile of the display device */ static KisOpenGLImageTexturesSP getImageTextures(KisImageWSP image, const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); /** * Default constructor. */ KisOpenGLImageTextures(); /** * Destructor. */ virtual ~KisOpenGLImageTextures(); /** * Set the color profile of the display device. * @param profile The color profile of the display device */ void setMonitorProfile(const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); void setChannelFlags(const QBitArray &channelFlags); bool internalColorManagementActive() const; bool setInternalColorManagementActive(bool value); /** * The background checkers texture. */ static const int BACKGROUND_TEXTURE_CHECK_SIZE = 32; static const int BACKGROUND_TEXTURE_SIZE = BACKGROUND_TEXTURE_CHECK_SIZE * 2; /** * Generate a background texture from the given QImage. This is used for the checker * pattern on which the image is rendered. */ void generateCheckerTexture(const QImage & checkImage); GLuint checkerTexture() const; void updateConfig(bool useBuffer, int NumMipmapLevels); public: inline QRect storedImageBounds() { return m_storedImageBounds; } inline int xToCol(int x) { return x / m_texturesInfo.effectiveWidth; } inline int yToRow(int y) { return y / m_texturesInfo.effectiveHeight; } inline KisTextureTile* getTextureTileCR(int col, int row) { int tile = row * m_numCols + col; KIS_ASSERT_RECOVER_RETURN_VALUE(m_textureTiles.size() > tile, 0); return m_textureTiles[tile]; } inline KisTextureTile* getTextureTile(int x, int y) { return getTextureTileCR(xToCol(x), yToRow(y)); } inline qreal texelSize() const { Q_ASSERT(m_texturesInfo.width == m_texturesInfo.height); return 1.0 / m_texturesInfo.width; } public Q_SLOTS: KisOpenGLUpdateInfoSP updateCache(const QRect& rect); void recalculateCache(KisUpdateInfoSP info); void slotImageSizeChanged(qint32 w, qint32 h); protected: KisOpenGLImageTextures(KisImageWSP image, const KoColorProfile *monitorProfile, KoColorConversionTransformation::Intent renderingIntent, KoColorConversionTransformation::ConversionFlags conversionFlags); void createImageTextureTiles(); void destroyImageTextureTiles(); static bool imageCanShareTextures(); private: QRect calculateTileRect(int col, int row) const; static void getTextureSize(KisGLTexturesInfo *texturesInfo); void updateTextureFormat(); private: KisImageWSP m_image; QRect m_storedImageBounds; const KoColorProfile *m_monitorProfile; KoColorConversionTransformation::Intent m_renderingIntent; KoColorConversionTransformation::ConversionFlags m_conversionFlags; /** * If the destination color space coincides with the one of the image, * then effectively, there is no conversion happens. That is used * for working with OCIO. */ const KoColorSpace* m_tilesDestinationColorSpace; /** * Shows whether the internal color management should be enabled or not. * Please note that if you disable color management, *but* your image color * space will not be supported (non-RGB), then it will be enabled anyway. * And this valiable will hold the real state of affairs! */ bool m_internalColorManagementActive; GLuint m_checkerTexture; KisGLTexturesInfo m_texturesInfo; int m_numCols; QVector m_textureTiles; QBitArray m_channelFlags; bool m_allChannelsSelected; bool m_onlyOneChannelSelected; int m_selectedChannelIndex; bool m_useOcio; private: typedef QMap ImageTexturesMap; static ImageTexturesMap imageTexturesMap; }; #endif // HAVE_OPENGL #endif // KIS_OPENGL_IMAGE_TEXTURES_H_ diff --git a/krita/ui/operations/kis_filter_selection_operation.h b/krita/ui/operations/kis_filter_selection_operation.h index 5765bd93500..9f3ab03585d 100644 --- a/krita/ui/operations/kis_filter_selection_operation.h +++ b/krita/ui/operations/kis_filter_selection_operation.h @@ -1,34 +1,34 @@ /* * Copyright (c) 2012 Dmitry Kazakov * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_FILTER_SELECTION_OPERATION_H #define KIS_FILTER_SELECTION_OPERATION_H -#include +#include #include "kis_operation.h" class KisSelectionFilter; class KisViewManager; struct KRITAUI_EXPORT KisFilterSelectionOperation : public KisOperation { KisFilterSelectionOperation(const QString& id) : KisOperation(id) {} void runFilter(KisSelectionFilter* filter, KisViewManager *view, const KisOperationConfiguration &config); }; #endif // KIS_FILTER_SELECTION_OPERATION_H diff --git a/krita/ui/operations/kis_operation.h b/krita/ui/operations/kis_operation.h index 6e279d67d69..663ade607a1 100644 --- a/krita/ui/operations/kis_operation.h +++ b/krita/ui/operations/kis_operation.h @@ -1,48 +1,48 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_OPERATION_H #define __KIS_OPERATION_H #include #include -#include +#include #include "kis_properties_configuration.h" #include "operations/kis_operation_configuration.h" class KisViewManager; class KisProcessingApplicator; class KRITAUI_EXPORT KisOperation { public: KisOperation(const QString &id); virtual ~KisOperation(); QString id() const; virtual void runFromXML(KisViewManager *view, const KisOperationConfiguration &config); protected: KisProcessingApplicator* beginAction(KisViewManager *view, const KUndo2MagicString &actionName); void endAction(KisProcessingApplicator *applicator, const QString &xmlData); private: const QString m_id; }; #endif /* __KIS_OPERATION_H */ diff --git a/krita/ui/operations/kis_operation_configuration.h b/krita/ui/operations/kis_operation_configuration.h index ac37a87ee5f..f506fe710fd 100644 --- a/krita/ui/operations/kis_operation_configuration.h +++ b/krita/ui/operations/kis_operation_configuration.h @@ -1,36 +1,36 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_OPERATION_CONFIGURATION_H #define __KIS_OPERATION_CONFIGURATION_H #include -#include +#include #include "kis_properties_configuration.h" class KRITAUI_EXPORT KisOperationConfiguration : public KisPropertiesConfiguration { public: KisOperationConfiguration(); KisOperationConfiguration(const QString &id); QString id() const; }; #endif /* __KIS_OPERATION_CONFIGURATION_H */ diff --git a/krita/ui/operations/kis_operation_registry.h b/krita/ui/operations/kis_operation_registry.h index 6432db11a8d..febb12d9e30 100644 --- a/krita/ui/operations/kis_operation_registry.h +++ b/krita/ui/operations/kis_operation_registry.h @@ -1,35 +1,35 @@ /* * Copyright (c) 2012 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_OPERATION_REGISTRY_H #define __KIS_OPERATION_REGISTRY_H -#include +#include #include #include "kis_operation.h" class KRITAUI_EXPORT KisOperationRegistry : public KoGenericRegistry { public: KisOperationRegistry(); ~KisOperationRegistry(); static KisOperationRegistry* instance(); }; #endif /* __KIS_OPERATION_REGISTRY_H */ diff --git a/krita/ui/operations/kis_operation_ui_widget.h b/krita/ui/operations/kis_operation_ui_widget.h index 9bac4437210..b8a083d65a0 100644 --- a/krita/ui/operations/kis_operation_ui_widget.h +++ b/krita/ui/operations/kis_operation_ui_widget.h @@ -1,54 +1,54 @@ /* * Copyright (c) 2013 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_OPERATION_UI_WIDGET_H #define KIS_OPERATION_UI_WIDGET_H #include -#include +#include class KisOperationConfiguration; /** * Base class for the QWidget based operation config widgets */ class KRITAUI_EXPORT KisOperationUIWidget : public QWidget { public: explicit KisOperationUIWidget(const QString& caption, QWidget* parent = 0); virtual ~KisOperationUIWidget(); /** * Caption of the operation widget, used in dialog caption */ QString caption() const; /** * Fetch the setting from the config widet * @param config configuration to which the setting will be written */ virtual void getConfiguration(KisOperationConfiguration* config) = 0; private: class Private; Private* const d; }; #endif // KIS_OPERATION_UI_WIDGET_H diff --git a/krita/ui/ora/kis_open_raster_stack_load_visitor.h b/krita/ui/ora/kis_open_raster_stack_load_visitor.h index ecee866a5d4..0ddee4de294 100644 --- a/krita/ui/ora/kis_open_raster_stack_load_visitor.h +++ b/krita/ui/ora/kis_open_raster_stack_load_visitor.h @@ -1,56 +1,56 @@ /* * Copyright (c) 2006 Cyrille Berger * * 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_OPEN_RASTER_STACK_LOAD_VISITOR_H_ #define KIS_OPEN_RASTER_STACK_LOAD_VISITOR_H_ #include "kis_global.h" #include "kis_types.h" -#include +#include class QDomElement; class KisAdjustmentLayer; class KisUndoStore; class KisGroupLayer; class KisOpenRasterLoadContext; class KisPaintLayer; class KRITAUI_EXPORT KisOpenRasterStackLoadVisitor { public: KisOpenRasterStackLoadVisitor(KisUndoStore *undoStore, KisOpenRasterLoadContext* orlc); virtual ~KisOpenRasterStackLoadVisitor(); public: void loadImage(); void loadPaintLayer(const QDomElement& elem, KisPaintLayerSP pL); void loadAdjustmentLayer(const QDomElement& elem, KisAdjustmentLayerSP pL); void loadGroupLayer(const QDomElement& elem, KisGroupLayerSP gL); KisImageWSP image(); vKisNodeSP activeNodes(); private: void loadLayerInfo(const QDomElement& elem, KisLayerSP layer); struct Private; Private* const d; }; #endif // KIS_LAYER_VISITOR_H_ diff --git a/krita/ui/ora/kis_open_raster_stack_save_visitor.h b/krita/ui/ora/kis_open_raster_stack_save_visitor.h index d2f8548806b..58cc77c7ee9 100644 --- a/krita/ui/ora/kis_open_raster_stack_save_visitor.h +++ b/krita/ui/ora/kis_open_raster_stack_save_visitor.h @@ -1,83 +1,83 @@ /* * Copyright (c) 2006-2007 Cyrille Berger * * 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_OPEN_RASTER_STACK_SAVE_VISITOR_H_ #define KIS_OPEN_RASTER_STACK_SAVE_VISITOR_H_ #include #include "kis_global.h" #include "kis_types.h" #include "kis_node_visitor.h" #include "kis_layer.h" -#include +#include class KisOpenRasterSaveContext; class KisAdjustmentLayer; class KisGroupLayer; class KisPaintLayer; class KisGeneratorLayer; class QDomElement; class KRITAUI_EXPORT KisOpenRasterStackSaveVisitor : public KisNodeVisitor { public: KisOpenRasterStackSaveVisitor(KisOpenRasterSaveContext*, vKisNodeSP activeNodes); virtual ~KisOpenRasterStackSaveVisitor(); using KisNodeVisitor::visit; public: bool visit(KisPaintLayer *layer); bool visit(KisGroupLayer *layer); bool visit(KisAdjustmentLayer *layer); bool visit(KisGeneratorLayer * layer); bool visit(KisNode*) { return true; } bool visit(KisCloneLayer*); bool visit(KisFilterMask*) { return true; } bool visit(KisTransformMask*) { return true; } bool visit(KisTransparencyMask*) { return true; } bool visit(KisSelectionMask*) { return true; } bool visit(KisExternalLayer*); private: bool saveLayer(KisLayer *layer); void saveLayerInfo(QDomElement& elt, KisLayer* layer); struct Private; Private* const d; }; #endif // KIS_LAYER_VISITOR_H_ diff --git a/krita/ui/ora/ora_load_context.h b/krita/ui/ora/ora_load_context.h index a2ecdaec0c1..96bce2939c3 100644 --- a/krita/ui/ora/ora_load_context.h +++ b/krita/ui/ora/ora_load_context.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _ORA_LOAD_CONTEXT_H_ #define _ORA_LOAD_CONTEXT_H_ #include -#include +#include class KoStore; class KRITAUI_EXPORT OraLoadContext : public KisOpenRasterLoadContext { public: OraLoadContext(KoStore* _store); virtual ~OraLoadContext(); virtual KisImageWSP loadDeviceData(const QString & fileName); virtual QDomDocument loadStack(); private: KoStore* m_store; }; #endif diff --git a/krita/ui/ora/ora_save_context.h b/krita/ui/ora/ora_save_context.h index 2acdc1b5e01..838de7645b8 100644 --- a/krita/ui/ora/ora_save_context.h +++ b/krita/ui/ora/ora_save_context.h @@ -1,38 +1,38 @@ /* * Copyright (c) 2007 Cyrille Berger * * This library is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; version 2.1 of the License. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef _ORA_SAVE_CONTEXT_H_ #define _ORA_SAVE_CONTEXT_H_ class KoStore; #include #include "kis_open_raster_save_context.h" -#include +#include class KRITAUI_EXPORT OraSaveContext : public KisOpenRasterSaveContext { public: OraSaveContext(KoStore* _store); virtual QString saveDeviceData(KisPaintDeviceSP dev, KisMetaData::Store *metaData, KisImageWSP image); virtual void saveStack(const QDomDocument& doc); private: int m_id; KoStore* m_store; }; #endif diff --git a/krita/ui/processing/fill_processing_visitor.h b/krita/ui/processing/fill_processing_visitor.h index 44676aef4cb..766edc07fba 100644 --- a/krita/ui/processing/fill_processing_visitor.h +++ b/krita/ui/processing/fill_processing_visitor.h @@ -1,63 +1,64 @@ /* * Copyright (c) 2013 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __FILL_PROCESSING_VISITOR_H #define __FILL_PROCESSING_VISITOR_H #include #include #include #include +#include -class KDE_EXPORT FillProcessingVisitor : public KisSimpleProcessingVisitor +class KRITAUI_EXPORT FillProcessingVisitor : public KisSimpleProcessingVisitor { public: FillProcessingVisitor(const QPoint &startPoint, KisSelectionSP selection, KisResourcesSnapshotSP resources, bool useFastMode, bool usePattern, bool selectionOnly, int feather, int sizemod, int fillThreshold, bool unmerged, bool m_useBgColor); private: void visitNodeWithPaintDevice(KisNode *node, KisUndoAdapter *undoAdapter); void visitExternalLayer(KisExternalLayer *layer, KisUndoAdapter *undoAdapter); private: QPoint m_startPoint; KisSelectionSP m_selection; bool m_useFastMode; bool m_selectionOnly; bool m_usePattern; KisResourcesSnapshotSP m_resources; int m_feather; int m_sizemod; int m_fillThreshold; bool m_unmerged; bool m_useBgColor; }; #endif /* __FILL_PROCESSING_VISITOR_H */ diff --git a/krita/ui/qtsingleapplication/qtsingleapplication.h b/krita/ui/qtsingleapplication/qtsingleapplication.h index b0122f19548..0f8dce8c1a2 100644 --- a/krita/ui/qtsingleapplication/qtsingleapplication.h +++ b/krita/ui/qtsingleapplication/qtsingleapplication.h @@ -1,74 +1,74 @@ /**************************************************************************** ** ** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies). ** Contact: http://www.qt-project.org/legal ** ** This file is part of Qt Creator. ** ** Commercial License Usage ** Licensees holding valid commercial Qt licenses may use this file in ** accordance with the commercial license agreement provided with the ** Software or, alternatively, in accordance with the terms contained in ** a written agreement between you and Digia. For licensing terms and ** conditions see http://www.qt.io/licensing. For further information ** use the contact form at http://www.qt.io/contact-us. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 or version 3 as published by the Free ** Software Foundation and appearing in the file LICENSE.LGPLv21 and ** LICENSE.LGPLv3 included in the packaging of this file. Please review the ** following information to ensure the GNU Lesser General Public License ** requirements will be met: https://www.gnu.org/licenses/lgpl.html and ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Digia gives you certain additional ** rights. These rights are described in the Digia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ****************************************************************************/ #include #include QT_FORWARD_DECLARE_CLASS(QSharedMemory) class QtLocalPeer; -#include +#include class KRITAUI_EXPORT QtSingleApplication : public KApplication { Q_OBJECT public: QtSingleApplication(const QString &id, int &argc, char **argv); ~QtSingleApplication(); bool isRunning(qint64 pid = -1); void setActivationWindow(QWidget* aw, bool activateOnMessage = true); QWidget* activationWindow() const; bool event(QEvent *event); QString applicationId() const; void setBlock(bool value); public Q_SLOTS: bool sendMessage(const QByteArray &message, int timeout = 5000, qint64 pid = -1); void activateWindow(); Q_SIGNALS: void messageReceived(const QByteArray &message, QObject *socket); void fileOpenRequest(const QString &file); private: QString instancesFileName(const QString &appId); qint64 firstPeer; QSharedMemory *instances; QtLocalPeer *pidPeer; QWidget *actWin; QString appId; bool block; }; diff --git a/krita/ui/recorder/kis_recorded_action_creator_factory.h b/krita/ui/recorder/kis_recorded_action_creator_factory.h index 9bcfa03728f..cd2d17c6832 100644 --- a/krita/ui/recorder/kis_recorded_action_creator_factory.h +++ b/krita/ui/recorder/kis_recorded_action_creator_factory.h @@ -1,56 +1,56 @@ /* * Copyright (c) 2009,2011 Cyrille Berger * * 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_RECORDED_ACTION_CREATOR_FACTORY_H_ #define _KIS_RECORDED_ACTION_CREATOR_FACTORY_H_ -#include +#include class KisRecordedAction; class KisRecordedActionCreator; class QString; class QWidget; /** * This class allows to create widgets that are used to create new actions. */ class KRITAUI_EXPORT KisRecordedActionCreatorFactory { public: KisRecordedActionCreatorFactory(const QString& _id, const QString& _name); virtual ~KisRecordedActionCreatorFactory(); QString id() const; QString name() const; /** * @return true if the creation of this action require the use of a creator widget */ virtual bool requireCreator() const = 0; /** * Create an creator for the action. */ virtual KisRecordedActionCreator* createCreator(QWidget* parent) const; /** * Create an action. If the action require a creator, it should return 0. */ virtual KisRecordedAction* createAction() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/recorder/kis_recorded_action_creator_factory_registry.h b/krita/ui/recorder/kis_recorded_action_creator_factory_registry.h index 4fb326657b5..babbd33bc9a 100644 --- a/krita/ui/recorder/kis_recorded_action_creator_factory_registry.h +++ b/krita/ui/recorder/kis_recorded_action_creator_factory_registry.h @@ -1,57 +1,57 @@ /* * Copyright (c) 2009,2011 Cyrille Berger * * 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_RECORDED_ACTION_CREATOR_FACTORY_REGISTRY_H_ #define _KIS_RECORDED_ACTION_CREATOR_FACTORY_REGISTRY_H_ -#include +#include #include class KisRecordedAction; class KisRecordedActionCreatorFactory; /** * This class allow to create a creator for a specific recorded action. * */ class KRITAUI_EXPORT KisRecordedActionCreatorFactoryRegistry { private: KisRecordedActionCreatorFactoryRegistry(); ~KisRecordedActionCreatorFactoryRegistry(); public: static KisRecordedActionCreatorFactoryRegistry* instance(); /** * Add a factory of action creator. */ void add(KisRecordedActionCreatorFactory* factory); /** * @return an creator for the given action, or a null pointer if there is * no factory for that action. */ KisRecordedActionCreatorFactory* get(const QString& _id) const; /** * @return the list of creators */ QList creators() const; private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/recorder/kis_recorded_action_editor_factory.h b/krita/ui/recorder/kis_recorded_action_editor_factory.h index 5c007a29fc3..1c906569a62 100644 --- a/krita/ui/recorder/kis_recorded_action_editor_factory.h +++ b/krita/ui/recorder/kis_recorded_action_editor_factory.h @@ -1,50 +1,50 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_RECORDED_ACTION_EDITOR_FACTORY_H_ #define _KIS_RECORDED_ACTION_EDITOR_FACTORY_H_ -#include +#include class QWidget; class KisRecordedAction; /** * This class allow to create widget that can edit a @ref KisRecordedAction */ class KRITAUI_EXPORT KisRecordedActionEditorFactory { public: KisRecordedActionEditorFactory(); virtual ~KisRecordedActionEditorFactory(); /** * Create an editor for the action. * The widget is expected to have a 'actionChanged' signal that is emitted * when the editor has changed one of the parameter of the action. */ virtual QWidget* createEditor(QWidget* parent, KisRecordedAction* action) const = 0; /** * @return true if this factory can create an editor for the given action. */ virtual bool canEdit(const KisRecordedAction* action) const = 0; private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/recorder/kis_recorded_action_editor_factory_registry.h b/krita/ui/recorder/kis_recorded_action_editor_factory_registry.h index 12661c2142f..25122d81e83 100644 --- a/krita/ui/recorder/kis_recorded_action_editor_factory_registry.h +++ b/krita/ui/recorder/kis_recorded_action_editor_factory_registry.h @@ -1,59 +1,59 @@ /* * Copyright (c) 2009 Cyrille Berger * * 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_RECORDED_ACTION_EDITOR_FACTORY_REGISTRY_H_ #define _KIS_RECORDED_ACTION_EDITOR_FACTORY_REGISTRY_H_ -#include +#include class QWidget; class KisRecordedAction; class KisRecordedActionEditorFactory; /** * This class allow to create an editor for a specific recorded action. * * If two editors can edit the same type of action, then the editor that * was added last is used in priority. */ class KRITAUI_EXPORT KisRecordedActionEditorFactoryRegistry { private: KisRecordedActionEditorFactoryRegistry(); ~KisRecordedActionEditorFactoryRegistry(); public: static KisRecordedActionEditorFactoryRegistry* instance(); /** * Add a factory of action editor. */ void add(KisRecordedActionEditorFactory* factory); /** * @return an editor for the given action, or a null pointer if there is * no factory for that action. */ QWidget* createEditor(QWidget* parent, KisRecordedAction* action) const; /** * @return true if there is an editor for this action. */ bool hasEditor(KisRecordedAction* action) const; private: struct Private; Private* const d; }; #endif diff --git a/krita/ui/tests/kis_asl_layer_style_serializer_test.cpp b/krita/ui/tests/kis_asl_layer_style_serializer_test.cpp index cad82053b22..95e5c58658f 100644 --- a/krita/ui/tests/kis_asl_layer_style_serializer_test.cpp +++ b/krita/ui/tests/kis_asl_layer_style_serializer_test.cpp @@ -1,422 +1,422 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #include "kis_asl_layer_style_serializer_test.h" #include #include #include #include #include #include #include "testutil.h" #include "kis_psd_layer_style.h" #include "kis_asl_layer_style_serializer.h" #include #define CMP(object, method, value) QCOMPARE(style->object()->method(), value) void KisAslLayerStyleSerializerTest::testReading() { KisAslLayerStyleSerializer s; // QString srcFileName(TestUtil::fetchDataFileLazy("asl/test_all_style.asl")); QString srcFileName(TestUtil::fetchDataFileLazy("asl/test_all_and_pattern.asl")); QFile aslFile(srcFileName); aslFile.open(QIODevice::ReadOnly); s.readFromDevice(&aslFile); QVector styles = s.styles(); QVERIFY(styles.size() == 1); KisPSDLayerStyleSP style = styles.first(); CMP(dropShadow, effectEnabled, true); CMP(dropShadow, blendMode, COMPOSITE_MULT); CMP(dropShadow, color, QColor(Qt::black)); CMP(dropShadow, opacity, 15); CMP(dropShadow, angle, -120); CMP(dropShadow, useGlobalLight, false); CMP(dropShadow, distance, 2); CMP(dropShadow, spread, 1); CMP(dropShadow, size, 7); CMP(dropShadow, antiAliased, true); CMP(dropShadow, noise, 3); // CMP(dropShadow, contourLookupTable,); CMP(innerShadow, effectEnabled, true); CMP(innerShadow, blendMode, COMPOSITE_DARKEN); CMP(innerShadow, color, QColor(Qt::black)); CMP(innerShadow, opacity, 28); CMP(innerShadow, angle, 120); CMP(innerShadow, useGlobalLight, true); CMP(innerShadow, distance, 8); CMP(innerShadow, spread, 15); CMP(innerShadow, size, 27); CMP(innerShadow, antiAliased, false); CMP(innerShadow, noise, 10); // CMP(innerShadow, contourLookupTable,); CMP(outerGlow, effectEnabled, true); CMP(outerGlow, blendMode, COMPOSITE_SCREEN); - CMP(outerGlow, color, QColor(255,255,189.997)); + CMP(outerGlow, color, QColor(255, 255, 189)); CMP(outerGlow, opacity, 43); CMP(outerGlow, spread, 23); CMP(outerGlow, size, 109); CMP(outerGlow, antiAliased, true); CMP(outerGlow, noise, 29); // CMP(outerGlow, contourLookupTable,); // CMP(outerGlow, gradient,); CMP(outerGlow, fillType, psd_fill_solid_color); CMP(outerGlow, technique, psd_technique_precise); CMP(outerGlow, range, 69); CMP(outerGlow, jitter, 18); CMP(innerGlow, effectEnabled, true); CMP(innerGlow, blendMode, COMPOSITE_SCREEN); - CMP(innerGlow, color, QColor(255,255,189.997)); + CMP(innerGlow, color, QColor(255, 255, 189)); CMP(innerGlow, opacity, 55); CMP(innerGlow, spread, 21); CMP(innerGlow, size, 128); CMP(innerGlow, antiAliased, true); CMP(innerGlow, noise, 33); // CMP(innerGlow, contourLookupTable,); // CMP(innerGlow, gradient,); CMP(innerGlow, fillType, psd_fill_solid_color); CMP(innerGlow, technique, psd_technique_softer); CMP(innerGlow, range, 32); CMP(innerGlow, jitter, 22); CMP(innerGlow, source, psd_glow_edge); CMP(satin, effectEnabled, true); CMP(satin, blendMode, COMPOSITE_MULT); CMP(satin, color, QColor(Qt::black)); CMP(satin, opacity, 68); CMP(satin, angle, 19); CMP(satin, distance, 11); CMP(satin, size, 14); CMP(satin, antiAliased, false); CMP(satin, invert, true); // CMP(satin, contourLookupTable,); CMP(colorOverlay, effectEnabled, true); CMP(colorOverlay, blendMode, COMPOSITE_OVER); CMP(colorOverlay, color, QColor(Qt::red)); CMP(colorOverlay, opacity, 63); CMP(gradientOverlay, effectEnabled, true); CMP(gradientOverlay, blendMode, COMPOSITE_OVER); CMP(gradientOverlay, opacity, 100); CMP(gradientOverlay, angle, 90); CMP(gradientOverlay, style, psd_gradient_style_linear); CMP(gradientOverlay, reverse, false); CMP(gradientOverlay, alignWithLayer, true); CMP(gradientOverlay, scale, 100); CMP(gradientOverlay, gradientXOffset, 0); CMP(gradientOverlay, gradientYOffset, 0); //CMP(gradientOverlay, dither, ); CMP(gradientOverlay, gradient()->name, QString("Two Color")); CMP(stroke, effectEnabled, true); CMP(stroke, blendMode, COMPOSITE_OVER); CMP(stroke, opacity, 67); CMP(stroke, size, 13); CMP(stroke, fillType, psd_fill_solid_color); CMP(stroke, position, psd_stroke_outside); - CMP(stroke, color, QColor(210.0, 33.7665, 87.6887)); + CMP(stroke, color, QColor(210, 33, 87)); CMP(bevelAndEmboss, effectEnabled, true); CMP(bevelAndEmboss, highlightBlendMode, COMPOSITE_SCREEN); CMP(bevelAndEmboss, highlightOpacity, 75); - CMP(bevelAndEmboss, highlightColor, QColor(255.0, 255.0, 255.0)); + CMP(bevelAndEmboss, highlightColor, QColor(255, 255, 255)); CMP(bevelAndEmboss, shadowBlendMode, COMPOSITE_MULT); CMP(bevelAndEmboss, shadowOpacity, 75); CMP(bevelAndEmboss, shadowColor, QColor(Qt::black)); CMP(bevelAndEmboss, technique, psd_technique_softer); CMP(bevelAndEmboss, style, psd_bevel_inner_bevel); CMP(bevelAndEmboss, useGlobalLight, true); CMP(bevelAndEmboss, angle, 120); CMP(bevelAndEmboss, altitude, 30); CMP(bevelAndEmboss, depth, 83); CMP(bevelAndEmboss, size, 49); CMP(bevelAndEmboss, direction, psd_direction_up); // FIXME: contour CMP(bevelAndEmboss, glossAntiAliased, false); CMP(bevelAndEmboss, soften, 2); CMP(bevelAndEmboss, contourEnabled, true); // FIXME: contour curve CMP(bevelAndEmboss, antiAliased, true); CMP(bevelAndEmboss, contourRange, 60); CMP(bevelAndEmboss, textureEnabled, false); CMP(patternOverlay, effectEnabled, true); CMP(patternOverlay, blendMode, COMPOSITE_OVER); CMP(patternOverlay, opacity, 100); CMP(patternOverlay, alignWithLayer, true); CMP(patternOverlay, scale, 100); CMP(patternOverlay, horizontalPhase, 201); CMP(patternOverlay, verticalPhase, 162); CMP(patternOverlay, pattern()->name, QString("$$$/Presets/Patterns/Patterns_pat/Bubbles=Bubbles")); CMP(patternOverlay, pattern()->filename, QString("b7334da0-122f-11d4-8bb5-e27e45023b5f.pat")); } void KisAslLayerStyleSerializerTest::testWriting() { QVector styles; QByteArray refXMLDoc; { KisAslLayerStyleSerializer s; QString srcFileName(TestUtil::fetchDataFileLazy("asl/test_all_and_pattern.asl")); QFile aslFile(srcFileName); aslFile.open(QIODevice::ReadOnly); s.readFromDevice(&aslFile); styles = s.styles(); { aslFile.seek(0); KisAslReader reader; QDomDocument doc = reader.readFile(&aslFile); refXMLDoc = doc.toByteArray(); } } // now we have an initialized KisPSDLayerStyle object { KisAslLayerStyleSerializer s; s.setStyles(styles); QFile dstFile("test_written.asl"); dstFile.open(QIODevice::WriteOnly); s.saveToDevice(&dstFile); dstFile.close(); } QByteArray resultXMLDoc; { QFile resultFile("test_written.asl"); resultFile.open(QIODevice::ReadOnly); KisAslReader reader; QDomDocument doc = reader.readFile(&resultFile); resultXMLDoc = doc.toByteArray(); } QFile refXMLFile("save_round_trip_src.xml"); refXMLFile.open(QIODevice::WriteOnly); refXMLFile.write(refXMLDoc); refXMLFile.close(); QFile resultXMLFile("save_round_trip_dst.xml"); resultXMLFile.open(QIODevice::WriteOnly); resultXMLFile.write(resultXMLDoc); resultXMLFile.close(); QCOMPARE(resultXMLDoc, refXMLDoc); } #include void KisAslLayerStyleSerializerTest::testWritingGlobalPatterns() { KisPSDLayerStyleSP style(new KisPSDLayerStyle()); KoResourceServer *server = KoResourceServerProvider::instance()->patternServer(); QList sortedResources = server->sortedResources(); KoPattern *pattern = sortedResources.first(); Q_ASSERT(pattern); qDebug() << ppVar(pattern->name()); qDebug() << ppVar(pattern->filename()); style->patternOverlay()->setEffectEnabled(true); style->patternOverlay()->setPattern(pattern); { KisAslLayerStyleSerializer s; s.setStyles(QVector() << style); QFile dstFile("test_written_pattern_only.asl"); dstFile.open(QIODevice::WriteOnly); s.saveToDevice(&dstFile); dstFile.close(); } /* QByteArray resultXMLDoc; { QFile resultFile("test_written.asl"); resultFile.open(QIODevice::ReadOnly); KisAslReader reader; QDomDocument doc = reader.readFile(&resultFile); resultXMLDoc = doc.toByteArray(); } */ } void KisAslLayerStyleSerializerTest::testReadMultipleStyles() { KisPSDLayerStyleSP style(new KisPSDLayerStyle()); QVector styles; { KisAslLayerStyleSerializer s; QString srcFileName(TestUtil::fetchDataFileLazy("asl/multiple_styles.asl")); QFile aslFile(srcFileName); aslFile.open(QIODevice::ReadOnly); s.readFromDevice(&aslFile); styles = s.styles(); } { KisAslLayerStyleSerializer s; QString dstFileName("multiple_styles_out.asl"); QFile aslFile(dstFileName); aslFile.open(QIODevice::WriteOnly); s.setStyles(styles); s.saveToDevice(&aslFile); } { KisAslLayerStyleSerializer s; QString srcFileName("multiple_styles_out.asl"); QFile aslFile(srcFileName); aslFile.open(QIODevice::ReadOnly); s.readFromDevice(&aslFile); styles = s.styles(); qDebug() << ppVar(styles.size()); } } void KisAslLayerStyleSerializerTest::testWritingGradients() { KoStopGradient stopGradient(""); { const KoColorSpace * cs = KoColorSpaceRegistry::instance()->rgb8(); QList stops; stops << KoGradientStop(0.0, KoColor(Qt::black, cs)); stops << KoGradientStop(0.3, KoColor(Qt::red, cs)); stops << KoGradientStop(0.6, KoColor(Qt::green, cs)); stops << KoGradientStop(1.0, KoColor(Qt::white, cs)); stopGradient.setStops(stops); } KisPSDLayerStyleSP style(new KisPSDLayerStyle()); style->outerGlow()->setEffectEnabled(true); style->outerGlow()->setFillType(psd_fill_gradient); style->outerGlow()->setGradient(toQShared(new KoStopGradient(stopGradient))); style->innerGlow()->setEffectEnabled(true); style->innerGlow()->setFillType(psd_fill_gradient); style->innerGlow()->setGradient(toQShared(new KoStopGradient(stopGradient))); style->gradientOverlay()->setEffectEnabled(true); style->gradientOverlay()->setGradient(toQShared(new KoStopGradient(stopGradient))); style->stroke()->setEffectEnabled(true); style->stroke()->setFillType(psd_fill_gradient); style->stroke()->setGradient(toQShared(new KoStopGradient(stopGradient))); { KisAslLayerStyleSerializer s; s.setStyles(QVector() << style); QFile dstFile("test_written_stop_gradient.asl"); dstFile.open(QIODevice::WriteOnly); s.saveToDevice(&dstFile); dstFile.close(); } QString xmlDoc; { QFile resultFile("test_written_stop_gradient.asl"); resultFile.open(QIODevice::ReadOnly); KisAslReader reader; QDomDocument doc = reader.readFile(&resultFile); xmlDoc = doc.toString(); } { // the reference document has stripped "Idnt" field which is random QRegExp rx(""); rx.setMinimal(true); int pos = 0; while ((pos = rx.indexIn(xmlDoc, pos)) != -1) { xmlDoc.remove(pos, rx.matchedLength()); } { //QFile xmlFile("reference_gradients.asl.xml"); //xmlFile.open(QIODevice::WriteOnly); //xmlFile.write(xmlDoc.toLatin1()); //xmlFile.close(); } QString refFileName(TestUtil::fetchDataFileLazy("reference_gradients.asl.xml")); QFile refFile(refFileName); refFile.open(QIODevice::ReadOnly); QString refDoc = QString(refFile.readAll()); QCOMPARE(xmlDoc, refDoc); } } QTEST_KDEMAIN(KisAslLayerStyleSerializerTest, GUI) diff --git a/krita/ui/tool/kis_delegated_tool_policies.h b/krita/ui/tool/kis_delegated_tool_policies.h index 159fd5b352c..bdc8b4d6217 100644 --- a/krita/ui/tool/kis_delegated_tool_policies.h +++ b/krita/ui/tool/kis_delegated_tool_policies.h @@ -1,40 +1,40 @@ /* * Copyright (c) 2014 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_DELEGATED_TOOL_POLICIES_H #define __KIS_DELEGATED_TOOL_POLICIES_H #include -#include "krita_export.h" +#include "kritaui_export.h" class KoCanvasBase; struct KRITAUI_EXPORT NoopActivationPolicy { static inline void onActivate(KoCanvasBase *canvas) { Q_UNUSED(canvas); } }; struct KRITAUI_EXPORT DeselectShapesActivationPolicy { static void onActivate(KoCanvasBase *canvas); }; #endif /* __KIS_DELEGATED_TOOL_POLICIES_H */ diff --git a/krita/ui/tool/kis_figure_painting_tool_helper.h b/krita/ui/tool/kis_figure_painting_tool_helper.h index 521e89e1623..2011d3fced4 100644 --- a/krita/ui/tool/kis_figure_painting_tool_helper.h +++ b/krita/ui/tool/kis_figure_painting_tool_helper.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_FIGURE_PAINTING_TOOL_HELPER_H #define __KIS_FIGURE_PAINTING_TOOL_HELPER_H #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_paint_information.h" #include "strokes/freehand_stroke.h" class KoCanvasResourceManager; class KisStrokesFacade; class KRITAUI_EXPORT KisFigurePaintingToolHelper { protected: typedef FreehandStrokeStrategy::PainterInfo PainterInfo; public: KisFigurePaintingToolHelper(const KUndo2MagicString &name, KisImageWSP image, KisNodeSP currentNode, KoCanvasResourceManager *resourceManager, KisPainter::StrokeStyle strokeStyle, KisPainter::FillStyle fillStyle); ~KisFigurePaintingToolHelper(); void paintLine(const KisPaintInformation &pi0, const KisPaintInformation &pi1); void paintPolyline(const vQPointF &points); void paintPolygon(const vQPointF &points); void paintRect(const QRectF &rect); void paintEllipse(const QRectF &rect); void paintPainterPath(const QPainterPath &path); private: KisStrokeId m_strokeId; KisResourcesSnapshotSP m_resources; PainterInfo *m_painterInfo; KisStrokesFacade *m_strokesFacade; }; #endif /* __KIS_FIGURE_PAINTING_TOOL_HELPER_H */ diff --git a/krita/ui/tool/kis_painting_information_builder.h b/krita/ui/tool/kis_painting_information_builder.h index 02db87c9f3e..017f5f8a630 100644 --- a/krita/ui/tool/kis_painting_information_builder.h +++ b/krita/ui/tool/kis_painting_information_builder.h @@ -1,110 +1,110 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_PAINTING_INFORMATION_BUILDER_H #define __KIS_PAINTING_INFORMATION_BUILDER_H #include #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_paint_information.h" class KoPointerEvent; class KisTool; class KisToolFreehand; class KisCoordinatesConverter; class KisSpeedSmoother; class KRITAUI_EXPORT KisPaintingInformationBuilder : public QObject { Q_OBJECT public: KisPaintingInformationBuilder(); ~KisPaintingInformationBuilder(); KisPaintInformation startStroke(KoPointerEvent *event, int timeElapsed); KisPaintInformation continueStroke(KoPointerEvent *event, int timeElapsed); KisPaintInformation hover(const QPointF &imagePoint, const KoPointerEvent *event); protected Q_SLOTS: void updateSettings(); protected: virtual QPointF adjustDocumentPoint(const QPointF &point, const QPointF &startPoint); virtual QPointF documentToImage(const QPointF &point); virtual QPointF imageToView(const QPointF &point); virtual qreal calculatePerspective(const QPointF &documentPoint); private: KisPaintInformation createPaintingInformation(KoPointerEvent *event, int timeElapsed); /** * Defines how many descret samples are stored in a precomputed array * of different pressures. */ static const int LEVEL_OF_PRESSURE_RESOLUTION; qreal pressureToCurve(qreal pressure); private: QVector m_pressureSamples; QPointF m_startPoint; QScopedPointer m_speedSmoother; }; class KRITAUI_EXPORT KisConverterPaintingInformationBuilder : public KisPaintingInformationBuilder { Q_OBJECT public: KisConverterPaintingInformationBuilder(const KisCoordinatesConverter *converter); protected: virtual QPointF documentToImage(const QPointF &point); virtual QPointF imageToView(const QPointF &point); private: const KisCoordinatesConverter *m_converter; }; class KRITAUI_EXPORT KisToolFreehandPaintingInformationBuilder : public KisPaintingInformationBuilder { Q_OBJECT public: KisToolFreehandPaintingInformationBuilder(KisToolFreehand *tool); protected: virtual QPointF documentToImage(const QPointF &point); virtual QPointF imageToView(const QPointF &point); virtual QPointF adjustDocumentPoint(const QPointF &point, const QPointF &startPoint); virtual qreal calculatePerspective(const QPointF &documentPoint); private: KisToolFreehand *m_tool; }; #endif /* __KIS_PAINTING_INFORMATION_BUILDER_H */ diff --git a/krita/ui/tool/kis_resources_snapshot.h b/krita/ui/tool/kis_resources_snapshot.h index 28425962e87..92426abda21 100644 --- a/krita/ui/tool/kis_resources_snapshot.h +++ b/krita/ui/tool/kis_resources_snapshot.h @@ -1,90 +1,90 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_RESOURCES_SNAPSHOT_H #define __KIS_RESOURCES_SNAPSHOT_H #include "kis_shared.h" #include "kis_shared_ptr.h" #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_painter.h" #include "kis_default_bounds.h" class KoCanvasResourceManager; class KoCompositeOp; class KisPainter; class KisPostExecutionUndoAdapter; class KisRecordedPaintAction; class KoPattern; class KRITAUI_EXPORT KisResourcesSnapshot : public KisShared { public: KisResourcesSnapshot(KisImageWSP image, KisNodeSP currentNode, KisPostExecutionUndoAdapter *undoAdapter, KoCanvasResourceManager *resourceManager, KisDefaultBoundsBaseSP bounds = 0); ~KisResourcesSnapshot(); void setupPainter(KisPainter *painter); // XXX: This was marked as KDE_DEPRECATED, but no althernative was // given in the apidox. void setupPaintAction(KisRecordedPaintAction *action); KisPostExecutionUndoAdapter* postExecutionUndoAdapter() const; void setCurrentNode(KisNodeSP node); void setStrokeStyle(KisPainter::StrokeStyle strokeStyle); void setFillStyle(KisPainter::FillStyle fillStyle); KisNodeSP currentNode() const; KisImageWSP image() const; bool needsIndirectPainting() const; QString indirectPaintingCompositeOp() const; /** * \return currently active selection. Note that it will return * null if current node *is* the current selection. This * is done to avoid recursive selection application when * painting on selectgion masks. */ KisSelectionSP activeSelection() const; bool needsAirbrushing() const; int airbrushingRate() const; void setOpacity(qreal opacity); quint8 opacity() const; const KoCompositeOp* compositeOp() const; KoPattern* currentPattern() const; KoColor currentFgColor() const; KoColor currentBgColor() const; KisPaintOpPresetSP currentPaintOpPreset() const; /// @return the channel lock flags of the current node with the global override applied QBitArray channelLockFlags() const; qreal effectiveZoom() const; private: struct Private; Private * const m_d; }; typedef KisSharedPtr KisResourcesSnapshotSP; #endif /* __KIS_RESOURCES_SNAPSHOT_H */ diff --git a/krita/ui/tool/kis_selection_tool_config_widget_helper.h b/krita/ui/tool/kis_selection_tool_config_widget_helper.h index 694569d0adb..02f47348b57 100644 --- a/krita/ui/tool/kis_selection_tool_config_widget_helper.h +++ b/krita/ui/tool/kis_selection_tool_config_widget_helper.h @@ -1,63 +1,63 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_SELECTION_TOOL_CONFIG_WIDGET_HELPER_H #define __KIS_SELECTION_TOOL_CONFIG_WIDGET_HELPER_H #include -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_selection.h" class QKeyEvent; class KisCanvas2; class KisSelectionOptions; class KRITAUI_EXPORT KisSelectionToolConfigWidgetHelper : public QObject { Q_OBJECT Q_PROPERTY(int selectionAction READ action WRITE slotSetAction NOTIFY selectionActionChanged); public: KisSelectionToolConfigWidgetHelper(const QString &windowTitle); void createOptionWidget(KisCanvas2 *canvas, const QString &toolId); KisSelectionOptions* optionWidget() const; SelectionMode selectionMode() const; SelectionAction selectionAction() const; int action() const { return selectionAction(); }; bool processKeyPressEvent(QKeyEvent *event); Q_SIGNALS: void selectionActionChanged(int newAction); public Q_SLOTS: void slotSetAction(int action); void slotSetSelectionMode(int mode); private: KisSelectionOptions* m_optionsWidget; SelectionAction m_selectionAction; SelectionMode m_selectionMode; QString m_windowTitle; }; #endif /* __KIS_SELECTION_TOOL_CONFIG_WIDGET_HELPER_H */ diff --git a/krita/ui/tool/kis_selection_tool_helper.h b/krita/ui/tool/kis_selection_tool_helper.h index a8e9d2a4c0b..5b62f243fb6 100644 --- a/krita/ui/tool/kis_selection_tool_helper.h +++ b/krita/ui/tool/kis_selection_tool_helper.h @@ -1,55 +1,55 @@ /* * Copyright (c) 2007 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SELECTION_TOOL_HELPER_H #define KIS_SELECTION_TOOL_HELPER_H -#include +#include #include "kundo2magicstring.h" #include "kis_layer.h" #include "kis_selection.h" class KoShape; class KisCanvas2; /** * XXX: Doc! */ class KRITAUI_EXPORT KisSelectionToolHelper { public: KisSelectionToolHelper(KisCanvas2* canvas, const KUndo2MagicString& name); virtual ~KisSelectionToolHelper(); void selectPixelSelection(KisPixelSelectionSP selection, SelectionAction action); void addSelectionShape(KoShape* shape); void addSelectionShapes(QList shapes); void cropRectIfNeeded(QRect *rect); void cropPathIfNeeded(QPainterPath *path); private: KisCanvas2* m_canvas; KisImageWSP m_image; KisLayerSP m_layer; KUndo2MagicString m_name; }; #endif diff --git a/krita/ui/tool/kis_shape_tool_helper.h b/krita/ui/tool/kis_shape_tool_helper.h index d0f5acd24cd..60e3074907c 100644 --- a/krita/ui/tool/kis_shape_tool_helper.h +++ b/krita/ui/tool/kis_shape_tool_helper.h @@ -1,41 +1,41 @@ /* * Copyright (c) 2009 Sven Langkamp * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_SHAPE_TOOL_HELPER_H #define KIS_SHAPE_TOOL_HELPER_H -#include +#include #include class KoShape; /** * KisShapeToolHelper provides shapes and fallback shapes for shape based tools */ class KRITAUI_EXPORT KisShapeToolHelper { public: static KoShape* createRectangleShape(const QRectF& rect); static KoShape* createEllipseShape(const QRectF& rect); }; #endif diff --git a/krita/ui/tool/kis_smoothing_options.h b/krita/ui/tool/kis_smoothing_options.h index c91d32d4106..66b597f2782 100644 --- a/krita/ui/tool/kis_smoothing_options.h +++ b/krita/ui/tool/kis_smoothing_options.h @@ -1,82 +1,82 @@ /* * Copyright (c) 2012 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_SMOOTHING_OPTIONS_H #define KIS_SMOOTHING_OPTIONS_H #include #include -#include +#include class KRITAUI_EXPORT KisSmoothingOptions { public: enum SmoothingType { NO_SMOOTHING = 0, SIMPLE_SMOOTHING, WEIGHTED_SMOOTHING, STABILIZER }; public: KisSmoothingOptions(); SmoothingType smoothingType() const; void setSmoothingType(SmoothingType value); qreal smoothnessDistance() const; void setSmoothnessDistance(qreal value); qreal tailAggressiveness() const; void setTailAggressiveness(qreal value); bool smoothPressure() const; void setSmoothPressure(bool value); bool useScalableDistance() const; void setUseScalableDistance(bool value); qreal delayDistance() const; void setDelayDistance(qreal value); void setUseDelayDistance(bool value); bool useDelayDistance() const; void setFinishStabilizedCurve(bool value); bool finishStabilizedCurve() const; void setStabilizeSensors(bool value); bool stabilizeSensors() const; private: SmoothingType m_smoothingType; qreal m_smoothnessDistance; qreal m_tailAggressiveness; bool m_smoothPressure; bool m_useScalableDistance; qreal m_delayDistance; bool m_useDelayDistance; bool m_finishStabilizedCurve; bool m_stabilizeSensors; }; typedef QSharedPointer KisSmoothingOptionsSP; #endif // KIS_SMOOTHING_OPTIONS_H diff --git a/krita/ui/tool/kis_tool.h b/krita/ui/tool/kis_tool.h index d11f6a2dcb0..00f2f3c24a3 100644 --- a/krita/ui/tool/kis_tool.h +++ b/krita/ui/tool/kis_tool.h @@ -1,368 +1,368 @@ /* * Copyright (c) 2006 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_H_ #define KIS_TOOL_H_ #include #include #include #include #include -#include +#include #include #define PRESS_CONDITION(_event, _mode, _button, _modifier) \ (this->mode() == (_mode) && (_event)->button() == (_button) && \ (_event)->modifiers() == (_modifier)) #define PRESS_CONDITION_WB(_event, _mode, _button, _modifier) \ (this->mode() == (_mode) && (_event)->button() & (_button) && \ (_event)->modifiers() == (_modifier)) #define PRESS_CONDITION_OM(_event, _mode, _button, _modifier) \ (this->mode() == (_mode) && (_event)->button() == (_button) && \ ((_event)->modifiers() & (_modifier) || \ (_event)->modifiers() == Qt::NoModifier)) #define RELEASE_CONDITION(_event, _mode, _button) \ (this->mode() == (_mode) && (_event)->button() == (_button)) #define RELEASE_CONDITION_WB(_event, _mode, _button) \ (this->mode() == (_mode) && (_event)->button() & (_button)) #define MOVE_CONDITION(_event, _mode) (this->mode() == (_mode)) #ifdef __GNUC__ #define WARN_WRONG_MODE(_mode) qWarning() << "Unexpected tool event has come to" << __func__ << "while being mode" << _mode << "!" #else #define WARN_WRONG_MODE(_mode) qWarning() << "Unexpected tool event has come while being mode" << _mode << "!" #endif #define CHECK_MODE_SANITY_OR_RETURN(_mode) if (mode() != _mode) { WARN_WRONG_MODE(mode()); return; } class KoCanvasBase; class KoPattern; class KoAbstractGradient; class KisFilterConfiguration; class QPainter; class QPainterPath; class QPolygonF; class KisRecordedPaintAction; /// Definitions of the toolgroups of Krita static const QString TOOL_TYPE_SHAPE = "0 Krita/Shape"; // Geometric shapes like ellipses and lines static const QString TOOL_TYPE_FREEHAND = "1 Krita/Freehand"; // Freehand drawing tools static const QString TOOL_TYPE_TRANSFORM = "2 Krita/Transform"; // Tools that transform the layer; static const QString TOOL_TYPE_FILL = "3 Krita/Fill"; // Tools that fill parts of the canvas static const QString TOOL_TYPE_VIEW = "4 Krita/View"; // Tools that affect the canvas: pan, zoom, etc. static const QString TOOL_TYPE_SELECTED = "5 Krita/Select"; // Tools that select pixels //activation id for Krita tools, Krita tools are always active and handle locked and invisible layers by themself static const QString KRITA_TOOL_ACTIVATION_ID = "flake/always"; class KRITAUI_EXPORT KisTool : public KoToolBase { Q_OBJECT Q_PROPERTY(bool isActive READ isActive NOTIFY isActiveChanged) public: enum { FLAG_USES_CUSTOM_PRESET=0x01, FLAG_USES_CUSTOM_COMPOSITEOP=0x02 }; KisTool(KoCanvasBase * canvas, const QCursor & cursor); virtual ~KisTool(); virtual int flags() const { return 0; } void deleteSelection(); // KoToolBase Implementation. public: /** * Called by KisToolProxy when the primary action of the tool is * going to be started now, that is when all the modifiers are * pressed and the only thing left is just to press the mouse * button. On coming of this callback the tool is supposed to * prepare the cursor and/or the outline to show the user shat is * going to happen next */ virtual void activatePrimaryAction(); /** * Called by KisToolProxy when the primary is no longer possible * to be started now, e.g. when its modifiers and released. The * tool is supposed revert all the preparetions it has doen in * activatePrimaryAction(). */ virtual void deactivatePrimaryAction(); /** * Called by KisToolProxy when a primary action for the tool is * started. The \p event stores the original event that * started the stroke. The \p event is _accepted_ by default. If * the tool decides to ignore this particular action (e.g. when * the node is not editable), it should call event->ignore(). Then * no further continuePrimaryAction() or endPrimaryAction() will * be called until the next user action. */ virtual void beginPrimaryAction(KoPointerEvent *event); /** * Called by KisToolProxy when the primary action is in progress * of pointer movement. If the tool has ignored the event in * beginPrimaryAction(), this method will not be called. */ virtual void continuePrimaryAction(KoPointerEvent *event); /** * Called by KisToolProxy when the primary action is being * finished, that is while mouseRelease or tabletRelease event. * If the tool has ignored the event in beginPrimaryAction(), this * method will not be called. */ virtual void endPrimaryAction(KoPointerEvent *event); /** * The same as beginPrimaryAction(), but called when the stroke is * started by a double-click * * \see beginPrimaryAction() */ virtual void beginPrimaryDoubleClickAction(KoPointerEvent *event); /** * Returns true if the tool can handle (and wants to handle) a * very tight flow of input events from the tablet */ virtual bool primaryActionSupportsHiResEvents() const; enum ToolAction { Primary, AlternateChangeSize, AlternatePickFgNode, AlternatePickBgNode, AlternatePickFgImage, AlternatePickBgImage, AlternateSecondary, AlternateThird, AlternateFourth, AlternateFifth, Alternate_NONE = 10000 }; enum AlternateAction { ChangeSize = AlternateChangeSize, PickFgNode = AlternatePickFgNode, PickBgNode = AlternatePickBgNode, PickFgImage = AlternatePickFgImage, PickBgImage = AlternatePickBgImage, Secondary = AlternateSecondary, Third = AlternateThird, Fourth = AlternateFourth, Fifth = AlternateFifth, NONE = 10000 }; static AlternateAction actionToAlternateAction(ToolAction action); virtual void activateAlternateAction(AlternateAction action); virtual void deactivateAlternateAction(AlternateAction action); virtual void beginAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void continueAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void endAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void beginAlternateDoubleClickAction(KoPointerEvent *event, AlternateAction action); void mousePressEvent(KoPointerEvent *event); void mouseDoubleClickEvent(KoPointerEvent *event); void mouseTripleClickEvent(KoPointerEvent *event); void mouseReleaseEvent(KoPointerEvent *event); void mouseMoveEvent(KoPointerEvent *event); bool isActive() const; public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); virtual void deactivate(); virtual void canvasResourceChanged(int key, const QVariant & res); // Implement this slot in case there are any widgets or properties which need // to be updated after certain operations, to reflect the inner state correctly. // At the moment this is used for smoothing options in the freehand brush, but // this will likely be expanded. virtual void updateSettingsViews(); Q_SIGNALS: void isActiveChanged(); protected: // conversion methods are also needed by the paint information builder friend class KisToolPaintingInformationBuilder; /// Convert from native (postscript points) to image pixel /// coordinates. QPointF convertToPixelCoord(KoPointerEvent *e); QPointF convertToPixelCoord(const QPointF& pt); protected: QPointF widgetCenterInWidgetPixels(); QPointF convertDocumentToWidget(const QPointF& pt); /// Convert from native (postscript points) to integer image pixel /// coordinates. This truncates the floating point components and /// should be used in preference to QPointF::toPoint(), which rounds, /// to ensure the cursor acts on the pixel it is visually over. QPoint convertToIntPixelCoord(KoPointerEvent *e); QRectF convertToPt(const QRectF &rect); QPointF viewToPixel(const QPointF &viewCoord) const; /// Convert an integer pixel coordinate into a view coordinate. /// The view coordinate is at the centre of the pixel. QPointF pixelToView(const QPoint &pixelCoord) const; /// Convert a floating point pixel coordinate into a view coordinate. QPointF pixelToView(const QPointF &pixelCoord) const; /// Convert a pixel rectangle into a view rectangle. QRectF pixelToView(const QRectF &pixelRect) const; /// Convert a pixel path into a view path QPainterPath pixelToView(const QPainterPath &pixelPath) const; /// Convert a pixel polygon into a view path QPolygonF pixelToView(const QPolygonF &pixelPolygon) const; /// Update the canvas for the given rectangle in image pixel coordinates. void updateCanvasPixelRect(const QRectF &pixelRect); /// Update the canvas for the given rectangle in view coordinates. void updateCanvasViewRect(const QRectF &viewRect); virtual QWidget* createOptionWidget(); /** * To determine whether this tool will change its behavior when * modifier keys are pressed */ virtual bool listeningToModifiers(); /** * Request that this tool no longer listen to modifier keys * (Responding to the request is optional) */ virtual void listenToModifiers(bool listen); protected: KisImageWSP image() const; QCursor cursor() const; /// Call this to set the document modified void notifyModified() const; KisImageWSP currentImage(); KoPattern* currentPattern(); KoAbstractGradient *currentGradient(); KisNodeSP currentNode(); KoColor currentFgColor(); KoColor currentBgColor(); KisPaintOpPresetSP currentPaintOpPreset(); KisFilterConfiguration *currentGenerator(); virtual void setupPaintAction(KisRecordedPaintAction* action); /// paint the path which is in view coordinates, default paint mode is XOR_MODE, BW_MODE is also possible /// never apply transformations to the painter, they would be useless, if drawing in OpenGL mode. The coordinates in the path should be in view coordinates. void paintToolOutline(QPainter * painter, const QPainterPath &path); /// Sets the systemLocked for the current node, this will not deactivate the tool buttons void setCurrentNodeLocked(bool locked); /// Checks checks if the current node is editable bool nodeEditable(); /// Checks checks if the selection is editable, only applies to local selection as global selection is always editable bool selectionEditable(); /// Override the cursor appropriately if current node is not editable bool overrideCursorIfNotEditable(); protected: enum ToolMode { HOVER_MODE, PAINT_MODE, SECONDARY_PAINT_MODE, MIRROR_AXIS_SETUP_MODE, GESTURE_MODE, PAN_MODE, OTHER // not used now }; virtual void setMode(ToolMode mode); virtual ToolMode mode() const; protected Q_SLOTS: /** * Called whenever the configuration settings change. */ virtual void resetCursorStyle(); /** * Called when the user requested undo while the stroke is * active. If you tool supports undo of the part of its actions, * override this method and do the needed work there. * * NOTE: Default implementation forwards this request to * requestStrokeCancellation() method, so that the stroke * would be cancelled. */ virtual void requestUndoDuringStroke(); /** * Called when the user requested the cancellation of the current * stroke. If you tool supports cancelling, override this method * and do the needed work there */ virtual void requestStrokeCancellation(); /** * Called when the image decided that the stroke should better be * ended. If you tool supports long strokes, override this method * and do the needed work there */ virtual void requestStrokeEnd(); private Q_SLOTS: void slotToggleFgBg(); void slotResetFgBg(); private: ToolMode m_mode; bool m_isActive; struct Private; Private* const d; }; #endif // KIS_TOOL_H_ diff --git a/krita/ui/tool/kis_tool_freehand.h b/krita/ui/tool/kis_tool_freehand.h index 274bcbe7d28..d4a189e6d29 100644 --- a/krita/ui/tool/kis_tool_freehand.h +++ b/krita/ui/tool/kis_tool_freehand.h @@ -1,131 +1,131 @@ /* * Copyright (c) 2003-2008 Boudewijn Rempt * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_FREEHAND_H_ #define KIS_TOOL_FREEHAND_H_ #include "kis_types.h" #include "kis_tool_paint.h" #include "kis_paint_information.h" #include "kis_resources_snapshot.h" #include "kis_paintop_settings.h" #include "kis_distance_information.h" #include "kis_smoothing_options.h" -#include "krita_export.h" +#include "kritaui_export.h" class KoPointerEvent; class KoCanvasBase; class KisPaintingInformationBuilder; class KisToolFreehandHelper; class KisRecordingAdapter; class KRITAUI_EXPORT KisToolFreehand : public KisToolPaint { Q_OBJECT public: EIGEN_MAKE_ALIGNED_OPERATOR_NEW KisToolFreehand(KoCanvasBase * canvas, const QCursor & cursor, const KUndo2MagicString &transactionText); virtual ~KisToolFreehand(); virtual int flags() const; public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); void deactivate(); protected: bool tryPickByPaintOp(KoPointerEvent *event, AlternateAction action); bool primaryActionSupportsHiResEvents() const; void beginPrimaryAction(KoPointerEvent *event); void continuePrimaryAction(KoPointerEvent *event); void endPrimaryAction(KoPointerEvent *event); void activateAlternateAction(AlternateAction action); void deactivateAlternateAction(AlternateAction action); void beginAlternateAction(KoPointerEvent *event, AlternateAction action); void continueAlternateAction(KoPointerEvent *event, AlternateAction action); void endAlternateAction(KoPointerEvent *event, AlternateAction action); virtual bool wantsAutoScroll() const; virtual void initStroke(KoPointerEvent *event); virtual void doStroke(KoPointerEvent *event); virtual void endStroke(); virtual QPainterPath getOutlinePath(const QPointF &documentPos, const KoPointerEvent *event, KisPaintOpSettings::OutlineMode outlineMode); KisPaintingInformationBuilder* paintingInformationBuilder() const; KisRecordingAdapter* recordingAdapter() const; void resetHelper(KisToolFreehandHelper *helper); protected Q_SLOTS: void explicitUpdateOutline(); virtual void resetCursorStyle(); void setAssistant(bool assistant); private: friend class KisToolFreehandPaintingInformationBuilder; /** * Adjusts a coordinates according to a KisPaintingAssitant, * if available. */ QPointF adjustPosition(const QPointF& point, const QPointF& strokeBegin); /** * Calculates a coefficient for KisPaintInformation * according to perspective grid values */ qreal calculatePerspective(const QPointF &documentPoint); protected: friend class KisViewManager; friend class KisView; friend class KisSketchView; KisSmoothingOptionsSP smoothingOptions() const; bool m_assistant; double m_magnetism; private: KisPaintingInformationBuilder *m_infoBuilder; KisToolFreehandHelper *m_helper; KisRecordingAdapter *m_recordingAdapter; QPointF m_initialGestureDocPoint; QPointF m_lastDocumentPoint; QPoint m_initialGestureGlobalPoint; }; #endif // KIS_TOOL_FREEHAND_H_ diff --git a/krita/ui/tool/kis_tool_freehand_helper.h b/krita/ui/tool/kis_tool_freehand_helper.h index 4de5e13e590..b49b306c58d 100644 --- a/krita/ui/tool/kis_tool_freehand_helper.h +++ b/krita/ui/tool/kis_tool_freehand_helper.h @@ -1,169 +1,169 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __KIS_TOOL_FREEHAND_HELPER_H #define __KIS_TOOL_FREEHAND_HELPER_H #include #include "kis_types.h" -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_paint_information.h" #include "strokes/freehand_stroke.h" #include "kis_default_bounds.h" #include "kis_paintop_settings.h" #include "kis_smoothing_options.h" class KoPointerEvent; class KoCanvasResourceManager; class KisPaintingInformationBuilder; class KisRecordingAdapter; class KisStrokesFacade; class KisPostExecutionUndoAdapter; class KisPaintOp; class KRITAUI_EXPORT KisToolFreehandHelper : public QObject { Q_OBJECT protected: typedef FreehandStrokeStrategy::PainterInfo PainterInfo; public: KisToolFreehandHelper(KisPaintingInformationBuilder *infoBuilder, const KUndo2MagicString &transactionText = KUndo2MagicString(), KisRecordingAdapter *recordingAdapter = 0); ~KisToolFreehandHelper(); void setSmoothness(KisSmoothingOptionsSP smoothingOptions); KisSmoothingOptionsSP smoothingOptions() const; bool isRunning() const; void initPaint(KoPointerEvent *event, KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP currentNode, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter, KisNodeSP overrideNode = 0, KisDefaultBoundsBaseSP bounds = 0); void paint(KoPointerEvent *event); void endPaint(); const KisPaintOp* currentPaintOp() const; QPainterPath paintOpOutline(const QPointF &savedCursorPos, const KoPointerEvent *event, const KisPaintOpSettings *globalSettings, KisPaintOpSettings::OutlineMode mode) const; int canvasRotation(); void setCanvasRotation(int rotation = 0); bool canvasMirroredH(); void setCanvasHorizontalMirrorState (bool mirrored = false); Q_SIGNALS: /** * The signal is emitted when the outline should be updated * explicitly by the tool. Used by Stabilizer option, because it * paints on internal timer events instead of the on every paint() * event */ void requestExplicitUpdateOutline(); protected: void cancelPaint(); int elapsedStrokeTime() const; void initPaintImpl(const KisPaintInformation &previousPaintInformation, KoCanvasResourceManager *resourceManager, KisImageWSP image, KisNodeSP node, KisStrokesFacade *strokesFacade, KisPostExecutionUndoAdapter *undoAdapter, KisNodeSP overrideNode = 0, KisDefaultBoundsBaseSP bounds = 0); protected: virtual void createPainters(QVector &painterInfos, const QPointF &lastPosition, int lastTime); // to be overridden in derived classes to add painting with // multiple painters virtual void paintAt(const QVector &painterInfos, const KisPaintInformation &pi); virtual void paintLine(const QVector &painterInfos, const KisPaintInformation &pi1, const KisPaintInformation &pi2); virtual void paintBezierCurve(const QVector &painterInfos, const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2); // lo-level methods for painting primitives void paintAt(PainterInfo *painterInfo, const KisPaintInformation &pi); void paintLine(PainterInfo *painterInfo, const KisPaintInformation &pi1, const KisPaintInformation &pi2); void paintBezierCurve(PainterInfo *painterInfo, const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2); // hi-level methods for painting primitives void paintAt(const KisPaintInformation &pi); void paintLine(const KisPaintInformation &pi1, const KisPaintInformation &pi2); void paintBezierCurve(const KisPaintInformation &pi1, const QPointF &control1, const QPointF &control2, const KisPaintInformation &pi2); private: void paintBezierSegment(KisPaintInformation pi1, KisPaintInformation pi2, QPointF tangent1, QPointF tangent2); void stabilizerStart(KisPaintInformation firstPaintInfo); void stabilizerEnd(); private Q_SLOTS: void finishStroke(); void doAirbrushing(); void stabilizerPollAndPaint(); private: struct Private; Private * const m_d; }; #endif /* __KIS_TOOL_FREEHAND_HELPER_H */ diff --git a/krita/ui/tool/kis_tool_paint.h b/krita/ui/tool/kis_tool_paint.h index 36d63680d05..7458201c263 100644 --- a/krita/ui/tool/kis_tool_paint.h +++ b/krita/ui/tool/kis_tool_paint.h @@ -1,215 +1,215 @@ /* * 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 #include #include #include #include #include #include #include #include #include #include #include #include -#include +#include #include #include #include #include #include "kis_tool.h" #include class QEvent; class QKeyEvent; class QPaintEvent; class QGridLayout; class QLabel; class QPoint; class KoCompositeOp; class KoCanvasBase; // wacom const static int LEVEL_OF_PRESSURE_RESOLUTION = 1024; class KRITAUI_EXPORT KisToolPaint : public KisTool { Q_OBJECT public: KisToolPaint(KoCanvasBase * canvas, const QCursor & cursor); virtual ~KisToolPaint(); virtual int flags() const; virtual void mousePressEvent(KoPointerEvent *event); virtual void mouseReleaseEvent(KoPointerEvent *event); virtual void mouseMoveEvent(KoPointerEvent *event); protected: void setMode(ToolMode mode); virtual void canvasResourceChanged(int key, const QVariant & v); virtual void paint(QPainter& gc, const KoViewConverter &converter); virtual void activatePrimaryAction(); virtual void deactivatePrimaryAction(); virtual void activateAlternateAction(AlternateAction action); virtual void deactivateAlternateAction(AlternateAction action); virtual void beginAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void continueAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void endAlternateAction(KoPointerEvent *event, AlternateAction action); virtual void requestUpdateOutline(const QPointF &outlineDocPoint, const KoPointerEvent *event); /** If the paint tool support outline like brushes, set to true. * If not (e.g. gradient tool), set to false. Default is false. */ void setSupportOutline(bool supportOutline) { m_supportOutline = supportOutline; } virtual QPainterPath getOutlinePath(const QPointF &documentPos, const KoPointerEvent *event, KisPaintOpSettings::OutlineMode outlineMode); protected: bool isOutlineEnabled() const; void setOutlineEnabled(bool enabled); bool pickColor(const QPointF &documentPixel, AlternateAction action); /// Add the tool-specific layout to the default option widget layout. void addOptionWidgetLayout(QLayout *layout); /// Add a widget and a label to the current option widget layout. virtual void addOptionWidgetOption(QWidget *control, QWidget *label = 0); void showControl(QWidget *control, bool value); void enableControl(QWidget *control, bool value); virtual QWidget * createOptionWidget(); /** * Quick help is a short help text about the way the tool functions. */ virtual QString quickHelp() const { return QString(); } virtual void setupPaintAction(KisRecordedPaintAction* action); qreal pressureToCurve(qreal pressure){ return m_pressureSamples.at( qRound(pressure * LEVEL_OF_PRESSURE_RESOLUTION) ); } enum NodePaintAbility { NONE, PAINT, VECTOR }; /// Checks if and how the tool can paint on the current node NodePaintAbility nodePaintAbility(); const KoCompositeOp* compositeOp(); public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); virtual void deactivate(); private Q_SLOTS: void slotPopupQuickHelp(); void increaseBrushSize(); void decreaseBrushSize(); void activatePickColorDelayed(); protected Q_SLOTS: virtual void updateTabletPressureSamples(); protected: quint8 m_opacity; bool m_paintOutline; QVector m_pressureSamples; QPointF m_outlineDocPoint; QPainterPath m_currentOutline; QRectF m_oldOutlineRect; bool m_showColorPreview; QRectF m_oldColorPreviewRect; QRectF m_oldColorPreviewUpdateRect; QColor m_colorPreviewCurrentColor; bool m_colorPreviewShowComparePlate; QColor m_colorPreviewBaseColor; private: QPainterPath tryFixBrushOutline(const QPainterPath &originalOutline); void setOpacity(qreal opacity); void activatePickColor(AlternateAction action); void deactivatePickColor(AlternateAction action); void pickColorWasOverridden(); int colorPreviewResourceId(AlternateAction action); QRectF colorPreviewDocRect(const QPointF &outlineDocPoint); private: bool m_specialHoverModifier; QGridLayout *m_optionsWidgetLayout; bool m_supportOutline; /** * Used as a switch for pickColor */ // used to skip some of the tablet events and don't update the colour that often QTimer m_colorPickerDelayTimer; AlternateAction delayedAction; bool m_isOutlineEnabled; std::vector m_standardBrushSizes; Q_SIGNALS: void sigPaintingFinished(); }; #endif // KIS_TOOL_PAINT_H_ diff --git a/krita/ui/tool/kis_tool_shape.h b/krita/ui/tool/kis_tool_shape.h index 94cd42a8ae3..7a14cf2cb00 100644 --- a/krita/ui/tool/kis_tool_shape.h +++ b/krita/ui/tool/kis_tool_shape.h @@ -1,84 +1,84 @@ /* * 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 +#include #include #include #include "kis_tool_paint.h" #include "kis_painter.h" #include "ui_wdggeometryoptions.h" class KoCanvasBase; class KoPathShape; class WdgGeometryOptions : public QWidget, public Ui::WdgGeometryOptions { Q_OBJECT public: WdgGeometryOptions(QWidget *parent) : QWidget(parent) { setupUi(this); } }; /** * Base for tools specialized in drawing shapes */ class KRITAUI_EXPORT KisToolShape : public KisToolPaint { Q_OBJECT public: KisToolShape(KoCanvasBase * canvas, const QCursor & cursor); virtual ~KisToolShape(); virtual int flags() const; WdgGeometryOptions *m_shapeOptionsWidget; public Q_SLOTS: virtual void activate(ToolActivation toolActivation, const QSet &shapes); virtual void outlineSettingChanged(int value); virtual void fillSettingChanged(int value); protected: QWidget* createOptionWidget(); virtual KisPainter::FillStyle fillStyle(); KisPainter::StrokeStyle strokeStyle(); virtual void setupPaintAction(KisRecordedPaintAction* action); void addShape(KoShape* shape); void addPathShape(KoPathShape* pathShape, const KUndo2MagicString& name); KConfigGroup m_configGroup; }; #endif // KIS_TOOL_SHAPE_H_ diff --git a/krita/ui/tool/kis_tool_utils.cpp b/krita/ui/tool/kis_tool_utils.cpp index a744009885d..3bb2d01a008 100644 --- a/krita/ui/tool/kis_tool_utils.cpp +++ b/krita/ui/tool/kis_tool_utils.cpp @@ -1,79 +1,80 @@ /* * Copyright (c) 2009 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 #include #include #include +#include namespace KisToolUtils { bool pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color) { KIS_ASSERT(dev); KoColor pickedColor; dev->pixel(pos.x(), pos.y(), &pickedColor); pickedColor.convertTo(dev->compositionSourceColorSpace()); bool validColorPicked = pickedColor.opacityU8() != OPACITY_TRANSPARENT_U8; if (validColorPicked) { pickedColor.setOpacity(OPACITY_OPAQUE_U8); *color = pickedColor; } return validColorPicked; } KisNodeSP findNode(KisNodeSP node, const QPoint &point, bool wholeGroup, bool editableOnly) { KisNodeSP foundNode = 0; while (node) { KisLayerSP layer = dynamic_cast(node.data()); if (!layer || !layer->isEditable()) { node = node->prevSibling(); continue; } KoColor color(layer->projection()->colorSpace()); layer->projection()->pixel(point.x(), point.y(), &color); - if(color.opacityU8() != OPACITY_TRANSPARENT_U8) { - if (layer->inherits("KisGroupLayer") && (!editableOnly || layer->isEditable())) { - // if this is a group and the pixel is transparent, - // don't even enter it + KisGroupLayerSP group = dynamic_cast(layer.data()); + if ((group && group->passThroughMode()) || color.opacityU8() != OPACITY_TRANSPARENT_U8) { + if (layer->inherits("KisGroupLayer") && (!editableOnly || layer->isEditable())) { + // if this is a group and the pixel is transparent, don't even enter it foundNode = findNode(node->lastChild(), point, wholeGroup, editableOnly); } else { foundNode = !wholeGroup ? node : node->parent(); } } if (foundNode) break; node = node->prevSibling(); } return foundNode; } } diff --git a/krita/ui/tool/kis_tool_utils.h b/krita/ui/tool/kis_tool_utils.h index 2cdc9a2ab78..3164b3c4f78 100644 --- a/krita/ui/tool/kis_tool_utils.h +++ b/krita/ui/tool/kis_tool_utils.h @@ -1,41 +1,41 @@ /* * Copyright (c) 2009 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_UTILS_H #define KIS_TOOL_UTILS_H #include #include #include -#include +#include namespace KisToolUtils { /** * return the color at the given position on the given paint device. */ bool KRITAUI_EXPORT pick(KisPaintDeviceSP dev, const QPoint& pos, KoColor *color); /** * Recursively search a node with a non-transparent pixel */ KisNodeSP KRITAUI_EXPORT findNode(KisNodeSP node, const QPoint &point, bool wholeGroup, bool editableOnly = true); } #endif // KIS_TOOL_UTILS_H diff --git a/krita/ui/tool/strokes/freehand_stroke.h b/krita/ui/tool/strokes/freehand_stroke.h index c52baacf162..99b9ea3a6c3 100644 --- a/krita/ui/tool/strokes/freehand_stroke.h +++ b/krita/ui/tool/strokes/freehand_stroke.h @@ -1,128 +1,128 @@ /* * Copyright (c) 2011 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef __FREEHAND_STROKE_H #define __FREEHAND_STROKE_H -#include "krita_export.h" +#include "kritaui_export.h" #include "kis_types.h" #include "kis_node.h" #include "kis_painter_based_stroke_strategy.h" #include "kis_distance_information.h" #include "kis_paint_information.h" class KisPainter; class KRITAUI_EXPORT FreehandStrokeStrategy : public KisPainterBasedStrokeStrategy { public: class Data : public KisStrokeJobData { public: enum DabType { POINT, LINE, CURVE, POLYLINE, POLYGON, RECT, ELLIPSE, PAINTER_PATH }; Data(KisNodeSP _node, PainterInfo *_painterInfo, const KisPaintInformation &_pi) : node(_node), painterInfo(_painterInfo), type(POINT), pi1(_pi) {} Data(KisNodeSP _node, PainterInfo *_painterInfo, const KisPaintInformation &_pi1, const KisPaintInformation &_pi2) : node(_node), painterInfo(_painterInfo), type(LINE), pi1(_pi1), pi2(_pi2) {} Data(KisNodeSP _node, PainterInfo *_painterInfo, const KisPaintInformation &_pi1, const QPointF &_control1, const QPointF &_control2, const KisPaintInformation &_pi2) : node(_node), painterInfo(_painterInfo), type(CURVE), pi1(_pi1), pi2(_pi2), control1(_control1), control2(_control2) {} Data(KisNodeSP _node, PainterInfo *_painterInfo, DabType _type, const vQPointF &_points) : node(_node), painterInfo(_painterInfo), type(_type), points(_points) {} Data(KisNodeSP _node, PainterInfo *_painterInfo, DabType _type, const QRectF &_rect) : node(_node), painterInfo(_painterInfo), type(_type), rect(_rect) {} Data(KisNodeSP _node, PainterInfo *_painterInfo, DabType _type, const QPainterPath &_path) : node(_node), painterInfo(_painterInfo), type(_type), path(_path) {} KisNodeSP node; PainterInfo *painterInfo; DabType type; KisPaintInformation pi1; KisPaintInformation pi2; QPointF control1; QPointF control2; vQPointF points; QRectF rect; QPainterPath path; }; public: FreehandStrokeStrategy(bool needsIndirectPainting, const QString &indirectPaintingCompositeOp, KisResourcesSnapshotSP resources, PainterInfo *painterInfo, const KUndo2MagicString &name); FreehandStrokeStrategy(bool needsIndirectPainting, const QString &indirectPaintingCompositeOp, KisResourcesSnapshotSP resources, QVector painterInfos, const KUndo2MagicString &name); ~FreehandStrokeStrategy(); void doStrokeCallback(KisStrokeJobData *data); private: void init(bool needsIndirectPainting, const QString &indirectPaintingCompositeOp); }; #endif /* __FREEHAND_STROKE_H */ diff --git a/krita/ui/widgets/kis_categorized_list_view.h b/krita/ui/widgets/kis_categorized_list_view.h index 65cb4bb3da5..4b2095382d1 100644 --- a/krita/ui/widgets/kis_categorized_list_view.h +++ b/krita/ui/widgets/kis_categorized_list_view.h @@ -1,63 +1,63 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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_CATEGORIZED_LIST_VIEW_H_ #define KIS_CATEGORIZED_LIST_VIEW_H_ -#include +#include #include #include class KRITAUI_EXPORT KisCategorizedListView: public QListView { Q_OBJECT public: KisCategorizedListView(bool useCheckBoxHack=false, QWidget* parent=0); virtual ~KisCategorizedListView(); virtual void setModel(QAbstractItemModel* model); Q_SIGNALS: void sigCategoryToggled(const QModelIndex& index, bool toggled); void sigEntryChecked(const QModelIndex& index); void rightClickedMenuDropSettingsTriggered(); void rightClickedMenuSaveSettingsTriggered(); protected Q_SLOTS: void slotIndexChanged(const QModelIndex& index); virtual void dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight); virtual void rowsInserted(const QModelIndex& parent, int start, int end); virtual void rowsAboutToBeRemoved(const QModelIndex &parent, int start, int end); virtual void mousePressEvent(QMouseEvent* event); virtual void mouseReleaseEvent(QMouseEvent* event); private: void updateRows(int begin, int end); private: bool m_useCheckBoxHack; }; #endif // KIS_CATEGORIZED_LIST_VIEW_H_ diff --git a/krita/ui/widgets/kis_channelflags_widget.h b/krita/ui/widgets/kis_channelflags_widget.h index 24a42a1e05b..a112fd7aaf1 100644 --- a/krita/ui/widgets/kis_channelflags_widget.h +++ b/krita/ui/widgets/kis_channelflags_widget.h @@ -1,71 +1,71 @@ /* * Copyright (c) 2007 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_CHANNELFLAGS_WIDGET_H #define KIS_CHANNELFLAGS_WIDGET_H #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include #include class QBitArray; class KoColorSpace; /** * A simple widget that shows a list of checkboxes in a scrollable * area. The checkboxes correspond to the channels in a colorspace and * are in the order the channels are packed in the pixel. The * resulting QBitArray can be used to decide which channels to modify * or not for filters, composition and eveything else. */ class KRITAUI_EXPORT KisChannelFlagsWidget : public QScrollArea { Q_OBJECT public: KisChannelFlagsWidget(const KoColorSpace *colorSpace, QWidget * parent = 0); ~KisChannelFlagsWidget(); public: /** * Set the channelflags -- they are supposed to be in pixel order. */ void setChannelFlags(const QBitArray & channelFlags); /** * retrieve the channel flags, in pixel order. */ QBitArray channelFlags() const; Q_SIGNALS: void channelSelectionChanced(); private: QList m_channelChecks; }; #endif diff --git a/krita/ui/widgets/kis_cmb_composite.h b/krita/ui/widgets/kis_cmb_composite.h index f3c58b2b766..b6c89754143 100644 --- a/krita/ui/widgets/kis_cmb_composite.h +++ b/krita/ui/widgets/kis_cmb_composite.h @@ -1,104 +1,104 @@ /* * widgets/kis_cmb_composite.h - part of KImageShop/Krayon/Krita * * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2011 Silvio Heinrich * * 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_COMPOSITEOP_WIDGETS_H_ #define KIS_COMPOSITEOP_WIDGETS_H_ #include -#include +#include #include "kis_categorized_list_view.h" class KAction; class KoID; class KoColorSpace; class KisSortedCompositeOpListModel; class KRITAUI_EXPORT KisCompositeOpListWidget: public KisCategorizedListView { public: KisCompositeOpListWidget(QWidget* parent=0); ~KisCompositeOpListWidget(); KoID selectedCompositeOp() const; private: KisSortedCompositeOpListModel *m_model; }; class KRITAUI_EXPORT KisCompositeOpComboBox: public QComboBox { Q_OBJECT public: KisCompositeOpComboBox(QWidget* parent=0); ~KisCompositeOpComboBox(); virtual void hidePopup(); void validate(const KoColorSpace *cs); void selectCompositeOp(const KoID &op); KoID selectedCompositeOp() const; QList blendmodeActions(); private Q_SLOTS: void slotCategoryToggled(const QModelIndex& index, bool toggled); void slotEntryChecked(const QModelIndex& index); void slotNextBlendingMode(); void slotPreviousBlendingMode(); void slotNormal(); void slotDissolve(); void slotBehind(); void slotClear(); void slotDarken(); void slotMultiply(); void slotColorBurn(); void slotLinearBurn(); void slotLighten(); void slotScreen(); void slotColorDodge(); void slotLinearDodge(); void slotOverlay(); void slotSoftLight(); void slotHardLight(); void slotVividLight(); void slotLinearLight(); void slotPinLight(); void slotHardMix(); void slotDifference(); void slotExclusion(); void slotHue(); void slotSaturation(); void slotColor(); void slotLuminosity(); private: KisSortedCompositeOpListModel *m_model; KisCategorizedListView *m_view; bool m_allowToHidePopup; QList m_actions; }; #endif // KIS_COMPOSITEOP_WIDGETS_H_ diff --git a/krita/ui/widgets/kis_cmb_idlist.h b/krita/ui/widgets/kis_cmb_idlist.h index 3b7f4e24ed4..f3b56accb80 100644 --- a/krita/ui/widgets/kis_cmb_idlist.h +++ b/krita/ui/widgets/kis_cmb_idlist.h @@ -1,61 +1,61 @@ /* * kis_cmb_imagetype.h - part of KImageShop/Krayon/Krita * * Copyright (c) 2005 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2011 Silvio Heinrich * * 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 #include -#include +#include /** * A combobox that is associated with a list of KoID's. The * descriptive (i18n'ed) text is displayed, but the various * signals return a KoID. */ class KRITAUI_EXPORT KisCmbIDList: public QComboBox { Q_OBJECT public: KisCmbIDList(QWidget * parent = 0, const char * name = 0); virtual ~KisCmbIDList(); public: void setIDList(const QList & list); void setCurrent(const KoID id); void setCurrent(const QString & s); KoID currentItem() const; Q_SIGNALS: void activated(const KoID &); void highlighted(const KoID &); private Q_SLOTS: void slotIDActivated(int i); void slotIDHighlighted(int i); private: QList m_list; }; #endif diff --git a/krita/ui/widgets/kis_color_space_selector.h b/krita/ui/widgets/kis_color_space_selector.h index e5d924c17fa..97a4437ea61 100644 --- a/krita/ui/widgets/kis_color_space_selector.h +++ b/krita/ui/widgets/kis_color_space_selector.h @@ -1,62 +1,62 @@ /* * Copyright (C) 2007 Cyrille Berger * Copyright (C) 2011 Srikanth Tiyyagura * * 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_SPACE_SELECTOR_H_ #define _KIS_COLOR_SPACE_SELECTOR_H_ #include -#include +#include class KoID; class KoColorSpace; class KRITAUI_EXPORT KisColorSpaceSelector : public QWidget { Q_OBJECT public: KisColorSpaceSelector(QWidget* parent); ~KisColorSpaceSelector(); const KoColorSpace* currentColorSpace(); void setCurrentColorModel(const KoID& id); void setCurrentColorDepth(const KoID& id); void setCurrentProfile(const QString& name); void setCurrentColorSpace(const KoColorSpace* colorSpace); Q_SIGNALS: /** * This signal is emitted when a new color space is selected. * @param valid indicates if the color space can be used */ void selectionChanged(bool valid); /// This signal is emitted, when a new color space is selected, that can be used (eg is valid) void colorSpaceChanged(const KoColorSpace*); private Q_SLOTS: void fillCmbDepths(const KoID& idd); void fillCmbProfiles(); void colorSpaceChanged(); void installProfile(); void uploadProfile(); void downloadProfile(); void buttonUpdate(); private: struct Private; Private * const d; }; #endif diff --git a/krita/ui/widgets/kis_curve_widget.h b/krita/ui/widgets/kis_curve_widget.h index 9b3ecc1c88e..9c1776f6eab 100644 --- a/krita/ui/widgets/kis_curve_widget.h +++ b/krita/ui/widgets/kis_curve_widget.h @@ -1,160 +1,160 @@ /* * Copyright (c) 2005 C. Boemann * Copyright (c) 2009 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_CURVE_WIDGET_H #define KIS_CURVE_WIDGET_H // Qt includes. #include #include #include #include #include #include #include #include #include -#include +#include class QSpinBox; class KisCubicCurve; /** * KisCurveWidget is a widget that shows a single curve that can be edited * by the user. The user can grab the curve and move it; this creates * a new control point. Control points can be deleted by selecting a point * and pressing the delete key. * * (From: http://techbase.kde.org/Projects/Widgets_and_Classes#KisCurveWidget) * KisCurveWidget allows editing of spline based y=f(x) curves. Handy for cases * where you want the user to control such things as tablet pressure * response, color transformations, acceleration by time, aeroplane lift *by angle of attack. */ class KRITAUI_EXPORT KisCurveWidget : public QWidget { Q_OBJECT Q_PROPERTY(bool pointSelected READ pointSelected NOTIFY pointSelectedChanged); public: friend class CurveEditorItem; /** * Create a new curve widget with a default curve, that is a straight * line from bottom-left to top-right. */ KisCurveWidget(QWidget *parent = 0, Qt::WFlags f = 0); virtual ~KisCurveWidget(); /** * Reset the curve to the default shape */ void reset(void); /** * Enable the guide and set the guide color to the specified color. * * XXX: it seems that the guide feature isn't actually implemented yet? */ void setCurveGuide(const QColor & color); /** * Set a background pixmap. The background pixmap will be drawn under * the grid and the curve. * * XXX: or is the pixmap what is drawn to the left and bottom of the curve * itself? */ void setPixmap(const QPixmap & pix); QPixmap getPixmap(); void setBasePixmap(const QPixmap & pix); QPixmap getBasePixmap(); /** * Whether or not there is a point selected * This does NOT include the first and last points */ bool pointSelected() const; Q_SIGNALS: /** * Emitted whenever a control point has changed position. */ void modified(void); /** * Emitted whenever the status of whether a control point is selected or not changes */ void pointSelectedChanged(); protected Q_SLOTS: void inOutChanged(int); protected: void keyPressEvent(QKeyEvent *); void paintEvent(QPaintEvent *); void mousePressEvent(QMouseEvent * e); void mouseReleaseEvent(QMouseEvent * e); void mouseMoveEvent(QMouseEvent * e); void leaveEvent(QEvent *); void resizeEvent(QResizeEvent *e); public: /** * @return get a list with all defined points. If you want to know what the * y value for a given x is on the curve defined by these points, use getCurveValue(). * @see getCurveValue */ KisCubicCurve curve(); /** * Replace the current curve with a curve specified by the curve defined by the control * points in @param inlist. */ void setCurve(KisCubicCurve inlist); /** * Connect/disconnect external spinboxes to the curve * @min/@max - is the range for their values */ void setupInOutControls(QSpinBox *in, QSpinBox *out, int min, int max); void dropInOutControls(); /** * Handy function that creates new point in the middle * of the curve and sets focus on the m_intIn field, * so the user can move this point anywhere in a moment */ void addPointInTheMiddle(); private: class Private; Private * const d; }; #endif /* KIS_CURVE_WIDGET_H */ diff --git a/krita/ui/widgets/kis_double_widget.h b/krita/ui/widgets/kis_double_widget.h index 52a9b870641..39a5bef8cec 100644 --- a/krita/ui/widgets/kis_double_widget.h +++ b/krita/ui/widgets/kis_double_widget.h @@ -1,77 +1,77 @@ /* * widgets/kis_double_widget.h - part of Krita * * Copyright (c) 1999 Carsten Pfeiffer * Copyright (c) 2004 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_DOUBLE_WIDGET_H #define KIS_DOUBLE_WIDGET_H #include #include -#include +#include class QHBoxLayout; class QDoubleSpinBox; class KRITAUI_EXPORT KisDoubleWidget : public QWidget { Q_OBJECT 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 setTickPosition(QSlider::TickPosition tickPosition); void setTickInterval(double tickInterval); double tickInterval() const; void setPrecision(int precision); void setSingleStep(double step); void setPageStep(double step); void setTracking(bool tracking); bool hasTracking() const; Q_SIGNALS: void valueChanged(double); void sliderPressed(); void sliderReleased(); public Q_SLOTS: void setValue(double value); protected Q_SLOTS: void setSliderValue(double); void sliderValueChanged(int); private: void init(double min, double max); protected: QHBoxLayout* m_layout; QSlider* m_slider; QDoubleSpinBox *m_spinBox; }; #endif // KIS_DOUBLE_WIDGET_H diff --git a/krita/ui/widgets/kis_floating_message.h b/krita/ui/widgets/kis_floating_message.h index 779c64c2671..472dd244096 100644 --- a/krita/ui/widgets/kis_floating_message.h +++ b/krita/ui/widgets/kis_floating_message.h @@ -1,94 +1,94 @@ /* * This file is part of KimageShop^WKrayon^WKrita * * Copyright (c) 2012 Boudewijn Rempt * Copyright (c) 2004 Christian Muehlhaeuser * Copyright (c) 2004-2006 Seb Ruiz * Copyright (c) 2004,2005 Max Howell * Copyright (c) 2005 Gabor Lehel * Copyright (c) 2008,2009 Mark Kretschmann * * 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_FLOATING_MESSAGE_H #define KIS_FLOATING_MESSAGE_H #include #include #include #include #include -#include +#include /** * @brief The KisFloatingMessage class shows the given message in a semi-transparent * bubble that doesn' take focus and slowly fades away. * * Heavily based on Amarok's Osd.cpp */ class KRITAUI_EXPORT KisFloatingMessage : public QWidget { Q_OBJECT public: enum Priority { High = 0, Medium, Low }; explicit KisFloatingMessage(const QString &message, QWidget *parent, bool showOverParent, int timeout, Priority priority, int alignment = Qt::AlignCenter | Qt::TextWordWrap); /// Show message above parent widget instead of screen void setShowOverParent(bool show); void setIcon(const QIcon& icon); void tryOverrideMessage(const QString message, const QIcon& icon, int timeout, KisFloatingMessage::Priority priority, int alignment = Qt::AlignCenter | Qt::TextWordWrap); protected: void paintEvent(QPaintEvent *e); public Q_SLOTS: void showMessage(); void removeMessage(); private Q_SLOTS: void startFade(); void updateOpacity(int value); private: QRect determineMetrics(const int M); QString m_message; QImage m_icon; QPixmap m_scaledIcon; QTimer m_timer; int m_m; QTimeLine m_fadeTimeLine; bool m_showOverParent; int m_timeout; Priority m_priority; int m_alignment; }; #endif // KIS_FLOATING_MESSAGE_H diff --git a/krita/ui/widgets/kis_gradient_slider.h b/krita/ui/widgets/kis_gradient_slider.h index b7597c5a7e0..2d15e5b4a80 100644 --- a/krita/ui/widgets/kis_gradient_slider.h +++ b/krita/ui/widgets/kis_gradient_slider.h @@ -1,97 +1,97 @@ /* * This file is part of Krita * * Copyright (c) 2006 Frederic Coiffier * * 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_SLIDER_H #define KIS_GRADIENT_SLIDER_H // Qt includes. #include #include #include #include -#include +#include class KRITAUI_EXPORT KisGradientSlider : public QWidget { Q_OBJECT typedef enum { BlackCursor, GammaCursor, WhiteCursor, None } eCursor; public: KisGradientSlider(QWidget *parent = 0); virtual ~KisGradientSlider(); int black() const; int white() const; public Q_SLOTS: void slotModifyBlack(int); void slotModifyWhite(int); void slotModifyGamma(double); Q_SIGNALS: void sigModifiedBlack(int); void sigModifiedWhite(int); void sigModifiedGamma(double); protected: void paintEvent(QPaintEvent *); void resizeEvent(QResizeEvent *); void mousePressEvent(QMouseEvent * e); void mouseReleaseEvent(QMouseEvent * e); void mouseMoveEvent(QMouseEvent * e); private: void calculateCursorPositions(); unsigned int calculateGammaCursor(); public: void enableGamma(bool b); double getGamma(void); private: int m_leftmost; int m_rightmost; eCursor m_grabCursor; double m_scalingFactor; int m_blackCursor; int m_whiteCursor; int m_gammaCursor; int m_black; int m_white; double m_gamma; bool m_gammaEnabled; bool m_feedback; }; #endif /* KIS_GRADIENT_SLIDER_H */ diff --git a/krita/ui/widgets/kis_multi_bool_filter_widget.h b/krita/ui/widgets/kis_multi_bool_filter_widget.h index 3cd58052bb4..7a569c23281 100644 --- a/krita/ui/widgets/kis_multi_bool_filter_widget.h +++ b/krita/ui/widgets/kis_multi_bool_filter_widget.h @@ -1,70 +1,70 @@ /* * Copyright (c) 2005 Michael Thaler * * 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 #include #include -#include "krita_export.h" +#include "kritaui_export.h" #include class KisPropertiesConfiguration; struct KisBoolWidgetParam { KRITAUI_EXPORT KisBoolWidgetParam(bool ninitvalue, const QString & label, const QString & name); bool initvalue; QString label; QString name; }; typedef std::vector vKisBoolWidgetParam; class KRITAUI_EXPORT KisMultiBoolFilterWidget : public KisConfigWidget { Q_OBJECT public: KisMultiBoolFilterWidget(const QString & filterid, QWidget * parent, const QString & caption, vKisBoolWidgetParam iwparam); virtual void setConfiguration(const KisPropertiesConfiguration* cfg); virtual KisPropertiesConfiguration* configuration() const; public: inline qint32 nbValues() const { return m_boolWidgets.count(); } inline bool valueAt(qint32 i) const { return m_boolWidgets[i]->isChecked(); } private: QVector m_boolWidgets; QString m_filterid; }; #endif diff --git a/krita/ui/widgets/kis_multi_double_filter_widget.h b/krita/ui/widgets/kis_multi_double_filter_widget.h index 4e3d2da133c..68235b8cdc7 100644 --- a/krita/ui/widgets/kis_multi_double_filter_widget.h +++ b/krita/ui/widgets/kis_multi_double_filter_widget.h @@ -1,80 +1,80 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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 #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KisDelayedActionDoubleInput : public KDoubleNumInput { Q_OBJECT public: KisDelayedActionDoubleInput(QWidget * parent, const QString & name); void cancelDelayedSignal(); private Q_SLOTS: void slotValueChanged(); void slotTimeToUpdate(); Q_SIGNALS: void valueChangedDelayed(double value); private: QTimer * m_timer; }; struct KRITAUI_EXPORT KisDoubleWidgetParam { KisDoubleWidgetParam(double nmin, double nmax, double ninitvalue, const QString & label, const QString & nname); double min; double max; double initvalue; QString label; QString name; }; typedef std::vector vKisDoubleWidgetParam; class KRITAUI_EXPORT KisMultiDoubleFilterWidget : public KisConfigWidget { Q_OBJECT public: KisMultiDoubleFilterWidget(const QString & filterid, QWidget * parent, const QString & caption, vKisDoubleWidgetParam dwparam); virtual void setConfiguration(const KisPropertiesConfiguration * cfg); virtual KisPropertiesConfiguration* configuration() const; public: inline qint32 nbValues() const { return m_nbdoubleWidgets; } inline double valueAt(qint32 i) { return m_doubleWidgets[i]->value(); } private: KisDelayedActionDoubleInput** m_doubleWidgets; qint32 m_nbdoubleWidgets; QString m_filterid; }; #endif diff --git a/krita/ui/widgets/kis_multi_integer_filter_widget.h b/krita/ui/widgets/kis_multi_integer_filter_widget.h index 99272d7e4a0..8eb4a16e8cc 100644 --- a/krita/ui/widgets/kis_multi_integer_filter_widget.h +++ b/krita/ui/widgets/kis_multi_integer_filter_widget.h @@ -1,83 +1,83 @@ /* * Copyright (c) 2004 Cyrille Berger * * 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 #include -#include "krita_export.h" +#include "kritaui_export.h" #include #include #include class KisDelayedActionIntegerInput : public KIntNumInput { Q_OBJECT public: KisDelayedActionIntegerInput(QWidget * parent, const QString & name); void cancelDelayedSignal(); private Q_SLOTS: void slotValueChanged(); void slotTimeToUpdate(); Q_SIGNALS: void valueChangedDelayed(int value); private: QTimer * m_timer; }; struct KRITAUI_EXPORT KisIntegerWidgetParam { KisIntegerWidgetParam(qint32 nmin, qint32 nmax, qint32 ninitvalue, const QString& label, const QString& nname); qint32 min; qint32 max; qint32 initvalue; QString label; QString name; }; typedef std::vector vKisIntegerWidgetParam; class KRITAUI_EXPORT KisMultiIntegerFilterWidget : public KisConfigWidget { Q_OBJECT public: KisMultiIntegerFilterWidget(const QString& filterid, QWidget* parent, const QString& caption, vKisIntegerWidgetParam iwparam); ~KisMultiIntegerFilterWidget(); virtual void setConfiguration(const KisPropertiesConfiguration* config); virtual KisPropertiesConfiguration* configuration() const; private: qint32 nbValues() const; qint32 valueAt(qint32 i); QVector m_integerWidgets; QString m_filterid; KisPropertiesConfiguration* m_config; }; #endif diff --git a/krita/ui/widgets/kis_multipliers_double_slider_spinbox.h b/krita/ui/widgets/kis_multipliers_double_slider_spinbox.h index 6d31c49a696..24dd8e42ae4 100644 --- a/krita/ui/widgets/kis_multipliers_double_slider_spinbox.h +++ b/krita/ui/widgets/kis_multipliers_double_slider_spinbox.h @@ -1,61 +1,61 @@ /* This file is part of the KDE project * Copyright (c) 2010 Cyrille Berger * * 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_MULTIPLIERS_DOUBLE_SLIDER_SPINBOX_H_ #define _KIS_MULTIPLIERS_DOUBLE_SLIDER_SPINBOX_H_ #include -#include +#include class KisDoubleSliderSpinBox; /** * This class add a combobox to a \ref KisDoubleSliderSpinBox which * allows to define a multiplier to let the user change the range. */ class KRITAUI_EXPORT KisMultipliersDoubleSliderSpinBox : public QWidget { Q_OBJECT public: KisMultipliersDoubleSliderSpinBox(QWidget* _parent = 0); ~KisMultipliersDoubleSliderSpinBox(); void addMultiplier(double v); /** * Set the range for the 1.0 multiplier */ void setRange(qreal minimum, qreal maximum, int decimals = 0); ///Get the value, don't use value() qreal value(); ///Set the value, don't use setValue() void setValue(qreal value); void setExponentRatio(qreal dbl); Q_SIGNALS: void valueChanged(qreal value); private: Q_PRIVATE_SLOT(d, void updateRange()) struct Private; Private* const d; }; #endif diff --git a/krita/ui/widgets/kis_paintop_list_widget.h b/krita/ui/widgets/kis_paintop_list_widget.h index 307be38f10b..364d80d31b2 100644 --- a/krita/ui/widgets/kis_paintop_list_widget.h +++ b/krita/ui/widgets/kis_paintop_list_widget.h @@ -1,60 +1,60 @@ /* * Copyright (c) 2004 Boudewijn Rempt (boud@valdyas.org) * Copyright (c) 2010 Lukáš Tvrdý * Copyright (c) 2011 Silvio Heinrich * * 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_LIST_WIDGET_H_ #define KIS_PAINTOP_LIST_WIDGET_H_ -#include +#include #include "kis_categorized_list_view.h" class KisPaintOpFactory; class KisSortedPaintOpListModel; /** * A ListBox filled with the paintops */ //* class KRITAUI_EXPORT KisPaintOpListWidget: public KisCategorizedListView { Q_OBJECT public: KisPaintOpListWidget(QWidget* parent=0, const char* name=0); ~KisPaintOpListWidget(); QString currentItem() const; void setPaintOpList(const QList& list); void setCurrent(const KisPaintOpFactory* op); void setCurrent(const QString & paintOpId); Q_SIGNALS: void activated(const QString&); private Q_SLOTS: void slotOpActivated(const QModelIndex& index); protected: QString itemAt(int idx) const; private: KisSortedPaintOpListModel *m_model; }; #endif // KIS_PAINTOP_LIST_WIDGET_H_ diff --git a/krita/ui/widgets/kis_paintop_presets_chooser_popup.h b/krita/ui/widgets/kis_paintop_presets_chooser_popup.h index c7d34408e72..a5c3e6baa8f 100644 --- a/krita/ui/widgets/kis_paintop_presets_chooser_popup.h +++ b/krita/ui/widgets/kis_paintop_presets_chooser_popup.h @@ -1,56 +1,56 @@ /* This file is part of the KDE project * Copyright (c) 2010 Sven Langkamp * Copyright 2011 Srikanth Tiyyagura * * 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_PAINTOP_PRESETS_CHOOSER_POPUP_H #define KIS_PAINTOP_PRESETS_CHOOSER_POPUP_H #include #include -#include +#include #include "kis_paintop_preset.h" class KoResource; class KRITAUI_EXPORT KisPaintOpPresetsChooserPopup : public QWidget { Q_OBJECT public: KisPaintOpPresetsChooserPopup(QWidget * parent = 0); virtual ~KisPaintOpPresetsChooserPopup(); void showButtons(bool show); void updateViewSettings(); public Q_SLOTS: void canvasResourceChanged( KoResource * resource, KisPaintOpPresetSP preset ); Q_SIGNALS: void resourceSelected( KoResource * resource); private Q_SLOTS: void slotThumbnailMode(); void slotDetailMode(); virtual void paintEvent(QPaintEvent* ); private: struct Private; Private * const m_d; }; #endif // KIS_PAINTOP_PRESETS_CHOOSER_POPUP_H diff --git a/krita/ui/widgets/kis_pattern_chooser.h b/krita/ui/widgets/kis_pattern_chooser.h index e7dff070975..61da1cd6f83 100644 --- a/krita/ui/widgets/kis_pattern_chooser.h +++ b/krita/ui/widgets/kis_pattern_chooser.h @@ -1,63 +1,63 @@ /* * Copyright (c) 2004 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_PATTERN_CHOOSER_H_ #define KIS_PATTERN_CHOOSER_H_ #include -#include +#include class QLabel; class KoResourceItemChooser; class KoResource; class KRITAUI_EXPORT KisPatternChooser : public QFrame { Q_OBJECT public: KisPatternChooser(QWidget *parent = 0); virtual ~KisPatternChooser(); /// Gets the currently selected resource /// @returns the selected resource, 0 is no resource is selected KoResource *currentResource(); void setCurrentPattern(KoResource *resource); void setCurrentItem(int row, int column); void setGrayscalePreview(bool grayscale); /// determines whether the preview right or below the splitter void setPreviewOrientation(Qt::Orientation orientation); Q_SIGNALS: /// Emitted when a resource was selected void resourceSelected(KoResource *resource); void updateItemSize(); private Q_SLOTS: void update(KoResource *resource); private: QLabel *m_lbName; KoResourceItemChooser *m_itemChooser; }; #endif // KIS_PATTERN_CHOOSER_H_ diff --git a/krita/ui/widgets/kis_popup_button.h b/krita/ui/widgets/kis_popup_button.h index 77d563bd5de..74887572cc4 100644 --- a/krita/ui/widgets/kis_popup_button.h +++ b/krita/ui/widgets/kis_popup_button.h @@ -1,76 +1,76 @@ /* * Copyright (c) 2007 Cyrille Berger * * 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_POPUP_BUTTON_H_ #define _KIS_POPUP_BUTTON_H_ #include -#include +#include /** * This class is a convenience class for a button that * when clicked displays a popup widget. */ class KRITAUI_EXPORT KisPopupButton : public QPushButton { Q_OBJECT public: KisPopupButton(QWidget* parent); ~KisPopupButton(); /** * Set the popup widget, the KisPopupButton becomes * the owner and parent of the widget. */ void setPopupWidget(QWidget* widget); /** * This function allow to force the popup to be visible. * @param v set to true to force the popup to be visible, set to false * to allow the popup to be hidden */ void setAlwaysVisible(bool v); /** * Set the width of the popup widget. * @return new width of the popup widget */ void setPopupWidgetWidth(int w); public Q_SLOTS: void showPopupWidget(); void hidePopupWidget(); void adjustPosition(); protected: void paintEvent(QPaintEvent* event); void paintPopupArrow(); private: struct Private; Private* const m_d; }; #endif diff --git a/krita/ui/widgets/kis_preset_chooser.h b/krita/ui/widgets/kis_preset_chooser.h index 898f92cdc20..39a11207b28 100644 --- a/krita/ui/widgets/kis_preset_chooser.h +++ b/krita/ui/widgets/kis_preset_chooser.h @@ -1,84 +1,84 @@ /* * Copyright (c) 2002 Patrick Julien * Copyright (C) 2011 Silvio Heinrich * Copyright (c) 2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_ITEM_CHOOSER_H_ #define KIS_ITEM_CHOOSER_H_ #include -#include +#include #include class KoAbstractResourceServerAdapter; class KisPresetDelegate; class KoResourceItemChooser; class KoResource; /** * A special type of item chooser that can contain extra widgets that show * more information about the currently selected item. Reimplement update() * to extract that information and fill the appropriate widgets. */ class KRITAUI_EXPORT KisPresetChooser : public QWidget { Q_OBJECT public: KisPresetChooser(QWidget *parent = 0, const char *name = 0); virtual ~KisPresetChooser(); enum ViewMode{ THUMBNAIL, /// Shows thumbnails DETAIL, /// Shows thumbsnails with text next to it STRIP /// Shows thumbnails arranged in a single row }; /// Sets a list of resources in the paintop list, when ever user press enter in the linedit of paintop_presets_popup Class void setViewMode(ViewMode mode); void showButtons(bool show); KoResource* currentResource(); /// Sets the visibility of tagging klineEdits void showTaggingBar(bool show); KoResourceItemChooser *itemChooser(); void setPresetFilter(const QString& paintOpId); Q_SIGNALS: void resourceSelected(KoResource * resource); public Q_SLOTS: void updateViewSettings(); private Q_SLOTS: void notifyConfigChanged(); protected: virtual void resizeEvent(QResizeEvent* event); private: KoResourceItemChooser *m_chooser; KisPresetDelegate* m_delegate; ViewMode m_mode; QSharedPointer m_adapter; }; #endif // KIS_ITEM_CHOOSER_H_ diff --git a/krita/ui/widgets/kis_progress_widget.h b/krita/ui/widgets/kis_progress_widget.h index dd92241ae0a..9ac24246abb 100644 --- a/krita/ui/widgets/kis_progress_widget.h +++ b/krita/ui/widgets/kis_progress_widget.h @@ -1,78 +1,78 @@ /* * Copyright (c) 2002 Patrick Julien * 2004 Adrian Page * 2009 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 KISPROGRESSWIDGET_H #define KISPROGRESSWIDGET_H #include #include #include -#include "krita_export.h" +#include "kritaui_export.h" class KoProgressUpdater; class QToolButton; class KoProgressBar; /** * KisProgressWidget combines a KoProgressBar with a button * that can be pressed to cancel the current action. */ class KRITAUI_EXPORT KisProgressWidget : public QWidget, public KisProgressInterface { Q_OBJECT public: KisProgressWidget(QWidget* parent = 0); virtual ~KisProgressWidget(); public: KoProgressProxy* progressProxy(); /** * create a new KoProgressUpdater instance that is * linked to this progress bar. * * Note: it is _your_ duty to call deleteLater on the * koprogressupdater when you are done! */ void detachUpdater(KoProgressUpdater* updater); void attachUpdater(KoProgressUpdater* updater); public Q_SLOTS: void cancel(); void correctVisibility(int progressValue); Q_SIGNALS: void sigCancellationRequested(); private: QToolButton* m_cancelButton; KoProgressBar* m_progressBar; QList m_activeUpdaters; }; #endif // KISPROGRESSWIDGET_H diff --git a/krita/ui/widgets/kis_scratch_pad.h b/krita/ui/widgets/kis_scratch_pad.h index cc272f224a0..3c146574d21 100644 --- a/krita/ui/widgets/kis_scratch_pad.h +++ b/krita/ui/widgets/kis_scratch_pad.h @@ -1,165 +1,165 @@ /* This file is part of the KDE project * Copyright 2010 (C) Boudewijn Rempt * Copyright 2011 (C) Dmitry Kazakov * * 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_SCRATCH_PAD_H #define KIS_SCRATCH_PAD_H #include #include #include #include #include #include -#include +#include class QColor; class KoColorProfile; class KoPointerEvent; class KisCanvasResourceProvider; class KisUpdateScheduler; class KisUndoStore; class KisPostExecutionUndoAdapter; class KisScratchPadEventFilter; class KisPaintingInformationBuilder; class KisToolFreehandHelper; class KisNodeGraphListener; /** * A scratchpad is a painting canvas with only one zoomlevel and based on * a paint layer, not on a KisImage. It can have a blank, tiled background or * a gradient background. */ class KRITAUI_EXPORT KisScratchPad : public QWidget { Q_OBJECT public: void setupScratchPad(KisCanvasResourceProvider* resourceProvider, const QColor &defaultColor); KisScratchPad(QWidget *parent = 0); virtual ~KisScratchPad(); /// set the specified rect as the area taken for @see cutoutOverlay void setCutoutOverlayRect(const QRect&rc); /// return the contents of the area under the cutoutOverlay rect QImage cutoutOverlay() const; // A callback for our own node graph listener void imageUpdated(const QRect &rect); // A callback for scratch pad default bounds QRect imageBounds() const; public Q_SLOTS: void fillDefault(); void fillGradient(); void fillBackground(); void fillLayer(); /** * Set the icon of the current preset */ void setPresetImage(const QImage& image); /** * Paint the icon of the current preset inside the * cutout overlay * * \see setPresetImage */ void paintPresetImage(); private Q_SLOTS: void setOnScreenResolution(qreal scaleX, qreal scaleY); void setDisplayProfile(const KoColorProfile* colorProfile); void slotUpdateCanvas(const QRect &rect); Q_SIGNALS: void colorSelected(const KoColor& color); void sigUpdateCanvas(const QRect &rect); protected: virtual void paintEvent ( QPaintEvent * event ); public Q_SLOTS: void slotMousePress(KoPointerEvent *event); void slotMouseRelease(KoPointerEvent *event); void slotMouseMove(KoPointerEvent *event); private: void beginStroke(KoPointerEvent *event); void doStroke(KoPointerEvent *event); void endStroke(KoPointerEvent *event); void beginPan(KoPointerEvent *event); void doPan(KoPointerEvent *event); void endPan(KoPointerEvent *event); void pick(KoPointerEvent *event); void updateTransformations(); QTransform documentToWidget() const; QTransform widgetToDocument() const; private: enum Mode { PAINTING, HOVERING, PANNING, PICKING }; KoColor m_defaultColor; Mode m_toolMode; KisPaintLayerSP m_paintLayer; const KoColorProfile* m_displayProfile; QCursor m_cursor; QRect m_cutoutOverlay; QBrush m_checkBrush; KisCanvasResourceProvider* m_resourceProvider; KisUpdateScheduler *m_updateScheduler; KisUndoStore *m_undoStore; KisPostExecutionUndoAdapter *m_undoAdapter; KisNodeGraphListener *m_nodeListener; KisScratchPadEventFilter *m_eventFilter; KisToolFreehandHelper *m_helper; KisPaintingInformationBuilder *m_infoBuilder; QTransform m_scaleTransform; QTransform m_translateTransform; QPointF m_panDocPoint; int m_scaleBorderWidth; QImage m_presetImage; }; #endif // KIS_SCRATCH_PAD_H diff --git a/krita/ui/widgets/kis_selection_options.h b/krita/ui/widgets/kis_selection_options.h index ee35e474574..efaf3187732 100644 --- a/krita/ui/widgets/kis_selection_options.h +++ b/krita/ui/widgets/kis_selection_options.h @@ -1,70 +1,70 @@ /* * Copyright (c) 2005 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_SELECTION_OPTIONS_H__ #define __KIS_SELECTION_OPTIONS_H__ #include -#include "krita_export.h" +#include "kritaui_export.h" #include "ui_wdgselectionoptions.h" class KisCanvas2; class QButtonGroup; class WdgSelectionOptions : public QWidget, public Ui::WdgSelectionOptions { Q_OBJECT public: WdgSelectionOptions(QWidget *parent) : QWidget(parent) { setupUi(this); } }; /** */ class KRITAUI_EXPORT KisSelectionOptions : public QWidget { Q_OBJECT public: KisSelectionOptions(KisCanvas2 * subject); virtual ~KisSelectionOptions(); int action(); bool antiAliasSelection(); void disableAntiAliasSelectionOption(); void disableSelectionModeOption(); void setAction(int); Q_SIGNALS: void actionChanged(int); void modeChanged(int); private: WdgSelectionOptions * m_page; QButtonGroup* m_mode; QButtonGroup* m_action; }; #endif diff --git a/krita/ui/widgets/kis_slider_spin_box.h b/krita/ui/widgets/kis_slider_spin_box.h index e55da864a60..d32c8bd381e 100644 --- a/krita/ui/widgets/kis_slider_spin_box.h +++ b/krita/ui/widgets/kis_slider_spin_box.h @@ -1,172 +1,172 @@ /* This file is part of the KDE project * Copyright (c) 2010 Justin Noel * * 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 KISSLIDERSPINBOX_H #define KISSLIDERSPINBOX_H #include #include #include -#include +#include class KisAbstractSliderSpinBoxPrivate; class KisSliderSpinBoxPrivate; class KisDoubleSliderSpinBoxPrivate; /** * XXX: when inactive, also show the progress bar part as inactive! */ class KRITAUI_EXPORT KisAbstractSliderSpinBox : public QWidget { Q_OBJECT Q_DISABLE_COPY(KisAbstractSliderSpinBox) Q_DECLARE_PRIVATE(KisAbstractSliderSpinBox) protected: explicit KisAbstractSliderSpinBox(QWidget* parent, KisAbstractSliderSpinBoxPrivate*); public: virtual ~KisAbstractSliderSpinBox(); void showEdit(); void hideEdit(); void setPrefix(const QString& prefix); void setSuffix(const QString& suffix); void setExponentRatio(qreal dbl); /** * If set to block, it informs inheriting classes that they shouldn't emit signals * if the update comes from a mouse dragging the slider. * Set this to true when dragging the slider and updates during the drag are not needed. */ void setBlockUpdateSignalOnDrag(bool block); virtual QSize sizeHint() const; virtual QSize minimumSizeHint() const; virtual QSize minimumSize() const; protected: virtual void paintEvent(QPaintEvent* e); virtual void mousePressEvent(QMouseEvent* e); virtual void mouseReleaseEvent(QMouseEvent* e); virtual void mouseMoveEvent(QMouseEvent* e); virtual void keyPressEvent(QKeyEvent* e); virtual void wheelEvent(QWheelEvent *); virtual bool eventFilter(QObject* recv, QEvent* e); QStyleOptionSpinBox spinBoxOptions() const; QStyleOptionProgressBar progressBarOptions() const; QRect progressRect(const QStyleOptionSpinBox& spinBoxOptions) const; QRect upButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const; QRect downButtonRect(const QStyleOptionSpinBox& spinBoxOptions) const; int valueForX(int x, Qt::KeyboardModifiers modifiers = Qt::NoModifier) const; virtual QString valueString() const = 0; /** * Sets the slider internal value. Inheriting classes should respect blockUpdateSignal * so that, in specific cases, we have a performance improvement. See setIgnoreMouseMoveEvents. */ virtual void setInternalValue(int value, bool blockUpdateSignal) = 0; protected Q_SLOTS: void contextMenuEvent(QContextMenuEvent * event); void editLostFocus(); protected: KisAbstractSliderSpinBoxPrivate* const d_ptr; // QWidget interface protected: virtual void changeEvent(QEvent *e); void paint(QPainter& painter); void paintPlastique(QPainter& painter); void paintBreeze(QPainter& painter); private: void setInternalValue(int value); }; class KRITAUI_EXPORT KisSliderSpinBox : public KisAbstractSliderSpinBox { Q_OBJECT Q_DECLARE_PRIVATE(KisSliderSpinBox) Q_PROPERTY( int minimum READ minimum WRITE setMinimum ) Q_PROPERTY( int maximum READ maximum WRITE setMaximum ) public: KisSliderSpinBox(QWidget* parent = 0); ~KisSliderSpinBox(); void setRange(int minimum, int maximum); int minimum() const; void setMinimum(int minimum); int maximum() const; void setMaximum(int maximum); int fastSliderStep() const; void setFastSliderStep(int step); ///Get the value, don't use value() int value(); void setSingleStep(int value); void setPageStep(int value); public Q_SLOTS: ///Set the value, don't use setValue() void setValue(int value); protected: virtual QString valueString() const; virtual void setInternalValue(int value, bool blockUpdateSignal); Q_SIGNALS: void valueChanged(int value); }; class KRITAUI_EXPORT KisDoubleSliderSpinBox : public KisAbstractSliderSpinBox { Q_OBJECT Q_DECLARE_PRIVATE(KisDoubleSliderSpinBox) public: KisDoubleSliderSpinBox(QWidget* parent = 0); ~KisDoubleSliderSpinBox(); void setRange(qreal minimum, qreal maximum, int decimals = 0); qreal minimum() const; void setMinimum(qreal minimum); qreal maximum() const; void setMaximum(qreal maximum); qreal fastSliderStep() const; void setFastSliderStep(qreal step); qreal value(); void setValue(qreal value); void setSingleStep(qreal value); protected: virtual QString valueString() const; virtual void setInternalValue(int value, bool blockUpdateSignal); Q_SIGNALS: void valueChanged(qreal value); }; #endif //kISSLIDERSPINBOX_H diff --git a/krita/ui/widgets/kis_tool_button.h b/krita/ui/widgets/kis_tool_button.h index c7669930cc2..2d8f8fafc0b 100644 --- a/krita/ui/widgets/kis_tool_button.h +++ b/krita/ui/widgets/kis_tool_button.h @@ -1,47 +1,47 @@ /* * Copyright (c) 2011 José Luis Vergara * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_TOOL_BUTTON_H #define KIS_TOOL_BUTTON_H #include -#include +#include /** This class exists to work around a bug in QToolButton when in * MenuPopupButton mode. The correct (mouse) behavior is to display * the menu with the first click, and let the user choose an item with * the next click. The buggy behavior presented by the tablet is to * present the menu and immediately select an item when the user * performs a stylus tip click. This workaround solves this. */ class KRITAUI_EXPORT KisToolButton : public QToolButton { Q_OBJECT public: explicit KisToolButton(QWidget *parent = 0); protected: virtual void mousePressEvent(QMouseEvent *e); virtual void mouseReleaseEvent(QMouseEvent *e); private: bool m_tabletContact; }; #endif // KIS_TOOL_BUTTON_H diff --git a/krita/ui/widgets/kis_tool_options_popup.cpp b/krita/ui/widgets/kis_tool_options_popup.cpp index d553549ec44..79affec2f2b 100644 --- a/krita/ui/widgets/kis_tool_options_popup.cpp +++ b/krita/ui/widgets/kis_tool_options_popup.cpp @@ -1,197 +1,200 @@ /* This file is part of the KDE project * Copyright (C) 2015 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #include "widgets/kis_tool_options_popup.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "kis_config.h" struct KisToolOptionsPopup::Private { public: QFont smallFont; bool detached; bool ignoreHideEvents; QRect detachedGeometry; QList > currentWidgetList; QSet currentAuxWidgets; QWidget *hiderWidget; // non current widgets are hidden by being children of this QGridLayout *housekeeperLayout; void recreateLayout(const QList > &optionWidgetList) { foreach(QPointer widget, currentWidgetList) { if (!widget.isNull() && widget && hiderWidget) { widget->setParent(hiderWidget); } } qDeleteAll(currentAuxWidgets); currentAuxWidgets.clear(); currentWidgetList = optionWidgetList; // need to unstretch row that have previously been stretched housekeeperLayout->setRowStretch(housekeeperLayout->rowCount()-1, 0); int cnt = 0; QFrame *s; QLabel *l; housekeeperLayout->setHorizontalSpacing(0); housekeeperLayout->setVerticalSpacing(2); int specialCount = 0; foreach(QPointer widget, currentWidgetList) { if (widget.isNull() || widget->objectName().isEmpty()) { continue; // skip this docker in release build when assert don't crash } + + widget->setMinimumWidth(300); + if (!widget->windowTitle().isEmpty()) { housekeeperLayout->addWidget(l = new QLabel(widget->windowTitle()), cnt++, 0); currentAuxWidgets.insert(l); } housekeeperLayout->addWidget(widget, cnt++, 0); QLayout *subLayout = widget->layout(); if (subLayout) { for (int i = 0; i < subLayout->count(); ++i) { QWidget *spacerWidget = subLayout->itemAt(i)->widget(); if (spacerWidget && spacerWidget->objectName().contains("SpecialSpacer")) { specialCount++; } } } widget->show(); if (widget != currentWidgetList.last()) { housekeeperLayout->addWidget(s = new QFrame(), cnt++, 0); s->setFrameShape(QFrame::HLine); currentAuxWidgets.insert(s); } } if (specialCount == currentWidgetList.count() || qApp->applicationName().contains("krita")) { housekeeperLayout->setRowStretch(cnt, 10000); } housekeeperLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); housekeeperLayout->invalidate(); } }; KisToolOptionsPopup::KisToolOptionsPopup(QWidget *parent) : QWidget(parent) , d(new Private()) { setObjectName("KisToolOptionsPopup"); KConfigGroup group(KGlobal::config(), "GUI"); d->smallFont = KGlobalSettings::generalFont(); qreal pointSize = group.readEntry("palettefontsize", d->smallFont.pointSize() * 0.75); pointSize = qMax(pointSize, KGlobalSettings::smallestReadableFont().pointSizeF()); d->smallFont.setPointSizeF(pointSize); setFont(d->smallFont); KisConfig cfg; d->detached = !cfg.paintopPopupDetached(); d->ignoreHideEvents = false; d->housekeeperLayout = new QGridLayout(); d->housekeeperLayout->setContentsMargins(4,4,4,0); setLayout(d->housekeeperLayout); d->housekeeperLayout->setSizeConstraint(QLayout::SetMinAndMaxSize); d->hiderWidget = new QWidget(this); d->hiderWidget->setVisible(false); } KisToolOptionsPopup::~KisToolOptionsPopup() { delete d; } void KisToolOptionsPopup::newOptionWidgets(const QList > &optionWidgetList) { d->recreateLayout(optionWidgetList); } void KisToolOptionsPopup::contextMenuEvent(QContextMenuEvent *e) { QMenu menu(this); QAction* action = menu.addAction(d->detached ? i18n("Attach to Toolbar") : i18n("Detach from Toolbar")); connect(action, SIGNAL(triggered()), this, SLOT(switchDetached())); menu.exec(e->globalPos()); } void KisToolOptionsPopup::hideEvent(QHideEvent *event) { if (d->ignoreHideEvents) { return; } if (d->detached) { d->detachedGeometry = window()->geometry(); } QWidget::hideEvent(event); } void KisToolOptionsPopup::showEvent(QShowEvent *) { if (d->detached) { window()->setGeometry(d->detachedGeometry); } } void KisToolOptionsPopup::switchDetached(bool show) { if (parentWidget()) { d->detached = !d->detached; if (d->detached) { d->ignoreHideEvents = true; parentWidget()->setWindowFlags(Qt::Tool); if (show) { parentWidget()->show(); } d->ignoreHideEvents = false; } else { parentWidget()->setWindowFlags(Qt::Popup); KisConfig cfg; parentWidget()->hide(); } KisConfig cfg; cfg.setToolOptionsPopupDetached(d->detached); } } diff --git a/krita/ui/widgets/kis_url_requester.h b/krita/ui/widgets/kis_url_requester.h index 9afc3633078..deefdeb7195 100644 --- a/krita/ui/widgets/kis_url_requester.h +++ b/krita/ui/widgets/kis_url_requester.h @@ -1,91 +1,91 @@ /* * Copyright (c) 2015 Dmitry Kazakov * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ #ifndef KIS_URL_REQUESTER_H #define KIS_URL_REQUESTER_H -#include "krita_export.h" +#include "kritaui_export.h" #include #include #include #include namespace Ui { class WdgUrlRequester; } /** * This represents an editable file name. * Visual it presents a QLineEdit + a buton that pops up * a file chooser. * * Signals are fired when the user changes the text * or selects a new file via the button/file chooser. */ class KRITAUI_EXPORT KisUrlRequester : public QWidget { Q_OBJECT public: explicit KisUrlRequester(QWidget *parent = 0); ~KisUrlRequester(); void setStartDir(const QString &path); KUrl url() const; void setUrl(const KUrl &url); void setMode(KoFileDialog::DialogType mode); KoFileDialog::DialogType mode() const; /** * Sets the mime type filters to use, same format as KoFileDialog::setMimeTypeFilters. * If this is not called, the default list is used, which simply selects all the image * file formats Krita can load. */ void setMimeTypeFilters(const QStringList &filterList, QString defaultFilter = QString()); /** * Sets the name filter, same as KoFileDialog::setNameFilter */ void setNameFilter(const QString &filter); public Q_SLOTS: void slotSelectFile(); Q_SIGNALS: void textChanged(const QString &fileName); void urlSelected(const KUrl &url); private: QString fileName() const; void setFileName(const QString &path); private: QScopedPointer m_ui; QString m_basePath; KoFileDialog::DialogType m_mode; QStringList m_mime_filter_list; QString m_mime_default_filter; QString m_nameFilter; }; #endif // KIS_URL_REQUESTER_H diff --git a/krita/ui/widgets/kis_wdg_generator.cpp b/krita/ui/widgets/kis_wdg_generator.cpp index 7aa2c9b6c3e..e86fe866d78 100644 --- a/krita/ui/widgets/kis_wdg_generator.cpp +++ b/krita/ui/widgets/kis_wdg_generator.cpp @@ -1,166 +1,167 @@ /* This file is part of the KDE project * Copyright (C) Boudewijn Rempt , (C) 2008 * * 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 "widgets/kis_wdg_generator.h" #include #include #include #include #include #include #include #include #include #include #include #include #include "ui_wdggenerators.h" class KisGeneratorItem : public QListWidgetItem { public: KisGeneratorItem(const QString & text, QListWidget * parent = 0, int type = Type) : QListWidgetItem(text, parent, type) { } KisGeneratorSP generator; }; struct KisWdgGenerator::Private { public: Private() : centralWidget(0), view(0) { } QWidget * centralWidget; // Active generator settings widget KisGeneratorSP currentGenerator; Ui_WdgGenerators uiWdgGenerators; KisPaintDeviceSP dev; QGridLayout *widgetLayout; KisViewManager *view; }; KisWdgGenerator::KisWdgGenerator(QWidget * parent) : QWidget(parent) , d(new Private()) { KisPaintDeviceSP dev = new KisPaintDevice(KoColorSpaceRegistry::instance()->rgb8(0)); } KisWdgGenerator::~KisWdgGenerator() { delete d; } void KisWdgGenerator::initialize(KisViewManager *view) { d->view = view; d->uiWdgGenerators.setupUi(this); d->widgetLayout = new QGridLayout(d->uiWdgGenerators.centralWidgetHolder); QList generators = KisGeneratorRegistry::instance()->values(); foreach(const KisGeneratorSP generator, generators) { Q_ASSERT(generator); KisGeneratorItem * item = new KisGeneratorItem(generator->name(), d->uiWdgGenerators.lstGenerators, QListWidgetItem::UserType + 1); item->generator = generator; } connect(d->uiWdgGenerators.lstGenerators, SIGNAL(currentRowChanged(int)), this, SLOT(slotGeneratorActivated(int))); if (d->uiWdgGenerators.lstGenerators->count() > 0) { d->uiWdgGenerators.lstGenerators->setCurrentRow(0); } } void KisWdgGenerator::setConfiguration(const KisFilterConfiguration * config) { for (int i = 0; i < d->uiWdgGenerators.lstGenerators->count(); ++i) { KisGeneratorItem * item = static_cast(d->uiWdgGenerators.lstGenerators->item(i)); if (item->generator->id() == config->name()) { // match! slotGeneratorActivated(i); + d->uiWdgGenerators.lstGenerators->setCurrentRow(i); KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { wdg->setConfiguration(config); } return; } } } KisFilterConfiguration * KisWdgGenerator::configuration() { KisConfigWidget * wdg = dynamic_cast(d->centralWidget); if (wdg) { KisFilterConfiguration * config = dynamic_cast(wdg->configuration()); if (config) { return config; } } else { return d->currentGenerator->defaultConfiguration(0); } return 0; } void KisWdgGenerator::slotGeneratorActivated(int row) { KisGeneratorItem * item = dynamic_cast(d->uiWdgGenerators.lstGenerators->item(row)); if (!item) { d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->currentGenerator = item->generator; delete d->centralWidget; KisConfigWidget* widget = d->currentGenerator->createConfigurationWidget(d->uiWdgGenerators.centralWidgetHolder, d->dev); if (!widget) { // No widget, so display a label instead d->centralWidget = new QLabel(i18n("No configuration options."), d->uiWdgGenerators.centralWidgetHolder); } else { d->centralWidget = widget; widget->setView(d->view); widget->setConfiguration(d->currentGenerator->defaultConfiguration(d->dev)); } } d->widgetLayout->addWidget(d->centralWidget, 0 , 0); d->uiWdgGenerators.centralWidgetHolder->setMinimumSize(d->centralWidget->minimumSize()); } #include "kis_wdg_generator.moc" diff --git a/krita/ui/widgets/kis_widget_chooser.h b/krita/ui/widgets/kis_widget_chooser.h index fc450af7b37..04908f5c462 100644 --- a/krita/ui/widgets/kis_widget_chooser.h +++ b/krita/ui/widgets/kis_widget_chooser.h @@ -1,104 +1,104 @@ /* * Copyright (c) 2011 Silvio Heinrich * * 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 H_KIS_WIDGET_CHOOSER_H_ #define H_KIS_WIDGET_CHOOSER_H_ -#include +#include #include #include #include class QToolButton; class QLabel; class QButtonGroup; class KRITAUI_EXPORT KisWidgetChooser: public QFrame { Q_OBJECT struct Data { Data(const QString& ID): id(ID), widget(0), label(0), choosen(false) { } Data(const Data& d): id(d.id), widget(d.widget), label(d.label), choosen(d.choosen) { } Data(const QString& ID, QWidget* w, QLabel* l): id(ID), widget(w), label(l), choosen(false) { } friend bool operator == (const Data& a, const Data& b) { return a.id == b.id; } QString id; QWidget* widget; QLabel* label; bool choosen; }; typedef QList::iterator Iterator; typedef QList::const_iterator ConstIterator; public: KisWidgetChooser(int id, QWidget* parent=0); ~KisWidgetChooser(); QWidget* chooseWidget(const QString& id); void addWidget(const QString& id, const QString& label, QWidget* widget); QWidget* getWidget(const QString& id) const; template TWidget* addWidget(const QString& id, const QString& label = "") { TWidget* widget = new TWidget(); addWidget(id, label, widget); return widget; } template TWidget* getWidget(const QString& id) const { return dynamic_cast(getWidget(id)); } public Q_SLOTS: void showPopupWidget(); private: void removeWidget(const QString& id); QLayout* createPopupLayout(); QLayout* createLayout(); void updateArrowIcon(); protected Q_SLOTS: void slotButtonPressed(); void slotWidgetChoosen(int index); // QWidget interface protected: virtual void changeEvent(QEvent *e); private: int m_chooserid; QIcon m_acceptIcon; QToolButton* m_arrowButton; QButtonGroup* m_buttons; QFrame* m_popup; QString m_choosenID; QList m_widgets; }; #endif // H_KIS_WIDGET_CHOOSER_H_ diff --git a/krita/ui/widgets/squeezedcombobox.h b/krita/ui/widgets/squeezedcombobox.h index c861c75fe1a..bc71cc358f3 100644 --- a/krita/ui/widgets/squeezedcombobox.h +++ b/krita/ui/widgets/squeezedcombobox.h @@ -1,136 +1,136 @@ /* ============================================================ * Author: Tom Albers * 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 widgets/squeezedcombobox.h */ #ifndef SQUEEZEDCOMBOBOX_H #define SQUEEZEDCOMBOBOX_H class QTimer; class QResizeEvent; class QWidget; // Qt includes. #include #include -#include +#include class SqueezedComboBox; /** @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 KRITAUI_EXPORT 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(); /** * * Returns true if the combobox contains the original (not-squeezed) * version of text. * @param text the original (not-squeezed) text to check for */ bool contains(const QString & text) const; /** * * Returns index of a orinal text, -1 if the text isn't found * @param text the original (not-squeezed) text to search for */ qint32 findOriginalText(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, QVariant userData = QVariant()); /** * Append an item. * @param newItem the original (long version) of the item which needs * to be added to the combobox */ void addSqueezedItem(const QString& newItem, QVariant userData = QVariant()); /** * Set the current item to the one matching the given text. * * @param itemText the original (long version) of the item text */ void setCurrent(const QString& itemText); /** * 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 Q_SLOTS: void slotTimeOut(); private: void resizeEvent(QResizeEvent *); QString squeezeText(const QString& original); // Prevent these from being used. void setCurrentText(const QString& itemText); void insertItem(const QString &text); void insertItem(qint32 index, const QString &text); void addItem(const QString &text); QMap m_originalItems; QTimer* m_timer; }; #endif // SQUEEZEDCOMBOBOX_H diff --git a/libs/db/expression.cpp b/libs/db/expression.cpp index d90592876db..d65658f66cf 100644 --- a/libs/db/expression.cpp +++ b/libs/db/expression.cpp @@ -1,1118 +1,1118 @@ /* This file is part of the KDE project Copyright (C) 2003-2015 JarosÅ‚aw Staniek Based on nexp.cpp : Parser module of Python-like language (C) 2001 JarosÅ‚aw Staniek, MIMUW (www.mimuw.edu.pl) 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 "expression.h" #include "utils.h" #include "driver_p.h" #include "parser/sqlparser.h" #include "parser/parser_p.h" #include #include #include CALLIGRADB_EXPORT QString KexiDB::exprClassName(int c) { if (c == KexiDBExpr_Unary) return "Unary"; else if (c == KexiDBExpr_Arithm) return "Arithm"; else if (c == KexiDBExpr_Logical) return "Logical"; else if (c == KexiDBExpr_Relational) return "Relational"; else if (c == KexiDBExpr_SpecialBinary) return "SpecialBinary"; else if (c == KexiDBExpr_Const) return "Const"; else if (c == KexiDBExpr_Variable) return "Variable"; else if (c == KexiDBExpr_Function) return "Function"; else if (c == KexiDBExpr_Aggregation) return "Aggregation"; else if (c == KexiDBExpr_TableList) return "TableList"; else if (c == KexiDBExpr_ArgumentList) return "ArgumentList"; else if (c == KexiDBExpr_QueryParameter) return "QueryParameter"; return "Unknown"; } using namespace KexiDB; //========================================= BaseExpr::BaseExpr(int token) : m_cl(KexiDBExpr_Unknown) , m_par(0) , m_token(token) { } BaseExpr::~BaseExpr() { } Field::Type BaseExpr::type() { return Field::InvalidType; } bool BaseExpr::isTextType() { return Field::isTextType(type()); } bool BaseExpr::isIntegerType() { return Field::isIntegerType(type()); } bool BaseExpr::isNumericType() { return Field::isNumericType(type()); } bool BaseExpr::isFPNumericType() { return Field::isFPNumericType(type()); } bool BaseExpr::isDateTimeType() { return Field::isDateTimeType(type()); } QString BaseExpr::debugString() { return QString("BaseExpr(%1,type=%1)").arg(m_token).arg(Driver::defaultSQLTypeName(type())); } bool BaseExpr::validate(ParseInfo& /*parseInfo*/) { return true; } QString BaseExpr::tokenToDebugString(int token) { if (token < 254) { if (isprint(token)) return QString(QChar(uchar(token))); else return QString::number(token); } return QLatin1String(tokenName(token)); } QString BaseExpr::tokenToString(const Driver *driver) { Q_UNUSED(driver); if (m_token < 255 && isprint(m_token)) return tokenToDebugString(); return QString(); } NArgExpr* BaseExpr::toNArg() { return dynamic_cast(this); } UnaryExpr* BaseExpr::toUnary() { return dynamic_cast(this); } BinaryExpr* BaseExpr::toBinary() { return dynamic_cast(this); } ConstExpr* BaseExpr::toConst() { return dynamic_cast(this); } VariableExpr* BaseExpr::toVariable() { return dynamic_cast(this); } FunctionExpr* BaseExpr::toFunction() { return dynamic_cast(this); } QueryParameterExpr* BaseExpr::toQueryParameter() { return dynamic_cast(this); } //========================================= NArgExpr::NArgExpr(int aClass, int token) : BaseExpr(token) { m_cl = aClass; } NArgExpr::NArgExpr(const NArgExpr& expr) : BaseExpr(expr) { foreach(BaseExpr* e, expr.list) { add(e->copy()); } } NArgExpr::~NArgExpr() { qDeleteAll(list); } NArgExpr* NArgExpr::copy() const { return new NArgExpr(*this); } Field::Type NArgExpr::type() { switch (m_token) { case KEXIDB_TOKEN_BETWEEN_AND: case KEXIDB_TOKEN_NOT_BETWEEN_AND: foreach (BaseExpr* e, list) { Field::Type type = e->type(); if (type == Field::InvalidType || type == Field::Null) { return type; } } return Field::Boolean; default:; } return BaseExpr::type(); } bool NArgExpr::containsInvalidArgument() { foreach (BaseExpr* e, list) { Field::Type type = e->type(); if (type == Field::InvalidType) { return true; } } return false; } bool NArgExpr::containsNullArgument() { foreach (BaseExpr* e, list) { Field::Type type = e->type(); if (type == Field::Null) { return true; } } return false; } QString NArgExpr::debugString() { QString s = QString("NArgExpr(") + tokenToString(0) + ", " + "class=" + exprClassName(m_cl); foreach(BaseExpr *expr, list) { s += ", " + expr->debugString(); } s += QString::fromLatin1(",type=%1)").arg(Driver::defaultSQLTypeName(type())); return s; } QString NArgExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { if (BaseExpr::token() == KEXIDB_TOKEN_BETWEEN_AND && list.count() == 3) { return list[0]->toString(driver) + " BETWEEN " + list[1]->toString(driver) + " AND " + list[2]->toString(driver); } if (BaseExpr::token() == KEXIDB_TOKEN_NOT_BETWEEN_AND && list.count() == 3) { return list[0]->toString(driver) + " NOT BETWEEN " + list[1]->toString(driver) + " AND " + list[2]->toString(driver); } QString s; s.reserve(256); foreach(BaseExpr* e, list) { if (!s.isEmpty()) s += ", "; s += e->toString(driver, params); } return s; } void NArgExpr::getQueryParameters(QuerySchemaParameterList& params) { foreach(BaseExpr *e, list) { e->getQueryParameters(params); } } BaseExpr* NArgExpr::arg(int nr) { return list.at(nr); } void NArgExpr::add(BaseExpr *expr) { list.append(expr); expr->setParent(this); } void NArgExpr::prepend(BaseExpr *expr) { list.prepend(expr); expr->setParent(this); } int NArgExpr::args() { return list.count(); } bool NArgExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) return false; foreach(BaseExpr *e, list) { if (!e->validate(parseInfo)) return false; } switch (m_token) { case KEXIDB_TOKEN_BETWEEN_AND: case KEXIDB_TOKEN_NOT_BETWEEN_AND: { if (list.count() != 3) { parseInfo.errMsg = i18n("Incorrect number of arguments"); parseInfo.errDescr = i18nc("@info BETWEEN..AND error", "%1 operator requires exactly three arguments.", "BETWEEN...AND"); return false; } if (!(!Field::isNumericType(list[0]->type()) || !Field::isNumericType(list[1]->type()) || !Field::isNumericType(list[2]->type()))) { return true; } else if (!(!Field::isTextType(list[0]->type()) || !Field::isTextType(list[1]->type()) || !Field::isTextType(list[2]->type()))) { return true; } if ((list[0]->type() == list[1]->type() && list[1]->type() == list[2]->type())) { return true; } parseInfo.errMsg = i18n("Incompatible types of arguments"); parseInfo.errDescr = i18nc("@info BETWEEN..AND type error", "%1 operator requires compatible types of arguments.", "BETWEEN..AND"); return false; } default:; } return true; } QString NArgExpr::tokenToString(const Driver *driver) { switch (m_token) { case KEXIDB_TOKEN_BETWEEN_AND: return "BETWEEN_AND"; case KEXIDB_TOKEN_NOT_BETWEEN_AND: return "NOT_BETWEEN_AND"; default: { const QString s = BaseExpr::tokenToString(driver); if (!s.isEmpty()) { return QString("'%1'").arg(s); } } } return QString("{INVALID_N_ARG_OPERATOR#%1}").arg(m_token); } //========================================= UnaryExpr::UnaryExpr(int token, BaseExpr *arg) : BaseExpr(token) , m_arg(arg) { m_cl = KexiDBExpr_Unary; if (m_arg) m_arg->setParent(this); } UnaryExpr::UnaryExpr(const UnaryExpr& expr) : BaseExpr(expr) , m_arg(expr.m_arg ? expr.m_arg->copy() : 0) { if (m_arg) m_arg->setParent(this); } UnaryExpr::~UnaryExpr() { delete m_arg; } UnaryExpr* UnaryExpr::copy() const { return new UnaryExpr(*this); } QString UnaryExpr::debugString() { return "UnaryExpr('" + tokenToDebugString() + "', " + (m_arg ? m_arg->debugString() : QString("")) + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type())); } QString UnaryExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { if (m_token == '(') //parentheses (special case) return '(' + (m_arg ? m_arg->toString(driver, params) : "") + ')'; if (m_token < 255 && isprint(m_token)) return tokenToDebugString() + (m_arg ? m_arg->toString(driver, params) : ""); if (m_token == NOT) return "NOT " + (m_arg ? m_arg->toString(driver, params) : ""); if (m_token == SQL_IS_NULL) return (m_arg ? m_arg->toString(driver, params) : "") + " IS NULL"; if (m_token == SQL_IS_NOT_NULL) return (m_arg ? m_arg->toString(driver, params) : "") + " IS NOT NULL"; return QString("{INVALID_OPERATOR#%1} ").arg(m_token) + (m_arg ? m_arg->toString(driver, params) : ""); } void UnaryExpr::getQueryParameters(QuerySchemaParameterList& params) { if (m_arg) m_arg->getQueryParameters(params); } Field::Type UnaryExpr::type() { //NULL IS NOT NULL : BOOLEAN //NULL IS NULL : BOOLEAN switch (m_token) { case SQL_IS_NULL: case SQL_IS_NOT_NULL: return Field::Boolean; } const Field::Type t = m_arg->type(); if (t == Field::Null) return Field::Null; if (m_token == NOT) return Field::Boolean; return t; } bool UnaryExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) return false; if (!m_arg->validate(parseInfo)) return false; //! @todo compare types... e.g. NOT applied to Text makes no sense... // update type if (m_arg->toQueryParameter()) { m_arg->toQueryParameter()->setType(type()); } return true; #if 0 BaseExpr *n = l.at(0); n->check(); /*typ wyniku: const bool dla "NOT " (negacja) int dla "# " (dlugosc stringu) int dla "+/- " */ if (is(NOT) && n->nodeTypeIs(TYP_BOOL)) { node_type = new NConstType(TYP_BOOL); } else if (is('#') && n->nodeTypeIs(TYP_STR)) { node_type = new NConstType(TYP_INT); } else if ((is('+') || is('-')) && n->nodeTypeIs(TYP_INT)) { node_type = new NConstType(TYP_INT); } else { ERR("Niepoprawny argument typu '%s' dla operatora '%s'", n->nodeTypeName(), is(NOT) ? QString("not") : QChar(typ())); } #endif } //========================================= BinaryExpr::BinaryExpr(int aClass, BaseExpr *left_expr, int token, BaseExpr *right_expr) : BaseExpr(token) , m_larg(left_expr) , m_rarg(right_expr) { m_cl = aClass; if (m_larg) m_larg->setParent(this); if (m_rarg) m_rarg->setParent(this); } BinaryExpr::BinaryExpr(const BinaryExpr& expr) : BaseExpr(expr) , m_larg(expr.m_larg ? expr.m_larg->copy() : 0) , m_rarg(expr.m_rarg ? expr.m_rarg->copy() : 0) { } BinaryExpr::~BinaryExpr() { delete m_larg; delete m_rarg; } BinaryExpr* BinaryExpr::copy() const { return new BinaryExpr(*this); } bool BinaryExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) return false; if (!m_larg->validate(parseInfo)) return false; if (!m_rarg->validate(parseInfo)) return false; //! @todo compare types..., BITWISE_SHIFT_RIGHT requires integers, etc... //update type for query parameters QueryParameterExpr * queryParameter = m_larg->toQueryParameter(); if (queryParameter) queryParameter->setType(m_rarg->type()); queryParameter = m_rarg->toQueryParameter(); if (queryParameter) queryParameter->setType(m_larg->type()); return true; } Field::Type BinaryExpr::type() { const Field::Type lt = m_larg->type(), rt = m_rarg->type(); if (lt == Field::InvalidType || rt == Field::InvalidType) return Field::InvalidType; if (lt == Field::Null || rt == Field::Null) { if (m_token != OR) //note that NULL OR something != NULL return Field::Null; } switch (m_token) { case BITWISE_SHIFT_RIGHT: case BITWISE_SHIFT_LEFT: case CONCATENATION: return lt; } const bool ltInt = Field::isIntegerType(lt); const bool rtInt = Field::isIntegerType(rt); if (ltInt && rtInt) return KexiDB::maximumForIntegerTypes(lt, rt); if (Field::isFPNumericType(lt) && (rtInt || lt == rt)) return lt; if (Field::isFPNumericType(rt) && (ltInt || lt == rt)) return rt; return Field::Boolean; } QString BinaryExpr::debugString() { return QLatin1String("BinaryExpr(") + "class=" + exprClassName(m_cl) + ',' + (m_larg ? m_larg->debugString() : QString::fromLatin1("")) + ",'" + tokenToDebugString() + "'," + (m_rarg ? m_rarg->debugString() : QString::fromLatin1("")) + QString::fromLatin1(",type=%1)").arg(Driver::defaultSQLTypeName(type())); } QString BinaryExpr::tokenToString(const Driver *driver) { if (m_token < 255 && isprint(m_token)) return tokenToDebugString(); // other arithmetic operations: << >> switch (m_token) { case BITWISE_SHIFT_RIGHT: return ">>"; case BITWISE_SHIFT_LEFT: return "<<"; // other relational operations: <= >= <> (or !=) LIKE IN case NOT_EQUAL: return "<>"; case NOT_EQUAL2: return "!="; case LESS_OR_EQUAL: return "<="; case GREATER_OR_EQUAL: return ">="; case LIKE: return driver ? driver->behaviour()->LIKE_OPERATOR : "LIKE"; case NOT_LIKE: return driver ? (QString::fromLatin1("NOT ") + driver->behaviour()->LIKE_OPERATOR) : QString::fromLatin1("NOT LIKE"); case SQL_IN: return "IN"; // other logical operations: OR (or ||) AND (or &&) XOR case SIMILAR_TO: return "SIMILAR TO"; case NOT_SIMILAR_TO: return "NOT SIMILAR TO"; case OR: return "OR"; case AND: return "AND"; case XOR: return "XOR"; // other string operations: || (as CONCATENATION) case CONCATENATION: return "||"; // SpecialBinary "pseudo operators": /* not handled here */ default:; } return QString("{INVALID_BINARY_OPERATOR#%1} ").arg(m_token); } QString BinaryExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { #define INFIX(a) \ (m_larg ? m_larg->toString(driver, params) : "") + ' ' + a + ' ' + (m_rarg ? m_rarg->toString(driver, params) : "") return INFIX(tokenToString(driver)); } void BinaryExpr::getQueryParameters(QuerySchemaParameterList& params) { if (m_larg) m_larg->getQueryParameters(params); if (m_rarg) m_rarg->getQueryParameters(params); } //========================================= ConstExpr::ConstExpr(int token, const QVariant& val) : BaseExpr(token) , value(val) { m_cl = KexiDBExpr_Const; } ConstExpr::ConstExpr(const ConstExpr& expr) : BaseExpr(expr) , value(expr.value) { } ConstExpr::~ConstExpr() { } ConstExpr* ConstExpr::copy() const { return new ConstExpr(*this); } Field::Type ConstExpr::type() { if (m_token == SQL_NULL) return Field::Null; else if (m_token == INTEGER_CONST) { //TODO ok? //TODO: add sign info? if (value.type() == QVariant::Int || value.type() == QVariant::UInt) { qint64 v = value.toInt(); if (v <= 0xff && v > -0x80) return Field::Byte; if (v <= 0xffff && v > -0x8000) return Field::ShortInteger; return Field::Integer; } return Field::BigInteger; } else if (m_token == CHARACTER_STRING_LITERAL) { //TODO: Field::defaultTextLength() is hardcoded now! if (Field::defaultMaxLength() > 0 && uint(value.toString().length()) > Field::defaultMaxLength()) { return Field::LongText; } else return Field::Text; } else if (m_token == REAL_CONST) return Field::Double; else if (m_token == DATE_CONST) return Field::Date; else if (m_token == DATETIME_CONST) return Field::DateTime; else if (m_token == TIME_CONST) return Field::Time; return Field::InvalidType; } QString ConstExpr::debugString() { return QString("ConstExpr('") + tokenToDebugString() + "'," + toString(0) + QString(",type=%1)").arg(Driver::defaultSQLTypeName(type())); } QString ConstExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { Q_UNUSED(driver); Q_UNUSED(params); if (m_token == SQL_NULL) return "NULL"; else if (m_token == CHARACTER_STRING_LITERAL) //TODO: better escaping! return QLatin1Char('\'') + value.toString() + QLatin1Char('\''); else if (m_token == REAL_CONST) return QString::number(value.toPoint().x()) + QLatin1Char('.') + QString::number(value.toPoint().y()); else if (m_token == DATE_CONST) return QLatin1Char('\'') + value.toDate().toString(Qt::ISODate) + QLatin1Char('\''); else if (m_token == DATETIME_CONST) return QLatin1Char('\'') + value.toDateTime().date().toString(Qt::ISODate) + QLatin1Char(' ') + value.toDateTime().time().toString(Qt::ISODate) + QLatin1Char('\''); else if (m_token == TIME_CONST) return QLatin1Char('\'') + value.toTime().toString(Qt::ISODate) + QLatin1Char('\''); return value.toString(); } void ConstExpr::getQueryParameters(QuerySchemaParameterList& params) { Q_UNUSED(params); } bool ConstExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) return false; return type() != Field::InvalidType; } //========================================= QueryParameterExpr::QueryParameterExpr(const QString& message) : ConstExpr(QUERY_PARAMETER, message) , m_type(Field::Text) { m_cl = KexiDBExpr_QueryParameter; } QueryParameterExpr::QueryParameterExpr(const QueryParameterExpr& expr) : ConstExpr(expr) , m_type(expr.m_type) { } QueryParameterExpr::~QueryParameterExpr() { } QueryParameterExpr* QueryParameterExpr::copy() const { return new QueryParameterExpr(*this); } Field::Type QueryParameterExpr::type() { return m_type; } void QueryParameterExpr::setType(Field::Type type) { m_type = type; } QString QueryParameterExpr::debugString() { return QString("QueryParameterExpr('") + QString::fromLatin1("[%2]").arg(value.toString()) + QString("',type=%1)").arg(Driver::defaultSQLTypeName(type())); } QString QueryParameterExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { Q_UNUSED(driver); return params ? params->getPreviousValueAsString(type()) : QString::fromLatin1("[%2]").arg(value.toString()); } void QueryParameterExpr::getQueryParameters(QuerySchemaParameterList& params) { QuerySchemaParameter param; param.message = value.toString(); param.type = type(); params.append(param); } bool QueryParameterExpr::validate(ParseInfo& parseInfo) { Q_UNUSED(parseInfo); return type() != Field::InvalidType; } //========================================= VariableExpr::VariableExpr(const QString& _name) : BaseExpr(0/*undefined*/) , name(_name) , field(0) , tablePositionForField(-1) , tableForQueryAsterisk(0) { m_cl = KexiDBExpr_Variable; } VariableExpr::VariableExpr(const VariableExpr& expr) : BaseExpr(expr) , name(expr.name) , field(expr.field) , tablePositionForField(expr.tablePositionForField) , tableForQueryAsterisk(expr.tableForQueryAsterisk) { } VariableExpr::~VariableExpr() { } VariableExpr* VariableExpr::copy() const { return new VariableExpr(*this); } QString VariableExpr::debugString() { return QString("VariableExpr(") + name + QString(",type=%1)").arg(field ? Driver::defaultSQLTypeName(type()) : QString("FIELD NOT DEFINED YET")); } QString VariableExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { Q_UNUSED(driver); Q_UNUSED(params); return name; } void VariableExpr::getQueryParameters(QuerySchemaParameterList& params) { Q_UNUSED(params); } //! We're assuming it's called after VariableExpr::validate() Field::Type VariableExpr::type() { if (field) return field->type(); //BTW, asterisks are not stored in VariableExpr outside of parser, so ok. return Field::InvalidType; } #define IMPL_ERROR(errmsg) parseInfo.errMsg = "Implementation error"; parseInfo.errDescr = errmsg bool VariableExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) return false; field = 0; tablePositionForField = -1; tableForQueryAsterisk = 0; /* taken from parser's addColumn(): */ KexiDBDbg << "checking variable name: " << name; QString tableName, fieldName; if (!KexiDB::splitToTableAndFieldParts(name, tableName, fieldName, KexiDB::SetFieldNameIfNoTableName)) { return false; } //! @todo shall we also support db name? if (tableName.isEmpty()) {//fieldname only if (fieldName == "*") { // querySchema->addAsterisk( new QueryAsterisk(querySchema) ); return true; } //find first table that has this field Field *firstField = 0; foreach(TableSchema *table, *parseInfo.querySchema->tables()) { Field *f = table->field(fieldName); if (f) { if (!firstField) { firstField = f; } else if (f->table() != firstField->table()) { //ambiguous field name parseInfo.errMsg = i18n("Ambiguous field name"); parseInfo.errDescr = i18nc("@info", "Both table %1 and %2 have " "defined %3 field. " "Use tableName.%4 notation to specify table name.", firstField->table()->name(), f->table()->name(), fieldName, fieldName); return false; } } } if (!firstField) { parseInfo.errMsg = i18n("Field not found"); parseInfo.errDescr = i18n("Table containing \"%1\" field not found.", fieldName); return false; } //ok field = firstField; //store // querySchema->addField(firstField); return true; } //table.fieldname or tableAlias.fieldname TableSchema *ts = parseInfo.querySchema->table(tableName); int tablePosition = -1; if (ts) {//table.fieldname //check if "table" is covered by an alias const QList tPositions = parseInfo.querySchema->tablePositions(tableName); QByteArray tableAlias; bool covered = true; foreach(int position, tPositions) { tableAlias = parseInfo.querySchema->tableAlias(position); if (tableAlias.isEmpty() || tableAlias.toLower() == tableName.toLatin1()) { covered = false; //uncovered break; } KexiDBDbg << " --" << "covered by " << tableAlias << " alias"; } if (covered) { parseInfo.errMsg = i18n("Could not access the table directly using its name"); parseInfo.errDescr = i18n("Table name %1 is covered by aliases. " "Instead of %2, " "you can write %3.", tableName, tableName + "." + fieldName, tableAlias + "." + QString(fieldName)); return false; } if (!tPositions.isEmpty()) { tablePosition = tPositions.first(); } } else {//try to find tableAlias tablePosition = parseInfo.querySchema->tablePositionForAlias(tableName.toLatin1()); if (tablePosition >= 0) { ts = parseInfo.querySchema->tables()->at(tablePosition); if (ts) { // KexiDBDbg << " --it's a tableAlias.name"; } } } if (!ts) { parseInfo.errMsg = i18n("Table not found"); parseInfo.errDescr = i18n("Unknown table \"%1\".", tableName); return false; } if (!parseInfo.repeatedTablesAndAliases.contains(tableName)) { //for sanity IMPL_ERROR(tableName + "." + fieldName + ", !positionsList "); return false; } const QList positionsList(parseInfo.repeatedTablesAndAliases.value(tableName)); //it's a table.* if (fieldName == "*") { if (positionsList.count() > 1) { parseInfo.errMsg = i18n("Ambiguous \"%1.*\" expression", tableName); parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined.", tableName); return false; } tableForQueryAsterisk = ts; // querySchema->addAsterisk( new QueryAsterisk(querySchema, ts) ); return true; } // KexiDBDbg << " --it's a table.name"; Field *realField = ts->field(fieldName); if (!realField) { parseInfo.errMsg = i18n("Field not found"); parseInfo.errDescr = i18n("Table \"%1\" has no \"%2\" field.", tableName, fieldName); return false; } // check if table or alias is used twice and both have the same column // (so the column is ambiguous) if (positionsList.count() > 1) { parseInfo.errMsg = i18n("Ambiguous \"%1.%2\" expression", tableName, fieldName); parseInfo.errDescr = i18n("More than one \"%1\" table or alias defined containing \"%2\" field.", tableName, fieldName); return false; } field = realField; //store tablePositionForField = tablePosition; // querySchema->addField(realField, tablePosition); return true; } //========================================= static const char* const FunctionExpr_builtIns_[] = {"SUM", "MIN", "MAX", "AVG", "COUNT", "STD", "STDDEV", "VARIANCE", 0 }; class BuiltInAggregates : public QSet { public: BuiltInAggregates() : QSet() { for (const char * const *p = FunctionExpr_builtIns_; *p; p++) insert(QByteArray::fromRawData(*p, qstrlen(*p))); } }; K_GLOBAL_STATIC(BuiltInAggregates, _builtInAggregates) //========================================= FunctionExpr::FunctionExpr(const QString& name_, NArgExpr* args_) : BaseExpr(0/*undefined*/) , name(name_.toUpper()) , args(args_) { if (_builtInAggregates->contains(name.toLatin1())) { m_cl = KexiDBExpr_Aggregation; } else { m_cl = KexiDBExpr_Function; } if (args) args->setParent(this); } FunctionExpr::FunctionExpr(const FunctionExpr& expr) : BaseExpr(0/*undefined*/) , name(expr.name) - , args(expr.args ? args->copy() : 0) + , args(expr.args ? expr.args->copy() : 0) { if (args) args->setParent(this); } FunctionExpr::~FunctionExpr() { delete args; } FunctionExpr* FunctionExpr::copy() const { return new FunctionExpr(*this); } QString FunctionExpr::debugString() { QString res; res.append(QString("FunctionExpr(") + name); if (args) res.append(QString(",") + args->debugString()); res.append(QString(",type=%1)").arg(Driver::defaultSQLTypeName(type()))); return res; } QString FunctionExpr::toString(const Driver *driver, QuerySchemaParameterValueListIterator* params) { return name + '(' + (args ? args->toString(driver, params) : QString()) + ')'; } void FunctionExpr::getQueryParameters(QuerySchemaParameterList& params) { args->getQueryParameters(params); } Field::Type FunctionExpr::type() { if (name == "SUBSTR") { if (args->containsNullArgument()) { return Field::Null; } return Field::Text; } //! @todo return Field::InvalidType; } bool FunctionExpr::validate(ParseInfo& parseInfo) { if (!BaseExpr::validate(parseInfo)) { return false; } if (args->token() != ',') { // arguments required: NArgExpr with token ',' return false; } if (!args->validate(parseInfo)) { return false; } if (name == "SUBSTR") { /* From https://www.sqlite.org/lang_corefunc.html: [1] substr(X,Y,Z) The substr(X,Y,Z) function returns a substring of input string X that begins with the Y-th character and which is Z characters long. If Z is omitted then [2] substr(X,Y) substr(X,Y) returns all characters through the end of the string X beginning with the Y-th. The left-most character of X is number 1. If Y is negative then the first character of the substring is found by counting from the right rather than the left. If Z is negative then the abs(Z) characters preceding the Y-th character are returned. If X is a string then characters indices refer to actual UTF-8 characters. If X is a BLOB then the indices refer to bytes. */ if (args->containsInvalidArgument()) { return false; } const int count = args->args(); if (count != 2 && count != 3) { parseInfo.errMsg = i18n("Incorrect number of arguments"); parseInfo.errDescr = i18nc("@info Number of arguments error", "%1() function requires 2 or 3 arguments.", name); return false; } BaseExpr *textExpr = args->arg(0); if (!textExpr->isTextType() && textExpr->type() != Field::Null) { parseInfo.errMsg = i18n("Incorrect type of argument"); parseInfo.errDescr = i18nc("@info Type error", "%1() function's first argument should be of type \"%2\". " "Specified argument is of type \"%3\".", name, Field::typeName(Field::Text), Field::typeName(textExpr->type())); return false; } BaseExpr *startExpr = args->arg(1); if (!startExpr->isIntegerType() && startExpr->type() != Field::Null) { parseInfo.errMsg = i18n("Incorrect type of argument"); parseInfo.errDescr = i18nc("@info Type error", "%1() function's second argument should be of type \"%2\". " "Specified argument is of type \"%3\".", name, Field::typeName(Field::Integer), Field::typeName(startExpr->type())); return false; } BaseExpr *lengthExpr = 0; if (count == 3) { lengthExpr = args->arg(2); if (!lengthExpr->isIntegerType() && lengthExpr->type() != Field::Null) { parseInfo.errMsg = i18n("Incorrect type of argument"); parseInfo.errDescr = i18nc("@info Type error", "%1() function's third argument should be of type \"%2\". " "Specified argument is of type \"%3\".", name, Field::typeName(Field::Integer), Field::typeName(lengthExpr->type())); return false; } } } else { return false; } return true; } bool FunctionExpr::isBuiltInAggregate(const QByteArray& fname) { return _builtInAggregates->contains(fname.toUpper()); } diff --git a/libs/main/KoDocument.h b/libs/main/KoDocument.h index 46c853b91d4..a4ed7f0b3c0 100644 --- a/libs/main/KoDocument.h +++ b/libs/main/KoDocument.h @@ -1,801 +1,801 @@ /* This file is part of the KDE project Copyright (C) 1998, 1999 Torben Weis Copyright (C) 2000-2005 David Faure Copyright (C) 2007 Thorsten Zachmann Copyright (C) 2010 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Library General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more details. You should have received a copy of the GNU Library General Public License along with this library; see the file COPYING.LIB. If not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ #ifndef KODOCUMENT_H #define KODOCUMENT_H #include #include #include "komain_export.h" #include #include #include class KUndo2Command; class KoPart; class KoStore; class KoDocumentInfo; class KoDocumentRdf; class KoDocumentRdfBase; class KoProgressUpdater; class KoProgressProxy; class KoDocumentInfoDlg; class KoUnit; class KoGridData; class KoGuidesData; class KoXmlWriter; class QDomDocument; // MSVC seems to need to know the declaration of the classes // we pass references of in, when used by external modules // e.g. // when building chartshapecore.lib, the forward-declaration // appraoch lead to unresolved externals warnings when it used // the pagelayout functions. // Also when building calligra_shape_formular.dll - FormulaDocument // referenced the same two pagelayout functions incorrectly. #if defined(_WIN32) || defined(_WIN64) #include #else - class KoPageLayout; + struct KoPageLayout; #endif class KoVersionInfo { public: QDateTime date; QString saved_by; QString comment; QString title; QByteArray data; //the content of the compressed version }; /** * The %Calligra document class * * This class provides some functionality each %Calligra document should have. * * @short The %Calligra document class */ class KOMAIN_EXPORT KoDocument : public QObject, public KoDocumentBase { Q_OBJECT Q_PROPERTY(bool backupFile READ backupFile WRITE setBackupFile) Q_PROPERTY(int pageCount READ pageCount) public: /** * Constructor. * * @param parent The KoPart that owns the document. XXX: should be removed! * @param undoStack accepts the stack for the document. You can create any type of stack if you need. * The stack objects will become owned by the document. This is used by Krita's KisDoc2. The default value for this * parameter is a usual Qt's stack. */ explicit KoDocument(KoPart *parent, KUndo2Stack *undoStack = new KUndo2Stack()); /** * Destructor. * * The destructor does not delete any attached KoView objects and it does not * delete the attached widget as returned by widget(). */ virtual ~KoDocument(); /// XXX: Temporary! KoPart *documentPart() const; /** * Reimplemented from KoParts::ReadWritePart for internal reasons * (for the autosave functionality) */ virtual bool openUrl(const KUrl & url); /** * Opens the document given by @p url, without storing the URL * in the KoDocument. * Call this instead of openUrl() to implement KoMainWindow's * File --> Import feature. * * @note This will call openUrl(). To differentiate this from an ordinary * Open operation (in any reimplementation of openUrl() or openFile()) * call isImporting(). */ bool importDocument(const KUrl &url); /** * Saves the document as @p url without changing the state of the * KoDocument (URL, modified flag etc.). Call this instead of * KoParts::ReadWritePart::saveAs() to implement KoMainWindow's * File --> Export feature. * * @note This will call KoDocument::saveAs(). To differentiate this * from an ordinary Save operation (in any reimplementation of * saveFile()) call isExporting(). */ bool exportDocument(const KUrl &url); /** * @brief Sets whether the document can be edited or is read only. * * This recursively applied to all child documents and * KoView::updateReadWrite is called for every attached * view. */ virtual void setReadWrite(bool readwrite = true); /** * To be preferred when a document exists. It is fast when calling * it multiple times since it caches the result that readNativeFormatMimeType() * delivers. * This comes from the X-KDE-NativeMimeType key in the .desktop file. */ virtual QByteArray nativeFormatMimeType() const = 0; /** * Returns the OASIS OpenDocument mimetype of the document, if supported * This comes from the X-KDE-NativeOasisMimeType key in the * desktop file * * @return the oasis mimetype or, if it hasn't one, the nativeformatmimetype. */ virtual QByteArray nativeOasisMimeType() const = 0; /// Checks whether a given mimetype can be handled natively. bool isNativeFormat(const QByteArray& mimetype) const; /// Returns a list of the mimetypes considered "native", i.e. which can /// be saved by KoDocument without a filter, in *addition* to the main one virtual QStringList extraNativeMimeTypes() const = 0; /** * Return the set of SupportedSpecialFormats that the application wants to * offer in the "Save" file dialog. */ virtual int supportedSpecialFormats() const; /** * Returns the actual mimetype of the document */ QByteArray mimeType() const; /** * @brief Sets the mime type for the document. * * When choosing "save as" this is also the mime type * selected by default. */ void setMimeType(const QByteArray & mimeType); /** * @brief Set the format in which the document should be saved. * * This is called on loading, and in "save as", so you shouldn't * have to call it. * * @param mimeType the mime type (format) to use. * @param specialOutputFlag is for "save as older version" etc. */ void setOutputMimeType(const QByteArray & mimeType, int specialOutputFlag = 0); QByteArray outputMimeType() const; int specialOutputFlag() const; /** * Returns true if this document was the result of opening a foreign * file format and if the user hasn't yet saved the document (in any * format). * * Used by KoMainWindow to warn the user when s/he lazily presses * CTRL+S to save in the same foreign format, putting all his/her * formatting at risk (normally an export confirmation only comes up * with Save As). * * @param exporting specifies whether this is the setting for a * File --> Export or File --> Save/Save As operation. */ bool confirmNonNativeSave(const bool exporting) const; void setConfirmNonNativeSave(const bool exporting, const bool on); /** * @return true if saving/exporting should inhibit the option dialog */ bool saveInBatchMode() const; /** * @param batchMode if true, do not show the option dialog when saving or exporting. */ void setSaveInBatchMode(const bool batchMode); /** * Sets the error message to be shown to the user (use i18n()!) * when loading or saving fails. * If you asked the user about something and they chose "Cancel", * set the message to the magic string "USER_CANCELED", to skip the error dialog. */ void setErrorMessage(const QString& errMsg); /** * Return the last error message. Usually KoDocument takes care of * showing it; this method is mostly provided for non-interactive use. */ QString errorMessage() const; /** * Show the last error message in a message box. * The dialog box will mention a loading problem. * openUrl/openFile takes care of doing it, but not loadNativeFormat itself, * so this is often called after loadNativeFormat returned false. */ void showLoadingErrorDialog(); /** * @brief Generates a preview picture of the document * @note The preview is used in the File Dialog and also to create the Thumbnail */ virtual QPixmap generatePreview(const QSize& size); /** * Paints the data itself. * It's this method that %Calligra Parts have to implement. * * @param painter The painter object onto which will be drawn. * @param rect The rect that should be used in the painter object. */ virtual void paintContent(QPainter &painter, const QRect &rect) = 0; /** * Tells the document that its title has been modified, either because * the modified status changes (this is done by setModified() ) or * because the URL or the document-info's title changed. */ void setTitleModified(); /** * @return true if the document is empty. */ virtual bool isEmpty() const; /** * @brief Sets the document to empty. * * Used after loading a template * (which is not empty, but not the user's input). * * @see isEmpty() */ virtual void setEmpty(); /** * @brief Loads a document from a store. * * You should never have to reimplement. * * @param store The store to load from * @param url An internal url, like tar:/1/2 */ virtual bool loadFromStore(KoStore *store, const QString& url); /** * @brief Loads an OASIS document from a store. * This is used for both the main document and embedded objects. */ virtual bool loadOasisFromStore(KoStore *store); /** * @brief Saves a sub-document to a store. * * You should not have to reimplement this. */ virtual bool saveToStore(KoStore *store, const QString& path); /** * Reimplement this method to load the contents of your Calligra document, * from the XML document. This is for the pre-Oasis file format (maindoc.xml). */ virtual bool loadXML(const KoXmlDocument & doc, KoStore *store) = 0; /** * Reimplement this to save the contents of the %Calligra document into * a QDomDocument. The framework takes care of saving it to the store. */ virtual QDomDocument saveXML(); /** * Return a correctly created QDomDocument for this KoDocument, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * @param tagName the name of the tag for the root element * @param version the DTD version (usually the application's version). */ QDomDocument createDomDocument(const QString& tagName, const QString& version) const; /** * Return a correctly created QDomDocument for an old (1.3-style) %Calligra document, * including processing instruction, complete DOCTYPE tag (with systemId and publicId), and root element. * This static method can be used e.g. by filters. * @param appName the app's instance name, e.g. words, kspread, kpresenter etc. * @param tagName the name of the tag for the root element, e.g. DOC for words/kpresenter. * @param version the DTD version (usually the application's version). */ static QDomDocument createDomDocument(const QString& appName, const QString& tagName, const QString& version); /** * The first thing to do in loadOasis is get hold of the office:body tag, then its child. * If the child isn't the expected one, the error message can indicate what it is instead. * This method returns a translated name for the type of document, * e.g. i18n("Word Processing") for office:text. */ static QString tagNameToDocumentType(const QString& localName); /** * Loads a document in the native format from a given URL. * Reimplement if your native format isn't XML. * * @param file the file to load - usually KReadOnlyPart::m_file or the result of a filter */ virtual bool loadNativeFormat(const QString & file); /** * Saves the document in native format, to a given file * You should never have to reimplement. * Made public for writing templates. */ virtual bool saveNativeFormat(const QString & file); /** * Saves the document in native ODF format to the given store. */ bool saveNativeFormatODF(KoStore *store, const QByteArray &mimeType); /** * Saves the document in the native format to the given store. */ bool saveNativeFormatCalligra(KoStore *store); /** * Activate/deactivate/configure the autosave feature. * @param delay in seconds, 0 to disable */ void setAutoSave(int delay); /** * Checks whether the document is currently in the process of autosaving */ bool isAutosaving() const; /** * Set whether the next openUrl call should check for an auto-saved file * and offer to open it. This is usually true, but can be turned off * (e.g. for the preview module). This only checks for names auto-saved * files, unnamed auto-saved files are only checked on KoApplication startup. */ void setCheckAutoSaveFile(bool b); /** * Set whether the next openUrl call should show error message boxes in case * of errors. This is usually the case, but e.g. not when generating thumbnail * previews. */ void setAutoErrorHandlingEnabled(bool b); /** * Checks whether error message boxes should be shown. */ bool isAutoErrorHandlingEnabled() const; /** * Retrieve the default value for autosave in seconds. * Called by the applications to use the correct default in their config */ static int defaultAutoSave(); /** * @return the information concerning this document. * @see KoDocumentInfo */ KoDocumentInfo *documentInfo() const; /** * @return the Rdf metadata for this document. * This method should only be used by code that links to * the RDF system and needs full access to the KoDocumentRdf object. * @see KoDocumentRdf */ KoDocumentRdfBase *documentRdf() const; /** * Replace the current rdf document with the given rdf document. The existing RDF document * will be deleted, and if RDF support is compiled out, KoDocument does not take ownership. * Otherwise, KoDocument will own the rdf document. */ void setDocumentRdf(KoDocumentRdfBase *rdfDocument); /** * @return the object to report progress to. * One can add more KoUpdaters to it to make the progress reporting more * accurate. If no active progress reporter is present, 0 is returned. **/ KoProgressUpdater *progressUpdater() const; /** * Set a custom progress proxy to use to report loading * progress to. */ void setProgressProxy(KoProgressProxy *progressProxy); KoProgressProxy* progressProxy() const; /** * Return true if url() is a real filename, false if url() is * an internal url in the store, like "tar:/..." */ virtual bool isStoredExtern() const; /** * @return the page layout associated with this document (margins, pageSize, etc). * Override this if you want to provide different sized pages. * * @see KoPageLayout */ virtual KoPageLayout pageLayout(int pageNumber = 0) const; virtual void setPageLayout(const KoPageLayout &pageLayout); /** * Performs a cleanup of unneeded backup files */ void removeAutoSaveFiles(); void setBackupFile(bool _b); bool backupFile()const; /** * Returns true if this document or any of its internal child documents are modified. */ Q_INVOKABLE bool isModified() const; /** * Returns true during loading (openUrl can be asynchronous) */ bool isLoading() const; int queryCloseDia(); /** * Sets the backup path of the document */ void setBackupPath(const QString & _path); /** * @return path to the backup document */ QString backupPath()const; /** * @return caption of the document * * Caption is of the form "[title] - [url]", * built out of the document info (title) and pretty-printed * document URL. * If the title is not present, only the URL it returned. */ QString caption() const; /** * Sets the document URL to empty URL * KParts doesn't allow this, but %Calligra apps have e.g. templates * After using loadNativeFormat on a template, one wants * to set the url to KUrl() */ void resetURL(); /** * Set when you want an external embedded document to be stored internally */ void setStoreInternal(bool i); /** * @return true when external embedded documents are stored internally */ bool storeInternal() const; bool hasExternURL() const; /** * @internal (public for KoMainWindow) */ void setMimeTypeAfterLoading(const QString& mimeType); /** * @return returns the number of pages in the document. */ virtual int pageCount() const; /** * Returns the unit used to display all measures/distances. */ KoUnit unit() const; /** * Sets the unit used to display all measures/distances. */ void setUnit(const KoUnit &unit); /** * Save the unit to the settings writer * * @param settingsWriter */ void saveUnitOdf(KoXmlWriter *settingsWriter) const; QList &versionList(); bool loadNativeFormatFromStore(QByteArray &data); /** * Adds a new version and then saves the whole document. * @param comment the comment for the version * @return true on success, otherwise false */ bool addVersion(const QString& comment); /// return the grid data for this document. KoGridData &gridData(); /// returns the guides data for this document. KoGuidesData &guidesData(); void clearUndoHistory(); /** * Sets the modified flag on the document. This means that it has * to be saved or not before deleting it. */ Q_INVOKABLE virtual void setModified(bool _mod); /** * Initialize an empty document using default values */ virtual void initEmpty(); /** * Returns the global undo stack */ KUndo2Stack *undoStack(); /** * Set the output stream to report profile information to. */ void setProfileStream(QTextStream *profilestream); /** * Set the output stream to report profile information to. */ void setProfileReferenceTime(const QTime& referenceTime); public Q_SLOTS: /** * Adds a command to the undo stack and executes it by calling the redo() function. * @param command command to add to the undo stack */ virtual void addCommand(KUndo2Command *command); /** * Begins recording of a macro command. At the end endMacro needs to be called. * @param text command description */ virtual void beginMacro(const KUndo2MagicString &text); /** * Ends the recording of a macro command. */ virtual void endMacro(); Q_SIGNALS: /** * This signal is emitted when the unit is changed by setUnit(). * It is common to connect views to it, in order to change the displayed units * (e.g. in the rulers) */ void unitChanged(const KoUnit &unit); /** * Progress info while loading or saving. The value is in percents (i.e. a number between 0 and 100) * Your KoDocument-derived class should emit the signal now and then during load/save. * KoMainWindow will take care of displaying a progress bar automatically. */ void sigProgress(int value); /** * Emitted e.g. at the beginning of a save operation * This is emitted by KoDocument and used by KoView to display a statusbar message */ void statusBarMessage(const QString& text); /** * Emitted e.g. at the end of a save operation * This is emitted by KoDocument and used by KoView to clear the statusbar message */ void clearStatusBarMessage(); /** * Emitted when the document is modified */ void modified(bool); void titleModified(const QString &caption, bool isModified); protected: friend class KoPart; /** * Generate a name for the document. */ QString newObjectName(); QString autoSaveFile(const QString & path) const; void setDisregardAutosaveFailure(bool disregardFailure); /** * Loads a document from KReadOnlyPart::m_file (KParts takes care of downloading * remote documents). * Applies a filter if necessary, and calls loadNativeFormat in any case * You should not have to reimplement, except for very special cases. * * NOTE: this method also creates a new KoView instance! * * This method is called from the KReadOnlyPart::openUrl method. */ virtual bool openFile(); /** * This method is called by @a openFile() to allow applications to setup there * own KoProgressUpdater-subTasks which are then taken into account for the * displayed progressbar during loading. */ virtual void setupOpenFileSubProgress(); /** * Saves a document to KReadOnlyPart::m_file (KParts takes care of uploading * remote documents) * Applies a filter if necessary, and calls saveNativeFormat in any case * You should not have to reimplement, except for very special cases. */ virtual bool saveFile(); /** * Overload this function if you have to load additional files * from a store. This function is called after loadXML() * and after loadChildren() have been called. */ virtual bool completeLoading(KoStore *store); /** * If you want to write additional files to a store, * then you must do it here. * In the implementation, you should prepend the document * url (using url().url()) before the filename, so that everything is kept relative * to this document. For instance it will produce urls such as * tar:/1/pictures/picture0.png, if the doc url is tar:/1 * But do this ONLY if the document is not stored extern (see isStoredExtern() ). * If it is, then the pictures should be saved to tar:/pictures. */ virtual bool completeSaving(KoStore *store); /** @internal */ virtual void setModified(); /** * Returns whether or not the current openUrl() or openFile() call is * actually an import operation (like File --> Import). * This is for informational purposes only. */ bool isImporting() const; /** * Returns whether or not the current saveFile() call is actually an export * operation (like File --> Export). * If this function returns true during saveFile() and you are changing * some sort of state, you _must_ restore it before the end of saveFile(); * otherwise, File --> Export will not work properly. */ bool isExporting() const; public: QString localFilePath() const; void setLocalFilePath( const QString &localFilePath ); virtual KoDocumentInfoDlg* createDocumentInfoDialog(QWidget *parent, KoDocumentInfo *docInfo) const; bool isReadWrite() const; KUrl url() const; void setUrl(const KUrl &url); virtual bool closeUrl(bool promptToSave = true); virtual bool saveAs( const KUrl &url ); public Q_SLOTS: virtual bool save(); bool waitSaveComplete(); Q_SIGNALS: void completed(); void canceled(const QString &); private Q_SLOTS: void slotAutoSave(); /// Called by the undo stack when undo or redo is called void slotUndoStackIndexChanged(int idx); protected: bool oldLoadAndParse(KoStore *store, const QString& filename, KoXmlDocument& doc); private: bool saveToStream(QIODevice *dev); QString checkImageMimeTypes(const QString &mimeType, const KUrl& url) const; bool loadNativeFormatFromStore(const QString& file); bool loadNativeFormatFromStoreInternal(KoStore *store); bool savePreview(KoStore *store); bool saveOasisPreview(KoStore *store, KoXmlWriter *manifestWriter); QString prettyPathOrUrl() const; bool queryClose(); bool saveToUrl(); bool openUrlInternal(const KUrl &url); void abortLoad(); class Private; Private *const d; Q_PRIVATE_SLOT(d, void _k_slotJobFinished( KJob * job )) Q_PRIVATE_SLOT(d, void _k_slotStatJobFinished(KJob*)) Q_PRIVATE_SLOT(d, void _k_slotGotMimeType(KIO::Job *job, const QString &mime)) Q_PRIVATE_SLOT(d, void _k_slotUploadFinished( KJob * job )) }; Q_DECLARE_METATYPE(KoDocument*) #endif diff --git a/libs/pigment/CMakeLists.txt b/libs/pigment/CMakeLists.txt index 4f548157f32..4d0828dc0d8 100644 --- a/libs/pigment/CMakeLists.txt +++ b/libs/pigment/CMakeLists.txt @@ -1,150 +1,152 @@ project(pigmentcms) # we have to repeat platform specifics from top-level if (WIN32) include_directories(${CMAKE_SOURCE_DIR}/winquirks) add_definitions(-D_USE_MATH_DEFINES) add_definitions(-DNOMINMAX) set(WIN32_PLATFORM_NET_LIBS ws2_32.lib netapi32.lib) endif () include_directories( ${PIGMENT_INCLUDES} ${QT_INCLUDES} ${Boost_INCLUDE_DIR}) set(FILE_OPENEXR_SOURCES) set(LINK_OPENEXR_LIB) if(OPENEXR_FOUND) include_directories(${OPENEXR_INCLUDE_DIR}) set(LINK_OPENEXR_LIB ${OPENEXR_LIBRARIES}) add_definitions(${OPENEXR_DEFINITIONS}) endif() set(LINK_VC_LIB) if(HAVE_VC) include_directories(${Vc_INCLUDE_DIR}) set(LINK_VC_LIB ${Vc_LIBRARIES}) ko_compile_for_all_implementations_no_scalar(__per_arch_factory_objs compositeops/KoOptimizedCompositeOpFactoryPerArch.cpp) message("Following objects are generated from the per-arch lib") message(${__per_arch_factory_objs}) endif() add_subdirectory(tests) add_subdirectory(benchmarks) set(pigmentcms_SRCS KoBasicHistogramProducers.cpp KoColor.cpp KoColorDisplayRendererInterface.cpp KoColorConversionAlphaTransformation.cpp KoColorConversionCache.cpp KoColorConversions.cpp KoColorConversionSystem.cpp KoColorConversionTransformation.cpp KoColorConversionTransformationFactory.cpp KoColorModelStandardIds.cpp KoColorProfile.cpp KoColorSpace.cpp KoColorSpaceEngine.cpp KoColorSpaceFactory.cpp KoColorSpaceMaths.cpp KoColorSpaceRegistry.cpp KoColorTransformation.cpp KoColorTransformationFactory.cpp KoColorTransformationFactoryRegistry.cpp KoCompositeColorTransformation.cpp KoCompositeOp.cpp KoCompositeOpRegistry.cpp KoCopyColorConversionTransformation.cpp KoFallBackColorTransformation.cpp KoHistogramProducer.cpp KoMultipleColorConversionTransformation.cpp KoUniqueNumberForIdServer.cpp colorspaces/KoAlphaColorSpace.cpp colorspaces/KoLabColorSpace.cpp colorspaces/KoRgbU16ColorSpace.cpp colorspaces/KoRgbU8ColorSpace.cpp colorspaces/KoSimpleColorSpaceEngine.cpp compositeops/KoOptimizedCompositeOpFactory.cpp compositeops/KoOptimizedCompositeOpFactoryPerArch_Scalar.cpp ${__per_arch_factory_objs} colorprofiles/KoDummyColorProfile.cpp resources/KoAbstractGradient.cpp resources/KoColorSet.cpp resources/KoPattern.cpp resources/KoResource.cpp + resources/KoMD5Generator.cpp + resources/KoHashGeneratorProvider.cpp resources/KoStopGradient.cpp resources/KoSegmentGradient.cpp ) set(PIGMENT_INSTALL_FILES pigment_export.h DebugPigment.h KoBasicHistogramProducers.h KoChannelInfo.h KoColor.h KoColorConversionTransformation.h KoColorConversionTransformationAbstractFactory.h KoColorConversionTransformationFactory.h KoColorModelStandardIds.h KoColorProfile.h KoColorSpace.h KoColorSpaceEngine.h KoColorSpaceFactory.h KoColorSpaceAbstract.h KoColorSpaceConstants.h KoColorSpaceMaths.h KoColorSpaceRegistry.h KoCmykColorSpaceTraits.h KoColorSpaceTraits.h KoGrayColorSpaceTraits.h KoLabColorSpaceTraits.h KoRgbColorSpaceTraits.h KoXyzColorSpaceTraits.h KoYcbcrColorSpaceTraits.h KoColorTransformation.h KoColorTransformationFactory.h KoColorTransformationFactoryRegistry.h KoCompositeOp.h KoConvolutionOp.h KoFallBackColorTransformation.h KoIntegerMaths.h KoLabDarkenColorTransformation.h KoMixColorsOp.h KoMixColorsOpImpl.h KoHistogramProducer.h ) set (EXTRA_LIBRARIES ${LINK_OPENEXR_LIB} ${LINK_VC_LIB}) if(MSVC OR (WIN32 AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel")) # avoid "cannot open file 'LIBC.lib'" error set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} /NODEFAULTLIB:LIBC.LIB") endif() kde4_add_library(pigmentcms SHARED ${pigmentcms_SRCS}) target_link_libraries( pigmentcms koplugin ${EXTRA_LIBRARIES} ${QT_QTGUI_LIBRARY} ${QT_QTXML_LIBRARY} ${WIN32_PLATFORM_NET_LIBS} ) target_link_libraries( pigmentcms LINK_INTERFACE_LIBRARIES koplugin ${QT_QTXML_LIBRARY} ${QT_QTGUI_LIBRARY} ${EXTRA_LIBRARIES} ) set_target_properties(pigmentcms PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS pigmentcms ${INSTALL_TARGETS_DEFAULT_ARGS}) install( FILES pigment.desktop pigmentextension.desktop DESTINATION ${SERVICETYPES_INSTALL_DIR}) install( FILES ${PIGMENT_INSTALL_FILES} DESTINATION ${INCLUDE_INSTALL_DIR}/calligra COMPONENT Devel) diff --git a/libs/pigment/resources/KoAbstractGradient.cpp b/libs/pigment/resources/KoAbstractGradient.cpp index 800a490b46b..28223e7157d 100644 --- a/libs/pigment/resources/KoAbstractGradient.cpp +++ b/libs/pigment/resources/KoAbstractGradient.cpp @@ -1,156 +1,150 @@ /* Copyright (c) 2007 Sven Langkamp Copyright (c) 2004 Adrian Page Copyright (c) 2009 Jan Hambrecht This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoAbstractGradient.h" #include "KoColorSpaceRegistry.h" #include -#include #include #include #define PREVIEW_WIDTH 64 #define PREVIEW_HEIGHT 64 struct KoAbstractGradient::Private { const KoColorSpace* colorSpace; QGradient::Spread spread; QGradient::Type type; }; KoAbstractGradient::KoAbstractGradient(const QString& filename) : KoResource(filename) , d(new Private) { d->colorSpace = KoColorSpaceRegistry::instance()->rgb8(); d->spread = QGradient::PadSpread; d->type = QGradient::NoGradient; } KoAbstractGradient::~KoAbstractGradient() { delete d; } KoAbstractGradient::KoAbstractGradient(const KoAbstractGradient &rhs) : KoResource(rhs) , d(new Private(*rhs.d)) { } void KoAbstractGradient::colorAt(KoColor&, qreal t) const { Q_UNUSED(t); } void KoAbstractGradient::setColorSpace(KoColorSpace* colorSpace) { d->colorSpace = colorSpace; } const KoColorSpace* KoAbstractGradient::colorSpace() const { return d->colorSpace; } void KoAbstractGradient::setSpread(QGradient::Spread spreadMethod) { d->spread = spreadMethod; } QGradient::Spread KoAbstractGradient::spread() const { return d->spread; } void KoAbstractGradient::setType(QGradient::Type repeatType) { d->type = repeatType; } QGradient::Type KoAbstractGradient::type() const { return d->type; } QImage KoAbstractGradient::generatePreview(int width, int height) const { QImage image(width, height, QImage::Format_RGB32); const int checkerSize = 4; const int checkerSize_2 = 2 * checkerSize; const int darkBackground = 128; const int lightBackground = 128 + 63; QRgb * lineA = reinterpret_cast(image.scanLine(0)); QRgb * lineB = reinterpret_cast(image.scanLine(checkerSize)); KoColor c; QColor color; // first create the two reference lines for (int x = 0; x < image.width(); ++x) { qreal t = static_cast(x) / (image.width() - 1); colorAt(c, t); c.toQColor(&color); const qreal alpha = color.alphaF(); int darkR = static_cast((1 - alpha) * darkBackground + alpha * color.red() + 0.5); int darkG = static_cast((1 - alpha) * darkBackground + alpha * color.green() + 0.5); int darkB = static_cast((1 - alpha) * darkBackground + alpha * color.blue() + 0.5); int lightR = static_cast((1 - alpha) * lightBackground + alpha * color.red() + 0.5); int lightG = static_cast((1 - alpha) * lightBackground + alpha * color.green() + 0.5); int lightB = static_cast((1 - alpha) * lightBackground + alpha * color.blue() + 0.5); bool defColor = (x % checkerSize_2) < checkerSize; if (lineA) lineA[x] = defColor ? qRgb(darkR, darkG, darkB) : qRgb(lightR, lightG, lightB); if (lineB) lineB[x] = defColor ? qRgb(lightR, lightG, lightB) : qRgb(darkR, darkG, darkB); } int bytesPerLine = image.bytesPerLine(); // now copy lines accordingly for (int y = 0; y < image.height(); ++y) { bool firstLine = (y % checkerSize_2) < checkerSize; QRgb * line = reinterpret_cast(image.scanLine(y)); if (line == lineA || line == lineB) continue; memcpy(line, firstLine ? lineA : lineB, bytesPerLine); } return image; } -QByteArray KoAbstractGradient::generateMD5() const -{ - return QByteArray(); -} - void KoAbstractGradient::updatePreview() { setImage(generatePreview(PREVIEW_WIDTH, PREVIEW_HEIGHT)); } diff --git a/libs/pigment/resources/KoAbstractGradient.h b/libs/pigment/resources/KoAbstractGradient.h index 167be693fd5..5c815cc74bf 100644 --- a/libs/pigment/resources/KoAbstractGradient.h +++ b/libs/pigment/resources/KoAbstractGradient.h @@ -1,92 +1,90 @@ /* Copyright (c) 2007 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOABSTRACTGRADIENT_H #define KOABSTRACTGRADIENT_H #include #include #include "KoColorSpace.h" #include "KoResource.h" #include class KoColor; /** * KoAbstractGradient is the base class of all gradient resources */ class PIGMENTCMS_EXPORT KoAbstractGradient : public KoResource { public: explicit KoAbstractGradient(const QString &filename); virtual ~KoAbstractGradient(); virtual KoAbstractGradient* clone() const = 0; virtual bool load() { return false; } virtual bool loadFromDevice(QIODevice *) { return false; } virtual bool save() { return false; } virtual bool saveToDevice(QIODevice*) const { return false; } /** * Creates a QGradient from the gradient. * The resulting QGradient might differ from original gradient */ virtual QGradient* toQGradient() const { return new QGradient(); } /// gets the color at position 0 <= t <= 1 virtual void colorAt(KoColor&, qreal t) const; void setColorSpace(KoColorSpace* colorSpace); const KoColorSpace * colorSpace() const; void setSpread(QGradient::Spread spreadMethod); QGradient::Spread spread() const; void setType(QGradient::Type repeatType); QGradient::Type type() const; void updatePreview(); QImage generatePreview(int width, int height) const; -protected: - virtual QByteArray generateMD5() const; KoAbstractGradient(const KoAbstractGradient &rhs); private: struct Private; Private* const d; }; Q_DECLARE_METATYPE(KoAbstractGradient*) #endif // KOABSTRACTGRADIENT_H diff --git a/libs/pigment/resources/KoColorSet.cpp b/libs/pigment/resources/KoColorSet.cpp index 47d3c6bcf3a..64527ec22af 100644 --- a/libs/pigment/resources/KoColorSet.cpp +++ b/libs/pigment/resources/KoColorSet.cpp @@ -1,540 +1,529 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoColorSet.h" #include #include // htonl #include #include #include #include #include #include -#include #include #include #include #include #include #include "KoColor.h" #include "KoColorSpaceRegistry.h" #include "KoColorModelStandardIds.h" KoColorSet::PaletteType detectFormat(const QString &fileName, const QByteArray &ba) { QFileInfo fi(fileName); // .pal if (ba.startsWith("RIFF") && ba.indexOf("PAL data", 8)) { return KoColorSet::RIFF_PAL; } // .gpl else if (ba.startsWith("GIMP Palette")) { return KoColorSet::GPL; } // .pal else if (ba.startsWith("JASC-PAL")) { return KoColorSet::PSP_PAL; } else if (fi.suffix().toLower() == "aco") { return KoColorSet::ACO; } else if (fi.suffix().toLower() == "act") { return KoColorSet::ACT; } return KoColorSet::UNKNOWN; } KoColorSet::KoColorSet(const QString& filename) : KoResource(filename) { // Implemented in KoResource class m_columns = 0; // Set the default value that the GIMP uses... } KoColorSet::KoColorSet() : KoResource("") { m_columns = 0; // Set the default value that the GIMP uses... } /// Create an copied palette KoColorSet::KoColorSet(const KoColorSet& rhs) : QObject(0) , KoResource("") { setFilename(rhs.filename()); m_ownData = false; m_name = rhs.m_name; m_comment = rhs.m_comment; m_columns = rhs.m_columns; m_colors = rhs.m_colors; setValid(true); } KoColorSet::~KoColorSet() { } bool KoColorSet::load() { QFile file(filename()); if (file.size() == 0) return false; if (!file.open(QIODevice::ReadOnly)) { kWarning() << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoColorSet::loadFromDevice(QIODevice *dev) { if (!dev->isOpen()) dev->open(QIODevice::ReadOnly); m_data = dev->readAll(); Q_ASSERT(m_data.size() != 0); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(m_data); - setMD5(md5.result()); return init(); } bool KoColorSet::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } saveToDevice(&file); file.close(); return true; } qint32 KoColorSet::nColors() { return m_colors.count(); } -QByteArray KoColorSet::generateMD5() const -{ - if (!m_data.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(m_data); - return md5.result(); - } - return QByteArray(); -} - bool KoColorSet::saveToDevice(QIODevice *dev) const { QTextStream stream(dev); stream << "GIMP Palette\nName: " << name() << "\nColumns: " << m_columns << "\n#\n"; for (int i = 0; i < m_colors.size(); i++) { const KoColorSetEntry& entry = m_colors.at(i); QColor c = entry.color.toQColor(); stream << c.red() << " " << c.green() << " " << c.blue() << "\t"; if (entry.name.isEmpty()) stream << "Untitled\n"; else stream << entry.name << "\n"; } + + KoResource::saveToDevice(dev); + return true; } bool KoColorSet::init() { m_colors.clear(); // just in case this is a reload (eg by KoEditColorSetDialog), if (filename().isNull()) { qWarning() << "Cannot load palette" << name() << "there is no filename set"; return false; } if (m_data.isNull()) { QFile file(filename()); if (file.size() == 0) { qWarning() << "Cannot load palette" << name() << "there is no data available"; return false; } file.open(QIODevice::ReadOnly); m_data = file.readAll(); file.close(); } bool res = false; PaletteType paletteType = detectFormat(filename(), m_data); switch(paletteType) { case GPL: res = loadGpl(); break; case ACT: res = loadAct(); break; case RIFF_PAL: res = loadRiff(); break; case PSP_PAL: res = loadPsp(); break; case ACO: res = loadAco(); break; default: res = false; } setValid(res); if (m_columns == 0) { m_columns = 10; } QImage img(m_columns * 4, (m_colors.size() / m_columns) * 4, QImage::Format_ARGB32); QPainter gc(&img); gc.fillRect(img.rect(), Qt::darkGray); int counter = 0; for(int i = 0; i < m_columns; ++i) { for (int j = 0; j < (m_colors.size() / m_columns); ++j) { if (counter < m_colors.size()) { QColor c = m_colors.at(counter).color.toQColor(); gc.fillRect(i * 4, j * 4, 4, 4, c); counter++; } else { break; } } } setImage(img); // save some memory m_data.clear(); return res; } void KoColorSet::add(const KoColorSetEntry & c) { m_colors.push_back(c); } void KoColorSet::remove(const KoColorSetEntry & c) { QVector::iterator it = m_colors.begin(); QVector::iterator end = m_colors.end(); while (it != end) { if ((*it) == c) { m_colors.erase(it); return; } ++it; } } void KoColorSet::removeAt(quint32 index) { m_colors.remove(index); } KoColorSetEntry KoColorSet::getColor(quint32 index) { return m_colors[index]; } void KoColorSet::setColumnCount(int columns) { m_columns = columns; } int KoColorSet::columnCount() { return m_columns; } QString KoColorSet::defaultFileExtension() const { return QString(".gpl"); } bool KoColorSet::loadGpl() { QString s = QString::fromUtf8(m_data.data(), m_data.count()); if (s.isEmpty() || s.isNull() || s.length() < 50) { kWarning(30009) << "Illegal Gimp palette file: " << filename(); return false; } quint32 index = 0; QStringList lines = s.split('\n', QString::SkipEmptyParts); if (lines.size() < 3) { return false; } QString columns; qint32 r, g, b; KoColorSetEntry e; // Read name if (!lines[0].startsWith("GIMP") || !lines[1].startsWith("Name: ")) { kWarning(30009) << "Illegal Gimp palette file: " << filename(); return false; } setName(i18n(lines[1].mid(strlen("Name: ")).trimmed().toLatin1())); index = 2; // Read columns if (lines[index].startsWith("Columns: ")) { columns = lines[index].mid(strlen("Columns: ")).trimmed(); m_columns = columns.toInt(); index = 3; } for (qint32 i = index; i < lines.size(); i++) { if (lines[i].startsWith('#')) { m_comment += lines[i].mid(1).trimmed() + ' '; } else if (!lines[i].isEmpty()) { QStringList a = lines[i].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() < 3) { break; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } } return true; } bool KoColorSet::loadAct() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; for (int i = 0; i < m_data.size(); i += 3) { quint8 r = m_data[i]; quint8 g = m_data[i+1]; quint8 b = m_data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } struct RiffHeader { quint32 riff; quint32 size; quint32 signature; quint32 data; quint32 datasize; quint16 version; quint16 colorcount; }; bool KoColorSet::loadRiff() { // http://worms2d.info/Palette_file QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; RiffHeader header; memcpy(&header, m_data.constData(), sizeof(RiffHeader)); header.colorcount = ntohl(header.colorcount); for (int i = sizeof(RiffHeader); (i < (int)(sizeof(RiffHeader) + header.colorcount) && i < m_data.size()); i += 4) { quint8 r = m_data[i]; quint8 g = m_data[i+1]; quint8 b = m_data[i+2]; e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); add(e); } return true; } bool KoColorSet::loadPsp() { QFileInfo info(filename()); setName(info.baseName()); KoColorSetEntry e; qint32 r, g, b; QString s = QString::fromUtf8(m_data.data(), m_data.count()); QStringList l = s.split('\n', QString::SkipEmptyParts); if (l.size() < 4) return false; if (l[0] != "JASC-PAL") return false; if (l[1] != "0100") return false; int entries = l[2].toInt(); for (int i = 0; i < entries; ++i) { QStringList a = l[i + 3].replace('\t', ' ').split(' ', QString::SkipEmptyParts); if (a.count() != 3) { continue; } r = a[0].toInt(); a.pop_front(); g = a[0].toInt(); a.pop_front(); b = a[0].toInt(); a.pop_front(); r = qBound(0, r, 255); g = qBound(0, g, 255); b = qBound(0, b, 255); e.color = KoColor(KoColorSpaceRegistry::instance()->rgb8()); e.color.fromQColor(QColor(r, g, b)); QString name = a.join(" "); e.name = name.isEmpty() ? i18n("Untitled") : name; add(e); } return true; } quint16 readShort(QIODevice *io) { quint16 val; quint64 read = io->read((char*)&val, 2); if (read != 2) return false; return ntohs(val); } bool KoColorSet::loadAco() { QFileInfo info(filename()); setName(info.baseName()); QBuffer buf(&m_data); buf.open(QBuffer::ReadOnly); quint16 version = readShort(&buf); quint16 numColors = readShort(&buf); KoColorSetEntry e; const quint16 quint16_MAX = 65535; for (int i = 0; i < numColors && !buf.atEnd(); ++i) { quint16 colorSpace = readShort(&buf); quint16 ch1 = readShort(&buf); quint16 ch2 = readShort(&buf); quint16 ch3 = readShort(&buf); quint16 ch4 = readShort(&buf); bool skip = false; if (colorSpace == 0) { // RGB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 1) { // HSB e.color = KoColor(KoColorSpaceRegistry::instance()->rgb16()); QColor c; c.setHsvF(ch1 / 65536.0, ch2 / 65536.0, ch3 / 65536.0); e.color.fromQColor(c); e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 2) { // CMYK e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(CMYKAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); reinterpret_cast(e.color.data())[0] = quint16_MAX - ch1; reinterpret_cast(e.color.data())[1] = quint16_MAX - ch2; reinterpret_cast(e.color.data())[2] = quint16_MAX - ch3; reinterpret_cast(e.color.data())[3] = quint16_MAX - ch4; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 7) { // LAB e.color = KoColor(KoColorSpaceRegistry::instance()->lab16()); reinterpret_cast(e.color.data())[0] = ch3; reinterpret_cast(e.color.data())[1] = ch2; reinterpret_cast(e.color.data())[2] = ch1; e.color.setOpacity(OPACITY_OPAQUE_U8); } else if (colorSpace == 8) { // GRAY e.color = KoColor(KoColorSpaceRegistry::instance()->colorSpace(GrayAColorModelID.id(), Integer16BitsColorDepthID.id(), "")); reinterpret_cast(e.color.data())[0] = ch1 * (quint16_MAX / 10000); e.color.setOpacity(OPACITY_OPAQUE_U8); } else { kWarning() << "Unsupported colorspace in palette" << filename() << "(" << colorSpace << ")"; skip = true; } if (version == 2) { quint16 v2 = readShort(&buf); if (v2 != 2) { kWarning() << "Version 2 block is not version 2" << filename() << "(" << v2 << ")"; return false; } quint16 size = readShort(&buf); QByteArray ba = buf.read(size); if (ba.size() != size) { kWarning() << "Version 2 name block is the wrong size" << filename(); return false; } e.name = QString::fromUtf8(ba.constData(), ba.size()); } if (!skip) { add(e); } } return true; } diff --git a/libs/pigment/resources/KoColorSet.h b/libs/pigment/resources/KoColorSet.h index ffd81b85168..d74d513baed 100644 --- a/libs/pigment/resources/KoColorSet.h +++ b/libs/pigment/resources/KoColorSet.h @@ -1,112 +1,108 @@ /* This file is part of the KDE project Copyright (c) 2005 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOCOLORSET #define KOCOLORSET #include #include #include #include "KoResource.h" #include "KoColor.h" struct KoColorSetEntry { KoColor color; QString name; bool operator==(const KoColorSetEntry& rhs) const { return color == rhs.color && name == rhs.name; } }; /** * Open Gimp, Photoshop or RIFF palette files. This is a straight port * from the Gimp. */ class PIGMENTCMS_EXPORT KoColorSet : public QObject, public KoResource { Q_OBJECT public: enum PaletteType { UNKNOWN = 0, GPL, // GIMP RIFF_PAL, // RIFF ACT, // Photoshop binary PSP_PAL, // PaintShop Pro ACO // Photoshop Swatches }; /** * Load a color set from a file. This can be a Gimp * palette, a RIFF palette or a Photoshop palette. */ explicit KoColorSet(const QString &filename); /// Create an empty color set KoColorSet(); /// Explicit copy constructor (KoResource copy constructor is private) KoColorSet(const KoColorSet& rhs); virtual ~KoColorSet(); virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; virtual QString defaultFileExtension() const; void setColumnCount(int columns); int columnCount(); public: void add(const KoColorSetEntry &); void remove(const KoColorSetEntry &); void removeAt(quint32 index); KoColorSetEntry getColor(quint32 index); qint32 nColors(); -protected: - - virtual QByteArray generateMD5() const; - private: bool init(); bool loadGpl(); bool loadAct(); bool loadRiff(); bool loadPsp(); bool loadAco(); QByteArray m_data; bool m_ownData; QString m_name; QString m_comment; qint32 m_columns; QVector m_colors; }; #endif // KOCOLORSET diff --git a/libs/pigment/resources/KoHashGenerator.h b/libs/pigment/resources/KoHashGenerator.h new file mode 100644 index 00000000000..83deb7ea524 --- /dev/null +++ b/libs/pigment/resources/KoHashGenerator.h @@ -0,0 +1,31 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 KOHASHGENERATOR_H +#define KOHASHGENERATOR_H + +#include + +class KoHashGenerator +{ +public: + virtual QByteArray generateHash(QString filename) = 0; + virtual QByteArray generateHash(const QByteArray &array) = 0; + virtual ~KoHashGenerator(){} +}; +#endif diff --git a/libs/pigment/resources/KoHashGeneratorProvider.cpp b/libs/pigment/resources/KoHashGeneratorProvider.cpp new file mode 100644 index 00000000000..26c3fbfeb43 --- /dev/null +++ b/libs/pigment/resources/KoHashGeneratorProvider.cpp @@ -0,0 +1,59 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 "KoHashGeneratorProvider.h" + +#include + +#include "KoMD5Generator.h" + +KoHashGeneratorProvider *KoHashGeneratorProvider::instance_var = 0; + +KoHashGeneratorProvider::KoHashGeneratorProvider() +{ + // Initialize default generators + hashGenerators.insert("MD5", new KoMD5Generator()); +} + +KoHashGeneratorProvider::~KoHashGeneratorProvider() +{ + qDeleteAll(hashGenerators); +} + +KoHashGenerator *KoHashGeneratorProvider::getGenerator(QString algorithm) +{ + QMutexLocker locker(&mutex); + return hashGenerators.value(algorithm); +} + +void KoHashGeneratorProvider::setGenerator(QString algorithm, KoHashGenerator *generator) +{ + if(hashGenerators.contains(algorithm)) { + hashGenerators[algorithm] = generator; + } + else + hashGenerators.insert(algorithm, generator); +} + +KoHashGeneratorProvider *KoHashGeneratorProvider::instance() +{ + if(!instance_var) + instance_var = new KoHashGeneratorProvider(); + + return instance_var; +} diff --git a/libs/pigment/resources/KoHashGeneratorProvider.h b/libs/pigment/resources/KoHashGeneratorProvider.h new file mode 100644 index 00000000000..3e8041238cb --- /dev/null +++ b/libs/pigment/resources/KoHashGeneratorProvider.h @@ -0,0 +1,44 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 KOHASHGENERATORPROVIDER_H +#define KOHASHGENERATORPROVIDER_H + +#include +#include + +#include + +class KoHashGenerator; + +class PIGMENTCMS_EXPORT KoHashGeneratorProvider +{ +public: + KoHashGeneratorProvider(); + ~KoHashGeneratorProvider(); + + KoHashGenerator *getGenerator(QString algorithm); + void setGenerator(QString algorithm, KoHashGenerator *generator); + static KoHashGeneratorProvider *instance(); +private: + static KoHashGeneratorProvider *instance_var; + QHash hashGenerators; + QMutex mutex; +}; + +#endif diff --git a/libs/pigment/resources/KoMD5Generator.cpp b/libs/pigment/resources/KoMD5Generator.cpp new file mode 100644 index 00000000000..a785960e746 --- /dev/null +++ b/libs/pigment/resources/KoMD5Generator.cpp @@ -0,0 +1,57 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 "KoMD5Generator.h" + +#include +#include +#include + +KoMD5Generator::KoMD5Generator() +{ + +} + +KoMD5Generator::~KoMD5Generator() +{ + +} + +QByteArray KoMD5Generator::generateHash(const QByteArray &array) +{ + if (!array.isEmpty()) { + QCryptographicHash md5(QCryptographicHash::Md5); + md5.addData(array); + return md5.result(); + } + + return array; +} + +QByteArray KoMD5Generator::generateHash(QString filename) +{ + QByteArray result; + + QFile f(filename); + if (f.exists() && f.open(QIODevice::ReadOnly)) { + QByteArray ba = f.readAll(); + result = generateHash(ba); + } + + return result; +} diff --git a/libs/pigment/resources/KoMD5Generator.h b/libs/pigment/resources/KoMD5Generator.h new file mode 100644 index 00000000000..770ace59d01 --- /dev/null +++ b/libs/pigment/resources/KoMD5Generator.h @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2015 Stefano Bonicatti + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this library; 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 KOMD5GENERATOR_H +#define KOMD5GENERATOR_H + +#include "KoHashGenerator.h" + +#include + +class PIGMENTCMS_EXPORT KoMD5Generator : public KoHashGenerator +{ +public: + KoMD5Generator(); + virtual ~KoMD5Generator(); + virtual QByteArray generateHash(QString filename); + virtual QByteArray generateHash(const QByteArray &array); +}; + +#endif diff --git a/libs/pigment/resources/KoPattern.cpp b/libs/pigment/resources/KoPattern.cpp index 1c1f521d558..9e3a31b5690 100644 --- a/libs/pigment/resources/KoPattern.cpp +++ b/libs/pigment/resources/KoPattern.cpp @@ -1,412 +1,399 @@ /* This file is part of the KDE project Copyright (c) 2000 Matthias Elter Copyright (c) 2004 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoPattern.h" #include #include #include #include #include #include -#include #include #include #include #include #include #include #include #include #include namespace { struct GimpPatternHeader { quint32 header_size; /* header_size = sizeof (PatternHeader) + brush name */ quint32 version; /* pattern file version # */ quint32 width; /* width of pattern */ quint32 height; /* height of pattern */ quint32 bytes; /* depth of pattern in bytes : 1, 2, 3 or 4*/ quint32 magic_number; /* GIMP brush magic number */ }; // Yes! This is _NOT_ what my pat.txt file says. It's really not 'GIMP', but 'GPAT' quint32 const GimpPatternMagic = (('G' << 24) + ('P' << 16) + ('A' << 8) + ('T' << 0)); } KoPattern::KoPattern(const QString& file) : KoResource(file) { } KoPattern::KoPattern(const QImage &image, const QString &name, const QString &folderName) : KoResource(QString()) { setPatternImage(image); setName(name); QFileInfo fileInfo(folderName + QDir::separator() + name + defaultFileExtension()); int i = 1; while (fileInfo.exists()) { fileInfo.setFile(folderName + QDir::separator() + name + QString("%1").arg(i) + defaultFileExtension()); i++; } setFilename(fileInfo.filePath()); } KoPattern::~KoPattern() { } bool KoPattern::load() { QFile file(filename()); if (file.size() == 0) return false; bool result; if (!file.open(QIODevice::ReadOnly)) { kWarning() << "Can't open file " << filename(); return false; } result = loadFromDevice(&file); file.close(); return result; } bool KoPattern::loadPatFromDevice(QIODevice *dev) { QByteArray data = dev->readAll(); return init(data); } bool KoPattern::savePatToDevice(QIODevice* dev) const { // Header: header_size (24+name length),version,width,height,colordepth of brush,magic,name // depth: 1 = greyscale, 2 = greyscale + A, 3 = RGB, 4 = RGBA // magic = "GPAT", as a single uint32, the docs are wrong here! // name is UTF-8 (\0-terminated! The docs say nothing about this!) // _All_ data in network order, it seems! (not mentioned in gimp-2.2.8/devel-docs/pat.txt!!) // We only save RGBA at the moment // Version is 1 for now... GimpPatternHeader ph; QByteArray utf8Name = name().toUtf8(); char const* name = utf8Name.data(); int nameLength = qstrlen(name); ph.header_size = htonl(sizeof(GimpPatternHeader) + nameLength + 1); // trailing 0 ph.version = htonl(1); ph.width = htonl(width()); ph.height = htonl(height()); ph.bytes = htonl(4); ph.magic_number = htonl(GimpPatternMagic); QByteArray bytes = QByteArray::fromRawData(reinterpret_cast(&ph), sizeof(GimpPatternHeader)); int wrote = dev->write(bytes); bytes.clear(); if (wrote == -1) return false; wrote = dev->write(name, nameLength + 1); // Trailing 0 apparantly! if (wrote == -1) return false; int k = 0; bytes.resize(width() * height() * 4); for (qint32 y = 0; y < height(); ++y) { for (qint32 x = 0; x < width(); ++x) { // RGBA only QRgb pixel = m_pattern.pixel(x, y); bytes[k++] = static_cast(qRed(pixel)); bytes[k++] = static_cast(qGreen(pixel)); bytes[k++] = static_cast(qBlue(pixel)); bytes[k++] = static_cast(qAlpha(pixel)); } } wrote = dev->write(bytes); if (wrote == -1) return false; + KoResource::saveToDevice(dev); + return true; } bool KoPattern::loadFromDevice(QIODevice *dev) { QString fileExtension; int index = filename().lastIndexOf('.'); if (index != -1) fileExtension = filename().mid(index + 1).toLower(); bool result; if (fileExtension == "pat") { result = loadPatFromDevice(dev); } else { QImage image; - result = image.load(dev, fileExtension.toUpper().toLatin1()); + // Workaround for some OS (Debian, Ubuntu), where loading directly from the QIODevice + // fails with "libpng error: IDAT: CRC error" + QByteArray data = dev->readAll(); + QBuffer buffer(&data); + result = image.load(&buffer, fileExtension.toUpper().toLatin1()); setPatternImage(image); } return result; } bool KoPattern::save() { QFile file(filename()); file.open(QIODevice::WriteOnly | QIODevice::Truncate); bool res = saveToDevice(&file); file.close(); return res; } bool KoPattern::saveToDevice(QIODevice *dev) const { QString fileExtension; int index = filename().lastIndexOf('.'); if (index != -1) fileExtension = filename().mid(index + 1).toLower(); if (fileExtension == "pat") { return savePatToDevice(dev); } else { return m_pattern.save(dev, fileExtension.toUpper().toLatin1()); } return true; } bool KoPattern::init(QByteArray& bytes) { int dataSize = bytes.size(); const char* data = bytes.constData(); // load Gimp patterns GimpPatternHeader bh; qint32 k; char* name; if ((int)sizeof(GimpPatternHeader) > dataSize) { return false; } memcpy(&bh, data, sizeof(GimpPatternHeader)); bh.header_size = ntohl(bh.header_size); bh.version = ntohl(bh.version); bh.width = ntohl(bh.width); bh.height = ntohl(bh.height); bh.bytes = ntohl(bh.bytes); bh.magic_number = ntohl(bh.magic_number); if ((int)bh.header_size > dataSize || bh.header_size == 0) { return false; } int size = bh.header_size - sizeof(GimpPatternHeader); name = new char[size]; memcpy(name, data + sizeof(GimpPatternHeader), size); if (name[size - 1]) { delete[] name; return false; } // size -1 so we don't add the end 0 to the QString... setName(QString::fromLatin1(name, size -1)); delete[] name; if (bh.width == 0 || bh.height == 0) { return false; } QImage::Format imageFormat; if (bh.bytes == 1 || bh.bytes == 3) { imageFormat = QImage::Format_RGB32; } else { imageFormat = QImage::Format_ARGB32; } QImage pattern = QImage(bh.width, bh.height, imageFormat); if (pattern.isNull()) { return false; } k = bh.header_size; if (bh.bytes == 1) { // Grayscale qint32 val; for (quint32 y = 0; y < bh.height; ++y) { QRgb* pixels = reinterpret_cast( pattern.scanLine(y) ); for (quint32 x = 0; x < bh.width; ++x, ++k) { if (k > dataSize) { kWarning(30009) << "failed in gray"; return false; } val = data[k]; pixels[x] = qRgb(val, val, val); } } // It was grayscale, so make the pattern as small as possible // by converting it to Indexed8 pattern = pattern.convertToFormat(QImage::Format_Indexed8); } else if (bh.bytes == 2) { // Grayscale + A qint32 val; qint32 alpha; for (quint32 y = 0; y < bh.height; ++y) { QRgb* pixels = reinterpret_cast( pattern.scanLine(y) ); for (quint32 x = 0; x < bh.width; ++x, ++k) { if (k + 2 > dataSize) { kWarning(30009) << "failed in grayA"; return false; } val = data[k]; alpha = data[k++]; pixels[x] = qRgba(val, val, val, alpha); } } } else if (bh.bytes == 3) { // RGB without alpha for (quint32 y = 0; y < bh.height; ++y) { QRgb* pixels = reinterpret_cast( pattern.scanLine(y) ); for (quint32 x = 0; x < bh.width; ++x) { if (k + 3 > dataSize) { kWarning(30009) << "failed in RGB"; return false; } pixels[x] = qRgb(data[k], data[k + 1], data[k + 2]); k += 3; } } } else if (bh.bytes == 4) { // Has alpha for (quint32 y = 0; y < bh.height; ++y) { QRgb* pixels = reinterpret_cast( pattern.scanLine(y) ); for (quint32 x = 0; x < bh.width; ++x) { if (k + 4 > dataSize) { kWarning(30009) << "failed in RGBA"; return false; } pixels[x] = qRgba(data[k], data[k + 1], data[k + 2], data[k + 3]); k += 4; } } } else { return false; } if (pattern.isNull()) { return false; } setPatternImage(pattern); setValid(true); return true; } qint32 KoPattern::width() const { return m_pattern.width(); } qint32 KoPattern::height() const { return m_pattern.height(); } void KoPattern::setPatternImage(const QImage& image) { m_pattern = image; setImage(image); setValid(true); } KoPattern& KoPattern::operator=(const KoPattern & pattern) { setFilename(pattern.filename()); setPatternImage(pattern.pattern()); setValid(true); return *this; } QString KoPattern::defaultFileExtension() const { return QString(".pat"); } KoPattern* KoPattern::clone() const { KoPattern* pat = new KoPattern(filename()); pat->setPatternImage(pattern()); pat->setName(name()); return pat; } QImage KoPattern::pattern() const { return m_pattern; } -QByteArray KoPattern::generateMD5() const -{ - if (!pattern().isNull()) { - QImage im = m_pattern.convertToFormat(QImage::Format_ARGB32); -#if QT_VERSION >= 0x040700 - QByteArray ba = QByteArray::fromRawData((const char*)im.constBits(), im.byteCount()); -#else - QByteArray ba = QByteArray::fromRawData((const char*)im.bits(), im.byteCount()); -#endif - - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - - return md5.result(); - } - return QByteArray(); -} - diff --git a/libs/pigment/resources/KoPattern.h b/libs/pigment/resources/KoPattern.h index 31acba45d14..0430a057e77 100644 --- a/libs/pigment/resources/KoPattern.h +++ b/libs/pigment/resources/KoPattern.h @@ -1,84 +1,80 @@ /* Copyright (c) 2000 Matthias Elter This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOPATTERN_H #define KOPATTERN_H #include "KoResource.h" #include #include /// Write API docs here class PIGMENTCMS_EXPORT KoPattern : public KoResource { public: /** * Creates a new KoPattern object using @p filename. No file is opened * in the constructor, you have to call load. * * @param filename the file name to save and load from. */ explicit KoPattern(const QString &filename); KoPattern(const QImage &image, const QString &name, const QString &folderName); virtual ~KoPattern(); public: virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; bool loadPatFromDevice(QIODevice *dev); bool savePatToDevice(QIODevice* dev) const; qint32 width() const; qint32 height() const; QString defaultFileExtension() const; KoPattern& operator=(const KoPattern& pattern); KoPattern* clone() const; /** * @brief pattern the actual pattern image * @return a valid QImage. There are no guarantees to the image format. */ QImage pattern() const; -protected: - - virtual QByteArray generateMD5() const; - private: bool init(QByteArray& data); void setPatternImage(const QImage& image); private: QImage m_pattern; mutable QByteArray m_md5; }; Q_DECLARE_METATYPE(KoPattern*) #endif // KOPATTERN_H diff --git a/libs/pigment/resources/KoResource.cpp b/libs/pigment/resources/KoResource.cpp index 2b568bf350a..ae228eb61da 100644 --- a/libs/pigment/resources/KoResource.cpp +++ b/libs/pigment/resources/KoResource.cpp @@ -1,125 +1,141 @@ /* This file is part of the KDE project Copyright (c) 2003 Patrick Julien Copyright (c) 2005 Boudewijn Rempt Copyright (c) 2007 Jan Hambrecht This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoResource.h" #include #include #include #include +#include "KoHashGenerator.h" +#include "KoHashGeneratorProvider.h" + struct KoResource::Private { QString name; QString filename; bool valid; bool removable; QByteArray md5; QImage image; }; KoResource::KoResource(const QString& filename) : d(new Private) { d->filename = filename; d->valid = false; QFileInfo fileInfo(filename); d->removable = fileInfo.isWritable(); } KoResource::~KoResource() { delete d; } KoResource::KoResource(const KoResource &rhs) : d(new Private(*rhs.d)) { } +bool KoResource::saveToDevice(QIODevice *dev) const +{ + d->md5 = QByteArray(); + + return true; +} + QImage KoResource::image() const { return d->image; } void KoResource::setImage(const QImage &image) { d->image = image; } QByteArray KoResource::md5() const { if (d->md5.isEmpty()) { const_cast(this)->setMD5(generateMD5()); } return d->md5; } void KoResource::setMD5(const QByteArray &md5) { d->md5 = md5; } +QByteArray KoResource::generateMD5() const +{ + KoHashGenerator *hashGenerator = KoHashGeneratorProvider::instance()->getGenerator("MD5"); + return hashGenerator->generateHash(d->filename); +} + QString KoResource::filename() const { return d->filename; } void KoResource::setFilename(const QString& filename) { d->filename = filename; QFileInfo fileInfo(filename); d->removable = ! fileInfo.exists() || fileInfo.isWritable(); } QString KoResource::shortFilename() const { QFileInfo fileInfo(d->filename); return fileInfo.fileName(); } QString KoResource::name() const { return d->name; } void KoResource::setName(const QString& name) { d->name = name; } bool KoResource::valid() const { return d->valid; } void KoResource::setValid(bool valid) { d->valid = valid; } bool KoResource::removable() const { return d->removable; } QString KoResource::defaultFileExtension() const { return QString(); } diff --git a/libs/pigment/resources/KoResource.h b/libs/pigment/resources/KoResource.h index 53a18e23b20..1529dd13ead 100644 --- a/libs/pigment/resources/KoResource.h +++ b/libs/pigment/resources/KoResource.h @@ -1,127 +1,127 @@ /* This file is part of the KDE project Copyright (c) 2003 Patrick Julien Copyright (c) 2005 Boudewijn Rempt This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KORESOURCE_H #define KORESOURCE_H #include #include #include #include class QDomDocument; class QDomElement; /** * The KoResource class provides a representation of resources. This * includes, but not limited to, brushes and patterns. */ class PIGMENTCMS_EXPORT KoResource { public: /** * Creates a new KoResource object using @p filename. No file is opened * in the constructor, you have to call load. * * @param filename the file name to save and load from. */ explicit KoResource(const QString &filename); virtual ~KoResource(); bool operator ==(const KoResource &other) const { return other.md5() == md5(); } public: /** * Load this resource. * @return true if loading the resource succeeded. */ virtual bool load() = 0; virtual bool loadFromDevice(QIODevice *dev) = 0; /** * Save this resource. *@return true if saving the resource succeeded. */ virtual bool save() = 0; - virtual bool saveToDevice(QIODevice* dev) const = 0; + virtual bool saveToDevice(QIODevice* dev) const; /** * @returns a QImage thumbnail image representing this resource. * * This image could be null. The image can be in any valid format. */ QImage image() const; void setImage(const QImage &image); /// @return the md5sum calculated over the contents of the resource. QByteArray md5() const; /// @returns true if resource can be removed by the user bool removable() const; /// @return the full path to this resource QString filename() const; void setFilename(const QString& filename); /// @return the name of the file without the path QString shortFilename() const; /// @return the user-visible name of the resource QString name() const; void setName(const QString& name); /// @return true if the resource is ready for use bool valid() const; void setValid(bool valid); /// @return the default file extension which should be used when saving the resource virtual QString defaultFileExtension() const; protected: /// override generateMD5 and in your resource subclass - virtual QByteArray generateMD5() const = 0; + virtual QByteArray generateMD5() const; /// call this when the contents of the resource change so the md5 needs to be recalculated void setMD5(const QByteArray &md5); protected: KoResource(const KoResource &rhs); private: struct Private; Private* const d; }; static inline bool operator==(const KoResource &resource1, const KoResource &resource2) { return (resource1.md5() == resource2.md5()); } static inline uint qHash(const KoResource &resource) { return qHash(resource.md5()); } #endif // KORESOURCE_H_ diff --git a/libs/pigment/resources/KoSegmentGradient.cpp b/libs/pigment/resources/KoSegmentGradient.cpp index 5387743e5ad..2e3c18ff58e 100644 --- a/libs/pigment/resources/KoSegmentGradient.cpp +++ b/libs/pigment/resources/KoSegmentGradient.cpp @@ -1,920 +1,902 @@ /* Copyright (c) 2000 Matthias Elter 2001 John Califf 2004 Boudewijn Rempt 2004 Adrian Page 2004, 2007 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoSegmentGradient.h" #include #include #include #include #include -#include #include #include #include "KoColorSpaceRegistry.h" #include "KoColorSpace.h" #include "KoMixColorsOp.h" #include #include KoGradientSegment::RGBColorInterpolationStrategy *KoGradientSegment::RGBColorInterpolationStrategy::m_instance = 0; KoGradientSegment::HSVCWColorInterpolationStrategy *KoGradientSegment::HSVCWColorInterpolationStrategy::m_instance = 0; KoGradientSegment::HSVCCWColorInterpolationStrategy *KoGradientSegment::HSVCCWColorInterpolationStrategy::m_instance = 0; KoGradientSegment::LinearInterpolationStrategy *KoGradientSegment::LinearInterpolationStrategy::m_instance = 0; KoGradientSegment::CurvedInterpolationStrategy *KoGradientSegment::CurvedInterpolationStrategy::m_instance = 0; KoGradientSegment::SineInterpolationStrategy *KoGradientSegment::SineInterpolationStrategy::m_instance = 0; KoGradientSegment::SphereIncreasingInterpolationStrategy *KoGradientSegment::SphereIncreasingInterpolationStrategy::m_instance = 0; KoGradientSegment::SphereDecreasingInterpolationStrategy *KoGradientSegment::SphereDecreasingInterpolationStrategy::m_instance = 0; KoSegmentGradient::KoSegmentGradient(const QString& file) : KoAbstractGradient(file) { } KoSegmentGradient::~KoSegmentGradient() { for (int i = 0; i < m_segments.count(); i++) { delete m_segments[i]; m_segments[i] = 0; } } KoSegmentGradient::KoSegmentGradient(const KoSegmentGradient &rhs) : KoAbstractGradient(rhs) { foreach(KoGradientSegment *segment, rhs.m_segments) { pushSegment(new KoGradientSegment(*segment)); } } KoAbstractGradient* KoSegmentGradient::clone() const { return new KoSegmentGradient(*this); } bool KoSegmentGradient::load() { QFile file(filename()); if (!file.open(QIODevice::ReadOnly)) { kWarning() << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&file); file.close(); return res; } bool KoSegmentGradient::loadFromDevice(QIODevice *dev) { QByteArray data = dev->readAll(); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(data); - setMD5(md5.result()); - QTextStream fileContent(data, QIODevice::ReadOnly); fileContent.setAutoDetectUnicode(true); QString header = fileContent.readLine(); if (header != "GIMP Gradient") { return false; } QString nameDefinition = fileContent.readLine(); QString numSegmentsText; if (nameDefinition.startsWith("Name: ")) { QString nameText = nameDefinition.right(nameDefinition.length() - 6); setName(nameText); numSegmentsText = fileContent.readLine(); } else { // Older format without name. numSegmentsText = nameDefinition; } kDebug(30009) << "Loading gradient: " << name(); int numSegments; bool ok; numSegments = numSegmentsText.toInt(&ok); if (!ok || numSegments < 1) { return false; } kDebug(30009) << "Number of segments = " << numSegments; const KoColorSpace* rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); for (int i = 0; i < numSegments; i++) { QString segmentText = fileContent.readLine(); QTextStream segmentFields(&segmentText); QStringList values = segmentText.split(' '); qreal leftOffset = values[0].toDouble(); qreal middleOffset = values[1].toDouble(); qreal rightOffset = values[2].toDouble(); qreal leftRed = values[3].toDouble(); qreal leftGreen = values[4].toDouble(); qreal leftBlue = values[5].toDouble(); qreal leftAlpha = values[6].toDouble(); qreal rightRed = values[7].toDouble(); qreal rightGreen = values[8].toDouble(); qreal rightBlue = values[9].toDouble(); qreal rightAlpha = values[10].toDouble(); int interpolationType = values[11].toInt(); int colorInterpolationType = values[12].toInt(); quint8 data[4]; data[2] = static_cast(leftRed * 255 + 0.5); data[1] = static_cast(leftGreen * 255 + 0.5); data[0] = static_cast(leftBlue * 255 + 0.5); data[3] = static_cast(leftAlpha * OPACITY_OPAQUE_U8 + 0.5); KoColor leftColor(data, rgbColorSpace); data[2] = static_cast(rightRed * 255 + 0.5); data[1] = static_cast(rightGreen * 255 + 0.5); data[0] = static_cast(rightBlue * 255 + 0.5); data[3] = static_cast(rightAlpha * OPACITY_OPAQUE_U8 + 0.5); KoColor rightColor(data, rgbColorSpace); KoGradientSegment *segment = new KoGradientSegment(interpolationType, colorInterpolationType, leftOffset, middleOffset, rightOffset, leftColor, rightColor); Q_CHECK_PTR(segment); if (!segment -> isValid()) { delete segment; return false; } m_segments.push_back(segment); } if (!m_segments.isEmpty()) { updatePreview(); setValid(true); return true; } else { return false; } } bool KoSegmentGradient::save() { QFile file(filename()); if (!file.open(QIODevice::WriteOnly)) { return false; } saveToDevice(&file); file.close(); return true; } bool KoSegmentGradient::saveToDevice(QIODevice *dev) const { QTextStream fileContent(dev); fileContent << "GIMP Gradient\n"; fileContent << "Name: " << name() << "\n"; fileContent << m_segments.count() << "\n"; foreach(KoGradientSegment* segment, m_segments) { fileContent << QString::number(segment->startOffset(), 'f') << " " << QString::number(segment->middleOffset(), 'f') << " " << QString::number(segment->endOffset(), 'f') << " "; QColor startColor = segment->startColor().toQColor(); QColor endColor = segment->endColor().toQColor(); fileContent << QString::number(startColor.redF(), 'f') << " " << QString::number(startColor.greenF(), 'f') << " " << QString::number(startColor.blueF(), 'f') << " " << QString::number(startColor.alphaF(), 'f') << " "; fileContent << QString::number(endColor.redF(), 'f') << " " << QString::number(endColor.greenF(), 'f') << " " << QString::number(endColor.blueF(), 'f') << " " << QString::number(endColor.alphaF(), 'f') << " "; fileContent << (int)segment->interpolation() << " " << (int)segment->colorInterpolation() << "\n"; } + + KoResource::saveToDevice(dev); + return true; } KoGradientSegment *KoSegmentGradient::segmentAt(qreal t) const { Q_ASSERT(t >= 0 || t <= 1); Q_ASSERT(!m_segments.empty()); for (QList::const_iterator it = m_segments.begin(); it != m_segments.end(); ++it) { if (t > (*it)->startOffset() - DBL_EPSILON && t < (*it)->endOffset() + DBL_EPSILON) { return *it; } } return 0; } void KoSegmentGradient::colorAt(KoColor& dst, qreal t) const { const KoGradientSegment *segment = segmentAt(t); Q_ASSERT(segment != 0); if (segment) { segment->colorAt(dst, t); } } QGradient* KoSegmentGradient::toQGradient() const { QGradient* gradient = new QLinearGradient(); QColor color; foreach(KoGradientSegment* segment, m_segments) { segment->startColor().toQColor(&color); gradient->setColorAt(segment->startOffset() , color); segment->endColor().toQColor(&color); gradient->setColorAt(segment->endOffset() , color); } return gradient; } QString KoSegmentGradient::defaultFileExtension() const { return QString(".ggr"); } -QByteArray KoSegmentGradient::generateMD5() const -{ - QBuffer buffer; - buffer.open(QIODevice::WriteOnly); - saveToDevice(&buffer); - QByteArray ba = buffer.buffer(); - - if (!ba.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - return md5.result(); - } - - return QByteArray(); -} - KoGradientSegment::KoGradientSegment(int interpolationType, int colorInterpolationType, qreal startOffset, qreal middleOffset, qreal endOffset, const KoColor& startColor, const KoColor& endColor) { m_interpolator = 0; switch (interpolationType) { case INTERP_LINEAR: m_interpolator = LinearInterpolationStrategy::instance(); break; case INTERP_CURVED: m_interpolator = CurvedInterpolationStrategy::instance(); break; case INTERP_SINE: m_interpolator = SineInterpolationStrategy::instance(); break; case INTERP_SPHERE_INCREASING: m_interpolator = SphereIncreasingInterpolationStrategy::instance(); break; case INTERP_SPHERE_DECREASING: m_interpolator = SphereDecreasingInterpolationStrategy::instance(); break; } m_colorInterpolator = 0; switch (colorInterpolationType) { case COLOR_INTERP_RGB: m_colorInterpolator = RGBColorInterpolationStrategy::instance(); break; case COLOR_INTERP_HSV_CCW: m_colorInterpolator = HSVCCWColorInterpolationStrategy::instance(); break; case COLOR_INTERP_HSV_CW: m_colorInterpolator = HSVCWColorInterpolationStrategy::instance(); break; } if (startOffset < DBL_EPSILON) { m_startOffset = 0; } else if (startOffset > 1 - DBL_EPSILON) { m_startOffset = 1; } else { m_startOffset = startOffset; } if (middleOffset < m_startOffset + DBL_EPSILON) { m_middleOffset = m_startOffset; } else if (middleOffset > 1 - DBL_EPSILON) { m_middleOffset = 1; } else { m_middleOffset = middleOffset; } if (endOffset < m_middleOffset + DBL_EPSILON) { m_endOffset = m_middleOffset; } else if (endOffset > 1 - DBL_EPSILON) { m_endOffset = 1; } else { m_endOffset = endOffset; } m_length = m_endOffset - m_startOffset; if (m_length < DBL_EPSILON) { m_middleT = 0.5; } else { m_middleT = (m_middleOffset - m_startOffset) / m_length; } m_startColor = startColor; m_endColor = endColor; } const KoColor& KoGradientSegment::startColor() const { return m_startColor; } const KoColor& KoGradientSegment::endColor() const { return m_endColor; } qreal KoGradientSegment::startOffset() const { return m_startOffset; } qreal KoGradientSegment::middleOffset() const { return m_middleOffset; } qreal KoGradientSegment::endOffset() const { return m_endOffset; } void KoGradientSegment::setStartOffset(qreal t) { m_startOffset = t; m_length = m_endOffset - m_startOffset; if (m_length < DBL_EPSILON) { m_middleT = 0.5; } else { m_middleT = (m_middleOffset - m_startOffset) / m_length; } } void KoGradientSegment::setMiddleOffset(qreal t) { m_middleOffset = t; if (m_length < DBL_EPSILON) { m_middleT = 0.5; } else { m_middleT = (m_middleOffset - m_startOffset) / m_length; } } void KoGradientSegment::setEndOffset(qreal t) { m_endOffset = t; m_length = m_endOffset - m_startOffset; if (m_length < DBL_EPSILON) { m_middleT = 0.5; } else { m_middleT = (m_middleOffset - m_startOffset) / m_length; } } int KoGradientSegment::interpolation() const { return m_interpolator->type(); } void KoGradientSegment::setInterpolation(int interpolationType) { switch (interpolationType) { case INTERP_LINEAR: m_interpolator = LinearInterpolationStrategy::instance(); break; case INTERP_CURVED: m_interpolator = CurvedInterpolationStrategy::instance(); break; case INTERP_SINE: m_interpolator = SineInterpolationStrategy::instance(); break; case INTERP_SPHERE_INCREASING: m_interpolator = SphereIncreasingInterpolationStrategy::instance(); break; case INTERP_SPHERE_DECREASING: m_interpolator = SphereDecreasingInterpolationStrategy::instance(); break; } } int KoGradientSegment::colorInterpolation() const { return m_colorInterpolator->type(); } void KoGradientSegment::setColorInterpolation(int colorInterpolationType) { switch (colorInterpolationType) { case COLOR_INTERP_RGB: m_colorInterpolator = RGBColorInterpolationStrategy::instance(); break; case COLOR_INTERP_HSV_CCW: m_colorInterpolator = HSVCCWColorInterpolationStrategy::instance(); break; case COLOR_INTERP_HSV_CW: m_colorInterpolator = HSVCWColorInterpolationStrategy::instance(); break; } } void KoGradientSegment::colorAt(KoColor& dst, qreal t) const { Q_ASSERT(t > m_startOffset - DBL_EPSILON && t < m_endOffset + DBL_EPSILON); qreal segmentT; if (m_length < DBL_EPSILON) { segmentT = 0.5; } else { segmentT = (t - m_startOffset) / m_length; } qreal colorT = m_interpolator->valueAt(segmentT, m_middleT); m_colorInterpolator->colorAt(dst, colorT, m_startColor, m_endColor); } bool KoGradientSegment::isValid() const { if (m_interpolator == 0 || m_colorInterpolator == 0) return false; return true; } KoGradientSegment::RGBColorInterpolationStrategy::RGBColorInterpolationStrategy() : m_colorSpace(KoColorSpaceRegistry::instance()->rgb8()), buffer(m_colorSpace), m_start(m_colorSpace), m_end(m_colorSpace) { } KoGradientSegment::RGBColorInterpolationStrategy *KoGradientSegment::RGBColorInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new RGBColorInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } void KoGradientSegment::RGBColorInterpolationStrategy::colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const { m_start.fromKoColor(start); m_end.fromKoColor(end); const quint8 *colors[2]; colors[0] = start.data(); colors[1] = end.data(); qint16 colorWeights[2]; colorWeights[0] = static_cast((1.0 - t) * 255 + 0.5); colorWeights[1] = 255 - colorWeights[0]; m_colorSpace->mixColorsOp()->mixColors(colors, colorWeights, 2, buffer.data()); dst.fromKoColor(buffer); } KoGradientSegment::HSVCWColorInterpolationStrategy::HSVCWColorInterpolationStrategy() : m_colorSpace(KoColorSpaceRegistry::instance()->rgb8()) { } KoGradientSegment::HSVCWColorInterpolationStrategy *KoGradientSegment::HSVCWColorInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new HSVCWColorInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } void KoGradientSegment::HSVCWColorInterpolationStrategy::colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const { QColor sc; QColor ec; start.toQColor(&sc); end.toQColor(&ec); int s = static_cast(sc.saturation() + t * (ec.saturation() - sc.saturation()) + 0.5); int v = static_cast(sc.value() + t * (ec.value() - sc.value()) + 0.5); int h; if (ec.hue() < sc.hue()) { h = static_cast(ec.hue() + (1 - t) * (sc.hue() - ec.hue()) + 0.5); } else { h = static_cast(ec.hue() + (1 - t) * (360 - ec.hue() + sc.hue()) + 0.5); if (h > 359) { h -= 360; } } // XXX: added an explicit cast. Is this correct? quint8 opacity = static_cast(sc.alpha() + t * (ec.alpha() - sc.alpha())); QColor result; result.setHsv(h, s, v); result.setAlpha(opacity); dst.fromQColor(result); } KoGradientSegment::HSVCCWColorInterpolationStrategy::HSVCCWColorInterpolationStrategy() : m_colorSpace(KoColorSpaceRegistry::instance()->rgb8()) { } KoGradientSegment::HSVCCWColorInterpolationStrategy *KoGradientSegment::HSVCCWColorInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new HSVCCWColorInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } void KoGradientSegment::HSVCCWColorInterpolationStrategy::colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const { QColor sc; QColor se; start.toQColor(&sc); end.toQColor(&se); int s = static_cast(sc.saturation() + t * (se.saturation() - sc.saturation()) + 0.5); int v = static_cast(sc.value() + t * (se.value() - sc.value()) + 0.5); int h; if (sc.hue() < se.hue()) { h = static_cast(sc.hue() + t * (se.hue() - sc.hue()) + 0.5); } else { h = static_cast(sc.hue() + t * (360 - sc.hue() + se.hue()) + 0.5); if (h > 359) { h -= 360; } } // XXX: Added an explicit static cast quint8 opacity = static_cast(sc.alpha() + t * (se.alpha() - sc.alpha())); QColor result; result.setHsv(h, s, v); result.setAlpha(opacity); dst.fromQColor(result); } KoGradientSegment::LinearInterpolationStrategy *KoGradientSegment::LinearInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new LinearInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } qreal KoGradientSegment::LinearInterpolationStrategy::calcValueAt(qreal t, qreal middle) { Q_ASSERT(t > -DBL_EPSILON && t < 1 + DBL_EPSILON); Q_ASSERT(middle > -DBL_EPSILON && middle < 1 + DBL_EPSILON); qreal value = 0; if (t <= middle) { if (middle < DBL_EPSILON) { value = 0; } else { value = (t / middle) * 0.5; } } else { if (middle > 1 - DBL_EPSILON) { value = 1; } else { value = ((t - middle) / (1 - middle)) * 0.5 + 0.5; } } return value; } qreal KoGradientSegment::LinearInterpolationStrategy::valueAt(qreal t, qreal middle) const { return calcValueAt(t, middle); } KoGradientSegment::CurvedInterpolationStrategy::CurvedInterpolationStrategy() { m_logHalf = log(0.5); } KoGradientSegment::CurvedInterpolationStrategy *KoGradientSegment::CurvedInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new CurvedInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } qreal KoGradientSegment::CurvedInterpolationStrategy::valueAt(qreal t, qreal middle) const { Q_ASSERT(t > -DBL_EPSILON && t < 1 + DBL_EPSILON); Q_ASSERT(middle > -DBL_EPSILON && middle < 1 + DBL_EPSILON); qreal value = 0; if (middle < DBL_EPSILON) { middle = DBL_EPSILON; } value = pow(t, m_logHalf / log(middle)); return value; } KoGradientSegment::SineInterpolationStrategy *KoGradientSegment::SineInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new SineInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } qreal KoGradientSegment::SineInterpolationStrategy::valueAt(qreal t, qreal middle) const { qreal lt = LinearInterpolationStrategy::calcValueAt(t, middle); qreal value = (sin(-M_PI_2 + M_PI * lt) + 1.0) / 2.0; return value; } KoGradientSegment::SphereIncreasingInterpolationStrategy *KoGradientSegment::SphereIncreasingInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new SphereIncreasingInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } qreal KoGradientSegment::SphereIncreasingInterpolationStrategy::valueAt(qreal t, qreal middle) const { qreal lt = LinearInterpolationStrategy::calcValueAt(t, middle) - 1; qreal value = sqrt(1 - lt * lt); return value; } KoGradientSegment::SphereDecreasingInterpolationStrategy *KoGradientSegment::SphereDecreasingInterpolationStrategy::instance() { if (m_instance == 0) { m_instance = new SphereDecreasingInterpolationStrategy(); Q_CHECK_PTR(m_instance); } return m_instance; } qreal KoGradientSegment::SphereDecreasingInterpolationStrategy::valueAt(qreal t, qreal middle) const { qreal lt = LinearInterpolationStrategy::calcValueAt(t, middle); qreal value = 1 - sqrt(1 - lt * lt); return value; } void KoSegmentGradient::createSegment(int interpolation, int colorInterpolation, double startOffset, double endOffset, double middleOffset, const QColor & left, const QColor & right) { pushSegment(new KoGradientSegment(interpolation, colorInterpolation, startOffset, middleOffset, endOffset, KoColor(left, colorSpace()), KoColor(right, colorSpace()))); } const QList KoSegmentGradient::getHandlePositions() const { QList handlePositions; handlePositions.push_back(m_segments[0]->startOffset()); for (int i = 0; i < m_segments.count(); i++) { handlePositions.push_back(m_segments[i]->endOffset()); } return handlePositions; } const QList KoSegmentGradient::getMiddleHandlePositions() const { QList middleHandlePositions; for (int i = 0; i < m_segments.count(); i++) { middleHandlePositions.push_back(m_segments[i]->middleOffset()); } return middleHandlePositions; } void KoSegmentGradient::moveSegmentStartOffset(KoGradientSegment* segment, double t) { QList::iterator it = qFind(m_segments.begin(), m_segments.end(), segment); if (it != m_segments.end()) { if (it == m_segments.begin()) { segment->setStartOffset(0.0); return; } KoGradientSegment* previousSegment = (*(it - 1)); if (t > segment->startOffset()) { if (t > segment->middleOffset()) t = segment->middleOffset(); } else { if (t < previousSegment->middleOffset()) t = previousSegment->middleOffset(); } previousSegment->setEndOffset(t); segment->setStartOffset(t); } } void KoSegmentGradient::moveSegmentEndOffset(KoGradientSegment* segment, double t) { QList::iterator it = qFind(m_segments.begin(), m_segments.end(), segment); if (it != m_segments.end()) { if (it + 1 == m_segments.end()) { segment->setEndOffset(1.0); return; } KoGradientSegment* followingSegment = (*(it + 1)); if (t < segment->endOffset()) { if (t < segment->middleOffset()) t = segment->middleOffset(); } else { if (t > followingSegment->middleOffset()) t = followingSegment->middleOffset(); } followingSegment->setStartOffset(t); segment->setEndOffset(t); } } void KoSegmentGradient::moveSegmentMiddleOffset(KoGradientSegment* segment, double t) { if (segment) { if (t > segment->endOffset()) segment->setMiddleOffset(segment->endOffset()); else if (t < segment->startOffset()) segment->setMiddleOffset(segment->startOffset()); else segment->setMiddleOffset(t); } } void KoSegmentGradient::splitSegment(KoGradientSegment* segment) { Q_ASSERT(segment != 0); QList::iterator it = qFind(m_segments.begin(), m_segments.end(), segment); if (it != m_segments.end()) { KoColor midleoffsetColor(segment->endColor().colorSpace()); segment->colorAt(midleoffsetColor, segment->middleOffset()); KoGradientSegment* newSegment = new KoGradientSegment( segment->interpolation(), segment->colorInterpolation(), segment ->startOffset(), (segment->middleOffset() - segment->startOffset()) / 2 + segment->startOffset(), segment->middleOffset(), segment->startColor(), midleoffsetColor); m_segments.insert(it, newSegment); segment->setStartColor(midleoffsetColor); segment->setStartOffset(segment->middleOffset()); segment->setMiddleOffset((segment->endOffset() - segment->startOffset()) / 2 + segment->startOffset()); } } void KoSegmentGradient::duplicateSegment(KoGradientSegment* segment) { Q_ASSERT(segment != 0); QList::iterator it = qFind(m_segments.begin(), m_segments.end(), segment); if (it != m_segments.end()) { double middlePostionPercentage = (segment->middleOffset() - segment->startOffset()) / segment->length(); double center = segment->startOffset() + segment->length() / 2; KoGradientSegment* newSegment = new KoGradientSegment( segment->interpolation(), segment->colorInterpolation(), segment ->startOffset(), segment->length() / 2 * middlePostionPercentage + segment->startOffset(), center, segment->startColor(), segment->endColor()); m_segments.insert(it, newSegment); segment->setStartOffset(center); segment->setMiddleOffset(segment->length() * middlePostionPercentage + segment->startOffset()); } } void KoSegmentGradient::mirrorSegment(KoGradientSegment* segment) { Q_ASSERT(segment != 0); KoColor tmpColor = segment->startColor(); segment->setStartColor(segment->endColor()); segment->setEndColor(tmpColor); segment->setMiddleOffset(segment->endOffset() - (segment->middleOffset() - segment->startOffset())); if (segment->interpolation() == INTERP_SPHERE_INCREASING) segment->setInterpolation(INTERP_SPHERE_DECREASING); else if (segment->interpolation() == INTERP_SPHERE_DECREASING) segment->setInterpolation(INTERP_SPHERE_INCREASING); if (segment->colorInterpolation() == COLOR_INTERP_HSV_CW) segment->setColorInterpolation(COLOR_INTERP_HSV_CCW); else if (segment->colorInterpolation() == COLOR_INTERP_HSV_CCW) segment->setColorInterpolation(COLOR_INTERP_HSV_CW); } KoGradientSegment* KoSegmentGradient::removeSegment(KoGradientSegment* segment) { Q_ASSERT(segment != 0); if (m_segments.count() < 2) return 0; QList::iterator it = qFind(m_segments.begin(), m_segments.end(), segment); if (it != m_segments.end()) { double middlePostionPercentage; KoGradientSegment* nextSegment; if (it == m_segments.begin()) { nextSegment = (*(it + 1)); middlePostionPercentage = (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length(); nextSegment->setStartOffset(segment->startOffset()); nextSegment->setMiddleOffset(middlePostionPercentage * nextSegment->length() + nextSegment->startOffset()); } else { nextSegment = (*(it - 1)); middlePostionPercentage = (nextSegment->middleOffset() - nextSegment->startOffset()) / nextSegment->length(); nextSegment->setEndOffset(segment->endOffset()); nextSegment->setMiddleOffset(middlePostionPercentage * nextSegment->length() + nextSegment->startOffset()); } delete segment; m_segments.erase(it); return nextSegment; } return 0; } bool KoSegmentGradient::removeSegmentPossible() const { if (m_segments.count() < 2) return false; return true; } const QList& KoSegmentGradient::segments() const { return m_segments; } diff --git a/libs/pigment/resources/KoSegmentGradient.h b/libs/pigment/resources/KoSegmentGradient.h index bdd6baae119..9b4b7a98834 100644 --- a/libs/pigment/resources/KoSegmentGradient.h +++ b/libs/pigment/resources/KoSegmentGradient.h @@ -1,424 +1,421 @@ /* Copyright (c) 2000 Matthias Elter 2004 Boudewijn Rempt 2004 Adrian Page 2004, 2007 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOSEGMENTGRADIENT_H #define KOSEGMENTGRADIENT_H #include #include #include #include "KoAbstractGradient.h" #include "KoColor.h" #include enum { INTERP_LINEAR = 0, INTERP_CURVED, INTERP_SINE, INTERP_SPHERE_INCREASING, INTERP_SPHERE_DECREASING }; enum { COLOR_INTERP_RGB, COLOR_INTERP_HSV_CCW, COLOR_INTERP_HSV_CW }; /// Write API docs here class PIGMENTCMS_EXPORT KoGradientSegment { public: KoGradientSegment(int interpolationType, int colorInterpolationType, qreal startOffset, qreal middleOffset, qreal endOffset, const KoColor& startColor, const KoColor& endColor); // startOffset <= t <= endOffset void colorAt(KoColor&, qreal t) const; const KoColor& startColor() const; const KoColor& endColor() const; void setStartColor(const KoColor& color) { m_startColor = color; } void setEndColor(const KoColor& color) { m_endColor = color; } qreal startOffset() const; qreal middleOffset() const; qreal endOffset() const; void setStartOffset(qreal t); void setMiddleOffset(qreal t); void setEndOffset(qreal t); qreal length() { return m_length; } int interpolation() const; int colorInterpolation() const; void setInterpolation(int interpolationType); void setColorInterpolation(int colorInterpolationType); bool isValid() const; protected: class ColorInterpolationStrategy { public: ColorInterpolationStrategy() {} virtual ~ColorInterpolationStrategy() {} virtual void colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const = 0; virtual int type() const = 0; }; class RGBColorInterpolationStrategy : public ColorInterpolationStrategy { public: static RGBColorInterpolationStrategy *instance(); virtual void colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const; virtual int type() const { return COLOR_INTERP_RGB; } private: RGBColorInterpolationStrategy(); static RGBColorInterpolationStrategy *m_instance; const KoColorSpace * const m_colorSpace; mutable KoColor buffer; mutable KoColor m_start; mutable KoColor m_end; }; class HSVCWColorInterpolationStrategy : public ColorInterpolationStrategy { public: static HSVCWColorInterpolationStrategy *instance(); virtual void colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const; virtual int type() const { return COLOR_INTERP_HSV_CW; } private: HSVCWColorInterpolationStrategy(); static HSVCWColorInterpolationStrategy *m_instance; const KoColorSpace * const m_colorSpace; }; class HSVCCWColorInterpolationStrategy : public ColorInterpolationStrategy { public: static HSVCCWColorInterpolationStrategy *instance(); virtual void colorAt(KoColor& dst, qreal t, const KoColor& start, const KoColor& end) const; virtual int type() const { return COLOR_INTERP_HSV_CCW; } private: HSVCCWColorInterpolationStrategy(); static HSVCCWColorInterpolationStrategy *m_instance; const KoColorSpace * const m_colorSpace; }; class InterpolationStrategy { public: InterpolationStrategy() {} virtual ~InterpolationStrategy() {} virtual qreal valueAt(qreal t, qreal middle) const = 0; virtual int type() const = 0; }; class LinearInterpolationStrategy : public InterpolationStrategy { public: static LinearInterpolationStrategy *instance(); virtual qreal valueAt(qreal t, qreal middle) const; virtual int type() const { return INTERP_LINEAR; } // This does the actual calculation and is made // static as an optimization for the other // strategies that need this for their own calculation. static qreal calcValueAt(qreal t, qreal middle); private: LinearInterpolationStrategy() {} static LinearInterpolationStrategy *m_instance; }; class CurvedInterpolationStrategy : public InterpolationStrategy { public: static CurvedInterpolationStrategy *instance(); virtual qreal valueAt(qreal t, qreal middle) const; virtual int type() const { return INTERP_CURVED; } private: CurvedInterpolationStrategy(); static CurvedInterpolationStrategy *m_instance; qreal m_logHalf; }; class SphereIncreasingInterpolationStrategy : public InterpolationStrategy { public: static SphereIncreasingInterpolationStrategy *instance(); virtual qreal valueAt(qreal t, qreal middle) const; virtual int type() const { return INTERP_SPHERE_INCREASING; } private: SphereIncreasingInterpolationStrategy() {} static SphereIncreasingInterpolationStrategy *m_instance; }; class SphereDecreasingInterpolationStrategy : public InterpolationStrategy { public: static SphereDecreasingInterpolationStrategy *instance(); virtual qreal valueAt(qreal t, qreal middle) const; virtual int type() const { return INTERP_SPHERE_DECREASING; } private: SphereDecreasingInterpolationStrategy() {} static SphereDecreasingInterpolationStrategy *m_instance; }; class SineInterpolationStrategy : public InterpolationStrategy { public: static SineInterpolationStrategy *instance(); virtual qreal valueAt(qreal t, qreal middle) const; virtual int type() const { return INTERP_SINE; } private: SineInterpolationStrategy() {} static SineInterpolationStrategy *m_instance; }; private: InterpolationStrategy *m_interpolator; ColorInterpolationStrategy *m_colorInterpolator; qreal m_startOffset; qreal m_middleOffset; qreal m_endOffset; qreal m_length; qreal m_middleT; KoColor m_startColor; KoColor m_endColor; }; /** * KoSegmentGradient stores a segment based gradients like Gimp gradients */ class PIGMENTCMS_EXPORT KoSegmentGradient : public KoAbstractGradient { public: explicit KoSegmentGradient(const QString &file); virtual ~KoSegmentGradient(); KoAbstractGradient* clone() const; /// reimplemented virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); /// not implemented virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; /// reimplemented void colorAt(KoColor& dst, qreal t) const; /** * Returns the segment at a given position * @param t position inside the gradient, with 0 <= t <= 1 * @return the segment the position, 0 if no segment is found */ KoGradientSegment *segmentAt(qreal t) const; /// reimplemented virtual QGradient* toQGradient() const; /// reimplemented QString defaultFileExtension() const; /** * a gradient colour picker can consist of one or more segments. * A segment has two end points - each colour in the gradient * colour picker represents a segment end point. * @param interpolation * @param colorInterpolation * @param startOffset * @param endOffset * @param middleOffset * @param left * @param right * @return void */ void createSegment(int interpolation, int colorInterpolation, double startOffset, double endOffset, double middleOffset, const QColor & left, const QColor & right); /** * gets a list of end points of the segments in the gradient * colour picker. If two colours, one segment then two end * points, and if three colours, then two segments with four * endpoints. * @return a list of double values */ const QList getHandlePositions() const; /** * gets a list of middle points of the segments in the gradient * colour picker. * @return a list of double values */ const QList getMiddleHandlePositions() const; /** * Moves the StartOffset of the specified segment to the * specified value and corrects the endoffset of the previous * segment. If the segment is the first Segment the startoffset * will be set to 0.0 . The offset will maximally be moved till * the middle of the current or the previous segment. This is * useful if someone clicks to move the handler for a segment, * to set the half the segment to the right and half the segment * to the left of the handler. * @param segment the segment for which to move the relative * offset within the gradient colour picker. * @param t the new startoff position for the segment * @return void */ void moveSegmentStartOffset(KoGradientSegment* segment, double t); /** * Moves the endoffset of the specified segment to the specified * value and corrects the startoffset of the following segment. * If the segment is the last segment the endoffset will be set * to 1.0 . The offset will maximally be moved till the middle * of the current or the following segment. This is useful if * someone moves the segment handler in the gradient colour * picker, and needs the segment to move with it. Sets the end * position of the segment to the correct new position. * @param segment the segment for which to move the relative * end position within the gradient colour picker. * @param t the new end position for the segment * @return void */ void moveSegmentEndOffset(KoGradientSegment* segment, double t); /** * moves the Middle of the specified segment to the specified * value. The offset will maximally be moved till the endoffset * or startoffset of the segment. This sets the middle of the * segment to the same position as the handler of the gradient * colour picker. * @param segment the segment for which to move the relative * middle position within the gradient colour picker. * @param t the new middle position for the segment * @return void */ void moveSegmentMiddleOffset(KoGradientSegment* segment, double t); /** * splits the specified segment into two equal parts * @param segment the segment to split * @return void */ void splitSegment(KoGradientSegment* segment); /** * duplicate the specified segment * @param segment the segment to duplicate * @return void */ void duplicateSegment(KoGradientSegment* segment); /** * create a segment horizontally reversed to the specified one. * @param segment the segment to reverse * @return void */ void mirrorSegment(KoGradientSegment* segment); /** * removes the specific segment from the gradient colour picker. * @param segment the segment to remove * @return the segment which will be at the place of the old * segment. 0 if the segment is not in the gradient or it is * not possible to remove the segment. */ KoGradientSegment* removeSegment(KoGradientSegment* segment); /** * checks if it's possible to remove a segment (at least two * segments in the gradient) * @return true if it's possible to remove an segment */ bool removeSegmentPossible() const; const QList& segments() const; protected: - KoSegmentGradient(const KoSegmentGradient &rhs); - virtual QByteArray generateMD5() const; - inline void pushSegment(KoGradientSegment* segment) { m_segments.push_back(segment); } QList m_segments; private: bool init(); }; #endif // KOSEGMENTGRADIENT_H diff --git a/libs/pigment/resources/KoStopGradient.cpp b/libs/pigment/resources/KoStopGradient.cpp index dc851da4ea0..e24ab537add 100644 --- a/libs/pigment/resources/KoStopGradient.cpp +++ b/libs/pigment/resources/KoStopGradient.cpp @@ -1,677 +1,657 @@ /* Copyright (C) 2005 Tim Beaulen Copyright (C) 2007 Jan Hambrecht Copyright (c) 2007 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #include "KoStopGradient.h" #include #include #include #include #include -#include #include #include #include "KoColorSpaceRegistry.h" #include "KoMixColorsOp.h" #include #include KoStopGradient::KoStopGradient(const QString& filename) : KoAbstractGradient(filename) { } KoStopGradient::~KoStopGradient() { } KoAbstractGradient* KoStopGradient::clone() const { return new KoStopGradient(*this); } bool KoStopGradient::load() { QFile f(filename()); if (!f.open(QIODevice::ReadOnly)) { kWarning() << "Can't open file " << filename(); return false; } bool res = loadFromDevice(&f); f.close(); return res; } bool KoStopGradient::loadFromDevice(QIODevice *dev) { QString strExt; const int result = filename().lastIndexOf('.'); if (result >= 0) { strExt = filename().mid(result).toLower(); } QByteArray ba = dev->readAll(); - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - setMD5(md5.result()); - QBuffer buf(&ba); if (strExt == ".kgr") { loadKarbonGradient(&buf); } else if (strExt == ".svg") { loadSvgGradient(&buf); } if (m_stops.count() >= 2) { setValid(true); } updatePreview(); return true; } bool KoStopGradient::save() { QFile fileOut(filename()); if (! fileOut.open(QIODevice::WriteOnly)) return false; bool retval = saveToDevice(&fileOut); fileOut.close(); return retval; } QGradient* KoStopGradient::toQGradient() const { QGradient* gradient; switch (type()) { case QGradient::LinearGradient: { gradient = new QLinearGradient(m_start, m_stop); break; } case QGradient::RadialGradient: { QPointF diff = m_stop - m_start; qreal radius = sqrt(diff.x() * diff.x() + diff.y() * diff.y()); gradient = new QRadialGradient(m_start, radius, m_focalPoint); break; } case QGradient::ConicalGradient: { qreal angle = atan2(m_start.y(), m_start.x()) * 180.0 / M_PI; if (angle < 0.0) angle += 360.0; gradient = new QConicalGradient(m_start, angle); break; } default: return 0; } QColor color; for (QList::const_iterator i = m_stops.begin(); i != m_stops.end(); ++i) { i->second.toQColor(&color); gradient->setColorAt(i->first , color); } return gradient; } void KoStopGradient::colorAt(KoColor& dst, qreal t) const { if (! m_stops.count()) return; if (t <= m_stops.first().first || m_stops.count() == 1) { // we have only one stop or t is before the first stop // -> use the color of the first stop dst.fromKoColor(m_stops.first().second); } else if (t >= m_stops.last().first) { // t is after the last stop // -> use the color of the last stop dst.fromKoColor(m_stops.last().second); } else { // we have at least two color stops // -> find the two stops which frame our t QList::const_iterator stop = m_stops.begin(); QList::const_iterator lastStop = m_stops.end(); // we already checked the first stop, so we start at the second for (++stop; stop != lastStop; ++stop) { // we break at the stop which is just after our t if (stop->first > t) break; } if ( !(*buffer.colorSpace() == *colorSpace())) { buffer = KoColor(colorSpace()); } const KoGradientStop& leftStop = *(stop - 1); const KoGradientStop& rightStop = *(stop); const quint8 *colors[2]; colors[0] = leftStop.second.data(); colors[1] = rightStop.second.data(); qreal localT; qreal stopDistance = rightStop.first - leftStop.first; if (stopDistance < DBL_EPSILON) { localT = 0.5; } else { localT = (t - leftStop.first) / stopDistance; } qint16 colorWeights[2]; colorWeights[0] = static_cast((1.0 - localT) * 255 + 0.5); colorWeights[1] = 255 - colorWeights[0]; colorSpace()->mixColorsOp()->mixColors(colors, colorWeights, 2, buffer.data()); dst.fromKoColor(buffer); } } KoStopGradient * KoStopGradient::fromQGradient(QGradient * gradient) { if (! gradient) return 0; KoStopGradient * newGradient = new KoStopGradient(""); newGradient->setType(gradient->type()); newGradient->setSpread(gradient->spread()); switch (gradient->type()) { case QGradient::LinearGradient: { QLinearGradient * g = static_cast(gradient); newGradient->m_start = g->start(); newGradient->m_stop = g->finalStop(); newGradient->m_focalPoint = g->start(); break; } case QGradient::RadialGradient: { QRadialGradient * g = static_cast(gradient); newGradient->m_start = g->center(); newGradient->m_stop = g->center() + QPointF(g->radius(), 0); newGradient->m_focalPoint = g->focalPoint(); break; } case QGradient::ConicalGradient: { QConicalGradient * g = static_cast(gradient); qreal radian = g->angle() * M_PI / 180.0; newGradient->m_start = g->center(); newGradient->m_stop = QPointF(100.0 * cos(radian), 100.0 * sin(radian)); newGradient->m_focalPoint = g->center(); break; } default: delete newGradient; return 0; } foreach(const QGradientStop & stop, gradient->stops()) { KoColor color(newGradient->colorSpace()); color.fromQColor(stop.second); newGradient->m_stops.append(KoGradientStop(stop.first, color)); } return newGradient; } void KoStopGradient::setStops(QList< KoGradientStop > stops) { m_stops.clear(); KoColor color; foreach(const KoGradientStop & stop, stops) { color = stop.second; color.convertTo(colorSpace()); m_stops.append(KoGradientStop(stop.first, color)); } updatePreview(); } QList KoStopGradient::stops() const { return m_stops; } void KoStopGradient::loadKarbonGradient(QIODevice *file) { QDomDocument doc; if (!(doc.setContent(file))) { file->close(); setValid(false); return; } QDomElement e; QDomNode n = doc.documentElement().firstChild(); if (!n.isNull()) { e = n.toElement(); if (!e.isNull() && e.tagName() == "GRADIENT") { parseKarbonGradient(e); } } } void KoStopGradient::loadSvgGradient(QIODevice *file) { QDomDocument doc; if (!(doc.setContent(file))) file->close(); else { for (QDomNode n = doc.documentElement().firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement e = n.toElement(); if (e.isNull()) continue; if (e.tagName() == "linearGradient" || e.tagName() == "radialGradient") { parseSvgGradient(e); return; } // Inkscape gradients are in another defs if (e.tagName() == "defs") { for (QDomNode defnode = e.firstChild(); !defnode.isNull(); defnode = defnode.nextSibling()) { QDomElement defelement = defnode.toElement(); if (defelement.isNull()) continue; if (defelement.tagName() == "linearGradient" || defelement.tagName() == "radialGradient") { parseSvgGradient(defelement); return; } } } } } } void KoStopGradient::parseKarbonGradient(const QDomElement& element) { m_start = QPointF(element.attribute("originX", "0.0").toDouble(), element.attribute("originY", "0.0").toDouble()); m_focalPoint = QPointF(element.attribute("focalX", "0.0").toDouble(), element.attribute("focalY", "0.0").toDouble()); m_stop = QPointF(element.attribute("vectorX", "0.0").toDouble(), element.attribute("vectorY", "0.0").toDouble()); setType((QGradient::Type)element.attribute("type", 0).toInt()); setSpread((QGradient::Spread)element.attribute("repeatMethod", 0).toInt()); m_stops.clear(); qreal color1, color2, color3, color4, opacity; KoColor color; // load stops QDomNodeList list = element.childNodes(); for (int i = 0; i < list.count(); ++i) { if (list.item(i).isElement()) { QDomElement colorstop = list.item(i).toElement(); if (colorstop.tagName() == "COLORSTOP") { QDomElement e = colorstop.firstChild().toElement(); opacity = e.attribute("opacity", "1.0").toFloat(); QColor tmpColor; const KoColorSpace* stopColorSpace; switch (e.attribute("colorSpace").toUShort()) { case 1: // cmyk color1 = e.attribute("v1", "0.0").toFloat(); color2 = e.attribute("v2", "0.0").toFloat(); color3 = e.attribute("v3", "0.0").toFloat(); color4 = e.attribute("v4", "0.0").toFloat(); stopColorSpace = KoColorSpaceRegistry::instance()->colorSpace( CMYKAColorModelID.id(), Integer8BitsColorDepthID.id(), QString()); if (stopColorSpace) { quint8 data[5]; data[0] = static_cast(color1 * 255 + 0.5); data[1] = static_cast(color2 * 255 + 0.5); data[2] = static_cast(color3 * 255 + 0.5); data[3] = static_cast(color4 * 255 + 0.5); data[4] = static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5); color.setColor(data, stopColorSpace); } else { // cmyk colorspace not found fallback to rgb color.convertTo(KoColorSpaceRegistry::instance()->rgb8()); tmpColor.setCmykF(color1, color2, color3, color4); tmpColor.setAlpha(static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5)); color.fromQColor(tmpColor); } break; case 2: // hsv color1 = e.attribute("v1", "0.0").toFloat(); color2 = e.attribute("v2", "0.0").toFloat(); color3 = e.attribute("v3", "0.0").toFloat(); color.convertTo(KoColorSpaceRegistry::instance()->rgb8()); tmpColor.setHsvF(color1, color2, color3); tmpColor.setAlpha(static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5)); color.fromQColor(tmpColor); break; case 3: // gray color1 = e.attribute("v1", "0.0").toFloat(); stopColorSpace = KoColorSpaceRegistry::instance()->colorSpace( GrayAColorModelID.id(), Integer8BitsColorDepthID.id(), QString()); if (stopColorSpace) { quint8 data[2]; data[0] = static_cast(color1 * 255 + 0.5); data[1] = static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5); color.setColor(data, stopColorSpace); } else { // gray colorspace not found fallback to rgb color.convertTo(KoColorSpaceRegistry::instance()->rgb8()); tmpColor.setRgbF(color1, color1, color1); tmpColor.setAlpha(static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5)); color.fromQColor(tmpColor); } break; default: // rgb color1 = e.attribute("v1", "0.0").toFloat(); color2 = e.attribute("v2", "0.0").toFloat(); color3 = e.attribute("v3", "0.0").toFloat(); stopColorSpace = KoColorSpaceRegistry::instance()->rgb8(); quint8 data[4]; data[2] = static_cast(color1 * 255 + 0.5); data[1] = static_cast(color2 * 255 + 0.5); data[0] = static_cast(color3 * 255 + 0.5); data[3] = static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5); color.setColor(data, stopColorSpace); } qreal offset = colorstop.attribute("ramppoint", "0.0").toFloat(); // midpoint = colorstop.attribute("midpoint", "0.5").toFloat(); m_stops.append(KoGradientStop(offset, color)); } } } } void KoStopGradient::parseSvgGradient(const QDomElement& element) { m_stops.clear(); setSpread(QGradient::PadSpread); /*QString href = e.attribute( "xlink:href" ).mid( 1 ); if( !href.isEmpty() ) { }*/ setName(element.attribute("id", i18n("SVG Gradient"))); const KoColorSpace* rgbColorSpace = KoColorSpaceRegistry::instance()->rgb8(); bool bbox = element.attribute("gradientUnits") != "userSpaceOnUse"; if (element.tagName() == "linearGradient") { if (bbox) { QString s; s = element.attribute("x1", "0%"); qreal xOrigin; if (s.endsWith('%')) xOrigin = s.remove('%').toDouble(); else xOrigin = s.toDouble() * 100.0; s = element.attribute("y1", "0%"); qreal yOrigin; if (s.endsWith('%')) yOrigin = s.remove('%').toDouble(); else yOrigin = s.toDouble() * 100.0; s = element.attribute("x2", "100%"); qreal xVector; if (s.endsWith('%')) xVector = s.remove('%').toDouble(); else xVector = s.toDouble() * 100.0; s = element.attribute("y2", "0%"); qreal yVector; if (s.endsWith('%')) yVector = s.remove('%').toDouble(); else yVector = s.toDouble() * 100.0; m_start = QPointF(xOrigin, yOrigin); m_stop = QPointF(xVector, yVector); } else { m_start = QPointF(element.attribute("x1").toDouble(), element.attribute("y1").toDouble()); m_stop = QPointF(element.attribute("x2").toDouble(), element.attribute("y2").toDouble()); } setType(QGradient::LinearGradient); } else { if (bbox) { QString s; s = element.attribute("cx", "50%"); qreal xOrigin; if (s.endsWith('%')) xOrigin = s.remove('%').toDouble(); else xOrigin = s.toDouble() * 100.0; s = element.attribute("cy", "50%"); qreal yOrigin; if (s.endsWith('%')) yOrigin = s.remove('%').toDouble(); else yOrigin = s.toDouble() * 100.0; s = element.attribute("cx", "50%"); qreal xVector; if (s.endsWith('%')) xVector = s.remove('%').toDouble(); else xVector = s.toDouble() * 100.0; s = element.attribute("r", "50%"); if (s.endsWith('%')) xVector += s.remove('%').toDouble(); else xVector += s.toDouble() * 100.0; s = element.attribute("cy", "50%"); qreal yVector; if (s.endsWith('%')) yVector = s.remove('%').toDouble(); else yVector = s.toDouble() * 100.0; s = element.attribute("fx", "50%"); qreal xFocal; if (s.endsWith('%')) xFocal = s.remove('%').toDouble(); else xFocal = s.toDouble() * 100.0; s = element.attribute("fy", "50%"); qreal yFocal; if (s.endsWith('%')) yFocal = s.remove('%').toDouble(); else yFocal = s.toDouble() * 100.0; m_start = QPointF(xOrigin, yOrigin); m_stop = QPointF(xVector, yVector); m_focalPoint = QPointF(xFocal, yFocal); } else { m_start = QPointF(element.attribute("cx").toDouble(), element.attribute("cy").toDouble()); m_stop = QPointF(element.attribute("cx").toDouble() + element.attribute("r").toDouble(), element.attribute("cy").toDouble()); m_focalPoint = QPointF(element.attribute("fx").toDouble(), element.attribute("fy").toDouble()); } setType(QGradient::RadialGradient); } // handle spread method QString spreadMethod = element.attribute("spreadMethod"); if (!spreadMethod.isEmpty()) { if (spreadMethod == "reflect") setSpread(QGradient::ReflectSpread); else if (spreadMethod == "repeat") setSpread(QGradient::RepeatSpread); } for (QDomNode n = element.firstChild(); !n.isNull(); n = n.nextSibling()) { QDomElement colorstop = n.toElement(); if (colorstop.tagName() == "stop") { qreal opacity = 0.0; QColor c; float off; QString temp = colorstop.attribute("offset"); if (temp.contains('%')) { temp = temp.left(temp.length() - 1); off = temp.toFloat() / 100.0; } else off = temp.toFloat(); if (!colorstop.attribute("stop-color").isEmpty()) parseSvgColor(c, colorstop.attribute("stop-color")); else { // try style attr QString style = colorstop.attribute("style").simplified(); QStringList substyles = style.split(';', QString::SkipEmptyParts); foreach(const QString & s, substyles) { QStringList substyle = s.split(':'); QString command = substyle[0].trimmed(); QString params = substyle[1].trimmed(); if (command == "stop-color") parseSvgColor(c, params); if (command == "stop-opacity") opacity = params.toDouble(); } } if (!colorstop.attribute("stop-opacity").isEmpty()) opacity = colorstop.attribute("stop-opacity").toDouble(); KoColor color(rgbColorSpace); color.fromQColor(c); color.setOpacity(static_cast(opacity * OPACITY_OPAQUE_U8 + 0.5)); //According to the SVG spec each gradient offset has to be equal to or greater than the previous one //if not it needs to be adjusted to be equal if (m_stops.count() > 0 && m_stops.last().first >= off) { off = m_stops.last().first; } m_stops.append(KoGradientStop(off, color)); } } } void KoStopGradient::parseSvgColor(QColor &color, const QString &s) { if (s.startsWith("rgb(")) { QString parse = s.trimmed(); QStringList colors = parse.split(','); QString r = colors[0].right((colors[0].length() - 4)); QString g = colors[1]; QString b = colors[2].left((colors[2].length() - 1)); if (r.contains('%')) { r = r.left(r.length() - 1); r = QString::number(int((qreal(255 * r.toDouble()) / 100.0))); } if (g.contains('%')) { g = g.left(g.length() - 1); g = QString::number(int((qreal(255 * g.toDouble()) / 100.0))); } if (b.contains('%')) { b = b.left(b.length() - 1); b = QString::number(int((qreal(255 * b.toDouble()) / 100.0))); } color = QColor(r.toInt(), g.toInt(), b.toInt()); } else { QString rgbColor = s.trimmed(); QColor c; if (rgbColor.startsWith('#')) c.setNamedColor(rgbColor); else { c = QColor(rgbColor); } color = c; } } QString KoStopGradient::defaultFileExtension() const { return QString(".svg"); } bool KoStopGradient::saveToDevice(QIODevice *dev) const { QTextStream stream(dev); const QString spreadMethod[3] = { QString("spreadMethod=\"pad\" "), QString("spreadMethod=\"reflect\" "), QString("spreadMethod=\"repeat\" ") }; const QString indent = " "; stream << "" << endl; stream << indent; stream << "" << endl; QColor color; // color stops foreach(const KoGradientStop & stop, m_stops) { stop.second.toQColor(&color); stream << indent << indent; stream << "(color.alpha()) / 255.0f << "\"" << " />" << endl; } stream << indent; stream << "" << endl; stream << "" << endl; - return true; -} - -QByteArray KoStopGradient::generateMD5() const -{ - QByteArray ba; - QBuffer buf(&ba); - buf.open(QBuffer::WriteOnly); - saveToDevice(&buf); - buf.close(); - - if (!ba.isEmpty()) { - QCryptographicHash md5(QCryptographicHash::Md5); - md5.addData(ba); - return md5.result(); - } + KoResource::saveToDevice(dev); - return ba; + return true; } diff --git a/libs/pigment/resources/KoStopGradient.h b/libs/pigment/resources/KoStopGradient.h index 2e1e3d4dafe..c3cce998bee 100644 --- a/libs/pigment/resources/KoStopGradient.h +++ b/libs/pigment/resources/KoStopGradient.h @@ -1,89 +1,87 @@ /* Copyright (c) 2007 Sven Langkamp This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #ifndef KOSTOPGRADIENT_H #define KOSTOPGRADIENT_H #include #include #include "KoColor.h" #include "KoAbstractGradient.h" #include "KoResource.h" #include typedef QPair KoGradientStop; /** * Resource for colorstop based gradients like Karbon gradients and SVG gradients */ class PIGMENTCMS_EXPORT KoStopGradient : public KoAbstractGradient { public: explicit KoStopGradient(const QString &filename); virtual ~KoStopGradient(); KoAbstractGradient* clone() const; virtual bool load(); virtual bool loadFromDevice(QIODevice *dev); virtual bool save(); virtual bool saveToDevice(QIODevice* dev) const; /// reimplemented virtual QGradient* toQGradient() const; /// reimplemented void colorAt(KoColor&, qreal t) const; /// Creates KoStopGradient from a QGradient static KoStopGradient * fromQGradient(QGradient * gradient); /// Sets the gradient stops void setStops(QList stops); QList stops() const; /// reimplemented QString defaultFileExtension() const; protected: - virtual QByteArray generateMD5() const; - QList m_stops; QPointF m_start; QPointF m_stop; QPointF m_focalPoint; private: mutable KoColor buffer; private: void loadKarbonGradient(QIODevice *file); void parseKarbonGradient(const QDomElement& element); void loadSvgGradient(QIODevice *file); void parseSvgGradient(const QDomElement& element); void parseSvgColor(QColor &color, const QString &s); }; #endif // KOSTOPGRADIENT_H diff --git a/libs/widgets/CMakeLists.txt b/libs/widgets/CMakeLists.txt index 1cabeaddce0..31578b6864f 100644 --- a/libs/widgets/CMakeLists.txt +++ b/libs/widgets/CMakeLists.txt @@ -1,171 +1,172 @@ add_subdirectory( tests ) add_subdirectory( pics ) include_directories(${KOTEXT_INCLUDES} ${KOODF_INCLUDES} ${PIGMENT_INCLUDES}) include_directories(${CMAKE_SOURCE_DIR}/libs/widgetutils) if (LIBATTICA_FOUND) include_directories(${LIBATTICA_INCLUDE_DIR}) endif () set(kowidgets_LIB_SRCS KoGlobal.cpp KoZoomWidget.cpp KoTagToolButton.cpp KoTagChooserWidget.cpp KoTagFilterWidget.cpp KoResourceTaggingManager.cpp KoResourceItemChooserContextMenu.cpp KoAspectButton.cpp KoCsvImportDialog.cpp KoPageLayoutDialog.cpp KoPageLayoutWidget.cpp KoPagePreviewWidget.cpp KoPositionSelector.cpp KoSliderCombo.cpp KoColorPopupButton.cpp KoConfigAuthorPage.cpp KoUnitDoubleSpinBox.cpp KoZoomAction.cpp KoZoomController.cpp KoZoomInput.cpp KoZoomHandler.cpp KoZoomMode.cpp KoDpi.cpp KoGlobal.cpp KoFileDialog.cpp KoColorPatch.cpp KoColorPopupAction.cpp KoColorSetWidget.cpp KoColorSlider.cpp KoDualColorButton.cpp KoEditColorSetDialog.cpp KoTriangleColorSelector.cpp KoResourcePopupAction.cpp KoStrokeConfigWidget.cpp KoFillConfigWidget.cpp KoShadowConfigWidget.cpp KoIconToolTip.cpp KoResourceItemChooser.cpp KoResourceItemChooserSync.cpp KoResourceSelector.cpp KoResourceModel.cpp KoResourceItemDelegate.cpp KoResourceItemView.cpp KoResourceTagStore.cpp KoRuler.cpp KoRulerController.cpp KoItemToolTip.cpp KoCheckerBoardPainter.cpp KoResourceServerAdapter.cpp KoResourceServerProvider.cpp KoLineStyleSelector.cpp KoLineStyleItemDelegate.cpp KoLineStyleModel.cpp KoMarkerModel.cpp KoMarkerItemDelegate.cpp KoMarkerSelector.cpp KoDockWidgetTitleBar.cpp KoDockWidgetTitleBarButton.cpp KoViewItemContextBar.cpp KoContextBarButton.cpp KoResourceFiltering.cpp KoResourceModelBase.cpp KoToolBox.cpp KoToolBoxDocker.cpp KoToolBoxFactory.cpp KoToolDocker.cpp KoModeBox.cpp KoModeBoxDocker.cpp KoModeBoxFactory.cpp KoDocumentInfoDlg.cpp KoDocumentInfoPropsPage.cpp KoGlobal.cpp + KoTableView.cpp ) kde4_add_ui_files( kowidgets_LIB_SRCS KoConfigAuthorPage.ui KoCsvImportDialog.ui koDocumentInfoAboutWidget.ui koDocumentInfoAuthorWidget.ui KoEditColorSet.ui KoPageLayoutWidget.ui KoShadowConfigWidget.ui ) kde4_add_library(kowidgets SHARED ${kowidgets_LIB_SRCS}) target_link_libraries(kowidgets kotext pigmentcms kowidgetutils ${KDE4_KIO_LIBS}) if(GHNS) target_link_libraries(kowidgets {KDE4_KNEWSTUFF3_LIBS}) endif () target_link_libraries(kowidgets LINK_INTERFACE_LIBRARIES kotext pigmentcms kowidgetutils ${KDE4_KDEUI_LIBS}) set_target_properties(kowidgets PROPERTIES VERSION ${GENERIC_CALLIGRA_LIB_VERSION} SOVERSION ${GENERIC_CALLIGRA_LIB_SOVERSION} ) install(TARGETS kowidgets ${INSTALL_TARGETS_DEFAULT_ARGS}) install( FILES KoGlobal.h KoResourceItemChooserContextMenu.h KoGenericRegistryModel.h KoPageLayoutDialog.h KoPageLayoutWidget.h KoPagePreviewWidget.h KoPositionSelector.h kowidgets_export.h KoZoomAction.h KoZoomController.h KoZoomInput.h KoDpi.h KoZoomHandler.h KoZoomMode.h KoGlobal.h KoFileDialog.h KoColorPatch.h KoStrokeConfigWidget.h KoFillConfigWidget.h KoShadowConfigWidget.h KoColorPopupAction.h KoColorSetWidget.h KoColorSlider.h KoDualColorButton.h KoEditColorSetDialog.h KoTriangleColorSelector.h KoResourceItemChooser.h KoResourceSelector.h KoResourceServer.h KoResourceServerAdapter.h KoResourceServerObserver.h KoResourceServerProvider.h KoResourceTagStore.h KoLineStyleSelector.h KoDockWidgetTitleBar.h KoDockWidgetTitleBarButton.h KoResourceModelBase.h KoGlobal.h DESTINATION ${INCLUDE_INSTALL_DIR}/calligra COMPONENT Devel) set(filedialogtester_SRCS KoFileDialogTester.cpp main.cpp ) kde4_add_ui_files(filedialogtester_SRCS KoFileDialogTester.ui ) kde4_add_executable(filedialogtester ${filedialogtester_SRCS}) target_link_libraries(filedialogtester kowidgets) diff --git a/libs/widgets/KoResourceItemView.cpp b/libs/widgets/KoResourceItemView.cpp index c1df724406c..56266c76508 100644 --- a/libs/widgets/KoResourceItemView.cpp +++ b/libs/widgets/KoResourceItemView.cpp @@ -1,121 +1,61 @@ /* This file is part of the KDE project * Copyright (C) 2008 Jan Hambrecht * Copyright (c) 2011 José Luis Vergara #include -#include #include KoResourceItemView::KoResourceItemView(QWidget *parent) - : QTableView(parent) + : KoTableView(parent) { - setSelectionMode(QAbstractItemView::SingleSelection); - verticalHeader()->hide(); - horizontalHeader()->hide(); - verticalHeader()->setDefaultSectionSize(20); - setContextMenuPolicy(Qt::DefaultContextMenu); - setViewMode(FIXED_COLUMNS); -} - -void KoResourceItemView::resizeEvent(QResizeEvent *event) -{ - QTableView::resizeEvent(event); - updateView(); - - emit sigSizeChanged(); } bool KoResourceItemView::viewportEvent(QEvent *event) { if (event->type() == QEvent::ToolTip && model()) { QHelpEvent *he = static_cast(event); QStyleOptionViewItem option = viewOptions(); QModelIndex index = model()->buddy(indexAt(he->pos())); if (index.isValid()) { option.rect = visualRect(index); m_tip.showTip(this, he->pos(), option, index); return true; } } return QTableView::viewportEvent(event); } -void KoResourceItemView::setViewMode(KoResourceItemView::ViewMode mode) -{ - m_viewMode = mode; - - switch (m_viewMode) { - case FIXED_COLUMNS: - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Horizontal scrollbar is never needed - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - break; - case FIXED_ROWS: - setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); - setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Vertical scrollbar is never needed - default: - setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); - setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); - } - -} void KoResourceItemView::selectionChanged(const QItemSelection &selected, const QItemSelection &/*deselected*/) { emit currentResourceChanged(selected.indexes().first()); } void KoResourceItemView::contextMenuEvent(QContextMenuEvent *event) { QTableView::contextMenuEvent(event); emit contextMenuRequested(event->globalPos()); } -void KoResourceItemView::updateView() -{ - int columnCount = model()->columnCount(QModelIndex()); - int rowCount = model()->rowCount(QModelIndex()); - int rowHeight, columnWidth; - - if (m_viewMode == FIXED_COLUMNS) { - columnWidth = viewport()->size().width() / columnCount; - - for (int i = 0; i < columnCount; ++i) { - setColumnWidth(i, columnWidth); - } - if (columnCount > 1) { - for (int i = 0; i < rowCount; ++i) { - setRowHeight(i, columnWidth); - } - } - } else if (m_viewMode == FIXED_ROWS) { - if (rowCount == 0) return; // Don't divide by zero - rowHeight = viewport()->size().height() / rowCount; - - for (int i = 0; i < rowCount; ++i) { - setRowHeight(i, rowHeight); - } - } -} - #include "KoResourceItemView.moc" diff --git a/libs/widgets/KoResourceItemView.h b/libs/widgets/KoResourceItemView.h index 7d53b5d97dc..ced0cb2eb7a 100644 --- a/libs/widgets/KoResourceItemView.h +++ b/libs/widgets/KoResourceItemView.h @@ -1,73 +1,57 @@ /* This file is part of the KDE project * Copyright (C) 2008 Jan Hambrecht * Copyright (c) 2011 José Luis Vergara * * 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 KORESOURCEITEMVIEW_H #define KORESOURCEITEMVIEW_H -#include +#include #include class QEvent; class QModelIndex; /// The resource view -class KoResourceItemView : public QTableView +class KoResourceItemView : public KoTableView { Q_OBJECT public: - enum ViewMode { - FIXED_COLUMNS, /// The number of columns is fixed - FIXED_ROWS /// The number of rows is fixed - }; explicit KoResourceItemView(QWidget *parent = 0); virtual ~KoResourceItemView() { disconnect(); } - /** reimplemented - * This will draw a number of rows based on the number of columns if m_viewMode is FIXED_COLUMS - * And it will draw a number of columns based on the number of rows if m_viewMode is FIXED_ROWS - */ - virtual void resizeEvent(QResizeEvent *event); - /// reimplemented virtual bool viewportEvent(QEvent *event); - void setViewMode(ViewMode mode); - - void updateView(); - Q_SIGNALS: void currentResourceChanged(const QModelIndex &); void contextMenuRequested(const QPoint &); - void sigSizeChanged(); - protected: virtual void contextMenuEvent(QContextMenuEvent *event); void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); private: KoIconToolTip m_tip; - ViewMode m_viewMode; + }; #endif // KORESOURCEITEMVIEW_H diff --git a/libs/widgets/KoResourceItemView.cpp b/libs/widgets/KoTableView.cpp similarity index 65% copy from libs/widgets/KoResourceItemView.cpp copy to libs/widgets/KoTableView.cpp index c1df724406c..48484e5e796 100644 --- a/libs/widgets/KoResourceItemView.cpp +++ b/libs/widgets/KoTableView.cpp @@ -1,121 +1,87 @@ -/* This file is part of the KDE project - * Copyright (C) 2008 Jan Hambrecht - * Copyright (c) 2011 José Luis Vergara * * 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 "KoTableView.h" -#include "KoResourceItemView.h" #include -#include #include -#include - -KoResourceItemView::KoResourceItemView(QWidget *parent) +KoTableView::KoTableView(QWidget *parent) : QTableView(parent) { setSelectionMode(QAbstractItemView::SingleSelection); verticalHeader()->hide(); horizontalHeader()->hide(); verticalHeader()->setDefaultSectionSize(20); setContextMenuPolicy(Qt::DefaultContextMenu); setViewMode(FIXED_COLUMNS); } -void KoResourceItemView::resizeEvent(QResizeEvent *event) +void KoTableView::resizeEvent(QResizeEvent *event) { QTableView::resizeEvent(event); updateView(); emit sigSizeChanged(); } -bool KoResourceItemView::viewportEvent(QEvent *event) -{ - if (event->type() == QEvent::ToolTip && model()) { - QHelpEvent *he = static_cast(event); - QStyleOptionViewItem option = viewOptions(); - QModelIndex index = model()->buddy(indexAt(he->pos())); - if (index.isValid()) { - option.rect = visualRect(index); - m_tip.showTip(this, he->pos(), option, index); - return true; - } - } - - return QTableView::viewportEvent(event); -} - -void KoResourceItemView::setViewMode(KoResourceItemView::ViewMode mode) +void KoTableView::setViewMode(KoTableView::ViewMode mode) { m_viewMode = mode; switch (m_viewMode) { case FIXED_COLUMNS: setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Horizontal scrollbar is never needed setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn); break; case FIXED_ROWS: setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOn); setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff); // Vertical scrollbar is never needed default: setHorizontalScrollBarPolicy(Qt::ScrollBarAsNeeded); setVerticalScrollBarPolicy(Qt::ScrollBarAsNeeded); } } -void KoResourceItemView::selectionChanged(const QItemSelection &selected, const QItemSelection &/*deselected*/) -{ - emit currentResourceChanged(selected.indexes().first()); -} - -void KoResourceItemView::contextMenuEvent(QContextMenuEvent *event) -{ - QTableView::contextMenuEvent(event); - emit contextMenuRequested(event->globalPos()); -} - -void KoResourceItemView::updateView() +void KoTableView::updateView() { int columnCount = model()->columnCount(QModelIndex()); int rowCount = model()->rowCount(QModelIndex()); int rowHeight, columnWidth; if (m_viewMode == FIXED_COLUMNS) { columnWidth = viewport()->size().width() / columnCount; for (int i = 0; i < columnCount; ++i) { setColumnWidth(i, columnWidth); } if (columnCount > 1) { for (int i = 0; i < rowCount; ++i) { setRowHeight(i, columnWidth); } } } else if (m_viewMode == FIXED_ROWS) { if (rowCount == 0) return; // Don't divide by zero rowHeight = viewport()->size().height() / rowCount; for (int i = 0; i < rowCount; ++i) { setRowHeight(i, rowHeight); } } } - - -#include "KoResourceItemView.moc" diff --git a/libs/widgets/KoResourceItemView.h b/libs/widgets/KoTableView.h similarity index 63% copy from libs/widgets/KoResourceItemView.h copy to libs/widgets/KoTableView.h index 7d53b5d97dc..1cc5a4e9026 100644 --- a/libs/widgets/KoResourceItemView.h +++ b/libs/widgets/KoTableView.h @@ -1,73 +1,64 @@ -/* This file is part of the KDE project - * Copyright (C) 2008 Jan Hambrecht - * Copyright (c) 2011 José Luis Vergara +/* + * Copyright (C) 2015 Boudewijn Rempt * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Library General Public * License as published by the Free Software Foundation; either * version 2 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Library General Public License for more details. * * You should have received a copy of the GNU Library General Public License * along with this library; see the file COPYING.LIB. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. */ - -#ifndef KORESOURCEITEMVIEW_H -#define KORESOURCEITEMVIEW_H +#ifndef KOTABLEVIEW_H +#define KOTABLEVIEW_H #include -#include + +#include "kowidgets_export.h" class QEvent; class QModelIndex; -/// The resource view -class KoResourceItemView : public QTableView +/** + * @brief The KoTableView class provides a QTableView with fixed columns or rows + */ +class KOWIDGETS_EXPORT KoTableView: public QTableView { Q_OBJECT public: enum ViewMode { FIXED_COLUMNS, /// The number of columns is fixed FIXED_ROWS /// The number of rows is fixed }; - explicit KoResourceItemView(QWidget *parent = 0); - virtual ~KoResourceItemView() { disconnect(); } + explicit KoTableView(QWidget *parent = 0); + virtual ~KoTableView() {} /** reimplemented * This will draw a number of rows based on the number of columns if m_viewMode is FIXED_COLUMS * And it will draw a number of columns based on the number of rows if m_viewMode is FIXED_ROWS */ virtual void resizeEvent(QResizeEvent *event); - /// reimplemented - virtual bool viewportEvent(QEvent *event); void setViewMode(ViewMode mode); void updateView(); Q_SIGNALS: - void currentResourceChanged(const QModelIndex &); - void contextMenuRequested(const QPoint &); - void sigSizeChanged(); -protected: - virtual void contextMenuEvent(QContextMenuEvent *event); - void selectionChanged(const QItemSelection &selected, const QItemSelection &deselected); - private: - KoIconToolTip m_tip; ViewMode m_viewMode; }; -#endif // KORESOURCEITEMVIEW_H +#endif // KOTABLEVIEW_H diff --git a/libs/widgets/KoToolBox.cpp b/libs/widgets/KoToolBox.cpp index 0886e69838a..304797df5f0 100644 --- a/libs/widgets/KoToolBox.cpp +++ b/libs/widgets/KoToolBox.cpp @@ -1,256 +1,343 @@ /* * Copyright (c) 2005-2009 Thomas Zander * Copyright (c) 2009 Peter Simonsson * Copyright (c) 2010 Cyrille Berger * * 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 "KoToolBox_p.h" #include "KoToolBoxLayout_p.h" -#include -#include #include #include #include #include #include #include +#include #include +#include +#include + +#include +#include +#include +#include +#include + +#include +#include + +#define BUTTON_MARGIN 10 class KoToolBox::Private { public: Private() : layout(0) , buttonGroup(0) , floating(false) + , contextSize(0) { } void addSection(Section *section, const QString &name); + QList buttons; QMap sections; KoToolBoxLayout *layout; QButtonGroup *buttonGroup; QHash visibilityCodes; bool floating; + QMap contextIconSizes; + QMenu* contextSize; }; void KoToolBox::Private::addSection(Section *section, const QString &name) { section->setName(name); layout->addSection(section); sections.insert(name, section); } KoToolBox::KoToolBox() : d(new Private) { d->layout = new KoToolBoxLayout(this); // add defaults d->addSection(new Section(this), "main"); d->addSection(new Section(this), "dynamic"); d->buttonGroup = new QButtonGroup(this); setLayout(d->layout); foreach(const KoToolButton & button, KoToolManager::instance()->createToolList()) { addButton(button.button, button.section, button.priority, button.buttonGroupId); d->visibilityCodes.insert(button.button, button.visibilityCode); } // Update visibility of buttons setButtonsVisible(QList()); connect(KoToolManager::instance(), SIGNAL(changedTool(KoCanvasController*, int)), this, SLOT(setActiveTool(KoCanvasController*, int))); connect(KoToolManager::instance(), SIGNAL(currentLayerChanged(const KoCanvasController*,const KoShapeLayer*)), this, SLOT(setCurrentLayer(const KoCanvasController*,const KoShapeLayer*))); connect(KoToolManager::instance(), SIGNAL(toolCodesSelected(QList)), this, SLOT(setButtonsVisible(QList))); connect(KoToolManager::instance(), SIGNAL(addedTool(KoToolButton,KoCanvasController*)), this, SLOT(toolAdded(KoToolButton,KoCanvasController*))); QTimer::singleShot(0, this, SLOT(adjustToFit())); } KoToolBox::~KoToolBox() { delete d; } void KoToolBox::addButton(QToolButton *button, const QString §ion, int priority, int buttonGroupId) { + d->buttons << button; // ensure same L&F button->setCheckable(true); button->setAutoRaise(true); + int toolbuttonSize = 14; // QApplication::style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, 0); + KConfigGroup cfg = KGlobal::config()->group("KoToolBox"); + int iconSize = cfg.readEntry("iconSize", toolbuttonSize); + button->setIconSize(QSize(iconSize, iconSize)); + foreach (Section *section, d->sections.values()) { + section->setButtonSize(QSize(iconSize + BUTTON_MARGIN, iconSize + BUTTON_MARGIN)); + } + QString sectionToBeAddedTo; if (section.contains(qApp->applicationName())) { sectionToBeAddedTo = "main"; } else if (section.contains("main")) { sectionToBeAddedTo = "main"; } else if (section.contains("dynamic")) { sectionToBeAddedTo = "dynamic"; } else { sectionToBeAddedTo = section; } Section *sectionWidget = d->sections.value(sectionToBeAddedTo); if (sectionWidget == 0) { sectionWidget = new Section(this); d->addSection(sectionWidget, sectionToBeAddedTo); } sectionWidget->addButton(button, priority); if (buttonGroupId < 0) d->buttonGroup->addButton(button); else d->buttonGroup->addButton(button, buttonGroupId); } void KoToolBox::setActiveTool(KoCanvasController *canvas, int id) { Q_UNUSED(canvas); QAbstractButton *button = d->buttonGroup->button(id); if (button) { button->setChecked(true); } else { kWarning(30004) << "KoToolBox::setActiveTool(" << id << "): no such button found"; } } void KoToolBox::setButtonsVisible(const QList &codes) { foreach(QToolButton *button, d->visibilityCodes.keys()) { QString code = d->visibilityCodes.value(button); if (code.startsWith(QLatin1String("flake/"))) { continue; } if (code.endsWith( QLatin1String( "/always"))) { button->setVisible(true); button->setEnabled( true ); } else if (code.isEmpty()) { button->setVisible(true); button->setEnabled( codes.count() != 0 ); } else { button->setVisible( codes.contains(code) ); } } layout()->invalidate(); update(); } void KoToolBox::setCurrentLayer(const KoCanvasController *canvas, const KoShapeLayer *layer) { Q_UNUSED(canvas); const bool enabled = layer == 0 || (layer->isEditable() && layer->isVisible()); foreach (QToolButton *button, d->visibilityCodes.keys()) { if (d->visibilityCodes[button].endsWith( QLatin1String( "/always") ) ) { continue; } button->setEnabled(enabled); } } void KoToolBox::paintEvent(QPaintEvent *) { QPainter painter(this); const QList sections = d->sections.values(); QList::const_iterator iterator = sections.begin(); int halfSpacing = layout()->spacing(); if (halfSpacing > 0) { halfSpacing /= 2; } while(iterator != sections.end()) { Section *section = *iterator; QStyleOption styleoption; styleoption.palette = palette(); if (section->separators() & Section::SeparatorTop) { int y = section->y() - halfSpacing; styleoption.state = QStyle::State_None; styleoption.rect = QRect(section->x(), y-1, section->width(), 2); style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &styleoption, &painter); } if (section->separators() & Section::SeparatorLeft) { int x = section->x() - halfSpacing; styleoption.state = QStyle::State_Horizontal; styleoption.rect = QRect(x-1, section->y(), 2, section->height()); style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &styleoption, &painter); } ++iterator; } painter.end(); } void KoToolBox::resizeEvent(QResizeEvent* event) { QWidget::resizeEvent(event); if (!d->floating) { setMinimumSize(layout()->minimumSize()); // This enforces the minimum size on the widget } } void KoToolBox::setOrientation(Qt::Orientation orientation) { d->layout->setOrientation(orientation); QTimer::singleShot(0, this, SLOT(update())); foreach(Section* section, d->sections) { section->setOrientation(orientation); } } void KoToolBox::setFloating(bool v) { setMinimumSize(QSize(1,1)); d->floating = v; } void KoToolBox::toolAdded(const KoToolButton &button, KoCanvasController *canvas) { Q_UNUSED(canvas); addButton(button.button, button.section, button.priority, button.buttonGroupId); d->visibilityCodes.insert(button.button, button.visibilityCode); setButtonsVisible(QList()); } void KoToolBox::adjustToFit() { int newWidth = width() - (width() % layout()->minimumSize().width()); - if(newWidth != width() && newWidth >= layout()->minimumSize().width()) { + if (newWidth != width() && newWidth >= layout()->minimumSize().width()) { setMaximumWidth(newWidth); QTimer::singleShot(0, this, SLOT(resizeUnlock())); } } void KoToolBox::resizeUnlock() { setMaximumWidth(QWIDGETSIZE_MAX); } + +void KoToolBox::slotContextIconSize() +{ + QAction* action = qobject_cast(sender()); + if (action && d->contextIconSizes.contains(action)) { + const int iconSize = d->contextIconSizes.value(action); + + KConfigGroup cfg = KGlobal::config()->group("KoToolBox"); + cfg.writeEntry("iconSize", iconSize); + + foreach(QToolButton *button, d->buttons) { + button->setIconSize(QSize(iconSize, iconSize)); + } + + foreach(Section *section, d->sections.values()) { + section->setButtonSize(QSize(iconSize + BUTTON_MARGIN, iconSize + BUTTON_MARGIN)); + } + + } + + adjustToFit(); +} + +void KoToolBox::contextMenuEvent(QContextMenuEvent *event) +{ + + int toolbuttonSize = 16; //QApplication::style()->pixelMetric(QStyle::PM_ToolBarIconSize, 0, 0); + + if (!d->contextSize) { + + d->contextSize = new QMenu(i18n("Icon Size"), this); + d->contextIconSizes.insert(d->contextSize->addAction(i18nc("@item:inmenu Icon size", "Default"), + this, SLOT(slotContextIconSize())), + toolbuttonSize); + + QList sizes; + sizes << 12 << 14 << 16 << 22 << 32 << 48 << 64; //<< 96 << 128 << 192 << 256; + foreach(int i, sizes) { + d->contextIconSizes.insert(d->contextSize->addAction(i18n("%1x%2", i, i), this, SLOT(slotContextIconSize())), i); + } + + QActionGroup *sizeGroup = new QActionGroup(d->contextSize); + foreach (QAction *action, d->contextSize->actions()) { + action->setActionGroup(sizeGroup); + action->setCheckable(true); + } + } + + KConfigGroup cfg = KGlobal::config()->group("KoToolBox"); + toolbuttonSize = cfg.readEntry("iconSize", toolbuttonSize); + + QMapIterator< QAction*, int > it = d->contextIconSizes; + while (it.hasNext()) { + it.next(); + if (it.value() == toolbuttonSize) { + it.key()->setChecked(true); + break; + } + } + + d->contextSize->exec(event->globalPos()); +} diff --git a/libs/widgets/KoToolBoxDocker.cpp b/libs/widgets/KoToolBoxDocker.cpp index 43fc2292fef..8fe7cfd959c 100644 --- a/libs/widgets/KoToolBoxDocker.cpp +++ b/libs/widgets/KoToolBoxDocker.cpp @@ -1,67 +1,68 @@ /* * Copyright (c) 2005-2009 Thomas Zander * Copyright (c) 2009 Peter Simonsson * Copyright (c) 2010 Cyrille Berger * * 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 "KoToolBoxDocker_p.h" #include "KoToolBox_p.h" #include #include KoToolBoxDocker::KoToolBoxDocker(KoToolBox *toolBox) - : m_toolBox(toolBox) + : QDockWidget(i18n("Toolbox")) + , m_toolBox(toolBox) { setFeatures(QDockWidget::DockWidgetMovable | QDockWidget::DockWidgetFloatable); setWidget(toolBox); connect(this, SIGNAL(dockLocationChanged(Qt::DockWidgetArea)), this, SLOT(updateToolBoxOrientation(Qt::DockWidgetArea))); connect(this, SIGNAL(topLevelChanged(bool)), this, SLOT(updateFloating(bool))); KoDockWidgetTitleBar* titleBar = new KoDockWidgetTitleBar(this); titleBar->setTextVisibilityMode(KoDockWidgetTitleBar::TextCanBeInvisible); titleBar->setToolTip(i18n("Tools")); setTitleBarWidget(titleBar); } void KoToolBoxDocker::setCanvas(KoCanvasBase *canvas) { setEnabled(canvas != 0); } void KoToolBoxDocker::unsetCanvas() { setEnabled(false); } void KoToolBoxDocker::updateToolBoxOrientation(Qt::DockWidgetArea area) { if (area == Qt::TopDockWidgetArea || area == Qt::BottomDockWidgetArea) { m_toolBox->setOrientation(Qt::Horizontal); } else { m_toolBox->setOrientation(Qt::Vertical); } m_toolBox->setFloating(area == Qt::NoDockWidgetArea); } void KoToolBoxDocker::updateFloating(bool v) { m_toolBox->setFloating(v); } diff --git a/libs/widgets/KoToolBoxFactory.cpp b/libs/widgets/KoToolBoxFactory.cpp index 5dfc1264560..6d267830f9e 100644 --- a/libs/widgets/KoToolBoxFactory.cpp +++ b/libs/widgets/KoToolBoxFactory.cpp @@ -1,49 +1,49 @@ /* * Copyright (c) 2006 Peter Simonsson * * 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 "KoToolBoxFactory.h" #include "KoToolBox_p.h" #include "KoToolBoxDocker_p.h" KoToolBoxFactory::KoToolBoxFactory() { } KoToolBoxFactory::~KoToolBoxFactory() { } QString KoToolBoxFactory::id() const { return QLatin1String("ToolBox"); } KoDockFactoryBase::DockPosition KoToolBoxFactory::defaultDockPosition() const { return KoDockFactoryBase::DockLeft; } QDockWidget* KoToolBoxFactory::createDockWidget() { KoToolBox *box = new KoToolBox(); KoToolBoxDocker *docker = new KoToolBoxDocker(box); - docker->setObjectName(QLatin1String("ToolBox")); + docker->setObjectName(id()); return docker; } diff --git a/libs/widgets/KoToolBoxLayout_p.h b/libs/widgets/KoToolBoxLayout_p.h index dc02f5d595a..c71ab465075 100644 --- a/libs/widgets/KoToolBoxLayout_p.h +++ b/libs/widgets/KoToolBoxLayout_p.h @@ -1,340 +1,351 @@ /* * Copyright (c) 2005-2009 Thomas Zander * Copyright (c) 2009 Peter Simonsson * Copyright (c) 2010 Cyrille Berger * * 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 _KO_TOOLBOX_LAYOUT_H_ #define _KO_TOOLBOX_LAYOUT_H_ #include #include #include #include #include - +#include +#include class SectionLayout : public QLayout { public: explicit SectionLayout(QWidget *parent) : QLayout(parent), m_orientation(Qt::Vertical) { } ~SectionLayout() { qDeleteAll( m_items ); m_items.clear(); } void addButton(QAbstractButton *button, int priority) { addChildWidget(button); m_priorities.insert(button, priority); int index = 1; foreach(QWidgetItem *item, m_items) { if (m_priorities.value(static_cast(item->widget())) > priority) break; index++; } m_items.insert(index-1, new QWidgetItem(button)); } QSize sizeHint() const { Q_ASSERT(0); return QSize(); } void addItem(QLayoutItem*) { Q_ASSERT(0); } + QLayoutItem* itemAt(int i) const { if (m_items.count() <= i) return 0; return m_items.at(i); } QLayoutItem* takeAt(int i) { return m_items.takeAt(i); } + int count() const { return m_items.count(); } void setGeometry (const QRect &rect) { int x = 0; int y = 0; const QSize &size = buttonSize(); if (m_orientation == Qt::Vertical) { foreach (QWidgetItem* w, m_items) { if (w->isEmpty()) continue; w->widget()->setGeometry(QRect(x, y, size.width(), size.height())); x += size.width(); if (x + size.width() > rect.width()) { x = 0; y += size.height(); } } } else { foreach (QWidgetItem* w, m_items) { if (w->isEmpty()) continue; w->widget()->setGeometry(QRect(x, y, size.width(), size.height())); y += size.height(); if (y + size.height() > rect.height()) { x += size.width(); y = 0; } } } } + void setButtonSize(const QSize size) + { + m_buttonSize = size; + } + const QSize &buttonSize() const { - if (!m_items.isEmpty() && ! m_buttonSize.isValid()) - const_cast (this)->m_buttonSize = m_items[0]->widget()->sizeHint(); return m_buttonSize; } void setOrientation (Qt::Orientation orientation) { m_orientation = orientation; } private: QSize m_buttonSize; QMap m_priorities; QList m_items; Qt::Orientation m_orientation; }; class Section : public QWidget { public: enum SeparatorFlag { SeparatorTop = 0x0001,/* SeparatorBottom = 0x0002, SeparatorRight = 0x0004,*/ SeparatorLeft = 0x0008 }; Q_DECLARE_FLAGS(Separators, SeparatorFlag) explicit Section(QWidget *parent = 0) : QWidget(parent), m_layout(new SectionLayout(this)) { setLayout(m_layout); } void addButton(QAbstractButton *button, int priority) { m_layout->addButton(button, priority); } void setName(const QString &name) { m_name = name; } QString name() const { return m_name; } + void setButtonSize(QSize size) + { + m_layout->setButtonSize(size); + } + QSize iconSize() const { return m_layout->buttonSize(); } int visibleButtonCount() const { int count = 0; for(int i = m_layout->count()-1; i >= 0; --i) { if (! static_cast (m_layout->itemAt(i))->isEmpty()) ++count; } return count; } void setSeparator(Separators separators) { m_separators = separators; } Separators separators() const { return m_separators; } void setOrientation (Qt::Orientation orientation) { m_layout->setOrientation(orientation); } private: SectionLayout *m_layout; QString m_name; Separators m_separators; }; Q_DECLARE_OPERATORS_FOR_FLAGS(Section::Separators) class KoToolBoxLayout : public QLayout { public: explicit KoToolBoxLayout(QWidget *parent) : QLayout(parent), m_orientation(Qt::Vertical), m_currentHeight(0) { setSpacing(6); } ~KoToolBoxLayout() { qDeleteAll( m_sections ); m_sections.clear(); } QSize sizeHint() const { if (m_sections.isEmpty()) return QSize(); QSize oneIcon = static_cast (m_sections[0]->widget())->iconSize(); return oneIcon; } QSize minimumSize() const { QSize s = sizeHint(); if (m_orientation == Qt::Vertical) { s.setHeight(m_currentHeight); } else { s.setWidth(m_currentHeight); } return s; } void addSection(Section *section) { addChildWidget(section); QList::iterator iterator = m_sections.begin(); int defaults = 2; // skip the first two as they are the 'main' and 'dynamic' sections. while (iterator != m_sections.end()) { if (--defaults < 0 && static_cast ((*iterator)->widget())->name() > section->name()) break; ++iterator; } m_sections.insert(iterator, new QWidgetItem(section)); } void addItem(QLayoutItem*) { Q_ASSERT(0); // don't let anything else be added. (code depends on this!) } QLayoutItem* itemAt(int i) const { if (m_sections.count() >= i) return 0; return m_sections.at(i); } QLayoutItem* takeAt(int i) { return m_sections.takeAt(i); } int count() const { return m_sections.count(); } void setGeometry (const QRect &rect) { // nothing to do? if (m_sections.isEmpty()) { m_currentHeight = 0; return; } // the names of the variables assume a vertical orientation, // but all calculations are done based on the real orientation const QSize iconSize = static_cast (m_sections.first()->widget())->iconSize(); const int maxWidth = (m_orientation == Qt::Vertical) ? rect.width() : rect.height(); // using min 1 as width to e.g. protect against div by 0 below const int iconWidth = qMax(1, (m_orientation == Qt::Vertical) ? iconSize.width() : iconSize.height()); const int iconHeight = qMax(1, (m_orientation == Qt::Vertical) ? iconSize.height() : iconSize.width()); const int maxColumns = qMax(1, (maxWidth / iconWidth)); int x = 0; int y = 0; bool firstSection = true; foreach (QWidgetItem *wi, m_sections) { Section *section = static_cast (wi->widget()); const int buttonCount = section->visibleButtonCount(); if (buttonCount == 0) { // move out of view, not perfect TODO: better solution section->setGeometry(1000, 1000, 0, 0); continue; } // rows needed for the buttons (calculation gets the ceiling value of the plain div) const int neededRowCount = ((buttonCount-1) / maxColumns) + 1; const int availableButtonCount = (maxWidth - x + 1) / iconWidth; if (firstSection) { firstSection = false; } else if (buttonCount > availableButtonCount) { // start on a new row, set separator x = 0; y += iconHeight + spacing(); const Section::Separators separator = (m_orientation == Qt::Vertical) ? Section::SeparatorTop : Section::SeparatorLeft; section->setSeparator( separator ); } else { // append to last row, set separators (on first row only to the left side) const bool isFirstRow = (y == 0); const Section::Separators separators = isFirstRow ? ((m_orientation == Qt::Vertical) ? Section::SeparatorLeft : Section::SeparatorTop) : (Section::SeparatorTop | Section::SeparatorLeft); section->setSeparator( separators ); } const int usedColumns = qMin(buttonCount, maxColumns); if (m_orientation == Qt::Vertical) { section->setGeometry(x, y, usedColumns * iconWidth, neededRowCount * iconHeight); } else { section->setGeometry(y, x, neededRowCount * iconHeight, usedColumns * iconWidth); } // advance by the icons in the last row const int lastRowColumnCount = buttonCount - ((neededRowCount-1) * maxColumns); x += (lastRowColumnCount * iconWidth) + spacing(); // advance by all but the last used row y += (neededRowCount - 1) * iconHeight; } // cache total height (or width), adding the iconHeight for the current row m_currentHeight = y + iconHeight; } void setOrientation (Qt::Orientation orientation) { m_orientation = orientation; invalidate(); } private: QList m_sections; Qt::Orientation m_orientation; mutable int m_currentHeight; }; #endif diff --git a/libs/widgets/KoToolBox_p.h b/libs/widgets/KoToolBox_p.h index f401ea1f711..7a0b3c17310 100644 --- a/libs/widgets/KoToolBox_p.h +++ b/libs/widgets/KoToolBox_p.h @@ -1,118 +1,122 @@ /* * Copyright (c) 2005 Boudewijn Rempt * Copyright (c) 2005-2008 Thomas Zander * Copyright (c) 2009 Peter Simonsson * Copyright (c) 2010 Cyrille Berger * * 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 _KO_TOOLBOX_H_ #define _KO_TOOLBOX_H_ #include #include #include #include class QToolButton; class KoCanvasController; class KoShapeLayer; /** * KoToolBox is a dock widget that can order tools according to type and * priority. * * The ToolBox is a container for tool buttons which are themselves * divided into sections. * * Adding buttons using addButton() will allow you to show those buttons. You should connect * the button to your handling method yourself. * * The unique property of this toolbox is that it can be shown horizontal as well as vertical, * rotating in a smart way to show the buttons optimally. * @see KoToolManager */ class KoToolBox : public QWidget { Q_OBJECT public: /// constructor explicit KoToolBox(); ~KoToolBox(); /** * Add a button to the toolbox. * The buttons should all be added before the first showing since adding will not really add * them to the UI until setup() is called. * * @param button the new button. Please make sure you connect to the button yourself. * @param section the section in which this button will be shown. Each section will be its own * widget. * @param priority the priority in the section. Lowest value means it will be shown first. * @param buttonGroupId if passed this will allow you to use setActiveTool() to trigger * this button * @see setup() */ void addButton(QToolButton *button, const QString §ion, int priority, int buttonGroupId=-1); public Q_SLOTS: /** * Using the buttongroup id passed in addButton() you can set the new active button. * If the id does not resolve to a visible button, this call is ignored. * @param canvas the currently active canvas. * @param id an id to identify the button to activate. */ void setActiveTool(KoCanvasController *canvas, int id); /** * Show only the dynamic buttons that have a code from parameter codes. * The toolbox allows buttons to be optionally registered with a visibilityCode. This code * can be passed here and all buttons that have that code are shown. All buttons that * have another visibility code registered are hidden. * @param canvas the currently active canvas. * @param codes a list of all the codes to show. */ void setButtonsVisible(const QList &codes); /// Set the orientation of the layout to @p orientation void setOrientation(Qt::Orientation orientation); void setFloating(bool v); private Q_SLOTS: void setCurrentLayer(const KoCanvasController *canvas, const KoShapeLayer* newLayer); /// add a tool post-initialization. The tool will also be activated. void toolAdded(const KoToolButton &button, KoCanvasController *canvas); /// resize the toolbox to show the icons without any gap at the edge void adjustToFit(); /// unlocks the with after adjustToFit void resizeUnlock(); + + /// set the icon size for all the buttons + void slotContextIconSize(); + protected: void paintEvent(QPaintEvent *event); -protected: void resizeEvent(QResizeEvent* event); + void contextMenuEvent(QContextMenuEvent *event); private: class Private; Private * const d; }; #endif // _KO_TOOLBOX_H_