~ubuntu-branches/ubuntu/wily/ubuntu-ui-toolkit/wily

« back to all changes in this revision

Viewing changes to modules/Ubuntu/Layouts/plugin/ullayouts.cpp

  • Committer: Package Import Robot
  • Author(s): CI Train Bot, Florian Boucault, Loïc Molinari, Benjamin Zeller, Richard Huddie, Tim Peeters, Zsombor Egri, Timo Jyrinki, Christian Dywan, Albert Astals Cid
  • Date: 2015-07-30 13:04:18 UTC
  • mfrom: (1.1.126)
  • Revision ID: package-import@ubuntu.com-20150730130418-nxjr780u6wqcdqeh
Tags: 1.3.1584+15.10.20150730-0ubuntu1
[ Florian Boucault ]
* New BottomEdgeHint component to represent extra features available from the 
  bottom edge of an application.

[ Loïc Molinari ]
* [UbuntuShape] Added a big radius.
* [UbuntuShape] Added relative radius support. Fixes LP: #1478124.
* Ensured components, styles, examples and tests use the new UbuntuShape 
  properties (not deprecated). Fixes LP: #1437412.

[ Benjamin Zeller ]
* Make use of the official qt build macros to blend into the Qt buildprocess.
* Fix debug builds, optimization is always enabled by the system qt build.

[ Richard Huddie ]
* Fix for autopilot bug lp:1476715. Don't throw an exception if maliit-server
  is not found. Fixes LP: #1476715.

[ Tim Peeters ]
* Clean up the MainView docs.
* Set theme version for Sections component.
* Implement AdaptivePageLayout.

[ Zsombor Egri ]
* Fix width for trailing and leading actions of a ListItem. Fixes LP: #1465582.
* Button and Haptics import wrong toolkit versions, thus they break style 
  versioning. Moving Icon and ProgressBar to 1.0 and 1.1 version source folder.
* SuruDark theme for ListItem style. Fixes LP: #1451225.
* Swiping ListItem when no actions are defined for the gesture breaks 
  selectMode. Fixes LP: #1468100.
* Fixing selected connection with the ListItem's select mode checkbox state. 
  Fixes LP: #1461501, LP: #1469471.

[ Timo Jyrinki ]
* Fix ucstylehints.cpp compilation with Qt 5.5. Fixes LP: #1473873.
* Add PageHeadStyle 1.3 reference to fix install_plugins_qmltypes failure with 
  Qt 5.5. Fixes LP: #1466484.

[ Christian Dywan ]
* Avoid hard-coded skipping of members by name "type" can be a property name 
  regardless of also being a field in the JSON description of a property.
* Add apicheck unit test for QML and Javascript.
* Remove "do cleanup" comments. Fixes LP: #1369874.
* Initialize defaultTypes later to avoid bogus types.
* Implement Action.shortcut property. Fixes LP: #1202464.
* Update text handler to 3gu assert.
* Add a deprecated note to ListItems.ThinDivider. Fixes LP: #1470951.
* Don't include overridden properties in API.
* Clean-up API check wrapper scripts.
* Track version members were introduced.
* Implement ListItemPopover on right-click. Fixes LP: #1452676.
* Move delegate's chevron into the row and size it explicitly. 
  Fixes LP: #1474418.
* Enable (Shift)Tab via activeFocusOnTab. Fixes LP: #1276797.
* Only swipe with left button and block timer otherwise. 
  Fixes LP: #1476300, LP: #1476310.
* Include Javascript libraries in QML documentation. Fixes LP: #1466058.

[ Albert Astals Cid ]
* Fix warning if there's no __propagated
* TypeError: Cannot call method 'hasOwnProperty' of null.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * Copyright 2013 Canonical Ltd.
3
 
 *
4
 
 * This program is free software; you can redistribute it and/or modify
5
 
 * it under the terms of the GNU Lesser General Public License as published by
6
 
 * the Free Software Foundation; version 3.
7
 
 *
8
 
 * This program is distributed in the hope that it will be useful,
9
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 
 * GNU Lesser General Public License for more details.
12
 
 *
13
 
 * You should have received a copy of the GNU Lesser General Public License
14
 
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
15
 
 *
16
 
 * Author: Zsombor Egri <zsombor.egri@canonical.com>
17
 
 */
