File indexing completed on 2024-11-24 03:56:27
0001 /* 0002 * SPDX-FileCopyrightText: 2019-2023 Mattia Basaglia <dev@dragon.best> 0003 * 0004 * SPDX-License-Identifier: GPL-3.0-or-later 0005 */ 0006 0007 #include "keyboard_shortcuts_model.hpp" 0008 #include "app/widgets/clearable_keysequence_edit.hpp" 0009 0010 app::settings::KeyboardShortcutsModel::KeyboardShortcutsModel(app::settings::ShortcutSettings* settings, QObject* parent) 0011 : QAbstractItemModel(parent), settings(settings) 0012 {} 0013 0014 int app::settings::KeyboardShortcutsModel::columnCount(const QModelIndex&) const 0015 { 0016 return 2; 0017 } 0018 0019 int app::settings::KeyboardShortcutsModel::rowCount(const QModelIndex& parent) const 0020 { 0021 if ( !parent.isValid() ) 0022 return settings->get_groups().size(); 0023 0024 if ( !parent.parent().isValid() && parent.row() < settings->get_groups().size() ) 0025 { 0026 auto& grp = settings->get_groups()[parent.row()]; 0027 return grp.actions.size(); 0028 } 0029 0030 return 0; 0031 } 0032 0033 QVariant app::settings::KeyboardShortcutsModel::headerData(int section, Qt::Orientation orientation, int role) const 0034 { 0035 if ( orientation == Qt::Horizontal && role == Qt::DisplayRole ) 0036 return section == 0 ? tr("Name") : tr("Shortcut"); 0037 return {}; 0038 } 0039 0040 Qt::ItemFlags app::settings::KeyboardShortcutsModel::flags(const QModelIndex& index) const 0041 { 0042 auto flags = QAbstractItemModel::flags(index); 0043 0044 if ( index.isValid() && index.parent().isValid() && index.column() == 1 ) 0045 flags |= Qt::ItemIsEditable; 0046 0047 return flags; 0048 } 0049 0050 QVariant app::settings::KeyboardShortcutsModel::data(const QModelIndex& index, int role) const 0051 { 0052 if ( !index.isValid() ) 0053 return {}; 0054 0055 if ( !index.parent().isValid() ) 0056 { 0057 if ( role != Qt::DisplayRole || index.column() != 0 || index.row() >= settings->get_groups().size() ) 0058 return {}; 0059 0060 auto& grp = settings->get_groups()[index.row()]; 0061 return grp.label; 0062 } 0063 0064 int grp_index = index.internalId(); 0065 if ( grp_index >= settings->get_groups().size() ) 0066 return {}; 0067 0068 auto& grp = settings->get_groups()[grp_index]; 0069 if ( index.row() >= int(grp.actions.size()) ) 0070 return {}; 0071 0072 auto act = grp.actions[index.row()]; 0073 if ( index.column() == 0 ) 0074 { 0075 switch ( role ) 0076 { 0077 case Qt::DisplayRole: 0078 return act->label; 0079 case Qt::DecorationRole: 0080 return act->icon; 0081 default: 0082 return {}; 0083 } 0084 } 0085 else 0086 { 0087 switch ( role ) 0088 { 0089 case Qt::DisplayRole: 0090 case Qt::EditRole: 0091 return act->shortcut; 0092 case DefaultKeyRole: 0093 return act->default_shortcut; 0094 default: 0095 return {}; 0096 } 0097 } 0098 } 0099 0100 bool app::settings::KeyboardShortcutsModel::setData(const QModelIndex& index, const QVariant& value, int role) 0101 { 0102 if ( !index.isValid() ) 0103 return false; 0104 0105 if ( !index.parent().isValid() ) 0106 return false; 0107 0108 int grp_index = index.internalId(); 0109 if ( grp_index >= settings->get_groups().size() ) 0110 return false; 0111 0112 if ( index.column() != 1 || role != Qt::EditRole ) 0113 return false; 0114 0115 auto& grp = settings->get_groups()[grp_index]; 0116 if ( index.row() >= int(grp.actions.size()) ) 0117 return false; 0118 0119 auto act = grp.actions[index.row()]; 0120 0121 QKeySequence ks; 0122 0123 if ( value.canConvert<QKeySequence>() ) 0124 ks = value.value<QKeySequence>(); 0125 else if ( value.canConvert<QString>() ) 0126 ks = QKeySequence(value.toString(), QKeySequence::PortableText); 0127 else 0128 return false; 0129 0130 act->overwritten = ks != act->default_shortcut; 0131 act->shortcut = ks; 0132 if ( act->action ) 0133 act->action->setShortcut(ks); 0134 Q_EMIT dataChanged(index, index, {role}); 0135 return true; 0136 } 0137 0138 0139 QModelIndex app::settings::KeyboardShortcutsModel::index(int row, int column, const QModelIndex& parent) const 0140 { 0141 if ( !parent.isValid() ) 0142 { 0143 if ( row >= settings->get_groups().size() ) 0144 return {}; 0145 return createIndex(row, column, 1000 + row); 0146 } 0147 0148 return createIndex(row, column, parent.internalId()-1000); 0149 } 0150 0151 QModelIndex app::settings::KeyboardShortcutsModel::parent(const QModelIndex& child) const 0152 { 0153 if ( !child.isValid() ) 0154 return {}; 0155 0156 int id = child.internalId(); 0157 if ( id >= 1000 ) 0158 return {}; 0159 0160 return createIndex(id, 0, id+1000); 0161 } 0162 0163 app::settings::ShortcutAction * app::settings::KeyboardShortcutsModel::action(const QModelIndex& index) const 0164 { 0165 if ( !index.isValid() ) 0166 return nullptr; 0167 0168 if ( !index.parent().isValid() ) 0169 return nullptr; 0170 0171 int grp_index = index.internalId(); 0172 if ( grp_index >= settings->get_groups().size() ) 0173 return nullptr; 0174 0175 auto& grp = settings->get_groups()[grp_index]; 0176 if ( index.row() >= int(grp.actions.size()) ) 0177 return nullptr; 0178 0179 return grp.actions[index.row()]; 0180 } 0181 0182 void app::settings::KeyboardShortcutsModel::begin_change_data() 0183 { 0184 Q_EMIT beginResetModel(); 0185 } 0186 0187 void app::settings::KeyboardShortcutsModel::end_change_data() 0188 { 0189 Q_EMIT endResetModel(); 0190 } 0191 0192 bool app::settings::KeyboardShortcutsFilterModel::filterAcceptsRow(int source_row, const QModelIndex& source_parent) const 0193 { 0194 if ( !source_parent.isValid() ) 0195 return true; 0196 0197 #if QT_VERSION_MAJOR >= 6 0198 auto re = filterRegularExpression(); 0199 #else 0200 auto re = filterRegExp(); 0201 #endif 0202 0203 QModelIndex i0 = sourceModel()->index(source_row, 0, source_parent); 0204 QModelIndex i1 = sourceModel()->index(source_row, 1, source_parent); 0205 0206 return sourceModel()->data(i0).toString().contains(re) || sourceModel()->data(i1).toString().contains(re); 0207 } 0208 0209 QWidget * app::settings::KeyboardShortcutsDelegate::createEditor(QWidget* parent, const QStyleOptionViewItem& option, const QModelIndex& index) const 0210 { 0211 if ( index.data(Qt::EditRole).canConvert<QKeySequence>() ) 0212 return new ClearableKeysequenceEdit(parent); 0213 return QStyledItemDelegate::createEditor(parent, option, index); 0214 } 0215 0216 void app::settings::KeyboardShortcutsDelegate::setEditorData(QWidget* editor, const QModelIndex& index) const 0217 { 0218 QVariant edit_data = index.data(Qt::EditRole); 0219 if ( edit_data.canConvert<QKeySequence>() ) 0220 { 0221 ClearableKeysequenceEdit* widget = static_cast<ClearableKeysequenceEdit*>(editor); 0222 widget->set_key_sequence(edit_data.value<QKeySequence>()); 0223 QVariant default_data = index.data(KeyboardShortcutsModel::DefaultKeyRole); 0224 if ( default_data.canConvert<QKeySequence>() ) 0225 widget->set_default_key_sequence(default_data.value<QKeySequence>()); 0226 } 0227 return QStyledItemDelegate::setEditorData(editor, index); 0228 } 0229 0230 void app::settings::KeyboardShortcutsDelegate::setModelData(QWidget* editor, QAbstractItemModel* model, const QModelIndex& index) const 0231 { 0232 if ( index.data(Qt::EditRole).canConvert<QKeySequence>() ) 0233 model->setData(index, static_cast<ClearableKeysequenceEdit*>(editor)->key_sequence()); 0234 return QStyledItemDelegate::setModelData(editor, model, index); 0235 } 0236 0237