diff --git a/libs/ui/KisPaletteModel.cpp b/libs/ui/KisPaletteModel.cpp index b5c4df2955..97cf1dd144 100644 --- a/libs/ui/KisPaletteModel.cpp +++ b/libs/ui/KisPaletteModel.cpp @@ -1,542 +1,578 @@ /* * 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. */ #include "KisPaletteModel.h" #include #include #include #include #include #include #include #include #include #include KisPaletteModel::KisPaletteModel(QObject* parent) : QAbstractTableModel(parent), m_colorSet(0), m_displayRenderer(KoDumbColorDisplayRenderer::instance()) { } KisPaletteModel::~KisPaletteModel() { } void KisPaletteModel::setDisplayRenderer(KoColorDisplayRendererInterface *displayRenderer) { if (displayRenderer) { if (m_displayRenderer) { disconnect(m_displayRenderer, 0, this, 0); } m_displayRenderer = displayRenderer; connect(m_displayRenderer, SIGNAL(displayConfigurationChanged()), SLOT(slotDisplayConfigurationChanged())); } else { m_displayRenderer = KoDumbColorDisplayRenderer::instance(); } } void KisPaletteModel::slotDisplayConfigurationChanged() { reset(); } QModelIndex KisPaletteModel::getLastEntryIndex() { int endRow = rowCount(); int endColumn = columnCount(); QModelIndex i = this->index(endRow, endColumn, QModelIndex()); while (qVariantValue(i.data(RetrieveEntryRole)).isEmpty()) { i = this->index(endRow, endColumn); endColumn -=1; if (endColumn<0) { endColumn = columnCount(); endRow-=1; } } return i; } QVariant KisPaletteModel::data(const QModelIndex& index, int role) const { KoColorSetEntry entry; if (m_colorSet && m_displayRenderer) { //now to figure out whether we have a groupname row or not. bool groupNameRow = false; quint32 indexInGroup = 0; QString indexGroupName = QString(); int rowstotal = m_colorSet->nColorsGroup()/columnCount(); - if (index.row()<=rowstotal) { + if (index.row()<=rowstotal && (quint32)(index.row()*columnCount()+index.column())nColorsGroup()) { indexInGroup = (quint32)(index.row()*columnCount()+index.column()); } + if (m_colorSet->nColorsGroup()==0) { + rowstotal+=1; //always add one for the default group when considering groups. + } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } + if (newrows==0) { + newrows+=1; //always add one for the group when considering groups. + } + quint32 tempIndex = (quint32)((index.row()-(rowstotal+2))*columnCount()+index.column()); if (index.row() == rowstotal+1) { //rowstotal+1 is taken up by the groupname. indexGroupName = groupName; groupNameRow = true; - } else if (index.row() > (rowstotal+1) && index.row() <= rowstotal+newrows){ + } else if (index.row() > (rowstotal+1) && index.row() <= rowstotal+newrows && + tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. indexGroupName = groupName; - indexInGroup = (quint32)((index.row()-(rowstotal+2))*columnCount()+index.column()); + indexInGroup = tempIndex; } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } if (groupNameRow) { switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return indexGroupName; } case IsHeaderRole: { return true; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); entryList.append(QString::number(0)); return entryList; } } } else { if (indexInGroup < m_colorSet->nColorsGroup(indexGroupName)) { entry = m_colorSet->getColorGroup(indexInGroup, indexGroupName); switch (role) { case Qt::ToolTipRole: case Qt::DisplayRole: { return entry.name; } case Qt::BackgroundRole: { QColor color = m_displayRenderer->toQColor(entry.color); return QBrush(color); } case IsHeaderRole: { return false; } case RetrieveEntryRole: { QStringList entryList; entryList.append(indexGroupName); entryList.append(QString::number(indexInGroup)); return entryList; } } } } } return QVariant(); } int KisPaletteModel::rowCount(const QModelIndex& /*parent*/) const { if (!m_colorSet) { return 0; } if (columnCount() > 0) { int countedrows = m_colorSet->nColorsGroup("")/columnCount(); + if (m_colorSet->nColorsGroup()%columnCount() > 0) { + countedrows+=1; + } + if (m_colorSet->nColorsGroup()==0) { + countedrows+=1; + } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()) { countedrows += 1; //add one for the name; - countedrows += (m_colorSet->nColorsGroup(groupName)/ columnCount()); + countedrows += 1+(m_colorSet->nColorsGroup(groupName)/ columnCount()); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { countedrows+=1; } + if (m_colorSet->nColorsGroup(groupName)==0) { + countedrows+=1; + } } countedrows +=1; //Our code up till now doesn't take 0 into account. return countedrows; } return m_colorSet->nColors()/15 + 1; } int KisPaletteModel::columnCount(const QModelIndex& /*parent*/) const { if (m_colorSet && m_colorSet->columnCount() > 0) { return m_colorSet->columnCount(); } return 15; } Qt::ItemFlags KisPaletteModel::flags(const QModelIndex& index) const { if (index.isValid()) { return Qt::ItemIsSelectable | Qt::ItemIsEnabled | Qt::ItemIsUserCheckable | Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled; } return Qt::ItemIsDropEnabled; } QModelIndex KisPaletteModel::index(int row, int column, const QModelIndex& parent) const { if (m_colorSet) { //make an int to hold the amount of rows we've looked at. The initial is the total rows in the default group. int rowstotal = m_colorSet->nColorsGroup()/columnCount(); - if (row<=rowstotal) { + if (row<=rowstotal && (quint32)(row*columnCount()+column)nColorsGroup()) { //if the total rows are in the default group, we just return an index. return QAbstractTableModel::index(row, column, parent); + } else if(row<0 && column<0) { + return QAbstractTableModel::index(0, 0, parent); + } + if (m_colorSet->nColorsGroup()==0) { + rowstotal+=1; //always add one for the default group when considering groups. } Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ //we make an int for the rows added by the current group. - int newrows = 1 + m_colorSet->nColorsGroup(groupName)/columnCount(); + int newrows = 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { newrows+=1; } + if (m_colorSet->nColorsGroup(groupName)==0) { + newrows+=1; //always add one for the group when considering groups. + } if (rowstotal + newrows>rowCount()) { newrows = rowCount() - rowstotal; } + quint32 tempIndex = (quint32)((row-(rowstotal+2))*columnCount()+column); if (row == rowstotal+1) { //rowstotal+1 is taken up by the groupname. return QAbstractTableModel::index(row, 0, parent); - } else if (row > (rowstotal+1) && row <= rowstotal+newrows){ + } else if (row > (rowstotal+1) && row <= rowstotal+newrows && tempIndexnColorsGroup(groupName)){ //otherwise it's an index to the colors in the group. return QAbstractTableModel::index(row, column, parent); } //add the new rows to the totalrows we've looked at. rowstotal += newrows; } } return QModelIndex(); } void KisPaletteModel::setColorSet(KoColorSet* colorSet) { m_colorSet = colorSet; reset(); } KoColorSet* KisPaletteModel::colorSet() const { return m_colorSet; } QModelIndex KisPaletteModel::indexFromId(int i) const { QModelIndex index = QModelIndex(); if (i < (int)colorSet()->nColorsGroup(0)) { index = QAbstractTableModel::index(i/columnCount(), i%columnCount()); + if (!index.isValid()) { + index = QAbstractTableModel::index(0,0,QModelIndex()); + } return index; } else { - int rowstotal = m_colorSet->nColorsGroup()/columnCount(); + int rowstotal = 1+m_colorSet->nColorsGroup()/columnCount(); int totalIndexes = colorSet()->nColorsGroup(); Q_FOREACH (QString groupName, m_colorSet->getGroupNames()){ totalIndexes += colorSet()->nColorsGroup(groupName); if (totalIndexesnColorsGroup(groupName)/columnCount(); + rowstotal += 1+m_colorSet->nColorsGroup(groupName)/columnCount(); if (m_colorSet->nColorsGroup(groupName)%columnCount() > 0) { rowstotal+=1; } rowstotal+=1; } else { index = QAbstractTableModel::index(rowstotal, i-(rowstotal*columnCount())); } } } return index; } int KisPaletteModel::idFromIndex(const QModelIndex &index) const { if (index.isValid()==false || qVariantValue(index.data(IsHeaderRole))) { return -1; } int i=0; QStringList entryList = qVariantValue(data(index, RetrieveEntryRole)); if (entryList.at(0)==QString()) { return entryList.at(1).toUInt(); } i = colorSet()->nColorsGroup(""); //find at which position the group is. int groupIndex = colorSet()->getGroupNames().indexOf(entryList.at(0)); //add all the groupsizes onto it till we get to our group. for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); } //then add the index. i += entryList.at(1).toUInt(); return i; } KoColorSetEntry KisPaletteModel::colorSetEntryFromIndex(const QModelIndex &index) const { QStringList entryList = qVariantValue(data(index, RetrieveEntryRole)); QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); return m_colorSet->getColorGroup(indexInGroup, groupName); } bool KisPaletteModel::addColorSetEntry(KoColorSetEntry entry, QString groupName) { QModelIndex i = getLastEntryIndex(); beginInsertRows(QModelIndex(), i.row(), i.row()+1); m_colorSet->add(entry, groupName); endInsertRows(); return true; } bool KisPaletteModel::removeEntry(QModelIndex index, bool keepColors) { QStringList entryList = qVariantValue(index.data(RetrieveEntryRole)); if (entryList.empty()) { return false; } QString groupName = entryList.at(0); quint32 indexInGroup = entryList.at(1).toUInt(); beginRemoveRows(QModelIndex(), index.row(), index.row()-1); if (qVariantValue(index.data(IsHeaderRole))==false) { m_colorSet->removeAt(indexInGroup, groupName); } else { m_colorSet->removeGroup(groupName, keepColors); } endRemoveRows(); return true; } bool KisPaletteModel::addGroup(QString groupName) { QModelIndex i = getLastEntryIndex(); beginInsertRows(QModelIndex(), i.row(), i.row()+1); m_colorSet->addGroup(groupName); endInsertRows(); return true; } bool KisPaletteModel::removeRows(int row, int count, const QModelIndex &parent) { Q_ASSERT(!parent.isValid()); int beginRow = qMax(0, row); int endRow = qMin(row + count - 1, (int)m_colorSet->nColors() - 1); beginRemoveRows(parent, beginRow, endRow); // Find the palette entry at row, count, remove from KoColorSet endRemoveRows(); return true; } bool KisPaletteModel::dropMimeData(const QMimeData *data, Qt::DropAction action, int row, int column, const QModelIndex &parent) { if (!data->hasFormat("krita/x-colorsetentry") && !data->hasFormat("krita/x-colorsetgroup")) { return false; } if (action == Qt::IgnoreAction) { return false; } int endRow; int endColumn; if (!parent.isValid()) { if (row < 0) { endRow = indexFromId(m_colorSet->nColors()).row(); endColumn = indexFromId(m_colorSet->nColors()).column(); } else { endRow = qMin(row, indexFromId(m_colorSet->nColors()).row()); endColumn = qMin(column, m_colorSet->columnCount()); } } else { endRow = qMin(parent.row(), rowCount()); endColumn = qMin(parent.column(), columnCount()); } if (data->hasFormat("krita/x-colorsetgroup")) { QByteArray encodedData = data->data("krita/x-colorsetgroup"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { QString groupName; stream >> groupName; QModelIndex index = this->index(endRow, 0); if (index.isValid()) { QStringList entryList = qVariantValue(index.data(RetrieveEntryRole)); QString groupDroppedOn = QString(); if (!entryList.isEmpty()) { groupDroppedOn = entryList.at(0); } int groupIndex = colorSet()->getGroupNames().indexOf(groupName); beginMoveRows( QModelIndex(), groupIndex, groupIndex, QModelIndex(), endRow); m_colorSet->moveGroup(groupName, groupDroppedOn); m_colorSet->save(); endMoveRows(); ++endRow; } } } else { QByteArray encodedData = data->data("krita/x-colorsetentry"); QDataStream stream(&encodedData, QIODevice::ReadOnly); while (!stream.atEnd()) { KoColorSetEntry entry; QString oldGroupName; int indexInGroup; QString colorXml; stream >> entry.name >> entry.id >> entry.spotColor >> indexInGroup >> oldGroupName >> colorXml; QDomDocument doc; doc.setContent(colorXml); QDomElement e = doc.documentElement(); QDomElement c = e.firstChildElement(); if (!c.isNull()) { QString colorDepthId = c.attribute("bitdepth", Integer8BitsColorDepthID.id()); entry.color = KoColor::fromXML(c, colorDepthId); } QModelIndex index = this->index(endRow, endColumn); - bool indexTooBig = false; - while (qVariantValue(index.data(RetrieveEntryRole)).isEmpty()) { - index = this->index(endRow, endColumn); - endColumn -=1; - if (endColumn<0) { - endColumn = columnCount(); - endRow-=1; - } - indexTooBig = true; + if (qVariantValue(index.data(IsHeaderRole))){ + endRow+=1; } if (index.isValid()) { /*this is to figure out the row of the old color. * That way we can in turn avoid moverows from complaining the * index is out of bounds when using index. * Makes me wonder if we shouldn't just insert the index of the * old color when requesting the mimetype... */ - int i = colorSet()->nColorsGroup(""); - //find at which position the group is. - int groupIndex = colorSet()->getGroupNames().indexOf(oldGroupName); - //add all the groupsizes onto it till we get to our group. - for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); + int i = indexInGroup; + if (oldGroupName != QString()) { + colorSet()->nColorsGroup(""); + //find at which position the group is. + int groupIndex = colorSet()->getGroupNames().indexOf(oldGroupName); + //add all the groupsizes onto it till we get to our group. + for(int g=0; gnColorsGroup(colorSet()->getGroupNames().at(g)); + } } - i+=indexInGroup; QModelIndex indexOld = indexFromId(i); if (action == Qt::MoveAction){ - beginMoveRows(QModelIndex(), indexOld.row(), indexOld.row(), QModelIndex(), endRow); + if (indexOld.row()!=endRow && indexOld.row()!=qMax(endRow+1,1)) { + beginMoveRows(QModelIndex(), indexOld.row(), indexOld.row(), QModelIndex(), qMax(endRow+1,1)); + } + if (indexOld.column()!=endColumn && indexOld.column()!=qMax(endColumn+1,1)) { + beginMoveColumns(QModelIndex(), indexOld.column(), indexOld.column(), QModelIndex(), qMax(endColumn+1,1)); + } } else { beginInsertRows(QModelIndex(), endRow, endRow); } QStringList entryList = qVariantValue(index.data(RetrieveEntryRole)); QString entryInGroup = "0"; QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); entryInGroup = entryList.at(1); } int location = entryInGroup.toInt(); - if (indexTooBig) { - location+=1; - } // Insert the entry + if (groupName==oldGroupName && qVariantValue(index.data(IsHeaderRole))==true) { + groupName=QString(); + location=m_colorSet->nColorsGroup(); + } m_colorSet->insertBefore(entry, location, groupName); if (groupName==oldGroupName && locationremoveAt(indexInGroup, oldGroupName); } m_colorSet->save(); if (action == Qt::MoveAction){ - endMoveRows(); + if (indexOld.row()!=endRow && indexOld.row()!=qMax(endRow+1,1)) { + endMoveRows(); + } + if (indexOld.column()!=endColumn && indexOld.column()!=qMax(endColumn+1,1)) { + endMoveColumns(); + } + } else { endInsertRows(); } ++endRow; } } } return true; } QMimeData *KisPaletteModel::mimeData(const QModelIndexList &indexes) const { QMimeData *mimeData = new QMimeData(); QByteArray encodedData; QDataStream stream(&encodedData, QIODevice::WriteOnly); QString mimeTypeName = "krita/x-colorsetentry"; //Q_FOREACH(const QModelIndex &index, indexes) { QModelIndex index = indexes.last(); if (index.isValid()) { if (qVariantValue(index.data(IsHeaderRole))==false) { KoColorSetEntry entry = colorSetEntryFromIndex(index); QStringList entryList = qVariantValue(index.data(RetrieveEntryRole)); QString groupName = QString(); int indexInGroup = 0; if (!entryList.isEmpty()) { groupName = entryList.at(0); QString iig = entryList.at(1); indexInGroup = iig.toInt(); } QDomDocument doc; QDomElement root = doc.createElement("Color"); root.setAttribute("bitdepth", entry.color.colorSpace()->colorDepthId().id()); doc.appendChild(root); entry.color.toXML(doc, root); stream << entry.name << entry.id << entry.spotColor << indexInGroup << groupName << doc.toString(); } else { mimeTypeName = "krita/x-colorsetgroup"; QStringList entryList = qVariantValue(index.data(RetrieveEntryRole)); QString groupName = QString(); if (!entryList.isEmpty()) { groupName = entryList.at(0); } stream << groupName; } } mimeData->setData(mimeTypeName, encodedData); return mimeData; } QStringList KisPaletteModel::mimeTypes() const { return QStringList() << "krita/x-colorsetentry" << "krita/x-colorsetgroup"; } Qt::DropActions KisPaletteModel::supportedDropActions() const { return Qt::MoveAction; } diff --git a/libs/ui/input/kis_shortcut_matcher.cpp b/libs/ui/input/kis_shortcut_matcher.cpp index 30760f2d64..87195c82fb 100644 --- a/libs/ui/input/kis_shortcut_matcher.cpp +++ b/libs/ui/input/kis_shortcut_matcher.cpp @@ -1,566 +1,566 @@ /* * 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_shortcut_matcher.h" #include #include #include #include "kis_assert.h" #include "kis_abstract_input_action.h" #include "kis_stroke_shortcut.h" #include "kis_touch_shortcut.h" #ifdef DEBUG_MATCHER #include #define DEBUG_ACTION(text) dbgInput << __FUNCTION__ << "-" << text; #define DEBUG_SHORTCUT(text, shortcut) dbgInput << __FUNCTION__ << "-" << text << "act:" << shortcut->action()->name(); #define DEBUG_KEY(text) dbgInput << __FUNCTION__ << "-" << text << "keys:" << m_d->keys; #define DEBUG_BUTTON_ACTION(text, button) dbgInput << __FUNCTION__ << "-" << text << "button:" << button << "btns:" << m_d->buttons << "keys:" << m_d->keys; #define DEBUG_EVENT_ACTION(text, event) if (event) {dbgInput << __FUNCTION__ << "-" << text << "type:" << event->type();} #else #define DEBUG_ACTION(text) #define DEBUG_KEY(text) #define DEBUG_SHORTCUT(text, shortcut) #define DEBUG_BUTTON_ACTION(text, button) #define DEBUG_EVENT_ACTION(text, event) #endif class Q_DECL_HIDDEN KisShortcutMatcher::Private { public: Private() : runningShortcut(0) , readyShortcut(0) , touchShortcut(0) , suppressAllActions(false) , cursorEntered(false) , usingTouch(false) {} ~Private() { qDeleteAll(singleActionShortcuts); qDeleteAll(strokeShortcuts); qDeleteAll(touchShortcuts); } QList singleActionShortcuts; QList strokeShortcuts; QList touchShortcuts; QSet keys; // Model of currently pressed keys QSet buttons; // Model of currently pressed buttons KisStrokeShortcut *runningShortcut; KisStrokeShortcut *readyShortcut; QList candidateShortcuts; KisTouchShortcut *touchShortcut; bool suppressAllActions; bool cursorEntered; bool usingTouch; inline bool actionsSuppressed() const { return suppressAllActions || !cursorEntered; } inline bool actionsSuppressedIgnoreFocus() const { return suppressAllActions; } }; KisShortcutMatcher::KisShortcutMatcher() : m_d(new Private) {} KisShortcutMatcher::~KisShortcutMatcher() { delete m_d; } bool KisShortcutMatcher::hasRunningShortcut() const { return m_d->runningShortcut; } void KisShortcutMatcher::addShortcut(KisSingleActionShortcut *shortcut) { m_d->singleActionShortcuts.append(shortcut); } void KisShortcutMatcher::addShortcut(KisStrokeShortcut *shortcut) { m_d->strokeShortcuts.append(shortcut); } void KisShortcutMatcher::addShortcut( KisTouchShortcut* shortcut ) { m_d->touchShortcuts.append(shortcut); } bool KisShortcutMatcher::supportsHiResInputEvents() { return m_d->runningShortcut && m_d->runningShortcut->action() && m_d->runningShortcut->action()->supportsHiResInputEvents(); } bool KisShortcutMatcher::keyPressed(Qt::Key key) { bool retval = false; if (m_d->keys.contains(key)) { DEBUG_ACTION("Peculiar, records show key was already pressed"); } if (!m_d->runningShortcut) { retval = tryRunSingleActionShortcutImpl(key, (QEvent*)0, m_d->keys); } m_d->keys.insert(key); DEBUG_KEY("Pressed"); if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } return retval; } bool KisShortcutMatcher::autoRepeatedKeyPressed(Qt::Key key) { bool retval = false; if (!m_d->keys.contains(key)) { DEBUG_ACTION("Peculiar, autorepeated key but can't remember it was pressed"); } if (!m_d->runningShortcut) { // Autorepeated key should not be included in the shortcut QSet filteredKeys = m_d->keys; filteredKeys.remove(key); retval = tryRunSingleActionShortcutImpl(key, (QEvent*)0, filteredKeys); } return retval; } bool KisShortcutMatcher::keyReleased(Qt::Key key) { if (!m_d->keys.contains(key)) reset("Peculiar, key released but can't remember it was pressed"); else m_d->keys.remove(key); if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } return false; } bool KisShortcutMatcher::buttonPressed(Qt::MouseButton button, QEvent *event) { DEBUG_BUTTON_ACTION("entered", button); bool retval = false; if (m_d->usingTouch) { return retval; } if (m_d->buttons.contains(button)) { DEBUG_ACTION("Peculiar, button was already pressed."); } if (!m_d->runningShortcut) { prepareReadyShortcuts(); retval = tryRunReadyShortcut(button, event); } m_d->buttons.insert(button); if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } return retval; } bool KisShortcutMatcher::buttonReleased(Qt::MouseButton button, QEvent *event) { DEBUG_BUTTON_ACTION("entered", button); bool retval = false; if (m_d->usingTouch) { return retval; } if (m_d->runningShortcut && !m_d->readyShortcut) { retval = tryEndRunningShortcut(button, event); DEBUG_BUTTON_ACTION("ended", button); } if (!m_d->buttons.contains(button)) reset("Peculiar, button released but we can't remember it was pressed"); else m_d->buttons.remove(button); if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } return retval; } bool KisShortcutMatcher::wheelEvent(KisSingleActionShortcut::WheelAction wheelAction, QWheelEvent *event) { if (m_d->runningShortcut || m_d->usingTouch) { DEBUG_ACTION("Wheel event canceled."); return false; } return tryRunWheelShortcut(wheelAction, event); } bool KisShortcutMatcher::pointerMoved(QEvent *event) { if (m_d->usingTouch || !m_d->runningShortcut) { return false; } m_d->runningShortcut->action()->inputEvent(event); return true; } void KisShortcutMatcher::enterEvent() { m_d->cursorEntered = true; if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } } void KisShortcutMatcher::leaveEvent() { m_d->cursorEntered = false; if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } } bool KisShortcutMatcher::touchBeginEvent( QTouchEvent* event ) { Q_UNUSED(event) return true; } bool KisShortcutMatcher::touchUpdateEvent( QTouchEvent* event ) { bool retval = false; if( m_d->touchShortcut && !m_d->touchShortcut->match( event ) ) { retval = tryEndTouchShortcut( event ); } if( !m_d->touchShortcut ) { retval = tryRunTouchShortcut( event ); } else { m_d->touchShortcut->action()->inputEvent( event ); retval = true; } return retval; } bool KisShortcutMatcher::touchEndEvent( QTouchEvent* event ) { m_d->usingTouch = false; // we need to say we are done because qt will not send further event // we should try and end the shortcut too (it might be that there is none? (sketch)) if( tryEndTouchShortcut( event ) ) { return true; } return false; } Qt::MouseButtons listToFlags(const QList &list) { Qt::MouseButtons flags; Q_FOREACH (Qt::MouseButton b, list) { flags |= b; } return flags; } void KisShortcutMatcher::reinitialize() { reset("reinitialize"); if (!m_d->runningShortcut) { prepareReadyShortcuts(); tryActivateReadyShortcut(); } } void KisShortcutMatcher::lostFocusEvent(const QPointF &localPos) { if (m_d->runningShortcut) { forceEndRunningShortcut(localPos); } } void KisShortcutMatcher::reset() { m_d->keys.clear(); m_d->buttons.clear(); DEBUG_ACTION("reset!"); } void KisShortcutMatcher::reset(QString msg) { m_d->keys.clear(); m_d->buttons.clear(); Q_UNUSED(msg); DEBUG_ACTION(msg); } void KisShortcutMatcher::suppressAllActions(bool value) { m_d->suppressAllActions = value; } void KisShortcutMatcher::clearShortcuts() { reset("Clearing shortcuts"); qDeleteAll(m_d->singleActionShortcuts); m_d->singleActionShortcuts.clear(); qDeleteAll(m_d->strokeShortcuts); qDeleteAll(m_d->touchShortcuts); m_d->strokeShortcuts.clear(); m_d->candidateShortcuts.clear(); m_d->touchShortcuts.clear(); m_d->runningShortcut = 0; m_d->readyShortcut = 0; } bool KisShortcutMatcher::tryRunWheelShortcut(KisSingleActionShortcut::WheelAction wheelAction, QWheelEvent *event) { return tryRunSingleActionShortcutImpl(wheelAction, event, m_d->keys); } // Note: sometimes event can be zero!! template bool KisShortcutMatcher::tryRunSingleActionShortcutImpl(T param, U *event, const QSet &keysState) { if (m_d->actionsSuppressedIgnoreFocus()) { DEBUG_EVENT_ACTION("Event suppressed", event) return false; } KisSingleActionShortcut *goodCandidate = 0; Q_FOREACH (KisSingleActionShortcut *s, m_d->singleActionShortcuts) { if(s->isAvailable() && s->match(keysState, param) && (!goodCandidate || s->priority() > goodCandidate->priority())) { goodCandidate = s; } } if (goodCandidate) { DEBUG_EVENT_ACTION("Beginning action for event", event) goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event); goodCandidate->action()->end(0); } else { DEBUG_EVENT_ACTION("Could not match a candidate for event", event) } return goodCandidate; } void KisShortcutMatcher::prepareReadyShortcuts() { m_d->candidateShortcuts.clear(); if (m_d->actionsSuppressed()) return; Q_FOREACH (KisStrokeShortcut *s, m_d->strokeShortcuts) { if (s->matchReady(m_d->keys, m_d->buttons)) { m_d->candidateShortcuts.append(s); } } } bool KisShortcutMatcher::tryRunReadyShortcut( Qt::MouseButton button, QEvent* event ) { KisStrokeShortcut *goodCandidate = 0; Q_FOREACH (KisStrokeShortcut *s, m_d->candidateShortcuts) { if (s->isAvailable() && s->matchBegin(button) && (!goodCandidate || s->priority() > goodCandidate->priority())) { goodCandidate = s; } } if (goodCandidate) { if (m_d->readyShortcut) { if (m_d->readyShortcut != goodCandidate) { m_d->readyShortcut->action()->deactivate(m_d->readyShortcut->shortcutIndex()); goodCandidate->action()->activate(goodCandidate->shortcutIndex()); } m_d->readyShortcut = 0; } else { DEBUG_EVENT_ACTION("Matched *new* shortcut for event", event); goodCandidate->action()->activate(goodCandidate->shortcutIndex()); } DEBUG_SHORTCUT("Starting new action", goodCandidate); goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event); m_d->runningShortcut = goodCandidate; } return goodCandidate; } void KisShortcutMatcher::tryActivateReadyShortcut() { KisStrokeShortcut *goodCandidate = 0; Q_FOREACH (KisStrokeShortcut *s, m_d->candidateShortcuts) { if (!goodCandidate || s->priority() > goodCandidate->priority()) { goodCandidate = s; } } if (goodCandidate) { if (m_d->readyShortcut && m_d->readyShortcut != goodCandidate) { DEBUG_SHORTCUT("Deactivated previous shortcut action", m_d->readyShortcut); m_d->readyShortcut->action()->deactivate(m_d->readyShortcut->shortcutIndex()); m_d->readyShortcut = 0; } if (!m_d->readyShortcut) { DEBUG_SHORTCUT("Preparing new ready action", goodCandidate); goodCandidate->action()->activate(goodCandidate->shortcutIndex()); m_d->readyShortcut = goodCandidate; } } else if (m_d->readyShortcut) { DEBUG_SHORTCUT("Deactivating action", m_d->readyShortcut); m_d->readyShortcut->action()->deactivate(m_d->readyShortcut->shortcutIndex()); m_d->readyShortcut = 0; } } bool KisShortcutMatcher::tryEndRunningShortcut( Qt::MouseButton button, QEvent* event ) { Q_ASSERT(m_d->runningShortcut); Q_ASSERT(!m_d->readyShortcut); if (m_d->runningShortcut->matchBegin(button)) { // first reset running shortcut to avoid infinite recursion via end() KisStrokeShortcut *runningShortcut = m_d->runningShortcut; m_d->runningShortcut = 0; if (runningShortcut->action()) { DEBUG_EVENT_ACTION("Ending running shortcut at event", event); KisAbstractInputAction* action = runningShortcut->action(); int shortcutIndex = runningShortcut->shortcutIndex(); action->end(event); action->deactivate(shortcutIndex); } } return !m_d->runningShortcut; } void KisShortcutMatcher::forceEndRunningShortcut(const QPointF &localPos) { KIS_SAFE_ASSERT_RECOVER_RETURN(m_d->runningShortcut); KIS_SAFE_ASSERT_RECOVER_RETURN(!m_d->readyShortcut); // first reset running shortcut to avoid infinite recursion via end() KisStrokeShortcut *runningShortcut = m_d->runningShortcut; m_d->runningShortcut = 0; - if (m_d->runningShortcut->action()) { + if (runningShortcut->action()) { DEBUG_ACTION("Forced ending running shortcut at event"); KisAbstractInputAction* action = runningShortcut->action(); int shortcutIndex = runningShortcut->shortcutIndex(); QMouseEvent event = runningShortcut->fakeEndEvent(localPos); action->end(&event); action->deactivate(shortcutIndex); } } bool KisShortcutMatcher::tryRunTouchShortcut( QTouchEvent* event ) { KisTouchShortcut *goodCandidate = 0; if (m_d->actionsSuppressed()) return false; Q_FOREACH (KisTouchShortcut* shortcut, m_d->touchShortcuts) { if( shortcut->match( event ) && (!goodCandidate || shortcut->priority() > goodCandidate->priority()) ) { goodCandidate = shortcut; } } if( goodCandidate ) { if( m_d->runningShortcut ) { QMouseEvent mouseEvent(QEvent::MouseButtonRelease, event->touchPoints().at(0).pos().toPoint(), Qt::LeftButton, Qt::LeftButton, event->modifiers()); tryEndRunningShortcut(Qt::LeftButton, &mouseEvent); } goodCandidate->action()->activate(goodCandidate->shortcutIndex()); goodCandidate->action()->begin(goodCandidate->shortcutIndex(), event); m_d->touchShortcut = goodCandidate; m_d->usingTouch = true; } return goodCandidate; } bool KisShortcutMatcher::tryEndTouchShortcut( QTouchEvent* event ) { if(m_d->touchShortcut) { // first reset running shortcut to avoid infinite recursion via end() KisTouchShortcut *touchShortcut = m_d->touchShortcut; m_d->touchShortcut = 0; touchShortcut->action()->end(event); touchShortcut->action()->deactivate(m_d->touchShortcut->shortcutIndex()); return true; } return false; } diff --git a/plugins/extensions/pykrita/plugin/plugins/palette_docker/kritapykrita_palette_docker.desktop b/plugins/extensions/pykrita/plugin/plugins/palette_docker/kritapykrita_palette_docker.desktop index dab756003b..42ba662d65 100644 --- a/plugins/extensions/pykrita/plugin/plugins/palette_docker/kritapykrita_palette_docker.desktop +++ b/plugins/extensions/pykrita/plugin/plugins/palette_docker/kritapykrita_palette_docker.desktop @@ -1,7 +1,19 @@ [Desktop Entry] Type=Service ServiceTypes=Krita/PythonPlugin X-KDE-Library=palette_docker X-Python-2-Compatible=false Name=Palette docker +Name[ca]=Acoblador de paletes +Name[nl]=Vastzetter van palet +Name[pt]=Área acoplável da paleta +Name[sv]=Dockningsfönster för palett +Name[uk]=Панель палітри +Name[x-test]=xxPalette dockerxx Comment=A Python-based docker to edit color palettes. +Comment[ca]=Un acoblador basant en el Python per editar paletes de colors. +Comment[nl]=Een op Python gebaseerde vastzetter om kleurpaletten te bewerken. +Comment[pt]=Uma área acoplável, feita em Python, para editar paletas de cores. +Comment[sv]=Ett Python-baserat dockningsfönster för att redigera färgpaletter. +Comment[uk]=Бічна панель для редагування палітр кольорів на основі Python. +Comment[x-test]=xxA Python-based docker to edit color palettes.xx