18
 
 
19
 
#include "ullayouts.h"
20
 
#include "ullayouts_p.h"
21
 
#include "ulitemlayout.h"
22
 
#include "ulconditionallayout.h"
23
 
#include "propertychanges_p.h"
24
 
#include <QtQml/QQmlInfo>
25
 
#include <QtQuick/private/qquickitem_p.h>
26
 
 
27
 
ULLayoutsPrivate::ULLayoutsPrivate(ULLayouts *qq)
28
 
    : QQmlIncubator(Asynchronous)
29
 
    , q_ptr(qq)
30
 
    , currentLayoutItem(0)
31
 
    , previousLayoutItem(0)
32
 
    , contentItem(new QQuickItem)
33
 
    , currentLayoutIndex(-1)
34
 
    , ready(false)
35
 
{
36
 
    // hidden container for the components that are not laid out
37
 
    // any component not subject of layout is reparented into this component
38
 
    contentItem->setParent(qq);
39
 
    contentItem->setParentItem(qq);
40
 
}
41
 
 
42
 
 
43
 
/******************************************************************************
44
 
 * QQmlListProperty functions
45
 
 */
46
 
void ULLayoutsPrivate::append_layout(QQmlListProperty<ULConditionalLayout> *list, ULConditionalLayout *layout)
47
 
{
48
 
    ULLayouts *_this = static_cast<ULLayouts*>(list->object);
49
 
    if (layout) {
50
 
        layout->setParent(_this);
51
 
        _this->d_ptr->layouts.append(layout);
52
 
    }
53
 
}
54
 
 
55
 
int ULLayoutsPrivate::count_layouts(QQmlListProperty<ULConditionalLayout> *list)
56
 
{
57
 
    ULLayouts *_this = static_cast<ULLayouts*>(list->object);
58
 
    return _this->d_ptr->layouts.count();
59
 
}
60
 
 
61
 
ULConditionalLayout *ULLayoutsPrivate::at_layout(QQmlListProperty<ULConditionalLayout> *list, int index)
62
 
{
63
 
    ULLayouts *_this = static_cast<ULLayouts*>(list->object);
64
 
    return _this->d_ptr->layouts.at(index);
65
 
}
66
 
 
67
 
void ULLayoutsPrivate::clear_layouts(QQmlListProperty<ULConditionalLayout> *list)
68
 
{
69
 
    ULLayouts *_this = static_cast<ULLayouts*>(list->object);
70
 
    _this->d_ptr->layouts.clear();
71
 
}
72
 
 
73
 
 
74
 
/******************************************************************************
75
 
 * ULLayoutsPrivate also acts as QQmlIncubator for the dynamically created layouts.
76
 
 * QQmlIncubator stuff
77
 
 */
78
 
void ULLayoutsPrivate::setInitialState(QObject *object)
79
 
{
80
 
    Q_Q(ULLayouts);
81
 
    // object context's parent is the creation context; link it to the object so we
82
 
    // delete them together
83
 
    qmlContext(object)->parentContext()->setParent(object);
84
 
    // set parent
85
 
    object->setParent(q);
86
 
    QQuickItem *item = static_cast<QQuickItem*>(object);
87
 
    // set disabled and invisible, and set its parent as last action
88
 
    item->setVisible(false);
89
 
}
90
 
 
91
 
/*
92
 
 * Called upon QQmlComponent::create() to notify the status of the component
93
 
 * creation.
94
 
 */
95
 
void ULLayoutsPrivate::statusChanged(Status status)
96
 
{
97
 
    Q_Q(ULLayouts);
98
 
    if (status == Ready) {
99
 
        // complete layouting
100
 
        previousLayoutItem = currentLayoutItem;
101
 
 
102
 
        // reset the layout
103
 
        currentLayoutItem = qobject_cast<QQuickItem*>(object());
104
 
        Q_ASSERT(currentLayoutItem);
105
 
 
106
 
        //reparent components to be laid out
107
 
        reparentItems();
108
 
        // set parent item, then enable and show layout
109
 
        changes.addChange(new ParentChange(currentLayoutItem, q, false));
110
 
 
111
 
        // hide default layout, then show the new one
112
 
        // there's no need to queue these property changes as we do not need
113
 
        // to back up their previosus states
114
 
        contentItem->setVisible(false);
115
 
        currentLayoutItem->setVisible(true);
116
 
        // apply changes
117
 
        changes.apply();
118
 
        // clear previous layout
119
 
        delete previousLayoutItem;
120
 
        previousLayoutItem = 0;
121
 
 
122
 
        Q_EMIT q->currentLayoutChanged();
123
 
    } else if (status == Error) {
124
 
        error(q, errors());
125
 
    }
126
 
}
127
 
 
128
 
