LCOV - code coverage report
Current view: top level - src/palette/internal - palettemodel.cpp Coverage Total Hit
Test: filtered_coverage.info Lines: 0.0 % 564 0
Test Date: 2026-11-05 04:07:02

            Line data    Source code
       1              : /*
       2              :  * SPDX-License-Identifier: GPL-3.0-only
       3              :  * MuseScore-Studio-CLA-applies
       4              :  *
       5              :  * MuseScore Studio
       6              :  * Music Composition & Notation
       7              :  *
       8              :  * Copyright (C) 2021 MuseScore Limited and others
       9              :  *
      10              :  * This program is free software: you can redistribute it and/or modify
      11              :  * it under the terms of the GNU General Public License version 3 as
      12              :  * published by the Free Software Foundation.
      13              :  *
      14              :  * This program is distributed in the hope that it will be useful,
      15              :  * but WITHOUT ANY WARRANTY; without even the implied warranty of
      16              :  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      17              :  * GNU General Public License for more details.
      18              :  *
      19              :  * You should have received a copy of the GNU General Public License
      20              :  * along with this program.  If not, see <https://www.gnu.org/licenses/>.
      21              :  */
      22              : 
      23              : #include "palettemodel.h"
      24              : 
      25              : #include <QMimeData>
      26              : 
      27              : #include "internal/palettetree.h"
      28              : #include "internal/palettecelliconengine.h"
      29              : 
      30              : #include "engraving/dom/actionicon.h"
      31              : #include "engraving/dom/beam.h"
      32              : #include "engraving/dom/chordrest.h"
      33              : #include "engraving/dom/note.h"
      34              : #include "engraving/dom/select.h"
      35              : 
      36              : #include "modularity/ioc.h"
      37              : #include "translation.h"
      38              : 
      39              : using namespace mu;
      40              : using namespace mu::palette;
      41              : using namespace mu::engraving;
      42              : 
      43              : //---------------------------------------------------------
      44              : //   PaletteTreeModel::PaletteTreeModel
      45              : //---------------------------------------------------------
      46              : 
      47            0 : PaletteTreeModel::PaletteTreeModel(PaletteTreePtr tree, const muse::modularity::ContextPtr& ctx, QObject* parent)
      48            0 :     : QAbstractItemModel(parent), muse::Contextable(ctx), _paletteTree(tree)
      49              : {
      50            0 :     connect(this, &QAbstractItemModel::dataChanged, this, &PaletteTreeModel::onDataChanged);
      51            0 :     connect(this, &QAbstractItemModel::layoutChanged, this, &PaletteTreeModel::setTreeChanged);
      52            0 :     connect(this, &QAbstractItemModel::modelReset, this, &PaletteTreeModel::setTreeChanged);
      53            0 :     connect(this, &QAbstractItemModel::rowsInserted, this, &PaletteTreeModel::setTreeChanged);
      54            0 :     connect(this, &QAbstractItemModel::rowsMoved, this, &PaletteTreeModel::setTreeChanged);
      55            0 :     connect(this, &QAbstractItemModel::rowsRemoved, this, &PaletteTreeModel::setTreeChanged);
      56              : 
      57            0 :     configuration()->colorsChanged().onNotify(this, [this]() {
      58            0 :         notifyAboutCellsChanged(Qt::DecorationRole);
      59            0 :     });
      60            0 : }
      61              : 
      62              : //---------------------------------------------------------
      63              : //   PaletteTreeModel::onDataChanged
      64              : //---------------------------------------------------------
      65              : 
      66            0 : void PaletteTreeModel::onDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight,
      67              :                                      const QVector<int>& roles)
      68              : {
      69              :     Q_UNUSED(topLeft);
      70              :     Q_UNUSED(bottomRight);
      71            0 :     static const std::set<int> nonPersistentRoles({ CellActiveRole, PaletteExpandedRole, Qt::DecorationRole });
      72              : 
      73            0 :     bool treeChanged = false;
      74            0 :     for (int role : roles) {
      75            0 :         if (!nonPersistentRoles.count(role)) {
      76            0 :             treeChanged = true;
      77            0 :             break;
      78              :         }
      79              :     }
      80              : 
      81            0 :     if (treeChanged) {
      82            0 :         setTreeChanged();
      83              :     }
      84            0 : }
      85              : 
      86              : //---------------------------------------------------------
      87              : //   PaletteTreeModel::setTreeChanged
      88              : //---------------------------------------------------------
      89              : 
      90            0 : void PaletteTreeModel::setTreeChanged()
      91              : {
      92            0 :     _treeChanged = true;
      93            0 :     if (!_treeChangedSignalBlocked) {
      94            0 :         emit treeChanged();
      95              :     }
      96            0 : }
      97              : 
      98              : //---------------------------------------------------------
      99              : //   PaletteTreeModel::blockTreeChanged
     100              : //---------------------------------------------------------
     101              : 
     102            0 : bool PaletteTreeModel::blockTreeChanged(bool block)
     103              : {
     104            0 :     const bool wasBlocked = _treeChangedSignalBlocked;
     105            0 :     _treeChangedSignalBlocked = block;
     106              : 
     107            0 :     if (wasBlocked && !block && _treeChanged) {
     108            0 :         emit treeChanged();
     109              :     }
     110              : 
     111            0 :     return wasBlocked;
     112              : }
     113              : 
     114              : //---------------------------------------------------------
     115              : //   PaletteTreeModel::iptrToPalette
     116              : //---------------------------------------------------------
     117              : 
     118            0 : Palette* PaletteTreeModel::iptrToPalette(void* iptr, int* idx)
     119              : {
     120            0 :     const auto palette = std::find_if(palettes().begin(), palettes().end(), [iptr](const PalettePtr& p) {
     121            0 :         return iptr == p.get();
     122              :     });
     123              : 
     124            0 :     if (idx) {
     125            0 :         (*idx) = palette - palettes().begin();
     126              :     }
     127              : 
     128            0 :     if (palette != palettes().end()) {
     129            0 :         return static_cast<Palette*>(iptr);
     130              :     }
     131            0 :     return nullptr;
     132              : }
     133              : 
     134            0 : void PaletteTreeModel::notifyAboutCellsChanged(int changedRole)
     135              : {
     136            0 :     const size_t npalettes = palettes().size();
     137            0 :     for (size_t row = 0; row < npalettes; ++row) {
     138            0 :         Palette* palette = palettes()[row].get();
     139              : 
     140            0 :         const QModelIndex parent = index(int(row), 0, QModelIndex());
     141            0 :         const QModelIndex first = index(0, 0, parent);
     142            0 :         const QModelIndex last = index(palette->cellsCount() - 1, 0, parent);
     143            0 :         emit dataChanged(first, last, { changedRole });
     144              :     }
     145            0 : }
     146              : 
     147              : //---------------------------------------------------------
     148              : //   PaletteTreeModel::findPalette
     149              : //---------------------------------------------------------
     150              : 
     151            0 : const Palette* PaletteTreeModel::findPalette(const QModelIndex& index) const
     152              : {
     153            0 :     if (index.internalPointer() != _paletteTree.get()) {
     154            0 :         return nullptr;
     155              :     }
     156              : 
     157            0 :     const int row = index.row();
     158            0 :     if (index.column() != 0 || row < 0 || row > int(palettes().size())) {
     159            0 :         return nullptr;
     160              :     }
     161              : 
     162            0 :     return palettes()[row].get();
     163              : }
     164              : 
     165              : //---------------------------------------------------------
     166              : //   PaletteTreeModel::findPalette
     167              : //---------------------------------------------------------
     168              : 
     169            0 : Palette* PaletteTreeModel::findPalette(const QModelIndex& index)
     170              : {
     171            0 :     return const_cast<Palette*>(const_cast<const PaletteTreeModel*>(this)->findPalette(index));
     172              : }
     173              : 
     174              : //---------------------------------------------------------
     175              : //   PaletteTreeModel::findCell
     176              : //---------------------------------------------------------
     177              : 
     178            0 : PaletteCellConstPtr PaletteTreeModel::findCell(const QModelIndex& index) const
     179              : {
     180            0 :     if (const Palette* pp = iptrToPalette(index.internalPointer())) {
     181            0 :         const int row = index.row();
     182            0 :         if (index.column() != 0 || row < 0 || row >= pp->cellsCount()) {
     183            0 :             return nullptr;
     184              :         }
     185            0 :         return pp->cellAt(row);
     186              :     }
     187              : 
     188            0 :     return nullptr;
     189              : }
     190              : 
     191              : //---------------------------------------------------------
     192              : //   PaletteTreeModel::findCell
     193              : //---------------------------------------------------------
     194              : 
     195            0 : PaletteCellPtr PaletteTreeModel::findCell(const QModelIndex& index)
     196              : {
     197            0 :     return std::const_pointer_cast<PaletteCell>(const_cast<const PaletteTreeModel*>(this)->findCell(index));
     198              : }
     199              : 
     200              : //---------------------------------------------------------
     201              : //   PaletteTreeModel::setPaletteTree
     202              : //---------------------------------------------------------
     203              : 
     204            0 : void PaletteTreeModel::setPaletteTree(PaletteTreePtr newTree)
     205              : {
     206            0 :     beginResetModel();
     207            0 :     _paletteTree = newTree;
     208            0 :     endResetModel();
     209              : 
     210            0 :     _treeChanged = false;
     211            0 : }
     212              : 
     213              : //---------------------------------------------------------
     214              : //   PaletteTreeModel::index
     215              : //---------------------------------------------------------
     216              : 
     217            0 : QModelIndex PaletteTreeModel::index(int row, int column, const QModelIndex& parent) const
     218              : {
     219            0 :     if (!hasIndex(row, column, parent)) {
     220            0 :         return QModelIndex();
     221              :     }
     222              : 
     223            0 :     if (!parent.isValid()) {
     224            0 :         return createIndex(row, column, const_cast<void*>(static_cast<const void*>(_paletteTree.get())));
     225              :     }
     226              : 
     227            0 :     void* iptr = parent.internalPointer();
     228              : 
     229            0 :     if (iptr == _paletteTree.get()) {
     230            0 :         return createIndex(row, column, palettes()[parent.row()].get());
     231              :     }
     232              : 
     233            0 :     return QModelIndex();
     234              : }
     235              : 
     236              : //---------------------------------------------------------
     237              : //   PaletteTreeModel::parent
     238              : //---------------------------------------------------------
     239              : 
     240            0 : QModelIndex PaletteTreeModel::parent(const QModelIndex& modelIndex) const
     241              : {
     242            0 :     void* iptr = modelIndex.internalPointer();
     243              : 
     244            0 :     if (iptr == _paletteTree.get()) {
     245            0 :         return QModelIndex();
     246              :     }
     247              : 
     248              :     int row;
     249            0 :     if (iptrToPalette(iptr, &row)) {
     250            0 :         return index(row, /* column */ 0, QModelIndex());
     251              :     }
     252              : 
     253            0 :     return QModelIndex();
     254              : }
     255              : 
     256              : //---------------------------------------------------------
     257              : //   PaletteTreeModel::rowCount
     258              : //---------------------------------------------------------
     259              : 
     260            0 : int PaletteTreeModel::rowCount(const QModelIndex& parent) const
     261              : {
     262            0 :     if (!parent.isValid()) {
     263            0 :         return int(palettes().size());
     264              :     }
     265              : 
     266            0 :     void* iptr = parent.internalPointer();
     267              : 
     268            0 :     if (iptr == _paletteTree.get()) {
     269            0 :         const int row = parent.row();
     270            0 :         if (parent.column() != 0 || row < 0 || row >= int(palettes().size())) {
     271            0 :             return 0;
     272              :         }
     273            0 :         return palettes()[row]->cellsCount();
     274              :     }
     275              : 
     276            0 :     return 0;
     277              : }
     278              : 
     279              : //---------------------------------------------------------
     280              : //   PaletteTreeModel::columnCount
     281              : //---------------------------------------------------------
     282              : 
     283            0 : int PaletteTreeModel::columnCount(const QModelIndex& parent) const
     284              : {
     285              :     Q_UNUSED(parent);
     286            0 :     return 1;
     287              : }
     288              : 
     289              : //---------------------------------------------------------
     290              : //   PaletteTreeModel::data
     291              : //---------------------------------------------------------
     292              : 
     293            0 : QVariant PaletteTreeModel::data(const QModelIndex& index, int role) const
     294              : {
     295            0 :     if (const Palette* pp = findPalette(index)) {
     296            0 :         switch (role) {
     297            0 :         case Qt::DisplayRole:
     298              :         case Qt::ToolTipRole:
     299            0 :             return pp->translatedName();
     300            0 :         case Qt::AccessibleTextRole:
     301            0 :             return QString("%1 palette").arg(pp->translatedName());
     302            0 :         case VisibleRole:
     303            0 :             return pp->isVisible();
     304            0 :         case CustomRole:
     305            0 :             return pp->isCustom();
     306            0 :         case EditableRole:
     307            0 :             return pp->isEditable();
     308            0 :         case GridSizeRole:
     309            0 :             return pp->scaledGridSize();
     310            0 :         case DrawGridRole:
     311            0 :             return pp->drawGrid();
     312            0 :         case PaletteExpandedRole:
     313            0 :             return pp->isExpanded();
     314              :         // TODO showMore?
     315            0 :         case PaletteTypeRole:
     316            0 :             return QVariant::fromValue(pp->type());
     317            0 :         case PaletteContentTypeRole:
     318            0 :             return QVariant::fromValue(pp->contentType());
     319              :         }
     320            0 :         return QVariant();
     321              :     }
     322              : 
     323            0 :     if (PaletteCellConstPtr cell = findCell(index)) {
     324            0 :         switch (role) {
     325            0 :         case Qt::DisplayRole:
     326            0 :             return QVariant();             // Don't show element names in
     327              :         // item views (i.e. just show icons). If you need
     328              :         // to know the name, use the ToolTip instead.
     329            0 :         case Qt::ToolTipRole:
     330            0 :             return cell->translatedName();
     331            0 :         case Qt::AccessibleTextRole: {
     332            0 :             QString name = cell->translatedName();
     333              :             //ScoreAccessibility::makeReadable(name); //! TODO
     334            0 :             return name;
     335            0 :         }
     336            0 :         case Qt::DecorationRole: {
     337            0 :             qreal extraMag = 1.0;
     338            0 :             if (const Palette* pp = iptrToPalette(index.internalPointer())) {
     339            0 :                 extraMag = pp->mag();
     340              :             }
     341            0 :             return QIcon(new PaletteCellIconEngine(cell, extraMag * configuration()->paletteScaling()));
     342              :         }
     343            0 :         case PaletteCellRole:
     344            0 :             return QVariant::fromValue(cell.get());
     345            0 :         case VisibleRole:
     346            0 :             return cell->visible;
     347            0 :         case CustomRole:
     348            0 :             return cell->custom;
     349            0 :         case EditableRole: {
     350            0 :             if (const Palette* pp = iptrToPalette(index.internalPointer())) {
     351            0 :                 return pp->isEditable();
     352              :             }
     353            0 :             return false;
     354              :         }
     355            0 :         case MimeDataRole: {
     356            0 :             QVariantMap map;
     357            0 :             if (cell->element) {
     358            0 :                 map[mimeSymbolFormat] = cell->element->mimeData().toQByteArray();
     359              :             }
     360            0 :             map[PaletteCell::mimeDataFormat] = cell->toMimeData();
     361            0 :             return map;
     362            0 :         }
     363            0 :         case CellActiveRole:
     364            0 :             return cell->active;
     365            0 :         default:
     366            0 :             break;
     367              :         }
     368            0 :         return QVariant();
     369            0 :     }
     370              : 
     371              :     // data for root item
     372            0 :     switch (role) {
     373            0 :     case EditableRole:
     374            0 :         return true;
     375            0 :     default:
     376            0 :         break;
     377              :     }
     378              : 
     379            0 :     return QVariant();
     380              : }
     381              : 
     382              : //---------------------------------------------------------
     383              : //   PaletteTreeModel::setData
     384              : //---------------------------------------------------------
     385              : 
     386            0 : bool PaletteTreeModel::setData(const QModelIndex& index, const QVariant& value, int role)
     387              : {
     388            0 :     if (Palette* pp = findPalette(index)) {
     389            0 :         switch (role) {
     390            0 :         case VisibleRole:
     391            0 :             if (value.canConvert<bool>()) {
     392            0 :                 const bool val = value.toBool();
     393            0 :                 if (val != pp->isVisible()) {
     394            0 :                     pp->setVisible(val);
     395            0 :                     emit dataChanged(index, index, { VisibleRole });
     396              :                 }
     397            0 :                 return true;
     398              :             }
     399            0 :             return false;
     400            0 :         case EditableRole:
     401            0 :             if (value.canConvert<bool>()) {
     402            0 :                 const bool val = value.toBool();
     403            0 :                 if (val != pp->isEditable()) {
     404            0 :                     pp->setEditable(val);
     405            0 :                     emit dataChanged(index, index, { EditableRole });
     406              :                     // notify cells editability changed too
     407            0 :                     const QModelIndex childFirstIndex = PaletteTreeModel::index(0, 0, index);
     408            0 :                     const int rows = rowCount(index);
     409            0 :                     const QModelIndex childLastIndex = PaletteTreeModel::index(rows - 1, 0, index);
     410            0 :                     emit dataChanged(childFirstIndex, childLastIndex, { EditableRole });
     411              :                 }
     412            0 :                 return true;
     413              :             }
     414            0 :             return false;
     415            0 :         case PaletteExpandedRole:
     416            0 :             if (value.canConvert<bool>()) {
     417            0 :                 const bool val = value.toBool();
     418            0 :                 if (val != pp->isExpanded()) {
     419            0 :                     const bool singlePalette = configuration()->isSinglePalette().val;
     420              : 
     421            0 :                     if (singlePalette && val) {
     422            0 :                         for (auto& palette : palettes()) {
     423            0 :                             palette->setExpanded(false);
     424              :                         }
     425            0 :                         pp->setExpanded(val);
     426              : 
     427            0 :                         const QModelIndex parent = index.parent();
     428            0 :                         const int rows = rowCount(parent);
     429            0 :                         const QModelIndex first = PaletteTreeModel::index(0, 0, parent);
     430            0 :                         const QModelIndex last = PaletteTreeModel::index(rows - 1, 0, parent);
     431            0 :                         emit dataChanged(first, last, { PaletteExpandedRole });
     432            0 :                     } else {
     433            0 :                         pp->setExpanded(val);
     434            0 :                         emit dataChanged(index, index, { PaletteExpandedRole });
     435              :                     }
     436              :                 }
     437            0 :                 return true;
     438              :             }
     439            0 :             return false;
     440            0 :         case Qt::DisplayRole:
     441            0 :             pp->setName(value.toString());
     442            0 :             emit dataChanged(index, index, { Qt::DisplayRole, Qt::AccessibleTextRole });
     443            0 :             return true;
     444              : //                   case CustomRole:
     445              : //                         if (value.canConvert<bool>()) {
     446              : //                               const bool val = value.toBool();
     447              : //                               if (val != pp->custom()) {
     448              : //                                     pp->setCustom(val);
     449              : //                                     emit dataChanged(index, index, { CustomRole });
     450              : //                                     }
     451              : //                               return true;
     452              : //                               }
     453              : //                         return false;
     454              : //                   case gridSizeRole:
     455              : //                         return pp->gridSize();
     456              : //                   case drawGridRole:
     457              : //                         return pp->drawGrid();
     458            0 :         default:
     459            0 :             break;
     460              :         }
     461            0 :         return false;
     462              :     }
     463              : 
     464            0 :     if (PaletteCellPtr cell = findCell(index)) {
     465            0 :         switch (role) {
     466              : //                   case Qt::DisplayRole:
     467              : //                   case Qt::ToolTipRole:
     468              :         // or EditRole?
     469              : //                         return cell->name;
     470            0 :         case PaletteCellRole: {
     471            0 :             PaletteCell* newCell = value.value<PaletteCell*>();
     472            0 :             if (!newCell) {
     473            0 :                 return false;
     474              :             }
     475            0 :             cell->element = newCell->element;
     476            0 :             cell->untranslatedElement = newCell->untranslatedElement;
     477            0 :             cell->name = newCell->name;
     478            0 :             cell->id = newCell->id;
     479            0 :             emit dataChanged(index, index);
     480            0 :             return true;
     481              :         };
     482            0 :         case VisibleRole:
     483            0 :             if (value.canConvert<bool>()) {
     484            0 :                 const bool val = value.toBool();
     485            0 :                 if (val != cell->visible) {
     486            0 :                     cell->visible = val;
     487            0 :                     emit dataChanged(index, index, { VisibleRole });
     488              :                 }
     489            0 :                 return true;
     490              :             }
     491            0 :             return false;
     492            0 :         case CustomRole:
     493            0 :             if (value.canConvert<bool>()) {
     494            0 :                 const bool val = value.toBool();
     495            0 :                 if (val != cell->custom) {
     496            0 :                     cell->custom = val;
     497            0 :                     emit dataChanged(index, index, { CustomRole });
     498              :                 }
     499            0 :                 return true;
     500              :             }
     501            0 :             return false;
     502            0 :         case MimeDataRole: {
     503            0 :             const QVariantMap map = value.toMap();
     504              : 
     505            0 :             if (map.contains(PaletteCell::mimeDataFormat)) {
     506            0 :                 const QByteArray cellMimeData = map[PaletteCell::mimeDataFormat].toByteArray();
     507            0 :                 PaletteCellPtr newCell(PaletteCell::fromMimeData(cellMimeData, iocContext()));
     508            0 :                 if (!newCell) {
     509            0 :                     return false;
     510              :                 }
     511              : 
     512            0 :                 cell->element = newCell->element;
     513            0 :                 cell->untranslatedElement = newCell->untranslatedElement;
     514            0 :                 cell->name = newCell->name;
     515            0 :                 cell->id = newCell->id;
     516            0 :             } else if (map.contains(mimeSymbolFormat)) {
     517            0 :                 const QByteArray elementMimeData = map[mimeSymbolFormat].toByteArray();
     518            0 :                 PaletteCellPtr newCell = PaletteCell::fromElementMimeData(elementMimeData, iocContext());
     519              : 
     520            0 :                 cell->element = newCell->element;
     521            0 :                 cell->untranslatedElement = newCell->untranslatedElement;
     522            0 :                 cell->name = newCell->name;
     523            0 :                 cell->id = newCell->id;
     524              : 
     525            0 :                 cell->custom = true;               // mark the updated cell custom
     526            0 :             } else {
     527            0 :                 return false;
     528              :             }
     529              : 
     530            0 :             emit dataChanged(index, index);
     531            0 :             return true;
     532            0 :         }
     533            0 :         default:
     534            0 :             break;
     535              :         }
     536            0 :         return false;
     537            0 :     }
     538              : 
     539            0 :     return false;
     540              : }
     541              : 
     542              : //---------------------------------------------------------
     543              : //   PaletteTreeModel::roleNames
     544              : //---------------------------------------------------------
     545              : 
     546            0 : QHash<int, QByteArray> PaletteTreeModel::roleNames() const
     547              : {
     548            0 :     QHash<int, QByteArray> roles(QAbstractItemModel::roleNames());
     549            0 :     roles[MimeDataRole] = "mimeData";
     550            0 :     roles[GridSizeRole] = "gridSize";
     551            0 :     roles[DrawGridRole] = "drawGrid";
     552            0 :     roles[CustomRole] = "custom";
     553            0 :     roles[EditableRole] = "editable";
     554            0 :     roles[PaletteExpandedRole] = "expanded";
     555            0 :     roles[CellActiveRole] = "cellActive";
     556            0 :     roles[Qt::AccessibleTextRole] = "accessibleText";
     557            0 :     return roles;
     558            0 : }
     559              : 
     560              : //---------------------------------------------------------
     561              : //   PaletteTreeModel::flags
     562              : //---------------------------------------------------------
     563              : 
     564            0 : Qt::ItemFlags PaletteTreeModel::flags(const QModelIndex& index) const
     565              : {
     566            0 :     return QAbstractItemModel::flags(index) | Qt::ItemIsDragEnabled;
     567              : }
     568              : 
     569              : //---------------------------------------------------------
     570              : //   PaletteTreeModel::supportedDropActions
     571              : //---------------------------------------------------------
     572              : 
     573            0 : Qt::DropActions PaletteTreeModel::supportedDropActions() const
     574              : {
     575            0 :     return Qt::DropActions(Qt::CopyAction | Qt::MoveAction);
     576              : }
     577              : 
     578              : //---------------------------------------------------------
     579              : //   PaletteTreeModel::mimeData
     580              : //---------------------------------------------------------
     581              : 
     582            0 : QMimeData* PaletteTreeModel::mimeData(const QModelIndexList& indexes) const
     583              : {
     584            0 :     QMimeData* mime = QAbstractItemModel::mimeData(indexes);   // TODO: needed or use only "our" MIME data?
     585              : 
     586            0 :     if (indexes.empty() || indexes.size() > 1) {
     587            0 :         return mime;
     588              :     }
     589              : 
     590            0 :     if (const Palette* pp = findPalette(indexes[0])) {
     591            0 :         mime->setData(Palette::mimeDataFormat, pp->toMimeData());
     592            0 :     } else if (PaletteCellConstPtr cell = findCell(indexes[0])) {
     593            0 :         mime->setData(mimeSymbolFormat, cell->element->mimeData().toQByteArray());
     594            0 :     }
     595              : 
     596            0 :     return mime;
     597              : }
     598              : 
     599              : //---------------------------------------------------------
     600              : //   PaletteTreeModel::mimeTypes
     601              : //---------------------------------------------------------
     602              : 
     603            0 : QStringList PaletteTreeModel::mimeTypes() const
     604              : {
     605            0 :     QStringList types = QAbstractItemModel::mimeTypes();
     606            0 :     types << mimeSymbolFormat;
     607            0 :     return types;
     608            0 : }
     609              : 
     610              : //---------------------------------------------------------
     611              : //   PaletteTreeModel::canDropMimeData
     612              : //---------------------------------------------------------
     613              : 
     614            0 : bool PaletteTreeModel::canDropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
     615              :                                        const QModelIndex& parent) const
     616              : {
     617              :     Q_UNUSED(column);
     618              : 
     619            0 :     if (!parent.isValid()) {
     620            0 :         return (action == Qt::CopyAction) && data->hasFormat(Palette::mimeDataFormat);
     621              :     }
     622              : 
     623            0 :     if (const Palette* pp = findPalette(parent)) {
     624            0 :         if (row < 0 || row > int(pp->cellsCount())) {
     625            0 :             return false;
     626              :         }
     627              : 
     628            0 :         if (data->hasFormat(PaletteCell::mimeDataFormat)) {
     629            0 :             return action & (Qt::CopyAction | Qt::MoveAction);
     630            0 :         } else if (data->hasFormat(mimeSymbolFormat)) {
     631            0 :             return action == Qt::CopyAction;
     632              :         }
     633              :     }
     634            0 :     return false;
     635              : }
     636              : 
     637              : //---------------------------------------------------------
     638              : //   PaletteTreeModel::dropMimeData
     639              : //---------------------------------------------------------
     640              : 
     641            0 : bool PaletteTreeModel::dropMimeData(const QMimeData* data, Qt::DropAction action, int row, int column,
     642              :                                     const QModelIndex& parent)
     643              : {
     644              :     Q_UNUSED(column);   // when dropping at the end of palette, column == -1. Probably an effect of proxy models
     645              : 
     646            0 :     if (!parent.isValid()) {
     647            0 :         if (action != Qt::CopyAction || !data->hasFormat(Palette::mimeDataFormat)) {
     648            0 :             return false;
     649              :         }
     650            0 :         if (row < 0 || row > int(palettes().size())) {
     651            0 :             return false;
     652              :         }
     653              : 
     654            0 :         auto palette = Palette::fromMimeData(data->data(Palette::mimeDataFormat), iocContext());
     655            0 :         if (!palette) {
     656            0 :             return false;
     657              :         }
     658              : 
     659            0 :         beginInsertRows(parent, row, row);
     660            0 :         palettes().insert(palettes().begin() + row, palette);
     661            0 :         endInsertRows();
     662            0 :         return true;
     663            0 :     }
     664              : 
     665            0 :     if (Palette* pp = findPalette(parent)) {
     666            0 :         if (row < 0 || row > int(pp->cellsCount())) {
     667            0 :             return false;
     668              :         }
     669              : 
     670            0 :         PaletteCellPtr cell;
     671              : 
     672            0 :         if (data->hasFormat(PaletteCell::mimeDataFormat)) {
     673            0 :             cell = PaletteCell::fromMimeData(data->data(PaletteCell::mimeDataFormat), iocContext());
     674            0 :             if (action == Qt::CopyAction) {
     675            0 :                 cell->custom = true;
     676              :             }
     677            0 :         } else if (data->hasFormat(mimeSymbolFormat)) {
     678            0 :             cell = PaletteCell::fromElementMimeData(data->data(mimeSymbolFormat), iocContext());
     679            0 :             cell->custom = true;       // the cell is created by dropping an element so it is custom
     680              :         }
     681              : 
     682            0 :         if (!cell) {
     683            0 :             return false;
     684              :         }
     685              : 
     686            0 :         beginInsertRows(parent, row, row);
     687            0 :         pp->insertCell(row, cell);
     688            0 :         endInsertRows();
     689            0 :         return true;
     690            0 :     }
     691            0 :     return false;
     692              : }
     693              : 
     694              : //---------------------------------------------------------
     695              : //   PaletteTreeModel::moveRows
     696              : //---------------------------------------------------------
     697              : 
     698            0 : bool PaletteTreeModel::moveRows(const QModelIndex& sourceParent, int sourceRow, int count,
     699              :                                 const QModelIndex& destinationParent, int destinationChild)
     700              : {
     701            0 :     const bool sameParent = sourceParent == destinationParent;
     702              : 
     703            0 :     if (!sourceParent.isValid()) {
     704              :         // moving palettes
     705            0 :         if (sourceRow + count > int(palettes().size()) || destinationChild >= int(palettes().size())) {
     706            0 :             return false;
     707              :         }
     708              : 
     709            0 :         if (!sameParent) {
     710              :             // Cannot move between different parents, at least for now
     711              :             // TODO: reconsider?
     712            0 :             return false;
     713              :         }
     714              : 
     715              :         // The moved rows are considered to be inserted *before* destinationRow,
     716              :         // so if we want to move a row down in the list within the same parent
     717              :         // then we should increment the destinationChild index.
     718            0 :         const int destinationRow = (destinationChild >= sourceRow) ? destinationChild + 1 : destinationChild;
     719              : 
     720            0 :         if (sameParent && sourceRow == destinationRow) {
     721            0 :             return false;
     722              :         }
     723              : 
     724            0 :         std::vector<PalettePtr> movedPalettes;
     725              : 
     726            0 :         auto srcBegin = palettes().begin() + sourceRow;
     727            0 :         auto srcEnd = srcBegin + count;
     728              : 
     729              :         // As of Qt 5.12, Qt proxy models rebuild the entire index mapping if
     730              :         // layoutChanged() gets emitted (i.e. if begin/endMoveRows() gets called).
     731              :         // Performance is much better when doing remove + insert rows instead.
     732            0 :         beginRemoveRows(sourceParent, sourceRow, sourceRow + count - 1);
     733            0 :         movedPalettes.reserve(count);
     734            0 :         movedPalettes.insert(movedPalettes.end(), std::make_move_iterator(srcBegin), std::make_move_iterator(srcEnd));
     735            0 :         palettes().erase(srcBegin, srcEnd);
     736            0 :         endRemoveRows();
     737              : 
     738            0 :         const int destIdx = (destinationRow < sourceRow) ? destinationRow : (destinationRow - count);
     739            0 :         auto dest = palettes().begin() + destIdx;
     740              : 
     741            0 :         beginInsertRows(destinationParent, destIdx, destIdx + count - 1);
     742            0 :         palettes().insert(dest, std::make_move_iterator(movedPalettes.begin()),
     743              :                           std::make_move_iterator(movedPalettes.end()));
     744            0 :         endInsertRows();
     745              : 
     746            0 :         return true;
     747            0 :     }
     748              : 
     749            0 :     Palette* sourcePalette = findPalette(sourceParent);
     750            0 :     Palette* destPalette = sameParent ? sourcePalette : findPalette(destinationParent);
     751            0 :     if (sourcePalette && destPalette) {
     752              :         // moving palette cells
     753            0 :         if (sourceRow + count > int(sourcePalette->cellsCount()) || destinationChild > int(destPalette->cellsCount())) {
     754            0 :             return false;
     755              :         }
     756              : 
     757              :         // The moved rows are considered to be inserted *before* destinationRow,
     758              :         // so if we want to move a row down in the list within the same parent
     759              :         // then we should increment the destinationChild index.
     760            0 :         const int destinationRow
     761            0 :             = (sameParent && destinationChild >= sourceRow) ? destinationChild + 1 : destinationChild;
     762              : 
     763            0 :         if (sameParent && sourceRow == destinationRow) {
     764            0 :             return false;
     765              :         }
     766              : 
     767              :         // As of Qt 5.12, Qt proxy models rebuild the entire index mapping if
     768              :         // layoutChanged() gets emitted (i.e. if begin/endMoveRows() gets called).
     769              :         // Performance is much better when doing remove + insert rows instead.
     770            0 :         beginRemoveRows(sourceParent, sourceRow, sourceRow + count - 1);
     771            0 :         auto movedCells(sourcePalette->takeCells(sourceRow, count));
     772            0 :         endRemoveRows();
     773              : 
     774            0 :         const int destIdx = (sameParent && destinationRow >= sourceRow) ? (destinationRow - count) : destinationRow;
     775              : 
     776            0 :         beginInsertRows(destinationParent, destIdx, destIdx + count - 1);
     777            0 :         destPalette->insertCells(destIdx, movedCells);
     778            0 :         endInsertRows();
     779              : 
     780            0 :         return true;
     781            0 :     }
     782              : 
     783            0 :     return false;
     784              : }
     785              : 
     786              : //---------------------------------------------------------
     787              : //   PaletteTreeModel::removeRows
     788              : //---------------------------------------------------------
     789              : 
     790            0 : bool PaletteTreeModel::removeRows(int row, int count, const QModelIndex& parent)
     791              : {
     792            0 :     if (!parent.isValid()) {
     793              :         // removing palettes
     794            0 :         if (row < 0 || row + count > int(palettes().size())) {
     795            0 :             return false;
     796              :         }
     797              : 
     798            0 :         beginRemoveRows(parent, row, row + count - 1);
     799            0 :         auto rangeBegin = palettes().begin() + row;
     800            0 :         auto rangeEnd = rangeBegin + count;
     801            0 :         palettes().erase(rangeBegin, rangeEnd);
     802            0 :         endRemoveRows();
     803            0 :         return true;
     804              :     }
     805              : 
     806            0 :     if (Palette* palette = findPalette(parent)) {
     807              :         // removing palette cells
     808            0 :         if (row < 0 || row + count > palette->cellsCount()) {
     809            0 :             return false;
     810              :         }
     811              : 
     812            0 :         beginRemoveRows(parent, row, row + count - 1);
     813            0 :         palette->takeCells(row, count);
     814            0 :         endRemoveRows();
     815            0 :         return true;
     816              :     }
     817              : 
     818            0 :     return false;
     819              : }
     820              : 
     821              : //---------------------------------------------------------
     822              : //   PaletteTreeModel::insertRows
     823              : //---------------------------------------------------------
     824              : 
     825            0 : bool PaletteTreeModel::insertRows(int row, int count, const QModelIndex& parent)
     826              : {
     827            0 :     if (!parent.isValid()) {
     828              :         // inserting palettes
     829            0 :         if (row < 0 || row > int(palettes().size())) {
     830            0 :             return false;
     831              :         }
     832              : 
     833            0 :         beginInsertRows(parent, row, row + count - 1);
     834            0 :         for (int i = 0; i < count; ++i) {
     835            0 :             PalettePtr p = std::make_shared<Palette>(iocContext(), Palette::Type::Custom);
     836            0 :             p->setName(QT_TRANSLATE_NOOP("palette", "Untitled palette"));
     837            0 :             p->setGridSize(QSize(48, 48));
     838            0 :             p->setExpanded(true);
     839            0 :             palettes().insert(palettes().begin() + row, p);
     840            0 :         }
     841            0 :         endInsertRows();
     842            0 :         return true;
     843              :     }
     844              : 
     845            0 :     if (Palette* palette = findPalette(parent)) {
     846              :         // inserting palette cells
     847            0 :         if (row < 0 || row > palette->cellsCount()) {
     848            0 :             return false;
     849              :         }
     850              : 
     851            0 :         beginInsertRows(parent, row, row + count - 1);
     852            0 :         for (int i = 0; i < count; ++i) {
     853            0 :             PaletteCellPtr cell = std::make_shared<PaletteCell>(iocContext(), palette);
     854            0 :             palette->insertCell(row, cell);
     855            0 :         }
     856            0 :         endInsertRows();
     857            0 :         return true;
     858              :     }
     859              : 
     860            0 :     return false;
     861              : }
     862              : 
     863              : //---------------------------------------------------------
     864              : //   PaletteTreeModel::insertPalette
     865              : //---------------------------------------------------------
     866              : 
     867            0 : bool PaletteTreeModel::insertPalette(PalettePtr pp, int row, const QModelIndex& parent)
     868              : {
     869            0 :     if (row < 0 || row > int(palettes().size()) || parent != QModelIndex()) {
     870            0 :         return false;
     871              :     }
     872            0 :     beginInsertRows(parent, row, row);
     873            0 :     palettes().insert(palettes().begin() + row, pp);
     874            0 :     endInsertRows();
     875            0 :     return true;
     876              : }
     877              : 
     878              : //---------------------------------------------------------
     879              : //   PaletteTreeModel::updateCellsState
     880              : //---------------------------------------------------------
     881              : 
     882            0 : void PaletteTreeModel::updateCellsState(const Selection& sel)
     883              : {
     884            0 :     const ChordRest* cr = sel.firstChordRest();
     885            0 :     const BeamMode bm = cr ? cr->beamMode() : BeamMode::NONE;
     886            0 :     const ActionIconType beamActionType = Beam::actionIconTypeForBeamMode(bm);
     887            0 :     bool deactivateAll = !cr;
     888              : 
     889            0 :     for (EngravingItem* e : sel.elements()) {
     890            0 :         if (e->isNote()) {
     891            0 :             e = toNote(e)->chord();
     892              :         }
     893            0 :         if (e->isChordRest()) {
     894            0 :             if (toChordRest(e)->beamMode() != bm) {
     895            0 :                 deactivateAll = true;
     896              :             }
     897              :         }
     898              :     }
     899              : 
     900            0 :     const size_t npalettes = palettes().size();
     901            0 :     for (size_t row = 0; row < npalettes; ++row) {
     902            0 :         Palette* palette = palettes()[row].get();
     903              :         // TODO: should this be turned on for all palettes?
     904            0 :         if (palette->type() != Palette::Type::Beam) {
     905            0 :             continue;
     906              :         }
     907              : 
     908            0 :         for (int ci = 0; ci < palette->cellsCount(); ++ci) {
     909            0 :             PaletteCellPtr cell = palette->cellAt(ci);
     910            0 :             if (deactivateAll) {
     911            0 :                 cell->active = false;
     912            0 :             } else if (cell->element && cell->element->isActionIcon()) {
     913            0 :                 const ActionIcon* action = toActionIcon(cell->element.get());
     914            0 :                 cell->active = (action->actionType() == beamActionType);
     915              :             }
     916            0 :         }
     917              :     }
     918              : 
     919            0 :     notifyAboutCellsChanged(CellActiveRole);
     920            0 : }
     921              : 
     922              : //---------------------------------------------------------
     923              : //   PaletteTreeModel::retranslate
     924              : //---------------------------------------------------------
     925              : 
     926            0 : void PaletteTreeModel::retranslate()
     927              : {
     928            0 :     _paletteTree->retranslate();
     929            0 : }
     930              : 
     931              : //---------------------------------------------------------
     932              : //   PaletteTreeModel::findPaletteCell
     933              : //---------------------------------------------------------
     934              : 
     935            0 : QModelIndex PaletteTreeModel::findPaletteCell(const PaletteCell& cell, const QModelIndex& parent) const
     936              : {
     937            0 :     if (const Palette* pp = findPalette(parent)) {
     938            0 :         const int idx = pp->indexOfCell(cell);
     939            0 :         if (idx == -1) {
     940            0 :             return QModelIndex();
     941              :         }
     942            0 :         return index(idx, /* column */ 0, parent);
     943              :     }
     944            0 :     return QModelIndex();
     945              : }
     946              : 
     947              : //---------------------------------------------------------
     948              : //   PaletteTreeModel::match
     949              : ///   Currently only searching for a given palette cell is
     950              : ///   implemented, for anything else the corresponding
     951              : ///   member function of QAbstractItemModel is used.
     952              : //---------------------------------------------------------
     953              : 
     954            0 : QModelIndexList PaletteTreeModel::match(const QModelIndex& start, int role, const QVariant& value, int hits,
     955              :                                         Qt::MatchFlags flags) const
     956              : {
     957            0 :     if (role != PaletteCellRole || flags != Qt::MatchExactly || hits != 1
     958            0 :         || !value.canConvert<const PaletteCell*>()
     959            0 :         || !findPalette(start.parent())
     960              :         ) {
     961            0 :         return QAbstractItemModel::match(start, role, value, hits, flags);
     962              :     }
     963              : 
     964            0 :     const PaletteCell* cell = value.value<const PaletteCell*>();
     965            0 :     if (!cell) {
     966            0 :         return QModelIndexList();
     967              :     }
     968              : 
     969            0 :     return QModelIndexList({ findPaletteCell(*cell, start.parent()) });
     970              : }
     971              : 
     972              : //---------------------------------------------------------
     973              : //   PaletteTreeModel::itemDataChanged
     974              : //---------------------------------------------------------
     975              : 
     976            0 : void PaletteTreeModel::itemDataChanged(const QModelIndex& idx)
     977              : {
     978            0 :     emit dataChanged(idx, idx);
     979            0 :     if (findPalette(idx)) {
     980              :         // palette cells appearance depends on palette settings
     981            0 :         const QModelIndex childFirstIndex = index(0, 0, idx);
     982            0 :         const int rows = rowCount(idx);
     983            0 :         const QModelIndex childLastIndex = index(rows - 1, 0, idx);
     984            0 :         emit dataChanged(childFirstIndex, childLastIndex, { Qt::DecorationRole });
     985              :     }
     986            0 : }
     987              : 
     988              : //---------------------------------------------------------
     989              : //   PaletteCellFilter::addChainedFilter
     990              : ///   Ownership over the added filter is passed to this
     991              : ///   filter.
     992              : //---------------------------------------------------------
     993              : 
     994            0 : void PaletteCellFilter::addChainedFilter(PaletteCellFilter* newFilter)
     995              : {
     996            0 :     PaletteCellFilter* f = this;
     997            0 :     while (f->chainedFilter) {
     998            0 :         f = f->chainedFilter;
     999              :     }
    1000              : 
    1001            0 :     newFilter->setParent(f);
    1002            0 :     f->chainedFilter = newFilter;
    1003            0 :     connect(newFilter, &PaletteCellFilter::filterChanged, f, &PaletteCellFilter::filterChanged);
    1004            0 : }
    1005              : 
    1006              : //---------------------------------------------------------
    1007              : //   PaletteCellFilter::accept
    1008              : //---------------------------------------------------------
    1009              : 
    1010            0 : bool PaletteCellFilter::accept(const PaletteCell& cell) const
    1011              : {
    1012            0 :     const PaletteCellFilter* f = this;
    1013            0 :     while (f) {
    1014            0 :         if (!f->acceptCell(cell)) {
    1015            0 :             return false;
    1016              :         }
    1017            0 :         f = f->chainedFilter;
    1018              :     }
    1019            0 :     return true;
    1020              : }
    1021              : 
    1022              : //---------------------------------------------------------
    1023              : //   PaletteCellFilter::connectToModel
    1024              : //---------------------------------------------------------
    1025              : 
    1026            0 : void PaletteCellFilter::connectToModel(const QAbstractItemModel* model)
    1027              : {
    1028              : //       TODO: are all these needed?
    1029              : //       columnsInserted(const QModelIndex &parent, int first, int last)
    1030              : //       columnsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int column)
    1031              : //       columnsRemoved(const QModelIndex &parent, int first, int last)
    1032            0 :     connect(model, &QAbstractItemModel::dataChanged, this, &PaletteCellFilter::filterChanged);
    1033              : //       dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = ...)
    1034            0 :     connect(model, &QAbstractItemModel::layoutChanged, this, &PaletteCellFilter::filterChanged);
    1035              : //       layoutChanged(const QList<QPersistentModelIndex> &parents = ..., QAbstractItemModel::LayoutChangeHint hint = ...)
    1036            0 :     connect(model, &QAbstractItemModel::modelReset, this, &PaletteCellFilter::filterChanged);
    1037              : //       modelReset()
    1038            0 :     connect(model, &QAbstractItemModel::rowsInserted, this, &PaletteCellFilter::filterChanged);
    1039              : //       rowsInserted(const QModelIndex &parent, int first, int last)
    1040            0 :     connect(model, &QAbstractItemModel::rowsMoved, this, &PaletteCellFilter::filterChanged);
    1041              : //       rowsMoved(const QModelIndex &parent, int start, int end, const QModelIndex &destination, int row)
    1042            0 :     connect(model, &QAbstractItemModel::rowsRemoved, this, &PaletteCellFilter::filterChanged);
    1043              : //       rowsRemoved(const QModelIndex &parent, int first, int last)
    1044            0 : }
    1045              : 
    1046              : //---------------------------------------------------------
    1047              : //   ExcludePaletteCellFilter
    1048              : //---------------------------------------------------------
    1049              : 
    1050              : class ExcludePaletteCellFilter : public PaletteCellFilter
    1051              : {
    1052              :     const Palette* excludePalette;
    1053              :     const QPersistentModelIndex paletteIndex; // filter is valid as long as this index is valid too
    1054              : 
    1055              : public:
    1056            0 :     ExcludePaletteCellFilter(const Palette* p, QPersistentModelIndex index, QObject* parent = nullptr)
    1057            0 :         : PaletteCellFilter(parent), excludePalette(p), paletteIndex(index) {}
    1058              : 
    1059            0 :     bool acceptCell(const PaletteCell& cell) const override
    1060              :     {
    1061            0 :         return paletteIndex.isValid() && -1 == excludePalette->indexOfCell(cell, /* matchName */ false);
    1062              :     }
    1063              : };
    1064              : 
    1065              : //---------------------------------------------------------
    1066              : //   PaletteTreeModel::getFilter
    1067              : ///   The ownership of the returned filter is passed to a
    1068              : ///   caller.
    1069              : //---------------------------------------------------------
    1070              : 
    1071            0 : PaletteCellFilter* PaletteTreeModel::getFilter(const QModelIndex& index) const
    1072              : {
    1073            0 :     if (const Palette* pp = findPalette(index)) {
    1074            0 :         ExcludePaletteCellFilter* filter = new ExcludePaletteCellFilter(pp, index);
    1075            0 :         filter->connectToModel(this);
    1076            0 :         return filter;
    1077              :     }
    1078              : 
    1079              :     // TODO: make a filter for a single cell?
    1080              : 
    1081            0 :     return nullptr;
    1082              : }
    1083              : 
    1084              : //---------------------------------------------------------
    1085              : //   FilterPaletteTreeModel::FilterPaletteTreeModel
    1086              : //---------------------------------------------------------
    1087              : 
    1088            0 : FilterPaletteTreeModel::FilterPaletteTreeModel(PaletteCellFilter* filter, PaletteTreeModel* model, QObject* parent)
    1089            0 :     : QSortFilterProxyModel(parent), cellFilter(filter)
    1090              : {
    1091            0 :     cellFilter->setParent(this);
    1092              : //       connect(cellFilter, &PaletteCellFilter::filterChanged, this, &QSortFilterProxyModel::invalidate);
    1093            0 :     connect(cellFilter, &PaletteCellFilter::filterChanged, this, &FilterPaletteTreeModel::invalidateFilter);
    1094              : 
    1095            0 :     setSourceModel(model);
    1096            0 : }
    1097              : 
    1098              : //---------------------------------------------------------
    1099              : //   FilterPaletteTreeModel::filterAcceptsRow
    1100              : //---------------------------------------------------------
    1101              : 
    1102            0 : bool FilterPaletteTreeModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
    1103              : {
    1104            0 :     const QModelIndex& cellIndex = sourceModel()->index(sourceRow, /* column */ 0, sourceParent);
    1105            0 :     const QVariant cellData = sourceModel()->data(cellIndex, PaletteTreeModel::PaletteCellRole);
    1106            0 :     const PaletteCell* cell = cellData.value<const PaletteCell*>();
    1107            0 :     if (!cell) { // a palette or just an unrelated model
    1108            0 :         return true;
    1109              :     }
    1110            0 :     return cellFilter->accept(*cell);
    1111            0 : }
    1112              : 
    1113              : //---------------------------------------------------------
    1114              : //   PaletteCellFilterProxyModel::PaletteCellFilterProxyModel
    1115              : //---------------------------------------------------------
    1116              : 
    1117            0 : PaletteCellFilterProxyModel::PaletteCellFilterProxyModel(QObject* parent)
    1118            0 :     : QSortFilterProxyModel(parent)
    1119              : {
    1120            0 :     setFilterRole(Qt::ToolTipRole);   // palette cells have no data for DisplayRole
    1121            0 : }
    1122              : 
    1123              : //---------------------------------------------------------
    1124              : //   PaletteCellFilterProxyModel::filterAcceptsRow
    1125              : //---------------------------------------------------------
    1126              : 
    1127            0 : bool PaletteCellFilterProxyModel::filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const
    1128              : {
    1129            0 :     const QAbstractItemModel* model = sourceModel();
    1130            0 :     const QModelIndex rowIndex = model->index(sourceRow, 0, sourceParent);
    1131            0 :     const int rowCount = model->rowCount(rowIndex);
    1132              : 
    1133            0 :     if (rowCount == 0) {
    1134            0 :         if (QSortFilterProxyModel::filterAcceptsRow(sourceRow, sourceParent)) {
    1135            0 :             return true;
    1136              :         }
    1137              :         // accept row if its parent is accepted by filter: necessary to be able to search by palette name
    1138            0 :         if (sourceParent.isValid()
    1139            0 :             && QSortFilterProxyModel::filterAcceptsRow(sourceParent.row(), sourceParent.parent())) {
    1140            0 :             return true;
    1141              :         }
    1142            0 :         return false;
    1143              :     }
    1144              : 
    1145            0 :     for (int i = 0; i < rowCount; ++i) {
    1146            0 :         if (filterAcceptsRow(i, rowIndex)) {
    1147            0 :             return true;
    1148              :         }
    1149              :     }
    1150              : 
    1151            0 :     return false;
    1152              : }
        

Generated by: LCOV version 2.0-1