Kirigami2

PageRow.qml
1 /*
2  * SPDX-FileCopyrightText: 2016 Marco Martin <[email protected]>
3  *
4  * SPDX-License-Identifier: LGPL-2.0-or-later
5  */
6 
7 import QtQuick 2.5
8 import QtQuick.Layouts 1.2
9 import QtQml.Models 2.2
10 import QtQuick.Templates 2.0 as T
11 import QtQuick.Controls 2.0 as QQC2
12 import org.kde.kirigami 2.7
13 import "private/globaltoolbar" as GlobalToolBar
14 import "templates" as KT
15 
25 T.Control {
26  id: root
27 
28 //BEGIN PROPERTIES
32  property alias depth: columnView.count
33 
37  readonly property Item lastItem: columnView.contentChildren.length > 0 ? columnView.contentChildren[columnView.contentChildren.length - 1] : null
38 
42  property alias currentItem: columnView.currentItem
43 
47  property alias currentIndex: columnView.currentIndex
48 
52  property variant initialPage
53 
57  contentItem: columnView
58 
68  property alias columnView: columnView
69 
75  property alias items: columnView.contentChildren;
76 
82  property alias visibleItems: columnView.visibleItems
83 
89  property alias firstVisibleItem: columnView.firstVisibleItem
90 
96  property alias lastVisibleItem: columnView.lastVisibleItem
97 
104  property int defaultColumnWidth: Units.gridUnit * 20
105 
113  property alias interactive: columnView.interactive
114 
120  readonly property bool wideMode: root.width >= root.defaultColumnWidth*2 && depth >= 2
121 
128  property alias separatorVisible: columnView.separatorVisible
129 
153  readonly property alias globalToolBar: globalToolBar
154 
155  implicitWidth: contentItem.implicitWidth + leftPadding + rightPadding
156  implicitHeight: contentItem.implicitHeight + topPadding + bottomPadding
157 //END PROPERTIES
158 
159 //BEGIN FUNCTIONS
182  function push(page, properties) {
183  var item = insertPage(depth, page, properties);
184  currentIndex = depth - 1;
185  return item;
186  }
187 
212  function insertPage(position, page, properties) {
213  if (!page) {
214  return null
215  }
216  //don't push again things already there
217  if (page.createObject === undefined && typeof page != "string" && columnView.containsItem(page)) {
218  print("The item " + page + " is already in the PageRow");
219  return null;
220  }
221 
222  position = Math.max(0, Math.min(depth, position));
223 
224  columnView.pop(columnView.currentItem);
225 
226  // figure out if more than one page is being pushed
227  var pages;
228  var propsArray = [];
229  if (page instanceof Array) {
230  pages = page;
231  page = pages.pop();
232  //compatibility with pre-qqc1 api, can probably be removed
233  if (page.createObject === undefined && page.parent === undefined && typeof page != "string") {
234  properties = properties || page.properties;
235  page = page.page;
236  }
237  }
238  if (properties instanceof Array) {
239  propsArray = properties;
240  properties = propsArray.pop();
241  } else {
242  propsArray = [properties];
243  }
244 
245  // push any extra defined pages onto the stack
246  if (pages) {
247  var i;
248  for (i = 0; i < pages.length; i++) {
249  var tPage = pages[i];
250  var tProps = propsArray[i];
251  //compatibility with pre-qqc1 api, can probably be removed
252  if (tPage.createObject === undefined && tPage.parent === undefined && typeof tPage != "string") {
253  if (columnView.containsItem(tPage)) {
254  print("The item " + page + " is already in the PageRow");
255  continue;
256  }
257  tProps = tPage.properties;
258  tPage = tPage.page;
259  }
260 
261  var pageItem = pagesLogic.initAndInsertPage(position, tPage, tProps);
262  ++position;
263  }
264  }
265 
266  // initialize the page
267  var pageItem = pagesLogic.initAndInsertPage(position, page, properties);
268 
269  pagePushed(pageItem);
270 
271  return pageItem;
272  }
273 
280  function movePage(fromPos, toPos) {
281  columnView.moveItem(fromPos, toPos);
282  }
283 
290  function removePage(page) {
291  if (depth == 0) {
292  return null;
293  }
294 
295  return columnView.removeItem(page);
296  }
297 
305  function pop(page) {
306  if (depth == 0) {
307  return null;
308  }
309 
310  return columnView.pop(page);
311  }
312 
319  signal pageInserted(int position, Item page)
320 
321 
326  signal pagePushed(Item page)
327 
328 
334  signal pageRemoved(Item page)
335 
336 
352  function replace(page, properties) {
353  if (currentIndex >= 1) {
354  pop(columnView.contentChildren[currentIndex-1]);
355  } else if (currentIndex == 0) {
356  pop();
357  } else {
358  console.warn("There's no page to replace");
359  }
360  return push(page, properties);
361  }
362 
367  function clear() {
368  return columnView.clear();
369  }
370 
375  function get(idx) {
376  return columnView.contentChildren[idx];
377  }
378 
382  function flickBack() {
383  if (depth > 1) {
384  currentIndex = Math.max(0, currentIndex - 1);
385  }
386  }
387 
395  property alias layers: layersStack
396 //END FUNCTIONS
397 
398  onInitialPageChanged: {
399  if (initialPage) {
400  clear();
401  push(initialPage, null)
402  }
403  }
404 /*
405  onActiveFocusChanged: {
406  if (activeFocus) {
407  layersStack.currentItem.forceActiveFocus()
408  if (columnView.activeFocus) {
409  print("SSS"+columnView.currentItem)
410  columnView.currentItem.forceActiveFocus();
411  }
412  }
413  }
414 */
415  Keys.forwardTo: [currentItem]
416 
417  GlobalToolBar.PageRowGlobalToolBarStyleGroup {
418  id: globalToolBar
419  readonly property int leftReservedSpace: globalToolBarUI.item ? globalToolBarUI.item.leftReservedSpace : 0
420  readonly property int rightReservedSpace: globalToolBarUI.item ? globalToolBarUI.item.rightReservedSpace : 0
421  readonly property int height: globalToolBarUI.height
422  readonly property Item leftHandleAnchor: globalToolBarUI.item ? globalToolBarUI.item.leftHandleAnchor : null
423  readonly property Item rightHandleAnchor: globalToolBarUI.item ? globalToolBarUI.item.rightHandleAnchor : null
424  }
425 
426  QQC2.StackView {
427  id: layersStack
428  z: 99
429  anchors {
430  fill: parent
431  }
432  //placeholder as initial item
433  initialItem: columnView
434 
435  function clear () {
436  //don't let it kill the main page row
437  var d = layersStack.depth;
438  for (var i = 1; i < d; ++i) {
439  pop();
440  }
441  }
442 
443  popEnter: Transition {
444  OpacityAnimator {
445  from: 0
446  to: 1
447  duration: Units.longDuration
448  easing.type: Easing.InOutCubic
449  }
450  }
451  popExit: Transition {
452  ParallelAnimation {
453  OpacityAnimator {
454  from: 1
455  to: 0
456  duration: Units.longDuration
457  easing.type: Easing.InOutCubic
458  }
459  YAnimator {
460  from: 0
461  to: height/2
462  duration: Units.longDuration
463  easing.type: Easing.InCubic
464  }
465  }
466  }
467 
468  pushEnter: Transition {
469  ParallelAnimation {
470  //NOTE: It's a PropertyAnimation instead of an Animator because with an animator the item will be visible for an instant before starting to fade
471  PropertyAnimation {
472  property: "opacity"
473  from: 0
474  to: 1
475  duration: Units.longDuration
476  easing.type: Easing.InOutCubic
477  }
478  YAnimator {
479  from: height/2
480  to: 0
481  duration: Units.longDuration
482  easing.type: Easing.OutCubic
483  }
484  }
485  }
486 
487 
488  pushExit: Transition {
489  OpacityAnimator {
490  from: 1
491  to: 0
492  duration: Units.longDuration
493  easing.type: Easing.InOutCubic
494  }
495  }
496 
497  replaceEnter: Transition {
498  ParallelAnimation {
499  OpacityAnimator {
500  from: 0
501  to: 1
502  duration: Units.longDuration
503  easing.type: Easing.InOutCubic
504  }
505  YAnimator {
506  from: height/2
507  to: 0
508  duration: Units.longDuration
509  easing.type: Easing.OutCubic
510  }
511  }
512  }
513 
514  replaceExit: Transition {
515  ParallelAnimation {
516  OpacityAnimator {
517  from: 1
518  to: 0
519  duration: Units.longDuration
520  easing.type: Easing.InCubic
521  }
522  YAnimator {
523  from: 0
524  to: -height/2
525  duration: Units.longDuration
526  easing.type: Easing.InOutCubic
527  }
528  }
529  }
530  }
531 
532  Loader {
533  id: globalToolBarUI
534  anchors {
535  left: parent.left
536  top: parent.top
537  right: parent.right
538  }
539  z: 100
540  active: globalToolBar.actualStyle != ApplicationHeaderStyle.None || (firstVisibleItem && firstVisibleItem.globalToolBarStyle == ApplicationHeaderStyle.ToolBar)
541  visible: active
542  height: active ? implicitHeight : 0
543  source: Qt.resolvedUrl("private/globaltoolbar/PageRowGlobalToolBarUI.qml");
544  }
545 
546  QtObject {
547  id: pagesLogic
548  readonly property var componentCache: new Array()
549 
550  function initAndInsertPage(position, page, properties) {
551  var pageComp;
552 
553  if (page.createObject) {
554  // page defined as component
555  pageComp = page;
556  } else if (typeof page == "string") {
557  // page defined as string (a url)
558  pageComp = pagesLogic.componentCache[page];
559  if (!pageComp) {
560  pageComp = pagesLogic.componentCache[page] = Qt.createComponent(page);
561  }
562  }
563  if (pageComp) {
564  // instantiate page from component
565  // FIXME: parent directly to columnView or root?
566  page = pageComp.createObject(null, properties || {});
567  columnView.insertItem(position, page);
568 
569  if (pageComp.status === Component.Error) {
570  throw new Error("Error while loading page: " + pageComp.errorString());
571  }
572  } else {
573  // copy properties to the page
574  for (var prop in properties) {
575  if (properties.hasOwnProperty(prop)) {
576  page[prop] = properties[prop];
577  }
578  }
579  columnView.insertItem(position, page);
580  }
581 
582  return page;
583  }
584  }
585 
586  ColumnView {
587  id: columnView
588 
589  topPadding: globalToolBarUI.item && globalToolBarUI.item.breadcrumbVisible
590  ? globalToolBarUI.height : 0
591 
592  // Internal hidden api for Page
593  readonly property Item __pageRow: root
594  columnResizeMode: root.wideMode ? ColumnView.FixedColumns : ColumnView.SingleColumn
595  columnWidth: root.defaultColumnWidth
596 
597  onItemInserted: root.pageInserted(position, item);
598  onItemRemoved: root.pageRemoved(item);
599  }
600 
601  Rectangle {
602  anchors.bottom: parent.bottom
603  height: Units.smallSpacing
604  x: (columnView.width - width) * (columnView.contentX / (columnView.contentWidth - columnView.width))
605  width: columnView.width * (columnView.width/columnView.contentWidth)
606  color: Theme.textColor
607  opacity: 0
608  onXChanged: {
609  opacity = 0.3
610  scrollIndicatorTimer.restart();
611  }
612  Behavior on opacity {
613  OpacityAnimator {
614  duration: Units.longDuration
615  easing.type: Easing.InOutQuad
616  }
617  }
618  Timer {
619  id: scrollIndicatorTimer
620  interval: Units.longDuration * 4
621  onTriggered: parent.opacity = 0;
622  }
623  }
624 }
ColumnView is a container that lays out items horizontally in a row, when not all items fit in the Co...
Definition: columnview.h:119
int gridUnit
The fundamental unit of space that should be used for sizes, expressed in pixels. ...
QTextStream & left(QTextStream &s)
int smallSpacing
units.smallSpacing is the amount of spacing that should be used around smaller UI elements...
A set of named colors for the application.
QTextStream & right(QTextStream &s)
int longDuration
units.longDuration should be used for longer, screen-covering animations, for opening and closing of ...
A set of values to define semantically sizes and durations.
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Sat Sep 19 2020 22:37:51 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.