/*
129
 
 * Re-parent items to the new layout.
130
 
 */
131
 
void ULLayoutsPrivate::reparentItems()
132
 
{
133
 
    // create copy of items list, to keep track of which ones we change
134
 
    LaidOutItemsMap unusedItems = itemsToLayout;
135
 
 
136
 
    // iterate through the Layout definition to find containers - ItemLayout items
137
 
    QList<ULItemLayout*> containers = collectContainers(currentLayoutItem);
138
 
 
139
 
    Q_FOREACH(ULItemLayout *container, containers) {
140
 
        reparentToItemLayout(unusedItems, container);
141
 
    }
142
 
}
143
 
 
144
 
QList<ULItemLayout*> ULLayoutsPrivate::collectContainers(QQuickItem *fromItem)
145
 
{
146
 
    QList<ULItemLayout*> result;
147
 
    // check first if the fromItem is also a container
148
 
    ULItemLayout *container = qobject_cast<ULItemLayout*>(fromItem);
149
 
    if (container) {
150
 
        result.append(container);
151
 
    }
152
 
 
153
 
    // loop through children but exclude nested Layouts
154
 
    QList<QQuickItem*> children = fromItem->childItems();
155
 
    Q_FOREACH(QQuickItem *child, children) {
156
 
        if (qobject_cast<ULLayouts*>(child)) {
157
 
            continue;
158
 
        }
159
 
        result.append(collectContainers(child));
160
 
    }
161
 
    return result;
162
 
}
163
 
 
164
 
/*
165
 
 * Re-parent to ItemLayout.
166
 
 */
167
 
void ULLayoutsPrivate::reparentToItemLayout(LaidOutItemsMap &map, ULItemLayout *fragment)
168
 
{
169
 
    QString itemName = fragment->item();
170
 
    if (itemName.isEmpty()) {
171
 
        warning(fragment, "item not specified for ItemLayout");
172
 
        return;
173
 
    }
174
 
 
175
 
    QQuickItem *item = map.value(itemName);
176
 
    if (!item) {
177
 
        warning(fragment, "item \"" + itemName
178
 
                          + "\" not specified or has been specified for layout by"
179
 
                             " more than one active ItemLayout");
180
 
        return;
181
 
    }
182
 
 
183
 
    // the component fills the parent
184
 
    changes.addParentChange(item, fragment, true);
185
 
    changes.addChange(new AnchorChange(item, "fill", fragment));
186
 
    changes.addChange(new PropertyChange(item, "anchors.margins", 0));
187
 
    changes.addChange(new PropertyChange(item, "anchors.leftMargin", 0));
188
 
    changes.addChange(new PropertyChange(item, "anchors.topMargin", 0));
189
 
    changes.addChange(new PropertyChange(item, "anchors.rightMargin", 0));
190
 
    changes.addChange(new PropertyChange(item, "anchors.bottomMargin", 0));
191
 
           // backup size
192
 
    changes.addChange(new PropertyBackup(item, "width"));
193
 
    changes.addChange(new PropertyBackup(item, "height"));
194
 
           // break and backup anchors
195
 
    changes.addChange(new AnchorBackup(item));
196
 
 
197
 
    // remove from unused ones
198
 
    map.remove(itemName);
199
 
}
200
 
 
201
 
/*
202
 
 * Validates the declared conditional layouts by checking whether they have name
203
 
 * property set and whether the value set is unique, and whether the conditional
204
 
 * layout has container defined.
205
 
 */
206
 
void ULLayoutsPrivate::validateConditionalLayouts()
207
 
