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