2
* This file is part of Maliit Plugins
4
* Copyright (C) 2012 Openismus GmbH. All rights reserved.
6
* Contact: maliit-discuss@lists.maliit.org
8
* Redistribution and use in source and binary forms, with or without modification,
9
* are permitted provided that the following conditions are met:
11
* Redistributions of source code must retain the above copyright notice, this list
12
* of conditions and the following disclaimer.
13
* Redistributions in binary form must reproduce the above copyright notice, this list
14
* of conditions and the following disclaimer in the documentation and/or other materials
15
* provided with the distribution.
16
* Neither the name of Nokia Corporation nor the names of its contributors may be
17
* used to endorse or promote products derived from this software without specific
18
* prior written permission.
20
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
21
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
22
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
23
* THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
24
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
26
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
#include "keydescription.h"
37
#include "logic/keyareaconverter.h"
38
#include "logic/dynamiclayout.h"
40
#include <QtGui/QGuiApplication>
43
namespace MaliitKeyboard {
46
QUrl toUrl(const QString &directory,
47
const QString &base_name)
49
if (not (directory.isEmpty() || base_name.isEmpty())) {
50
return QUrl(directory + "/" + base_name);
64
QString image_directory;
65
QHash<int, QByteArray> roles;
67
explicit LayoutPrivate();
71
LayoutPrivate::LayoutPrivate()
77
// Model roles are used as variables in QML, hence the under_score naming
79
roles[Layout::RoleKeyRectangle] = "key_rectangle";
80
roles[Layout::RoleKeyReactiveArea] = "key_reactive_area";
81
roles[Layout::RoleKeyBackground] = "key_background";
82
roles[Layout::RoleKeyBackgroundBorders] = "key_background_borders";
83
roles[Layout::RoleKeyText] = "key_text";
84
roles[Layout::RoleKeyFont] = "key_font";
85
roles[Layout::RoleKeyFontColor] = "key_font_color";
86
roles[Layout::RoleKeyFontSize] = "key_font_size";
87
roles[Layout::RoleKeyFontStretch] = "key_font_stretch";
88
roles[Layout::RoleKeyIcon] = "key_icon";
89
roles[Layout::RoleKeyActionInsert] = "key_action_insert";
93
Layout::Layout(QObject *parent)
94
: QAbstractListModel(parent)
95
, d_ptr(new LayoutPrivate)
103
void Layout::setTitle(const QString &title)
107
if (d->title != title) {
109
Q_EMIT titleChanged(d->title);
114
QString Layout::title() const
121
void Layout::setKeyArea(const KeyArea &area)
126
const bool geometry_changed(d->key_area.rect() != area.rect());
127
const bool background_changed(d->key_area.area().background() != area.area().background());
128
const bool background_borders_changed(d->key_area.area().backgroundBorders() != area.area().backgroundBorders());
129
const bool visible_changed((d->key_area.keys().isEmpty() && not area.keys().isEmpty())
130
|| (not d->key_area.keys().isEmpty() && area.keys().isEmpty()));
131
const bool origin_changed(d->key_area.origin() != area.origin());
135
if (origin_changed) {
136
Q_EMIT originChanged(d->key_area.origin());
139
if (geometry_changed) {
140
Q_EMIT widthChanged(width());
141
Q_EMIT heightChanged(height());
144
if (background_changed) {
145
Q_EMIT backgroundChanged(background());
148
if (background_borders_changed) {
149
Q_EMIT backgroundBordersChanged(backgroundBorders());
152
if (visible_changed) {
153
Q_EMIT visibleChanged(not d->key_area.keys().isEmpty());
160
KeyArea Layout::keyArea() const
167
void Layout::replaceKey(int index,
171
d->key_area.rKeys().replace(index, key);
172
Q_EMIT dataChanged(this->index(index, 0), this->index(index, 0));
176
bool Layout::isVisible() const
179
return (not d->key_area.keys().isEmpty());
183
int Layout::width() const
186
return d->key_area.rect().width();
190
int Layout::height() const
193
return d->key_area.rect().height();
196
int Layout::wordRibbonHeight() const
198
return uiConst->wordRibbonHeight(
199
uiConst->screenToMaliitOrientation(
200
qGuiApp->primaryScreen()->orientation()) );
203
QPoint Layout::origin() const
206
return d->key_area.origin();
210
QUrl Layout::background() const
213
return toUrl(d->image_directory, d->key_area.area().background());
217
QRectF Layout::backgroundBorders() const
221
const QMargins &m(d->key_area.area().backgroundBorders());
222
return QRectF(m.left(), m.top(), m.right(), m.bottom());
225
int Layout::invisibleTouchAreaHeight() const
227
return uiConst->invisibleTouchAreaHeight(
228
uiConst->screenToMaliitOrientation(
229
qGuiApp->primaryScreen()->orientation()) );
232
void Layout::setImageDirectory(const QString &directory)
236
if (d->image_directory != directory) {
237
d->image_directory = directory;
238
// TODO: Make sure we don't accidentially invalidate the whole model twice
240
backgroundChanged(background());
246
int Layout::rowCount(const QModelIndex &parent) const
250
return d->key_area.keys().count();
254
QVariant Layout::data(const QModelIndex &index,
259
const QVector<Key> &keys(d->key_area.keys());
260
const Key &key(index.row() < keys.count()
261
? keys.at(index.row())
265
case RoleKeyReactiveArea:
266
return QVariant(key.rect());
268
case RoleKeyRectangle: {
269
const QRect &r(key.rect());
270
const QMargins &m(key.margins());
272
return QVariant(QRectF(m.left(), m.top(),
273
r.width() - (m.left() + m.right()),
274
r.height() - (m.top() + m.bottom())));
277
case RoleKeyBackground:
278
return QVariant(toUrl(d->image_directory, key.area().background()));
280
case RoleKeyBackgroundBorders: {
281
// Neither QML nor QVariant support QMargins type.
282
// We need to transform QMargins into a QRectF so that we can abuse
283
// left, top, right, bottom (of the QRectF) *as if* it was a QMargins.
284
const QMargins &m(key.area().backgroundBorders());
285
return QVariant(QRectF(m.left(), m.top(), m.right(), m.bottom()));
289
return QVariant(key.label().text());
292
return QVariant(QString(key.label().font().name()));
294
case RoleKeyFontColor:
295
// FIXME: QML expects QVariant(QColor(...)) here, but then we'd have a QtGui dependency, no?
296
return QVariant(QString(key.label().font().color()));
298
case RoleKeyFontSize:
299
// FIXME: Using qMax to suppress warning about "invalid" 0.0 font sizes in QFont::setPointSizeF.
300
return QVariant(qMax<int>(1, key.label().font().size()));
302
case RoleKeyFontStretch:
303
return QVariant(key.label().font().stretch());
306
return QVariant(toUrl(d->image_directory, key.icon()));
308
case RoleKeyActionInsert:
309
return QVariant(key.action() == Key::ActionInsert);
312
qWarning() << __PRETTY_FUNCTION__
313
<< "Invalid index or role (" << index.row() << role << ").";
319
QHash<int, QByteArray> Layout::roleNames() const
326
QVariant Layout::data(int index,
327
const QString &role) const
330
const QModelIndex idx(this->index(index, 0));
331
return data(idx, roleNames().key(role.toLatin1()));
335
}} // namespace Model, MaliitKeyboard