{
208
 
    Q_Q(ULLayouts);
209
 
 
210
 
    QStringList names;
211
 
    for (int i = 0; i < layouts.count(); i++) {
212
 
        ULConditionalLayout *layout = layouts[i];
213
 
        if (!layout) {
214
 
            error(q, "Error in layout definitions!");
215
 
            continue;
216
 
        }
217
 
 
218
 
        if (layout->layoutName().isEmpty()) {
219
 
            warning(layout, "No name specified for layout. ConditionalLayout cannot be activated without name.");
220
 
            continue;
221
 
        }
222
 
        if (names.contains(layout->layoutName())) {
223
 
            warning(layout, "layout name \"" + layout->layoutName()
224
 
                            + "\" not unique. Layout may not behave as expected.");
225
 
        }
226
 
 
227
 
        if (!layout->layout()) {
228
 
            error(layout, "no container specified for layout \"" + layout->layoutName() +
229
 
                           "\". ConditionalLayout cannot be activated without a container.");
230
 
            continue;
231
 
        }
232
 
 
233
 
    }
234
 
}
235
 
 
236
 
/*
237
 
 * Collect items to be laid out.
238
 
 */
239
 
void ULLayoutsPrivate::getLaidOutItems(QQuickItem *container)
240
 
{
241
 
    Q_FOREACH(QQuickItem *child, container->childItems()) {
242
 
        // skip nested layouts
243
 
        if (qobject_cast<ULLayouts*>(child)) {
244
 
            continue;
245
 
        }
246
 
        ULLayoutsAttached *marker = qobject_cast<ULLayoutsAttached*>(
247
 
                    qmlAttachedPropertiesObject<ULLayouts>(child, false));
248
 
        if (marker && !marker->item().isEmpty()) {
249
 
            itemsToLayout.insert(marker->item(), child);
250
 
        } else {
251
 
            // continue to search in between the child's children
252
 
            getLaidOutItems(child);
253
 
        }
254
 
    }
255
 
}
256
 
 
257
 
/*
258
 
 * Apply layout change. The new layout creation will be completed in statusChange().
259
 
 */
260
 
void ULLayoutsPrivate::reLayout()
261
 
{
262
 
    if (!ready || (currentLayoutIndex < 0)) {
263
 
        return;
264
 
    }
265
 
    if (!layouts[currentLayoutIndex]->layout()) {
266
 
        return;
267
 
    }
268
 
 
269
 
    // redo changes
270
 
    changes.revert();
271
 
    changes.clear();
272
 
 
273
 
    // clear the incubator before using it
274
 
    clear();
275
 
    QQmlComponent *component = layouts[currentLayoutIndex]->layout();
276
 
    // create using incubation as it may be created asynchronously,
277
 
    // case when the attached properties are not yet enumerated
278
 
    Q_Q(ULLayouts);
279
 
    QQmlContext *context = new QQmlContext(qmlContext(q), q);
280
 
    component->create(*this, context);
281
 
}
282
 
 
283
 
/*
284
 
 * Updates the current layout.
285
 
 */
286
 
void ULLayoutsPrivate::updateLayout()
287
 
{
288
 
    if (!ready) {
289
 
        return;
290
 
    }
291
 
 
292
 
    // go through conditions and re-parent for the first valid one
293
 
    for (int i = 0; i < layouts.count(); i++) {
294
 
        ULConditionalLayout *layout = layouts[i];
295
 
        if (!layout->layout()) {
296
 
            warning(layout, "Cannot activate layout \"" + layout->layoutName() +
297
 
                    "\" with no container specified. Falling back to default layout.");
298
 
            break;
299
 
        }
300
 
        if (!layout->layoutName().isEmpty() && layout->when() && layout->when()->evaluate().toBool()) {
301
 
            if (currentLayoutIndex == i) {
302
 
                return;
303
 
            }
304
 
            currentLayoutIndex = i;
305
 
            // update layout
306
 
            reLayout();
307
 
            return;
308
 
        }
309
 
    }
310
 
    // check if we need to switch back to default layout
311
 
    if (currentLayoutIndex >= 0) {
312
 
        // revert and clear changes
313
 
        changes.revert();
314
 
        changes.clear();
315
 
        // make contentItem visible
316
 
 
317
 
        contentItem->setVisible(true);
318
 
        delete currentLayoutItem;
319
 
        currentLayoutItem = 0;
320
 
        currentLayoutIndex = -1;
321
 
        Q_Q(ULLayouts);
322
 
        Q_EMIT q->currentLayoutChanged();
323
 
    }
324
 
}
325
 
 
326
 
