2
* Copyright (C) 2010 Andriy Rysin (rysin@kde.org)
4
* This program is free software; you can redistribute it and/or modify
5
* it under the terms of the GNU General Public License as published by
6
* the Free Software Foundation; either version 2 of the License, or
7
* (at your option) any later version.
9
* This program is distributed in the hope that it will be useful,
10
* but WITHOUT ANY WARRANTY; without even the implied warranty of
11
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12
* GNU General Public License for more details.
14
* You should have received a copy of the GNU General Public License
15
* along with this program; if not, write to the Free Software
16
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
19
#include "kcm_view_models.h"
21
#include <klocalizedstring.h>
22
#include <kkeysequencewidget.h>
24
#include <QtGui/QTreeView>
25
#include <QtGui/QComboBox>
26
#include <QtGui/QLineEdit>
27
#include <QtGui/QPainter>
28
#include <QtGui/QKeySequence>
31
#include <QtCore/QMimeData>
34
#include "keyboard_config.h"
35
#include "xkb_rules.h"
37
#include "x11_helper.h"
40
const int LayoutsTableModel::MAP_COLUMN = 0;
41
const int LayoutsTableModel::LAYOUT_COLUMN = 1;
42
const int LayoutsTableModel::VARIANT_COLUMN = 2;
43
const int LayoutsTableModel::DISPLAY_NAME_COLUMN = 3;
44
const int LayoutsTableModel::SHORTCUT_COLUMN = 4;
45
static const int COLUMN_COUNT = 5;
47
LayoutsTableModel::LayoutsTableModel(Rules* rules_, Flags *flags_, KeyboardConfig* keyboardConfig_, QObject* parent):
48
QAbstractTableModel(parent),
49
keyboardConfig(keyboardConfig_),
55
void LayoutsTableModel::refresh()
61
int LayoutsTableModel::rowCount(const QModelIndex &/*parent*/) const
63
return keyboardConfig->layouts.count();
66
int LayoutsTableModel::columnCount(const QModelIndex&) const
71
Qt::ItemFlags LayoutsTableModel::flags(const QModelIndex &index) const
76
Qt::ItemFlags flags = QAbstractTableModel::flags(index);
78
if( index.column() == DISPLAY_NAME_COLUMN
79
|| index.column() == VARIANT_COLUMN
80
|| index.column() == SHORTCUT_COLUMN ) {
81
flags |= Qt::ItemIsEditable;
85
flags |= Qt::ItemIsDragEnabled | Qt::ItemIsDropEnabled;
92
QStringList LayoutsTableModel::mimeTypes() const
95
types << "application/keyboard-layout-item";
99
QMimeData *LayoutsTableModel::mimeData(const QModelIndexList &indexes) const
101
QMimeData *mimeData = new QMimeData();
102
QByteArray encodedData;
104
QDataStream stream(&encodedData, QIODevice::WriteOnly);
107
foreach (const QModelIndex& index, indexes) {
108
if (index.isValid()) {
112
foreach (int row, rows) {
114
kDebug() << "idx: " << row;
117
mimeData->setData("application/keyboard-layout-item", encodedData);
122
QVariant LayoutsTableModel::data(const QModelIndex &index, int role) const
124
if (!index.isValid())
127
if (index.row() >= keyboardConfig->layouts.size())
130
const LayoutUnit& layoutUnit = keyboardConfig->layouts.at(index.row());
132
if (role == Qt::DecorationRole) {
133
switch( index.column() ) {
134
case DISPLAY_NAME_COLUMN: {
135
if( keyboardConfig->showFlag ) {
136
QIcon icon = countryFlags->getIcon(layoutUnit.layout);
137
return icon.isNull() ? countryFlags->getTransparentPixmap() : icon;
140
//TODO: show the cells are editable
141
// case VARIANT_COLUMN: {
142
// case DISPLAY_NAME_COLUMN: {
144
// QPixmap pm = QPixmap(sz, sz+5);
145
// pm.fill(Qt::transparent);
147
// QPoint points[] = { QPoint(0, 0), QPoint(0, sz), QPoint(sz, 0) };
148
// p.drawPolygon(points, 3);
155
if( role == Qt::BackgroundRole ) {
156
if( keyboardConfig->layoutLoopCount != KeyboardConfig::NO_LOOPING
157
&& index.row() >= keyboardConfig->layoutLoopCount ) {
158
return QBrush(Qt::lightGray);
162
if (role == Qt::DisplayRole) {
163
switch( index.column() ) {
165
return layoutUnit.layout;
167
case LAYOUT_COLUMN: {
168
const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout);
169
return layoutInfo != NULL ? layoutInfo->description : layoutUnit.layout;
171
case VARIANT_COLUMN: {
172
if( layoutUnit.variant.isEmpty() )
174
const LayoutInfo* layoutInfo = rules->getLayoutInfo(layoutUnit.layout);
175
if( layoutInfo == NULL )
177
const VariantInfo* variantInfo = layoutInfo->getVariantInfo(layoutUnit.variant);
178
return variantInfo != NULL ? variantInfo->description : layoutUnit.variant;
181
case DISPLAY_NAME_COLUMN:
182
if( ! keyboardConfig->showFlag ) {
183
return layoutUnit.getDisplayName();
186
case SHORTCUT_COLUMN: {
187
return layoutUnit.getShortcut().toString();
192
else if (role==Qt::EditRole ) {
193
switch( index.column() ) {
194
case DISPLAY_NAME_COLUMN:
195
return layoutUnit.getDisplayName();
198
return layoutUnit.variant;
200
case SHORTCUT_COLUMN:
201
return layoutUnit.getShortcut().toString();
206
else if( role == Qt::TextAlignmentRole ) {
207
switch( index.column() ) {
209
case DISPLAY_NAME_COLUMN:
210
case SHORTCUT_COLUMN:
211
return Qt::AlignCenter;
219
QVariant LayoutsTableModel::headerData(int section, Qt::Orientation orientation, int role) const
221
if (role != Qt::DisplayRole)
224
if (orientation == Qt::Horizontal) {
225
const QString headers[] = {i18nc("layout map name", "Map"), i18n("Layout"), i18n("Variant"), i18n("Label"), i18n("Shortcut")};
226
return headers[section];
232
bool LayoutsTableModel::setData(const QModelIndex &index, const QVariant &value, int role)
234
if (role != Qt::EditRole
235
|| (index.column() != DISPLAY_NAME_COLUMN && index.column() != VARIANT_COLUMN && index.column() != SHORTCUT_COLUMN) )
238
if (index.row() >= keyboardConfig->layouts.size())
241
LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()];
243
switch( index.column() ) {
244
case DISPLAY_NAME_COLUMN: {
245
QString displayText = value.toString().left(3);
246
layoutUnit.setDisplayName(displayText);
249
case VARIANT_COLUMN: {
250
QString variant = value.toString();
251
layoutUnit.variant = variant;
254
case SHORTCUT_COLUMN: {
255
QString shortcut = value.toString();
256
layoutUnit.setShortcut(QKeySequence(shortcut));
260
emit dataChanged(index, index);
268
LabelEditDelegate::LabelEditDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent):
269
QStyledItemDelegate(parent),
270
keyboardConfig(keyboardConfig_)
273
QWidget *LabelEditDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & option ,
274
const QModelIndex & index ) const
276
if( keyboardConfig->showFlag )
279
QWidget* widget = QStyledItemDelegate::createEditor(parent, option, index);
280
QLineEdit* lineEdit = static_cast<QLineEdit*>(widget);
281
if( lineEdit != NULL ) {
282
lineEdit->setMaxLength(LayoutUnit::MAX_LABEL_LENGTH);
287
//void LabelEditDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
289
// QStyleOptionViewItem option2(option);
290
//// option2.decorationPosition = QStyleOptionViewItem::Right;
291
// option2.decorationAlignment = Qt::AlignHCenter | Qt::AlignVCenter;
292
// QStyledItemDelegate::paint(painter, option2, index);
297
// VariantComboDelegate
299
//TODO: reuse this function in kcm_add_layout_dialog.cpp
300
static void populateComboWithVariants(QComboBox* combo, const QString& layout, const Rules* rules)
303
const LayoutInfo* layoutInfo = rules->getLayoutInfo(layout);
304
foreach(const VariantInfo* variantInfo, layoutInfo->variantInfos) {
305
combo->addItem(variantInfo->description, variantInfo->name);
307
combo->model()->sort(0);
308
combo->insertItem(0, i18nc("variant", "Default"), "");
309
combo->setCurrentIndex(0);
312
VariantComboDelegate::VariantComboDelegate(const KeyboardConfig* keyboardConfig_, const Rules* rules_, QObject *parent):
313
QStyledItemDelegate(parent),
314
keyboardConfig(keyboardConfig_),
318
QWidget *VariantComboDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &/* option */,
319
const QModelIndex & index ) const
321
QComboBox *editor = new QComboBox(parent);
322
const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()];
323
populateComboWithVariants(editor, layoutUnit.layout, rules);
327
void VariantComboDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
329
QComboBox *combo = static_cast<QComboBox*>(editor);
330
QString variant = index.model()->data(index, Qt::EditRole).toString();
331
int itemIndex = combo->findData(variant);
332
if( itemIndex == -1 ) {
335
combo->setCurrentIndex(itemIndex);
338
void VariantComboDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
339
const QModelIndex &index) const
341
QComboBox *combo = static_cast<QComboBox*>(editor);
342
QString variant = combo->itemData(combo->currentIndex()).toString();
343
model->setData(index, variant, Qt::EditRole);
346
void VariantComboDelegate::updateEditorGeometry(QWidget *editor,
347
const QStyleOptionViewItem &option, const QModelIndex &/* index */) const
349
editor->setGeometry(option.rect);
353
// KKeySequenceWidgetDelegate
355
KKeySequenceWidgetDelegate::KKeySequenceWidgetDelegate(const KeyboardConfig* keyboardConfig_, QObject *parent):
356
QStyledItemDelegate(parent),
357
keyboardConfig(keyboardConfig_)
360
QWidget *KKeySequenceWidgetDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem & /*option*/,
361
const QModelIndex & index ) const
363
itemsBeingEdited.insert(index);
365
KKeySequenceWidget *editor = new KKeySequenceWidget(parent);
366
editor->setFocusPolicy(Qt::StrongFocus);
367
editor->setModifierlessAllowed(false);
369
const LayoutUnit& layoutUnit = keyboardConfig->layouts[index.row()];
370
editor->setKeySequence(layoutUnit.getShortcut());
372
editor->captureKeySequence();
377
//void KKeySequenceWidgetDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const
379
// KKeySequenceWidget *kkeysequencewidget = static_cast<KKeySequenceWidget*>(editor);
380
// QString shortcut = index.model()->data(index, Qt::EditRole).toString();
381
// kkeysequencewidget->setKeySequence(QKeySequence(shortcut));
382
// kkeysequencewidget->captureKeySequence();
383
//// kDebug() << "set editor data";
386
void KKeySequenceWidgetDelegate::setModelData(QWidget *editor, QAbstractItemModel *model,
387
const QModelIndex &index) const
389
KKeySequenceWidget *kkeysequencewidget = static_cast<KKeySequenceWidget*>(editor);
390
QString shortcut = kkeysequencewidget->keySequence().toString();
391
model->setData(index, shortcut, Qt::EditRole);
392
itemsBeingEdited.remove(index);
395
void KKeySequenceWidgetDelegate::paint(QPainter* painter, const QStyleOptionViewItem& option,
396
const QModelIndex& index) const
398
if (itemsBeingEdited.contains(index)) {
399
// StyledBackgroundPainter::drawBackground(painter,option,index);
402
QStyledItemDelegate::paint(painter,option,index);
406
// Xkb Options Tree View
409
int XkbOptionsTreeModel::rowCount(const QModelIndex& parent) const {
410
if( ! parent.isValid() )
411
return rules->optionGroupInfos.count();
412
if( ! parent.parent().isValid() )
413
return rules->optionGroupInfos[parent.row()]->optionInfos.count();
417
QVariant XkbOptionsTreeModel::data(const QModelIndex& index, int role) const
419
if (!index.isValid())
422
int row = index.row();
424
if (role == Qt::DisplayRole) {
425
if( ! index.parent().isValid() ) {
426
return rules->optionGroupInfos[row]->description;
429
int groupRow = index.parent().row();
430
const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow];
431
return xkbGroup->optionInfos[row]->description;
434
else if (role==Qt::CheckStateRole ) {
435
if( index.parent().isValid() ) {
436
int groupRow = index.parent().row();
437
const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow];
438
const QString& xkbOptionName = xkbGroup->optionInfos[row]->name;
439
return keyboardConfig->xkbOptions.indexOf(xkbOptionName) == -1
440
? Qt::Unchecked : Qt::Checked;
443
int groupRow = index.row();
444
const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow];
445
foreach(const OptionInfo* optionInfo, xkbGroup->optionInfos) {
446
if( keyboardConfig->xkbOptions.indexOf(optionInfo->name) != -1 )
447
return Qt::PartiallyChecked;
449
return Qt::Unchecked;
455
bool XkbOptionsTreeModel::setData(const QModelIndex & index, const QVariant & value, int role) {
456
int groupRow = index.parent().row();
457
if( groupRow < 0 ) return false;
459
const OptionGroupInfo* xkbGroup = rules->optionGroupInfos[groupRow];
460
const OptionInfo* option = xkbGroup->optionInfos[index.row()];
462
if( value.toInt() == Qt::Checked ) {
463
if( xkbGroup->exclusive ) {
464
// clear if exclusive (TODO: radiobutton)
465
int idx = keyboardConfig->xkbOptions.indexOf(QRegExp(xkbGroup->name + ".*"));
467
for(int i=0; i<xkbGroup->optionInfos.count(); i++)
468
if( xkbGroup->optionInfos[i]->name == keyboardConfig->xkbOptions[idx] ) {
469
setData(createIndex(i, index.column(), (quint32)index.internalId()-index.row()+i), Qt::Unchecked, role);
472
// m_kxkbConfig->m_options.removeAt(idx);
473
// idx = m_kxkbConfig->m_options.indexOf(QRegExp(xkbGroupNm+".*"));
476
if( keyboardConfig->xkbOptions.indexOf(option->name) < 0 ) {
477
keyboardConfig->xkbOptions.append(option->name);
481
keyboardConfig->xkbOptions.removeAll(option->name);
484
emit dataChanged(index, index);
485
emit dataChanged(index.parent(), index.parent());
489
void XkbOptionsTreeModel::gotoGroup(const QString& groupName, QTreeView* view) {
490
const OptionGroupInfo* optionGroupInfo = rules->getOptionGroupInfo(groupName);
491
int index = rules->optionGroupInfos.indexOf((OptionGroupInfo*)optionGroupInfo);
493
QModelIndex modelIdx = createIndex(index,0);
494
// view->selectionModel()->setCurrentIndex(createIndex(index,0), QItemSelectionModel::NoUpdate);
495
view->setExpanded(modelIdx, true);
496
view->scrollTo(modelIdx, QAbstractItemView::PositionAtTop);
497
view->selectionModel()->setCurrentIndex(modelIdx, QItemSelectionModel::Current);
498
view->setFocus(Qt::OtherFocusReason);
501
// kDebug() << "can't scroll to group" << group;