1/***************************************************************************
2 * Copyright (C) 2005-2014 by the Quassel Project *
3 * devel@quassel-irc.org *
4 * *
5 * This program is free software; you can redistribute it and/or modify *
6 * it under the terms of the GNU General Public License as published by *
7 * the Free Software Foundation; either version 2 of the License, or *
8 * (at your option) version 3. *
9 * *
10 * This program is distributed in the hope that it will be useful, *
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13 * GNU General Public License for more details. *
14 * *
15 * You should have received a copy of the GNU General Public License *
16 * along with this program; if not, write to the *
17 * Free Software Foundation, Inc., *
18 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
19 ***************************************************************************/
20
21#include <QTimer>
22
23#include "shortcutssettingspage.h"
24
25#include "action.h"
26#include "actioncollection.h"
27#include "qtui.h"
28#include "shortcutsmodel.h"
29#include "util.h"
30
31ShortcutsFilter::ShortcutsFilter(QObject *parent) : QSortFilterProxyModel(parent)
32{
33 setDynamicSortFilter(true);
34}
35
36
37void ShortcutsFilter::setFilterString(const QString &filterString)
38{
39 _filterString = filterString;
40 invalidateFilter();
41}
42
43
44bool ShortcutsFilter::filterAcceptsRow(int source_row, const QModelIndex &source_parent) const
45{
46 if (!source_parent.isValid())
47 return true;
48
49 QModelIndex index = source_parent.model()->index(source_row, 0, source_parent);
50 Q_ASSERT(index.isValid());
51 if (!qobject_cast<Action *>(index.data(ShortcutsModel::ActionRole).value<QObject *>())->isShortcutConfigurable())
52 return false;
53
54 for (int col = 0; col < source_parent.model()->columnCount(source_parent); col++) {
55 if (source_parent.model()->index(source_row, col, source_parent).data().toString().contains(_filterString, Qt::CaseInsensitive))
56 return true;
57 }
58 return false;
59}
60
61
62/****************************************************************************/
63
64ShortcutsSettingsPage::ShortcutsSettingsPage(const QHash<QString, ActionCollection *> &actionCollections, QWidget *parent)
65 : SettingsPage(tr("Interface"), tr("Shortcuts"), parent),
66 _shortcutsModel(new ShortcutsModel(actionCollections, this)),
67 _shortcutsFilter(new ShortcutsFilter(this))
68{
69 ui.setupUi(this);
70
71 _shortcutsFilter->setSourceModel(_shortcutsModel);
72 ui.shortcutsView->setModel(_shortcutsFilter);
73 ui.shortcutsView->expandAll();
74 ui.shortcutsView->resizeColumnToContents(0);
75 ui.shortcutsView->sortByColumn(0, Qt::AscendingOrder);
76
77 ui.keySequenceWidget->setModel(_shortcutsModel);
78 connect(ui.keySequenceWidget, SIGNAL(keySequenceChanged(QKeySequence, QModelIndex)), SLOT(keySequenceChanged(QKeySequence, QModelIndex)));
79
80 connect(ui.shortcutsView->selectionModel(), SIGNAL(currentChanged(QModelIndex, QModelIndex)), SLOT(setWidgetStates()));
81
82 setWidgetStates();
83
84 connect(ui.useDefault, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault()));
85 connect(ui.useCustom, SIGNAL(clicked(bool)), SLOT(toggledCustomOrDefault()));
86
87 connect(_shortcutsModel, SIGNAL(hasChanged(bool)), SLOT(setChangedState(bool)));
88
89 // fugly, but directly setting it from the ctor doesn't seem to work
90 QTimer::singleShot(0, ui.searchEdit, SLOT(setFocus()));
91}
92
93
94void ShortcutsSettingsPage::setWidgetStates()
95{
96 if (ui.shortcutsView->currentIndex().isValid() && ui.shortcutsView->currentIndex().parent().isValid()) {
97 QKeySequence active = ui.shortcutsView->currentIndex().data(ShortcutsModel::ActiveShortcutRole).value<QKeySequence>();
98 QKeySequence def = ui.shortcutsView->currentIndex().data(ShortcutsModel::DefaultShortcutRole).value<QKeySequence>();
99 ui.defaultShortcut->setText(def.isEmpty() ? tr("None") : def.toString(QKeySequence::NativeText));
100 ui.actionBox->setEnabled(true);
101 if (active == def) {
102 ui.useDefault->setChecked(true);
103 ui.keySequenceWidget->setKeySequence(QKeySequence());
104 }
105 else {
106 ui.useCustom->setChecked(true);
107 ui.keySequenceWidget->setKeySequence(active);
108 }
109 }
110 else {
111 ui.defaultShortcut->setText(tr("None"));
112 ui.actionBox->setEnabled(false);
113 ui.useDefault->setChecked(true);
114 ui.keySequenceWidget->setKeySequence(QKeySequence());
115 }
116}
117
118
119void ShortcutsSettingsPage::on_searchEdit_textChanged(const QString &text)
120{
121 _shortcutsFilter->setFilterString(text);
122}
123
124
125void ShortcutsSettingsPage::keySequenceChanged(const QKeySequence &seq, const QModelIndex &conflicting)
126{
127 if (conflicting.isValid())
128 _shortcutsModel->setData(conflicting, QKeySequence(), ShortcutsModel::ActiveShortcutRole);
129
130 QModelIndex rowIdx = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex());
131 Q_ASSERT(rowIdx.isValid());
132 _shortcutsModel->setData(rowIdx, seq, ShortcutsModel::ActiveShortcutRole);
133 setWidgetStates();
134}
135
136
137void ShortcutsSettingsPage::toggledCustomOrDefault()
138{
139 if (!ui.shortcutsView->currentIndex().isValid())
140 return;
141
142 QModelIndex index = _shortcutsFilter->mapToSource(ui.shortcutsView->currentIndex());
143 Q_ASSERT(index.isValid());
144
145 if (ui.useDefault->isChecked()) {
146 _shortcutsModel->setData(index, index.data(ShortcutsModel::DefaultShortcutRole));
147 }
148 else {
149 _shortcutsModel->setData(index, QKeySequence());
150 }
151 setWidgetStates();
152}
153
154
155void ShortcutsSettingsPage::save()
156{
157 _shortcutsModel->commit();
158 QtUi::saveShortcuts();
159 SettingsPage::save();
160}
161
162
163void ShortcutsSettingsPage::load()
164{
165 _shortcutsModel->load();
166
167 SettingsPage::load();
168}
169
170
171void ShortcutsSettingsPage::defaults()
172{
173 _shortcutsModel->defaults();
174
175 SettingsPage::defaults();
176}
177