void ULLayoutsPrivate::error(QObject *item, const QString &message)
327
 
{
328
 
    qmlInfo(item) << "ERROR: " << message;
329
 
    QQmlEngine *engine = qmlEngine(item);
330
 
    if (engine) {
331
 
        engine->quit();
332
 
    }
333
 
}
334
 
 
335
 
void ULLayoutsPrivate::error(QObject *item, const QList<QQmlError> &errors)
336
 
{
337
 
    qmlInfo(item, errors);
338
 
    QQmlEngine *engine = qmlEngine(item);
339
 
    if (engine) {
340
 
        engine->quit();
341
 
    }
342
 
}
343
 
 
344
 
void ULLayoutsPrivate::warning(QObject *item, const QString &message)
345
 
{
346
 
    qmlInfo(item) << "WARNING: " << message;
347
 
}
348
 
 
349
 
 
350
 
/*!
351
 
 * \qmltype Layouts
352
 
 * \instantiates ULLayouts
353
 
 * \inqmlmodule Ubuntu.Layouts 1.0
354
 
 * \ingroup ubuntu-layouts
355
 
 * \brief The Layouts component allows one to specify multiple different layouts for a
356
 
 * fixed set of Items, and applies the desired layout to those Items.
357
 
 *
358
 
 * Layouts is a layout block component incorporating layout definitions and
359
 
 * components to lay out. The layouts are defined in the \l layouts property, which
360
 
 * is a list of ConditionalLayout components, each declaring the sizes and positions
361
 
 * of the components specified to be laid out.
362
 
 *
363
 
 * \qml
364
 
 * Layouts {
365
 
 *     id: layouts
366
 
 *     layouts: [
367
 
 *         ConditionalLayout {
368
 
 *             name: "flow"
369
 
 *             when: layouts.width > units.gu(60) && layouts.width <= units.gu(100)
370
 
 *             Flow {
371
 
 *                 anchors.fill: parent
372
 
 *                 //[...]
373
 
 *             }
374
 
 *         },
375
 
 *         ConditionalLayout {
376
 
 *             name: "column"
377
 
 *             when: layouts.width > units.gu(100)
378
 
 *             Flickable {
379
 
 *                 anchors.fill: parent
380
 
 *                 contentHeight: column.childrenRect.height
381
 
 *                 Column {
382
 
 *                     id: column
383
 
 *                     //[...]
384
 
 *                 }
385
 
 *             }
386
 
 *         }
387
 
 *     ]
388
 
 * }
389
 
 * \endqml
390
 
 *
391
 
 * The components to be laid out must be declared as children of the Layouts component,
392
 
 * each set an attached property "Layouts.item" to be a unique string.
393
 
 *
394
 
 * \qml
395
 
 * Layouts {
396
 
 *     id: layouts
397
 
 *     layouts: [
398
 
 *         ConditionalLayout {
399
 
 *             name: "flow"
400
 
 *             when: layouts.width > units.gu(60) && layouts.width <= units.gu(100)
401
 
 *             Flow {
402
 
 *                 anchors.fill: parent
403
 
 *                 //[...]
404
 
 *             }
405
 
 *         },
406
 
 *         ConditionalLayout {
407
 
 *             name: "column"
408
 
 *             when: layouts.width > units.gu(100)
409
 
 *             Flickable {
410
 
 *                 anchors.fill: parent
411
 
 *                 contentHeight: column.childrenRect.height
412
 
 *                 Column {
413
 
 *                     id: column
414
 
 *                     //[...]
415
 
 *                 }
416
 
 *             }
417
 
 *         }
418
 
 *     ]
419
 
 *
420
 
 *     Row {
421
 
 *         anchors.fill: parent
422
 
 *         Button {
423
 
 *             text: "Press me"
424
 
 *             Layouts.item: "item1"
425
 
 *         }
426
 
 *         Button {
427
 
 *             text: "Cancel"
428
 
 *             Layouts.item: "item2"
429
 
 *         }
430
 
 *     }
431
 
 * }
432
 
 * \endqml
433
 
 *
434
 
 * The layout of the children of Layouts is considered the default layout, i.e.
435
 
 * currentLayout is an empty string. So in the above example, the buttons arranged
436
 
 * in a row is the default layout.
437
 
 *
438
 
 * The layouts defined by ConditionalLayout components are created and activated
439
 
 * when at least one of the layout's condition is evaluated to true. In which
440
 
 * case components marked for layout are re-parented to the components defined
441
 
 * to lay out those defined in the ConditionalLayout. In case multiple conditions
442
 
 * are evaluated to true, the first one in the list will be activated. The deactivated
443
 
 * layout is destroyed, exception being the default layout, which is kept in memory for
444
 
 * the entire lifetime of the Layouts component.
445
 
 *
446
 
 * Upon activation, the created component fills in the entire layout block.
447
 
 *
448
 
 * \qml
449
 
 * Layouts {
450
 
 *     id: layouts
451
 
 *     layouts: [
452
 
 *         ConditionalLayout {
453
 
 *             name: "flow"
454
 
 *             when: layouts.width > units.gu(60) && layouts.width <= units.gu(100)
455
 
 *             Flow {
456
 
 *                 anchors.fill: parent
457
 
 *                 ItemLayout {
458
 
 *                     item: "item1"
459
 
 *                 }
460
 
 *                 ItemLayout {
461
 
 *                     item: "item2"
462
 
 *                 }
463
 
 *             }
464
 
 *         },
465
 
 *         ConditionalLayout {
466
 
 *             name: "column"
467
 
 *             when: layouts.width > units.gu(100)
468
 
 *             Flickable {
469
 
 *                 anchors.fill: parent
470
 
 *                 contentHeight: column.childrenRect.height
471
 
 *                 Column {
472
 
 *                     id: column
473
 
 *                     ItemLayout {
474
 
 *                         item: "item1"
475
 
 *                     }
476
 
 *                     ItemLayout {
477
 
 *                         item: "item2"
478
 
 *                     }
479
 
 *                 }
480
 
 *             }
481
 
 *         }
482
 
 *     ]
483
 
 *
484
 
 *     Row {
485
 
 *         anchors.fill: parent
486
 
 *         Button {
487
 
 *             text: "Press me"
488
 
 *             Layouts.item: "item1"
489
 
 *         }
490
 
 *         Button {
491
 
 *             text: "Cancel"
492
 
 *             Layouts.item: "item2"
493
 
 *         }
494
 
 *     }
495
 
 * }
496
 
 * \endqml
497
 
 *
498
 
 * Conditional layouts must be named in order to be activatable. These names (strings)
499
 
 * should be unique within a Layouts item and can be used to identify changes in
500
 
 * between layouts in scripts, so additional layout specific customization on laid
501
 
 * out items can be done. The current layout is presented by the currentLayout
502
 
 * property.
503
 
 *
504
 
 * Extending the previous example by changing the button color to green when the
505
 
 * current layout is "column", the code would look as follows:
506
 
 * \qml
507
 
 * Layouts {
508
 
 *     id: layouts
509
 
 *     layouts: [
510
 
 *         ConditionalLayout {
511
 
 *             name: "flow"
512
 
 *             when: layouts.width > units.gu(60) && layouts.width <= units.gu(100)
513
 
 *             Flow {
514
 
 *                 anchors.fill: parent
515
 
 *                 ItemLayout {
516
 
 *                     item: "item1"
517
 
 *                 }
518
 
 *                 ItemLayout {
519
 
 *                     item: "item2"
520
 
 *                 }
521
 
 *             }
522
 
 *         },
523
 
 *         ConditionalLayout {
524
 
 *             name: "column"
525
 
 *             when: layouts.width > units.gu(100)
526
 
 *             Flickable {
527
 
 *                 anchors.fill: parent
528
 
 *                 contentHeight: column.childrenRect.height
529
 
 *                 Column {
530
 
 *                     id: column
531
 
 *                     ItemLayout {
532
 
 *                         item: "item1"
533
 
 *                     }
534
 
 *                     ItemLayout {
535
 
 *                         item: "item2"
536
 
 *                     }
537
 
 *                 }
538
 
 *             }
539
 
 *         }
540
 
 *     ]
541
 
 *
542
 
 *     Row {
543
 
 *         anchors.fill: parent
544
 
 *         Button {
545
 
 *             text: "Press me"
546
 
 *             Layouts.item: "item1"
547
 
 *             color: (layouts.currentLayout === "column") ? "green" : "gray"
548
 
 *         }
549
 
 *         Button {
550
 
 *             text: "Cancel"
551
 
 *             Layouts.item: "item2"
552
 
 *             color: (layouts.currentLayout === "column") ? "green" : "gray"
553
 
 *         }
554
 
 *     }
555
 
 * }
556
 
 * \endqml
557
 
 */
558
 
 
559
 
ULLayouts::ULLayouts(QQuickItem *parent):
560
 
    QQuickItem(parent),
561
 
    d_ptr(new ULLayoutsPrivate(this))
562
 
{
563
 
}
564
 
 
565
 
ULLayouts::~ULLayouts()
566
 
{
567
 
}
568
 
 
569
 
ULLayoutsAttached * ULLayouts::qmlAttachedProperties(QObject *owner)
570
 
{
571
 
    return new ULLayoutsAttached(owner);
572
 
}
573
 
 
574
 
void ULLayouts::componentComplete()
575
 
{
576
 
    QQuickItem::componentComplete();
577
 
    Q_D(ULLayouts);
578
 
    d->ready = true;
579
 
    d->validateConditionalLayouts();
580
 
    d->getLaidOutItems(d->contentItem);
581
 
    d->updateLayout();
582
 
}
583
 
 
584
 
void ULLayouts::geometryChanged(const QRectF &newGeometry, const QRectF &oldGeometry)
585
 
{
586
 
    Q_D(ULLayouts);
587
 
    QQuickItem::geometryChanged(newGeometry, oldGeometry);
588
 
    // simply update the container's width/height to the new width/height
589
 
    d->contentItem->setSize(newGeometry.size());
590
 
}
591
 
 
592
 
/*!
593
 
 * \qmlproperty string Layouts::currentLayout
594
 
 * The property holds the active layout name. The default layout is identified
595
 
 * by an empty string. This property can be used for additional customization
596
 
 * of the components which are not supported by the layouting.
597
 
 */
598
 
 
599
 
QString ULLayouts::currentLayout() const
600
 
{
601
 
    Q_D(const ULLayouts);
602
 
    return d->currentLayoutIndex >= 0 ? d->layouts[d->currentLayoutIndex]->layoutName() : QString();
603
 
}
604
 
 
605
 
/*!
606
 
 * \internal
607
 
 * Provides a list of layouts for internal use.
608
 
 */
609
 
QList<ULConditionalLayout*> ULLayouts::layoutList()
610
 
{
611
 
    Q_D(ULLayouts);
612
 
    return d->layouts;
613
 
}
614
 
 
615
 
/*!
616
 
 * \internal
617
 
 * Returns the contentItem for internal use.
618
 
 */
619
 
QQuickItem *ULLayouts::contentItem() const
620
 
{
621
 
    Q_D(const ULLayouts);
622
 
    return d->contentItem;
623
 
}
624
 
 
625
 
 
626
 
/*!
627
 
 * \qmlproperty list<ConditionalLayout> Layouts::layouts
628
 
 * The property holds the list of different ConditionalLayout elements.
629
 
 */
630
 
QQmlListProperty<ULConditionalLayout> ULLayouts::layouts()
631
 
{
632
 
    Q_D(ULLayouts);
633
 
    return QQmlListProperty<ULConditionalLayout>(this, &(d->layouts),
634
 
                                                 &ULLayoutsPrivate::append_layout,
635
 
                                                 &ULLayoutsPrivate::count_layouts,
636
 
                                                 &ULLayoutsPrivate::at_layout,
637
 
                                                 &ULLayoutsPrivate::clear_layouts);
638
 
}
639
 
 
640
 
/*!
641
 
 * \internal
642
 
 * Overrides the default data property.
643
 
 */
644
 
QQmlListProperty<QObject> ULLayouts::data()
645
 
{
646
 
    Q_D(ULLayouts);
647
 
    return QQuickItemPrivate::get(d->contentItem)->data();
648
 
}
649
 
 
650
 
/*!
651
 
 * \internal
652
 
 * Overrides the default children property.
653
 
 */
654
 
QQmlListProperty<QQuickItem> ULLayouts::children()
655
 
{
656
 
    Q_D(ULLayouts);
657
 
    return QQuickItemPrivate::get(d->contentItem)->children();
658
 
}
659
 
 
660
 
 
661
 
#include "moc_ullayouts.cpp"