Compare commits
46
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b9e4f4f2 | ||
|
|
da9dc2f46a | ||
|
|
d301b94c70 | ||
|
|
ea9a560277 | ||
|
|
eb4aae4060 | ||
|
|
597ae19242 | ||
|
|
7e02a32f48 | ||
|
|
4cc0d2bbca | ||
|
|
4bcd89b38a | ||
|
|
64b2a51c09 | ||
|
|
ab9ab2497b | ||
|
|
98dab4ff82 | ||
|
|
1452748331 | ||
|
|
074dc22ba5 | ||
|
|
9c5f79a695 | ||
|
|
6114c99311 | ||
|
|
86f50edfdc | ||
|
|
e945577e3c | ||
|
|
8360d3e415 | ||
|
|
71fbdef164 | ||
|
|
8aba017c24 | ||
|
|
a37489204c | ||
|
|
dab12dc7c8 | ||
|
|
409c2ccafa | ||
|
|
e1b0f2dc9a | ||
|
|
bdd699557d | ||
|
|
9fdc9aeaa3 | ||
|
|
6789446df3 | ||
|
|
5e15cc49f6 | ||
|
|
6e10959e40 | ||
|
|
0764e25a58 | ||
|
|
5043b0b625 | ||
|
|
694a4ca1ec | ||
|
|
c276a90e73 | ||
|
|
dce45c2ff3 | ||
|
|
d9da5bdc1d | ||
|
|
b6a6e220f7 | ||
|
|
478177f25e | ||
|
|
654bd9f284 | ||
|
|
a2e3659d99 | ||
|
|
5c3267f7e6 | ||
|
|
0631d500e1 | ||
|
|
8f8cb336c2 | ||
|
|
3e24b71075 | ||
|
|
40c0e48b04 | ||
|
|
8820cd89be |
@@ -12,3 +12,4 @@ Makefile
|
||||
.qmake.stash
|
||||
*_qml.cpp
|
||||
*_qmlcache.qrc
|
||||
sandbox/qmlcache_loader.cpp
|
||||
|
||||
+137
@@ -1,3 +1,140 @@
|
||||
<a name=""></a>
|
||||
## Version 0.16.0 (2021-11-01)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **StatusModal:** render footer correctly based on `showFooter` flag ([da9dc2f4](da9dc2f4))
|
||||
* **StatusRoundButton:** ensure disabled state uses correct background color ([eb4aae40](eb4aae40))
|
||||
|
||||
#### Features
|
||||
|
||||
* **StatusQ.Controls:**
|
||||
* introduce `StatusWalletColorSelect` control ([ea9a5602](ea9a5602), closes [#467](467))
|
||||
* introduce `StatusWalletColorButton` component ([597ae192](597ae192), closes [#466](466))
|
||||
* **StatusQ.Platform:** introduce StatusMacNotification component ([d301b94c](d301b94c))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## Version 0.15.0 (2021-10-26)
|
||||
|
||||
|
||||
#### Features
|
||||
|
||||
* **StatusQ.Controls:**
|
||||
* introduce StatusChatCommandButton ([4cc0d2bb](4cc0d2bb), closes [#429](429))
|
||||
* introduce `StatusTabBarIconButton` component ([4bcd89b3](4bcd89b3), closes [#428](428))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## Version 0.14.0 (2021-10-25)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **Spellchecking:** Add check for hunspell existence ([ab9ab249](ab9ab249))
|
||||
* **StatusModal:**
|
||||
* ensure `onEditButtonClicked` signal is emitted ([074dc22b](074dc22b), closes [#454](454))
|
||||
* expose `header.editable` property ([9c5f79a6](9c5f79a6), closes [#452](452))
|
||||
|
||||
#### Features
|
||||
|
||||
* **StatusSmartIdenticon:** Created a new StatusQ componnent to accomodate: ([14527483](14527483))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## Version 0.13.0 (2021-10-19)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* use proper double checkmark icon ([8aba017c](8aba017c))
|
||||
* **StatusBaseButton:** introduce missing `highlighted` property ([a3748920](a3748920))
|
||||
|
||||
#### Features
|
||||
|
||||
* **StatusFlatRoundButton:** Update the StatusFlatRoundButton to take over button behaviour from StatusIconButton under ui/shared/status ([71fbdef1](71fbdef1))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## Version 0.12.0 (2021-10-18)
|
||||
|
||||
|
||||
#### Features
|
||||
|
||||
* Resolve StatusQ modules highlighting and add qml compiler for detecting coompile time errors ([e1b0f2dc](e1b0f2dc))
|
||||
* **StatusModal:** Add edit avatar button ([5043b0b6](5043b0b6))
|
||||
* **StatusQ.Components:** introduce `StatusAddress` component ([6789446d](6789446d), closes [#430](430))
|
||||
* **StatusQ.Controls:**
|
||||
* introduce StatusColorSelector component ([bdd69955](bdd69955), closes [#444](444))
|
||||
* introduce `StatusAssetSelector` component ([9fdc9aea](9fdc9aea), closes [#442](442))
|
||||
* introduce `StatusAccountSelector` component ([5e15cc49](5e15cc49), closes [#435](435))
|
||||
* introduce `StatusSelect` ([6e10959e](6e10959e), closes [#436](436))
|
||||
* **StatusQ.Popups:** introduce `StatusMenuItemDelegate` ([0764e25a](0764e25a))
|
||||
|
||||
#### Breaking Changes
|
||||
|
||||
* **StatusQ.Popups:** introduce `StatusMenuItemDelegate` ([0764e25a](0764e25a))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## Version 0.11.1(2021-10-12)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* Sandbox doesn't build on Linux machines ([dce45c2f](dce45c2f))
|
||||
* **StatusChatInfoButton:** StatusChatInfoButton takes up entire available width ([c276a90e](c276a90e))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## v0.11.0 (2021-09-27)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* track category opened state ([0631d500](0631d500))
|
||||
* **StatusChatList:** ensure right click popup opens in correct position ([a2e3659d](a2e3659d))
|
||||
* **StatusSearchPopup:** use correct theme color for search result text ([654bd9f2](654bd9f2))
|
||||
* **StatusSpellcheckingMenuItems:** Exact menu items order ([478177f2](478177f2))
|
||||
|
||||
#### Features
|
||||
|
||||
* add star icons (#422) ([5c3267f7](5c3267f7))
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## v0.10.0 (2021-09-20)
|
||||
|
||||
|
||||
#### Bug Fixes
|
||||
|
||||
* **StatusChatInfoToolBar:** Right anchored title in StatusChatInfoToolBar ([6e8a36be](6e8a36be))
|
||||
* **StatusChatListCategoryItem:** Disable sensor when chevron clicked ([c83641d2](c83641d2))
|
||||
* **StatusQ.Controls.Validators:** fix bug that addressOrEns validator isn't properly exposed in QML ([1374c193](1374c193))
|
||||
|
||||
#### Features
|
||||
|
||||
* **Spellchecker:** Add Spellchecker class ([c65f80d2](c65f80d2))
|
||||
* **Spellchecking:**
|
||||
* Add dictionaries ([1d12d222](1d12d222))
|
||||
* Add huspell dependency ([f9457ef3](f9457ef3))
|
||||
* **StatusChatList:** expose `statusChatListItems` Repeater ([40c0e48b](40c0e48b))
|
||||
* **StatusExpandableItem:** Correct placement of expandable region in tertiary type ([1f244f62](1f244f62))
|
||||
* **StatusInput:**
|
||||
* add support for asynchronous validators ([8820cd89](8820cd89), closes [#395](395))
|
||||
* introduce `leftPadding` and `rightPadding` properties ([13dc8ae3](13dc8ae3))
|
||||
* introduce `reset` API ([a2ad08e4](a2ad08e4))
|
||||
* **StatusSpellcheckingMenuItems:** Add spellchecking menu ([3e24b710](3e24b710))
|
||||
|
||||
|
||||
|
||||
<a name=""></a>
|
||||
## v0.9.0 (2021-09-13)
|
||||
|
||||
|
||||
@@ -240,6 +240,63 @@ Column {
|
||||
loading: true
|
||||
size: StatusBaseButton.Size.Small
|
||||
}
|
||||
|
||||
// Tertiary
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
icon.name: "gif"
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
icon.name: "gif"
|
||||
enabled: false
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
icon.name: "gif"
|
||||
loading: true
|
||||
}
|
||||
|
||||
// No background Tertiary
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
color: "transparent"
|
||||
icon.name: "gif"
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
icon.name: "gif"
|
||||
color: "transparent"
|
||||
enabled: false
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Tertiary
|
||||
icon.name: "gif"
|
||||
color: "transparent"
|
||||
loading: true
|
||||
}
|
||||
|
||||
// Quartenery
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Quaternary
|
||||
icon.name: "gif"
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Quaternary
|
||||
icon.name: "gif"
|
||||
enabled: false
|
||||
}
|
||||
|
||||
StatusFlatRoundButton {
|
||||
type: StatusFlatRoundButton.Type.Quaternary
|
||||
icon.name: "gif"
|
||||
loading: true
|
||||
}
|
||||
}
|
||||
|
||||
StatusPickerButton {
|
||||
|
||||
@@ -12,6 +12,21 @@ GridLayout {
|
||||
columnSpacing: 5
|
||||
rowSpacing: 5
|
||||
|
||||
StatusSelectableText {
|
||||
color: Theme.palette.baseColor1
|
||||
text: "This is a multiline paragraph that can be selected and copied. A paragraph is a group of words put together to form a group that is usually longer than a sentence. Paragraphs are often made up of several sentences. There are usually between three and eight sentences. Paragraphs can begin with an indentation (about five spaces), or by missing a line out, and then starting again."
|
||||
font.pixelSize: 15
|
||||
width: 300
|
||||
multiline: true
|
||||
}
|
||||
|
||||
StatusSelectableText {
|
||||
color: Theme.palette.baseColor1
|
||||
text: "<p>This is a selectable link in rich text format to test <a href='www.google.com'>www.google.com</a></p>"
|
||||
font.pixelSize: 15
|
||||
width: 200
|
||||
}
|
||||
|
||||
StatusIconTabButton {
|
||||
icon.name: "chat"
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
StatusListItem {
|
||||
title: "Title"
|
||||
icon.isLetterIdenticon: true
|
||||
icon.background.color: "orange"
|
||||
icon.color: "orange"
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
|
||||
@@ -53,6 +53,11 @@ Column {
|
||||
onClicked: modalWithIdenticon.open()
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Modal with editable identicon"
|
||||
onClicked: modalWithEditableIdenticon.open()
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Modal with long titles"
|
||||
onClicked: modalWithLongTitles.open()
|
||||
@@ -63,6 +68,11 @@ Column {
|
||||
onClicked: modalWithHeaderPopupMenu.open()
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
text: "Spellchecking menu"
|
||||
onClicked: spellMenu.open()
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: simpleModal
|
||||
anchors.centerIn: parent
|
||||
@@ -254,6 +264,33 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
]
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: modalWithEditableIdenticon
|
||||
anchors.centerIn: parent
|
||||
header.title: "Header"
|
||||
header.subTitle: "SubTitle"
|
||||
header.headerImageEditable: true
|
||||
header.image.source: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAYAAAAeP4ixAAAAlklEQVR4nOzW0QmDQBAG4SSkl7SUQlJGCrElq9F3QdjjVhh/5nv3cFhY9vUIYQiNITSG0Bh
|
||||
CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2ImYgiNITTlTdG1nUZ5a92VITQxITFiJmIIjSE0htAYQrMHAAD//+wwFVpz+yqXAAAAAElFTkSuQmCC"
|
||||
header.image.isIdenticon: true
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.centerIn: parent
|
||||
text: "Some text content"
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
rightButtons: [
|
||||
StatusButton {
|
||||
text: "Change text"
|
||||
onClicked: {
|
||||
modalWithIdenticon.contentItem.text = "Changed!"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
StatusModal {
|
||||
id: modalWithLongTitles
|
||||
anchors.centerIn: parent
|
||||
@@ -309,4 +346,10 @@ CExPynn1gWf9bx498P7/nzPcxEzGExhBdJGYihtAYQlO+tUZvqrPbqeudo5iJGEJjCE15a3VtodH3q2I
|
||||
ListElement{name: "Account 1"; iconName: "filled-account"}
|
||||
ListElement{name: "Account 2"; iconName: "filled-account"}
|
||||
}
|
||||
|
||||
StatusSpellcheckingMenuItems {
|
||||
id: spellMenu
|
||||
anchors.centerIn: parent
|
||||
suggestions: ["suggestion1", "suggestion2", "suggestion3", "suggestion4"]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusAccountSelector {
|
||||
accounts: ListModel {
|
||||
ListElement {
|
||||
name: "Pascal"
|
||||
address: "0x1234567891011"
|
||||
iconColor: "red"
|
||||
balance: "0"
|
||||
walletType: "generated"
|
||||
assets: []
|
||||
fiatBalance: "1199.02"
|
||||
}
|
||||
ListElement {
|
||||
name: "Boris"
|
||||
address: "0x123"
|
||||
iconColor: "red"
|
||||
balance: "0"
|
||||
walletType: "generated"
|
||||
assets: []
|
||||
fiatBalance: "0"
|
||||
}
|
||||
ListElement {
|
||||
name: "Alexandra"
|
||||
address: "0x123"
|
||||
iconColor: "yellow"
|
||||
balance: "0"
|
||||
walletType: "generated"
|
||||
assets: []
|
||||
fiatBalance: "0"
|
||||
}
|
||||
ListElement {
|
||||
name: "Khushboo"
|
||||
address: "0x123"
|
||||
iconColor: "blue"
|
||||
balance: "0"
|
||||
walletType: "generated"
|
||||
assets: []
|
||||
fiatBalance: "0"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusAddress {
|
||||
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
|
||||
}
|
||||
|
||||
Item {
|
||||
width: 200
|
||||
height: childrenRect.height
|
||||
StatusAddress {
|
||||
text: "0x9ce0056c5fc6bb9459a4dcfa35eaad8c1fee5ce9"
|
||||
expandable: true
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusAssetSelector {
|
||||
assets: ListModel {
|
||||
ListElement {
|
||||
address: "0x1234"
|
||||
name: "Status Network Token"
|
||||
value: "20"
|
||||
symbol: "SNT"
|
||||
fiatBalance: "9992.01"
|
||||
fiatBalanceDisplay: "9992.01"
|
||||
}
|
||||
ListElement {
|
||||
address: "0x1234"
|
||||
name: "DAI Token"
|
||||
value: "20"
|
||||
symbol: "DAI"
|
||||
fiatBalance: "20"
|
||||
fiatBalanceDisplay: "20"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusChatCommandButton {
|
||||
icon.name: "send"
|
||||
icon.color: Theme.palette.miscColor2
|
||||
text: "Send transaction"
|
||||
}
|
||||
|
||||
StatusChatCommandButton {
|
||||
icon.name: "send"
|
||||
icon.rotation: 180
|
||||
icon.color: Theme.palette.miscColor8
|
||||
text: "Receive transaction"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusColorSelector {
|
||||
model: ["red", "blue", "green"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Platform 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusMacNotification {
|
||||
name: "Some name"
|
||||
message: "Some message here"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusSelect {
|
||||
id: select
|
||||
label: "Some label"
|
||||
model: ListModel {
|
||||
ListElement {
|
||||
name: "Pascal"
|
||||
}
|
||||
ListElement {
|
||||
name: "Khushboo"
|
||||
}
|
||||
ListElement {
|
||||
name: "Alexandra"
|
||||
}
|
||||
ListElement {
|
||||
name: "Eric"
|
||||
}
|
||||
}
|
||||
selectMenu.delegate: StatusMenuItemDelegate {
|
||||
statusPopupMenu: select
|
||||
action: StatusMenuItem {
|
||||
iconSettings.name: "filled-account"
|
||||
text: name
|
||||
onTriggered: {
|
||||
selectedItem.text = name
|
||||
}
|
||||
}
|
||||
}
|
||||
selectedItemComponent: Item {
|
||||
id: selectedItem
|
||||
anchors.fill: parent
|
||||
property string text: ""
|
||||
|
||||
StatusBaseText {
|
||||
text: selectedItem.text
|
||||
anchors.centerIn: parent
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
Row {
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "smileys-and-people"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "animals-and-nature"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "activity"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "travel-and-places"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "objects"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "symbols"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
|
||||
StatusTabBarIconButton {
|
||||
icon.name: "flags"
|
||||
onClicked: highlighted = !highlighted
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
Row {
|
||||
spacing: 4
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor1
|
||||
selected: true
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor2
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor3
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor4
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor5
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor6
|
||||
}
|
||||
StatusWalletColorButton {
|
||||
icon.color: Theme.palette.miscColor7
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
import Sandbox 0.1
|
||||
|
||||
Column {
|
||||
spacing: 8
|
||||
|
||||
StatusWalletColorSelect {
|
||||
model: Theme.palette.accountColors
|
||||
}
|
||||
}
|
||||
@@ -143,17 +143,62 @@ StatusWindow {
|
||||
selected: page.sourceComponent == statusTabSwitchesComponent
|
||||
onClicked: page.sourceComponent = statusTabSwitchesComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusChatCommandButton"
|
||||
selected: page.sourceComponent == statusChatCommandButtonPageComponent
|
||||
onClicked: page.sourceComponent = statusChatCommandButtonPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "Controls"
|
||||
selected: page.sourceComponent == controlsComponent
|
||||
onClicked: page.sourceComponent = controlsComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusTabBarIconButton"
|
||||
selected: page.sourceComponent == statusTabBarIconButtonPageComponent
|
||||
onClicked: page.sourceComponent = statusTabBarIconButtonPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusInput"
|
||||
selected: page.sourceComponent == statusInputPageComponent
|
||||
onClicked: page.sourceComponent = statusInputPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusSelect"
|
||||
selected: page.sourceComponent == statusSelectPageComponent
|
||||
onClicked: page.sourceComponent = statusSelectPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAccountSelector"
|
||||
selected: page.sourceComponent == statusAccountSelectorPageComponent
|
||||
onClicked: page.sourceComponent = statusAccountSelectorPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAssetSelector"
|
||||
selected: page.sourceComponent == statusAssetSelectorPageComponent
|
||||
onClicked: page.sourceComponent = statusAssetSelectorPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusColorSelector"
|
||||
selected: page.sourceComponent == statusColorSelectorPageComponent
|
||||
onClicked: page.sourceComponent = statusColorSelectorPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusWalletColorButton"
|
||||
selected: page.sourceComponent == statusWalletColorButtonPageComponent
|
||||
onClicked: page.sourceComponent = statusWalletColorButtonPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "StatusWalletColorSelect"
|
||||
selected: page.sourceComponent == statusWalletColorSelectPageComponent
|
||||
onClicked: page.sourceComponent = statusWalletColorSelectPageComponent
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Components" }
|
||||
StatusNavigationListItem {
|
||||
title: "StatusAddress"
|
||||
selected: page.sourceComponent == statusAddressPageComponent
|
||||
onClicked: page.sourceComponent = statusAddressPageComponent
|
||||
}
|
||||
StatusNavigationListItem {
|
||||
title: "List Items"
|
||||
selected: page.sourceComponent == listItemsComponent
|
||||
@@ -186,6 +231,12 @@ StatusWindow {
|
||||
selected: page.sourceComponent == statusModalComponent
|
||||
onClicked: page.sourceComponent = statusModalComponent
|
||||
}
|
||||
StatusListSectionHeadline { text: "StatusQ.Platform" }
|
||||
StatusNavigationListItem {
|
||||
title: "StatusMacNotification"
|
||||
selected: page.sourceComponent == notificationComponent
|
||||
onClicked: page.sourceComponent = notificationComponent
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,11 +307,51 @@ StatusWindow {
|
||||
StatusInputPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusSelectPageComponent
|
||||
StatusSelectPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusAccountSelectorPageComponent
|
||||
StatusAccountSelectorPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusAssetSelectorPageComponent
|
||||
StatusAssetSelectorPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusColorSelectorPageComponent
|
||||
StatusColorSelectorPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusTabBarIconButtonPageComponent
|
||||
StatusTabBarIconButtonPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusWalletColorButtonPageComponent
|
||||
StatusWalletColorButtonPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusWalletColorSelectPageComponent
|
||||
StatusWalletColorSelectPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: listItemsComponent
|
||||
ListItems {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusAddressPageComponent
|
||||
StatusAddressPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: layoutComponent
|
||||
Layout {}
|
||||
@@ -276,6 +367,11 @@ StatusWindow {
|
||||
Buttons {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusChatCommandButtonPageComponent
|
||||
StatusChatCommandButtonPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: popupMenuComponent
|
||||
StatusPopupMenuPage {}
|
||||
@@ -301,6 +397,11 @@ StatusWindow {
|
||||
StatusExpandableSettingsItemPage{}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: notificationComponent
|
||||
StatusMacNotificationPage {}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: demoAppCmp
|
||||
|
||||
|
||||
+9
-4
@@ -1,6 +1,8 @@
|
||||
QT += quick svg
|
||||
|
||||
CONFIG += c++11 warn_on
|
||||
CONFIG += c++11 warn_on qtquickcompiler
|
||||
|
||||
QML_IMPORT_PATH= $$PWD/../src
|
||||
|
||||
DEFINES += QT_DEPRECATED_WARNINGS
|
||||
|
||||
@@ -30,9 +32,12 @@ macx {
|
||||
hunspellTarget.commands = brew install hunspell
|
||||
QMAKE_EXTRA_TARGETS += hunspellTarget
|
||||
|
||||
|
||||
LIBS += -L"/usr/local/lib" -lhunspell-1.7
|
||||
INCLUDEPATH += /usr/local/include/hunspell
|
||||
exists (/usr/local/lib/libhunspell-1.7.a) {
|
||||
LIBS += -L"/usr/local/lib" -lhunspell-1.7
|
||||
INCLUDEPATH += /usr/local/include/hunspell
|
||||
DEFINES += USE_HUNSPELL
|
||||
message("hunspell exists in /usr/local/lib")
|
||||
}
|
||||
}
|
||||
|
||||
ios {
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
#include "spellchecker.h"
|
||||
|
||||
#ifdef USE_HUNSPELL
|
||||
#include "hunspell.hxx"
|
||||
#endif
|
||||
#include <QTextCodec>
|
||||
#include <QFile>
|
||||
#include <QDebug>
|
||||
@@ -12,22 +14,24 @@
|
||||
|
||||
SpellChecker::SpellChecker(QObject *parent)
|
||||
: QObject(parent)
|
||||
, m_hunspell(nullptr)
|
||||
, m_userDict("userDict_")
|
||||
#ifdef USE_HUNSPELL
|
||||
, m_hunspell(nullptr)
|
||||
#endif
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
SpellChecker::~SpellChecker()
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
delete m_hunspell;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool SpellChecker::spell(const QString &word)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
return m_hunspell->spell(m_codec->fromUnicode(word).toStdString());
|
||||
#else
|
||||
return true;
|
||||
@@ -36,12 +40,15 @@ bool SpellChecker::spell(const QString &word)
|
||||
|
||||
bool SpellChecker::isInit() const
|
||||
{
|
||||
#ifdef USE_HUNSPELL
|
||||
return !m_hunspell;
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
void SpellChecker::initHunspell()
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
if (m_hunspell) {
|
||||
delete m_hunspell;
|
||||
}
|
||||
@@ -102,7 +109,7 @@ QVariantList SpellChecker::suggest(const QString &word)
|
||||
{
|
||||
int numSuggestions = 0;
|
||||
QVariantList suggestions;
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
std::vector<std::string> wordlist;
|
||||
wordlist = m_hunspell->suggest(m_codec->fromUnicode(word).toStdString());
|
||||
|
||||
@@ -121,14 +128,14 @@ QVariantList SpellChecker::suggest(const QString &word)
|
||||
|
||||
void SpellChecker::ignoreWord(const QString &word)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
m_hunspell->add(m_codec->fromUnicode(word).constData());
|
||||
#endif
|
||||
}
|
||||
|
||||
void SpellChecker::addToUserWordlist(const QString &word)
|
||||
{
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
QString userDict = m_userDict + m_lang + ".txt";
|
||||
if (!userDict.isEmpty()) {
|
||||
QFile userDictonaryFile(userDict);
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
#include <QQuickTextDocument>
|
||||
#include <QSyntaxHighlighter>
|
||||
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
class Hunspell;
|
||||
#endif
|
||||
class QTextCodec;
|
||||
@@ -45,7 +45,7 @@ private:
|
||||
QString m_userDict;
|
||||
|
||||
QQuickTextDocument *m_document;
|
||||
#ifdef Q_OS_MACOS
|
||||
#ifdef USE_HUNSPELL
|
||||
Hunspell *m_hunspell;
|
||||
#endif
|
||||
QTextCodec *m_codec;
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
StatusBaseText {
|
||||
id: root
|
||||
|
||||
property bool expandable: false
|
||||
property bool expanded: false
|
||||
readonly property real actualWidth: implicitWidth
|
||||
property real maxWidth: width
|
||||
|
||||
font.family: Theme.palette.monoFont.name
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideMiddle
|
||||
color: Theme.palette.baseColor1
|
||||
|
||||
Component.onCompleted: {
|
||||
maxWidth = width
|
||||
expanded = actualWidth <= maxWidth
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
cursorShape: root.expandable ? Qt.PointingHandCursor : Qt.arrowCursor
|
||||
enabled: root.expandable
|
||||
|
||||
onClicked: {
|
||||
if (root.expanded) {
|
||||
width = root.width = root.maxWidth
|
||||
} else {
|
||||
width = root.width = root.actualWidth
|
||||
}
|
||||
root.expanded = !root.expanded
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ Column {
|
||||
property alias chatListItems: delegateModel
|
||||
property bool draggableItems: false
|
||||
|
||||
property alias statusChatListItems: statusChatListItems
|
||||
|
||||
property Component popupMenu
|
||||
|
||||
property var filterFn
|
||||
@@ -143,7 +145,9 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
popupMenuSlot.item.popup(mouse.x + 4, statusChatListItem.y + mouse.y + 6)
|
||||
let p = statusChatListItem.mapToItem(statusChatList, mouse.x, mouse.y)
|
||||
|
||||
popupMenuSlot.item.popup(p.x + 4, p.y + 6)
|
||||
popupMenuSlot.item.openHandler = originalOpenHandler
|
||||
return
|
||||
}
|
||||
|
||||
@@ -28,6 +28,9 @@ Item {
|
||||
property alias sensor: sensor
|
||||
property bool draggableItems: false
|
||||
property bool draggableCategories: false
|
||||
// Keeps track of expanded category state. Should only be modified
|
||||
// internally at runtime.
|
||||
property var openedCategoryState: new Object({})
|
||||
|
||||
property Component categoryPopupMenu
|
||||
property Component chatListPopupMenu
|
||||
@@ -147,6 +150,21 @@ Item {
|
||||
|
||||
popupMenu: statusChatListAndCategories.categoryPopupMenu
|
||||
chatListPopupMenu: statusChatListAndCategories.chatListPopupMenu
|
||||
|
||||
// Used to set the initial value of "opened" when the
|
||||
// model is bound/changed.
|
||||
opened: {
|
||||
let openedState = statusChatListAndCategories.openedCategoryState[model.categoryId]
|
||||
return openedState !== undefined ? openedState : true // defaults to open
|
||||
}
|
||||
|
||||
// Used to track the internal changes of the `opened`
|
||||
// property. This cannot be brought inside the component
|
||||
// as the state would be lost each time the model is
|
||||
// changed.
|
||||
onOpenedChanged: {
|
||||
statusChatListAndCategories.openedCategoryState[model.categoryId] = statusChatListCategory.opened
|
||||
}
|
||||
}
|
||||
|
||||
DropArea {
|
||||
|
||||
@@ -20,9 +20,15 @@ Rectangle {
|
||||
property bool hasUnreadMessages: false
|
||||
property bool hasMention: false
|
||||
property bool muted: false
|
||||
property StatusImageSettings image: StatusImageSettings {}
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
}
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
color: Theme.palette.miscColor5
|
||||
letterSize: 15
|
||||
}
|
||||
property int type: StatusChatListItem.Type.PublicChat
|
||||
property bool highlighted: false
|
||||
@@ -67,50 +73,14 @@ Rectangle {
|
||||
|
||||
onClicked: statusChatListItem.clicked(mouse)
|
||||
|
||||
Loader {
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
sourceComponent: !!statusChatListItem.image.source.toString() ?
|
||||
statusRoundedImageCmp : statusLetterIdenticonCmp
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticonCmp
|
||||
StatusLetterIdenticon {
|
||||
height: 24
|
||||
width: 24
|
||||
name: statusChatListItem.name
|
||||
letterSize: 15
|
||||
color: statusChatListItem.icon.color
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundedImageCmp
|
||||
Item {
|
||||
height: 24
|
||||
width: 24
|
||||
StatusRoundedImage {
|
||||
id: statusRoundedImage
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
image.source: statusChatListItem.image.source
|
||||
showLoadingIndicator: true
|
||||
color: statusChatListItem.image.isIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
border.width: statusChatListItem.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: statusLetterIdenticonCmp
|
||||
active: statusRoundedImage.image.status === Image.Error
|
||||
}
|
||||
}
|
||||
image: statusChatListItem.image
|
||||
icon: statusChatListItem.icon
|
||||
name: statusChatListItem.name
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
|
||||
@@ -18,6 +18,8 @@ Rectangle {
|
||||
property bool expanded: false
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: !!statusExpandableItem.icon.name.toString() ? 24 : 40
|
||||
height: !!statusExpandableItem.icon.name.toString() ? 24 : 40
|
||||
color: Theme.palette.directColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 32
|
||||
@@ -55,44 +57,17 @@ Rectangle {
|
||||
visible: (statusExpandableItem.type === StatusExpandableItem.Type.Tertiary)
|
||||
}
|
||||
|
||||
Loader {
|
||||
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 25
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: (statusExpandableItem.type === StatusExpandableItem.Type.Secondary) ? 0 : 11
|
||||
image: statusExpandableItem.image
|
||||
icon: statusExpandableItem.icon
|
||||
name: primaryText.text
|
||||
active: (statusExpandableItem.type !== StatusExpandableItem.Type.Tertiary)
|
||||
sourceComponent: !!statusExpandableItem.image.source.toString() ? roundedImage :
|
||||
!!statusExpandableItem.icon.name.toString() ? roundedIcon : letterIdenticon
|
||||
}
|
||||
|
||||
Component {
|
||||
id: roundedImage
|
||||
StatusRoundedImage {
|
||||
image.source: statusExpandableItem.image.source
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: roundedIcon
|
||||
StatusRoundIcon {
|
||||
icon.background.width: statusExpandableItem.icon.background.width
|
||||
icon.background.height: statusExpandableItem.icon.background.height
|
||||
icon.background.color: statusExpandableItem.icon.background.color
|
||||
icon.color: statusExpandableItem.icon.color
|
||||
icon.name: statusExpandableItem.icon.name
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: letterIdenticon
|
||||
StatusLetterIdenticon {
|
||||
height: 40
|
||||
width: 40
|
||||
name: primaryText.text
|
||||
letterSize: 20
|
||||
color: Theme.palette.miscColor5
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
|
||||
@@ -47,11 +47,12 @@ Rectangle {
|
||||
property real rightPadding: 16
|
||||
property bool enabled: true
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
height: 20
|
||||
width: 20
|
||||
height: isLetterIdenticon ? 40 : 20
|
||||
width: isLetterIdenticon ? 40 : 20
|
||||
rotation: 0
|
||||
isLetterIdenticon: false
|
||||
color: type === StatusListItem.Type.Danger ?
|
||||
letterSize: 21
|
||||
color: isLetterIdenticon ? background.color : type === StatusListItem.Type.Danger ?
|
||||
Theme.palette.dangerColor1 : Theme.palette.primaryColor1
|
||||
background: StatusIconBackgroundSettings {
|
||||
width: 40
|
||||
@@ -110,62 +111,20 @@ Rectangle {
|
||||
statusListItem.clicked(statusListItem.itemId)
|
||||
}
|
||||
|
||||
Loader {
|
||||
StatusSmartIdenticon {
|
||||
id: iconOrImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: statusListItem.leftPadding
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 12
|
||||
sourceComponent: {
|
||||
if (statusListItem.icon.isLetterIdenticon) {
|
||||
return statusLetterIdenticon
|
||||
}
|
||||
return !!statusListItem.icon.name ? statusRoundedIcon : statusRoundedImage
|
||||
}
|
||||
|
||||
image: statusListItem.image
|
||||
icon: statusListItem.icon
|
||||
name: statusListItem.title
|
||||
active: statusListItem.icon.isLetterIdenticon ||
|
||||
!!statusListItem.icon.name ||
|
||||
!!statusListItem.image.source.toString()
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundedIcon
|
||||
StatusRoundIcon {
|
||||
icon.width: statusListItem.icon.width
|
||||
icon.height: statusListItem.icon.height
|
||||
icon.name: statusListItem.icon.name
|
||||
icon.rotation: statusListItem.icon.rotation
|
||||
icon.color: statusListItem.icon.color
|
||||
color: statusListItem.icon.background.color
|
||||
width: statusListItem.icon.background.width
|
||||
height: statusListItem.icon.background.height
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundedImage
|
||||
StatusRoundedImage {
|
||||
image.source: statusListItem.image.source
|
||||
image.height: statusListItem.image.height
|
||||
image.width: statusListItem.image.width
|
||||
color: statusListItem.image.isIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
border.width: statusListItem.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticon
|
||||
StatusLetterIdenticon {
|
||||
width: statusListItem.icon.background.width
|
||||
height: statusListItem.icon.background.height
|
||||
color: statusListItem.icon.background.color
|
||||
name: statusListItem.title
|
||||
}
|
||||
}
|
||||
|
||||
Item {
|
||||
id: statusListItemTitleArea
|
||||
anchors.left: iconOrImage.active ? iconOrImage.right : parent.left
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
import QtQuick 2.13
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Loader {
|
||||
id: statusSmartIdenticon
|
||||
|
||||
property string name: ""
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
}
|
||||
|
||||
sourceComponent: statusSmartIdenticon.icon.isLetterIdenticon ? letterIdenticon :
|
||||
!!statusSmartIdenticon.image.source.toString() ? roundedImage :
|
||||
!!statusSmartIdenticon.icon.name.toString() ? roundedIcon : letterIdenticon
|
||||
|
||||
Component {
|
||||
id: roundedImage
|
||||
Item {
|
||||
width: statusSmartIdenticon.image.width
|
||||
height: statusSmartIdenticon.image.height
|
||||
StatusRoundedImage {
|
||||
id: statusRoundImage
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
image.source: statusSmartIdenticon.image.source
|
||||
showLoadingIndicator: true
|
||||
border.width: statusSmartIdenticon.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
color: statusSmartIdenticon.image.isIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
}
|
||||
Loader {
|
||||
anchors.centerIn: parent
|
||||
active: statusRoundImage.image.status === Image.Error
|
||||
sourceComponent: letterIdenticon
|
||||
onLoaded: {
|
||||
item.color = Theme.palette.miscColor5
|
||||
item.width = statusSmartIdenticon.image.width
|
||||
item.height = statusSmartIdenticon.image.height
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: roundedIcon
|
||||
StatusRoundIcon {
|
||||
icon.background.width: statusSmartIdenticon.icon.background.width
|
||||
icon.background.height: statusSmartIdenticon.icon.background.height
|
||||
icon.background.color: statusSmartIdenticon.icon.background.color
|
||||
icon.width: statusSmartIdenticon.icon.width
|
||||
icon.height: statusSmartIdenticon.icon.height
|
||||
icon.name: statusSmartIdenticon.icon.name
|
||||
icon.rotation: statusSmartIdenticon.icon.rotation
|
||||
icon.color: statusSmartIdenticon.icon.color
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: letterIdenticon
|
||||
StatusLetterIdenticon {
|
||||
width: statusSmartIdenticon.icon.width
|
||||
height: statusSmartIdenticon.icon.height
|
||||
color: statusSmartIdenticon.icon.color
|
||||
name: statusSmartIdenticon.name
|
||||
letterSize: statusSmartIdenticon.icon.letterSize
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
module StatusQ.Components
|
||||
|
||||
StatusAddress 0.1 StatusAddress.qml
|
||||
StatusBadge 0.1 StatusBadge.qml
|
||||
StatusChatInfoToolBar 0.1 StatusChatInfoToolBar.qml
|
||||
StatusChatList 0.1 StatusChatList.qml
|
||||
@@ -21,3 +22,4 @@ StatusRoundedImage 0.1 StatusRoundedImage.qml
|
||||
StatusMacWindowButtons 0.1 StatusMacWindowButtons.qml
|
||||
StatusListItemBadge 0.1 StatusListItemBadge.qml
|
||||
StatusExpandableItem 0.1 StatusExpandableItem.qml
|
||||
StatusSmartIdenticon 0.1 StatusSmartIdenticon.qml
|
||||
|
||||
@@ -0,0 +1,277 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtQml.Models 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property string label: "Choose account"
|
||||
property bool showAccountDetails: !!selectedAccount
|
||||
property var accounts
|
||||
property var selectedAccount
|
||||
property string currency: "usd"
|
||||
property alias selectField: select
|
||||
implicitWidth: 448
|
||||
height: select.height +
|
||||
(selectedAccountDetails.visible ? selectedAccountDetails.height + selectedAccountDetails.anchors.topMargin : 0)
|
||||
// set to asset symbol to display asset's balance top right
|
||||
// NOTE: if this asset is not selected as a wallet token in the UI, then
|
||||
// nothing will be displayed
|
||||
property string showBalanceForAssetSymbol: ""
|
||||
property var assetFound
|
||||
property double minRequiredAssetBalance: 0
|
||||
property int dropdownWidth: width
|
||||
property alias dropdownAlignment: select.menuAlignment
|
||||
property bool isValid: true
|
||||
property bool readOnly: false
|
||||
|
||||
property var assetBalanceTextFn: function (foundValue) {
|
||||
return "Balance: " + (parseFloat(foundValue) === 0.0 ? "0" : Utils.stripTrailingZeros(foundValue))
|
||||
}
|
||||
|
||||
readonly property string watchWalletType: "watch"
|
||||
|
||||
enum Type {
|
||||
Address,
|
||||
Contact,
|
||||
Account
|
||||
}
|
||||
|
||||
function validate() {
|
||||
if (showBalanceForAssetSymbol == "" || minRequiredAssetBalance == 0 || !assetFound) {
|
||||
return root.isValid
|
||||
}
|
||||
root.isValid = assetFound.value >= minRequiredAssetBalance
|
||||
return root.isValid
|
||||
}
|
||||
|
||||
onSelectedAccountChanged: {
|
||||
if (!selectedAccount) {
|
||||
return
|
||||
}
|
||||
if (selectedAccount.iconColor) {
|
||||
selectedIconImg.color = Utils.getThemeAccountColor(selectedAccount.iconColor, Theme.palette.accountColors) || Theme.palette.accountColors[0]
|
||||
}
|
||||
if (selectedAccount.name) {
|
||||
selectedTextField.text = selectedAccount.name
|
||||
}
|
||||
if (selectedAccount.address) {
|
||||
textSelectedAddress.text = selectedAccount.address + " •"
|
||||
}
|
||||
if (selectedAccount.fiatBalance) {
|
||||
textSelectedAddressFiatBalance.text = selectedAccount.fiatBalance + " " + currency.toUpperCase()
|
||||
}
|
||||
if (selectedAccount.assets && showBalanceForAssetSymbol) {
|
||||
assetFound = Utils.findAssetBySymbol(selectedAccount.assets, showBalanceForAssetSymbol)
|
||||
if (!assetFound) {
|
||||
console.warn("Cannot find asset '", showBalanceForAssetSymbol, "'. Ensure this asset has been added to the token list.")
|
||||
}
|
||||
}
|
||||
if (!selectedAccount.type) {
|
||||
selectedAccount.type = StatusAccountSelector.Type.Account
|
||||
}
|
||||
validate()
|
||||
}
|
||||
|
||||
onAssetFoundChanged: {
|
||||
if (!assetFound) {
|
||||
return
|
||||
}
|
||||
txtAssetBalance.text = root.assetBalanceTextFn(assetFound.value)
|
||||
txtAssetSymbol.text = " " + assetFound.symbol
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: txtAssetBalance
|
||||
visible: root.assetFound !== undefined
|
||||
anchors.bottom: select.top
|
||||
anchors.bottomMargin: -18
|
||||
anchors.right: txtAssetSymbol.left
|
||||
anchors.left: select.left
|
||||
anchors.leftMargin: select.width / 2.5
|
||||
|
||||
color: !root.isValid ? Theme.palette.dangerColor1 : Theme.palette.baseColor1
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: 13
|
||||
horizontalAlignment: Text.AlignRight
|
||||
height: 18
|
||||
|
||||
StatusToolTip {
|
||||
enabled: txtAssetBalance.truncated
|
||||
id: assetTooltip
|
||||
text: txtAssetBalance.text
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
enabled: txtAssetBalance.truncated
|
||||
anchors.fill: parent
|
||||
hoverEnabled: enabled
|
||||
onEntered: assetTooltip.visible = true
|
||||
onExited: assetTooltip.visible = false
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
id: txtAssetSymbol
|
||||
visible: txtAssetBalance.visible
|
||||
anchors.top: txtAssetBalance.top
|
||||
anchors.right: parent.right
|
||||
|
||||
color: txtAssetBalance.color
|
||||
font.pixelSize: 13
|
||||
height: txtAssetBalance.height
|
||||
}
|
||||
StatusSelect {
|
||||
id: select
|
||||
label: root.label
|
||||
model: root.accounts
|
||||
width: parent.width
|
||||
menuAlignment: StatusSelect.MenuAlignment.Left
|
||||
selectMenu.delegate: menuItem
|
||||
selectMenu.width: dropdownWidth
|
||||
selectedItemComponent: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
StatusIcon {
|
||||
id: selectedIconImg
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 20
|
||||
height: 20
|
||||
icon: "filled-account"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: selectedTextField
|
||||
elide: Text.ElideRight
|
||||
anchors.left: selectedIconImg.right
|
||||
anchors.leftMargin: 8
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: select.selectedItemRightMargin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 15
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
height: 22
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Row {
|
||||
id: selectedAccountDetails
|
||||
visible: root.showAccountDetails
|
||||
anchors.top: select.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 2
|
||||
|
||||
StatusBaseText {
|
||||
id: textSelectedAddress
|
||||
font.pixelSize: 12
|
||||
elide: Text.ElideMiddle
|
||||
width: 90
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
id: textSelectedAddressFiatBalance
|
||||
font.pixelSize: 12
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: menuItem
|
||||
MenuItem {
|
||||
id: itemContainer
|
||||
visible: walletType !== root.watchWalletType
|
||||
property bool isFirstItem: index === 0
|
||||
property bool isLastItem: index === accounts.rowCount() - 1
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!root.selectedAccount && isFirstItem) {
|
||||
root.selectedAccount = { address, name, iconColor, assets, fiatBalance }
|
||||
}
|
||||
}
|
||||
|
||||
height: walletType === root.watchWalletType ? 0 : (accountName.height + 14 + accountAddress.height + 14)
|
||||
|
||||
StatusIcon {
|
||||
id: iconImg
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 20
|
||||
height: 20
|
||||
icon: "filled-account"
|
||||
color: Utils.getThemeAccountColor(iconColor, Theme.palette.accountColors) || Theme.palette.accountColors[0]
|
||||
}
|
||||
|
||||
Column {
|
||||
id: column
|
||||
anchors.left: iconImg.right
|
||||
anchors.leftMargin: 14
|
||||
anchors.right: txtFiatBalance.left
|
||||
anchors.rightMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StatusBaseText {
|
||||
id: accountName
|
||||
text: name
|
||||
elide: Text.ElideRight
|
||||
font.pixelSize: 15
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
height: 22
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: accountAddress
|
||||
text: address
|
||||
elide: Text.ElideMiddle
|
||||
width: 80
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 12
|
||||
height: 16
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
id: txtFiatBalance
|
||||
anchors.right: fiatCurrencySymbol.left
|
||||
anchors.rightMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 15
|
||||
height: 22
|
||||
text: fiatBalance
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
StatusBaseText {
|
||||
id: fiatCurrencySymbol
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 15
|
||||
height: 22
|
||||
color: Theme.palette.baseColor1
|
||||
text: root.currency.toUpperCase()
|
||||
}
|
||||
background: Rectangle {
|
||||
color: itemContainer.highlighted ? Theme.palette.statusSelect.menuItemHoverBackgroundColor : Theme.palette.statusSelect.menuItemBackgroundColor
|
||||
}
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: itemContainer
|
||||
onClicked: {
|
||||
root.selectedAccount = { address, name, iconColor, assets, fiatBalance }
|
||||
select.selectMenu.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,150 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property var assets
|
||||
property var selectedAsset
|
||||
property var tokenAssetSourceFn: function (symbol) {
|
||||
return ""
|
||||
}
|
||||
property var assetGetterFn: function (index, field) {
|
||||
// This is merely to make the component work with nim model data
|
||||
// as well as static QML ListModel data
|
||||
if (typeof assets.get === "function") {
|
||||
return assets.get(index)[field]
|
||||
}
|
||||
return assets.rowData(index, field)
|
||||
}
|
||||
implicitWidth: 86
|
||||
implicitHeight: 32
|
||||
|
||||
function resetInternal() {
|
||||
assets = null
|
||||
selectedAsset = null
|
||||
}
|
||||
|
||||
onSelectedAssetChanged: {
|
||||
if (selectedAsset && selectedAsset.symbol) {
|
||||
iconImg.image.source = tokenAssetSourceFn(selectedAsset.symbol.toUpperCase())
|
||||
selectedTextField.text = selectedAsset.symbol.toUpperCase()
|
||||
}
|
||||
}
|
||||
|
||||
onAssetsChanged: {
|
||||
if (!assets) {
|
||||
return
|
||||
}
|
||||
selectedAsset = {
|
||||
name: assetGetterFn(0, "name"),
|
||||
symbol: assetGetterFn(0, "symbol"),
|
||||
value: assetGetterFn(0, "value"),
|
||||
fiatBalanceDisplay: assetGetterFn(0, "fiatBalanceDisplay"),
|
||||
address: assetGetterFn(0, "address"),
|
||||
fiatBalance: assetGetterFn(0, "fiatBalance")
|
||||
}
|
||||
}
|
||||
|
||||
StatusSelect {
|
||||
id: select
|
||||
width: parent.width
|
||||
bgColor: "transparent"
|
||||
bgColorHover: Theme.palette.directColor8
|
||||
model: root.assets
|
||||
caretRightMargin: 0
|
||||
select.radius: 6
|
||||
select.height: root.height
|
||||
selectMenu.width: 342
|
||||
selectedItemComponent: Item {
|
||||
anchors.fill: parent
|
||||
StatusRoundedImage {
|
||||
id: iconImg
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4
|
||||
width: 24
|
||||
height: 24
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
StatusBaseText {
|
||||
id: selectedTextField
|
||||
anchors.left: iconImg.right
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
font.pixelSize: 15
|
||||
height: 22
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
selectMenu.delegate: menuItem
|
||||
}
|
||||
|
||||
Component {
|
||||
id: menuItem
|
||||
MenuItem {
|
||||
id: itemContainer
|
||||
property bool isFirstItem: index === 0
|
||||
property bool isLastItem: index === assets.rowCount() - 1
|
||||
|
||||
width: parent.width
|
||||
height: 72
|
||||
StatusRoundedImage {
|
||||
id: iconImg
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image.source: root.tokenAssetSourceFn(symbol.toUpperCase())
|
||||
}
|
||||
Column {
|
||||
anchors.left: iconImg.right
|
||||
anchors.leftMargin: 12
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
StatusBaseText {
|
||||
text: symbol.toUpperCase()
|
||||
font.pixelSize: 15
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: name
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 15
|
||||
}
|
||||
}
|
||||
Column {
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
StatusBaseText {
|
||||
font.pixelSize: 15
|
||||
text: parseFloat(value).toFixed(4) + " " + symbol
|
||||
}
|
||||
StatusBaseText {
|
||||
font.pixelSize: 15
|
||||
anchors.right: parent.right
|
||||
text: fiatBalanceDisplay.toUpperCase()
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
background: Rectangle {
|
||||
color: itemContainer.highlighted ? Theme.palette.statusSelect.menuItemHoverBackgroundColor : Theme.palette.statusSelect.menuItemBackgroundColor
|
||||
}
|
||||
MouseArea {
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
anchors.fill: itemContainer
|
||||
onClicked: {
|
||||
root.selectedAsset = { address, name, value, symbol, fiatBalance, fiatBalanceDisplay }
|
||||
select.selectMenu.close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -54,6 +54,7 @@ Rectangle {
|
||||
signal clicked(var mouse)
|
||||
signal pressAndHold(var mouse)
|
||||
|
||||
property bool highlighted: false
|
||||
|
||||
|
||||
/// Implementation
|
||||
@@ -65,7 +66,7 @@ Rectangle {
|
||||
|
||||
color: {
|
||||
if (statusBaseButton.enabled) {
|
||||
return sensor.containsMouse ? hoverColor
|
||||
return sensor.containsMouse || highlighted ? hoverColor
|
||||
: normalColor
|
||||
} else {
|
||||
return disaledColor
|
||||
|
||||
@@ -47,6 +47,7 @@ Item {
|
||||
property bool valid: true
|
||||
property bool pristine: true
|
||||
property bool dirty: false
|
||||
property bool pending: false
|
||||
property bool leftIcon: true
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
implicitWidth: 168
|
||||
implicitHeight: 95
|
||||
|
||||
property string text: ""
|
||||
property bool highlighted: false
|
||||
property bool enabled: true
|
||||
|
||||
signal clicked(var mouse)
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
background: StatusIconBackgroundSettings {}
|
||||
}
|
||||
|
||||
color: {
|
||||
let actualColor = Qt.darker(root.icon.color, 1)
|
||||
actualColor.a = sensor.containsMouse && enabled ? 0.3 : 0.2
|
||||
return actualColor
|
||||
}
|
||||
|
||||
radius: 16
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
onClicked: function (mouse) {
|
||||
root.clicked(mouse)
|
||||
}
|
||||
|
||||
StatusRoundIcon {
|
||||
icon.name: root.icon.name
|
||||
icon.width: root.icon.width
|
||||
icon.height: root.icon.height
|
||||
icon.rotation: root.icon.rotation
|
||||
icon.color: Theme.palette.white
|
||||
icon.background.width: 40
|
||||
icon.background.height: 40
|
||||
icon.background.color: root.icon.color
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
text: root.text
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: 8
|
||||
font.pixelSize: 13
|
||||
font.weight: Font.Medium
|
||||
color: Theme.palette.white
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,8 +18,15 @@ Rectangle {
|
||||
property string subTitle: ""
|
||||
property bool muted: false
|
||||
property int pinnedMessagesCount: 0
|
||||
property StatusImageSettings image: StatusImageSettings {}
|
||||
property StatusIconSettings icon: StatusIconSettings {}
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 36
|
||||
height: 36
|
||||
}
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 36
|
||||
height: 36
|
||||
letterSize: 20
|
||||
}
|
||||
property int type: StatusChatInfoButton.Type.PublicChat
|
||||
property alias tooltip: statusToolTip
|
||||
property alias sensor: sensor
|
||||
@@ -27,6 +34,7 @@ Rectangle {
|
||||
signal clicked(var mouse)
|
||||
signal pinnedMessagesCountClicked(var mouse)
|
||||
signal unmute()
|
||||
signal linkActivated(string link)
|
||||
|
||||
enum Type {
|
||||
Unknown0, // 0
|
||||
@@ -49,51 +57,14 @@ Rectangle {
|
||||
|
||||
onClicked: statusChatInfoButton.clicked(mouse)
|
||||
|
||||
Loader {
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 4
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
|
||||
sourceComponent: !!statusChatInfoButton.image.source.toString() ?
|
||||
statusRoundImageComponent :
|
||||
statusLetterIdenticonComponent
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundImageComponent
|
||||
|
||||
Item {
|
||||
width: 36
|
||||
height: 36
|
||||
StatusRoundedImage {
|
||||
id: statusRoundImage
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
image.source: statusChatInfoButton.image.source
|
||||
showLoadingIndicator: true
|
||||
border.width: statusChatInfoButton.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
Loader {
|
||||
sourceComponent: statusLetterIdenticonComponent
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
active: statusRoundImage.image.status === Image.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticonComponent
|
||||
|
||||
StatusLetterIdenticon {
|
||||
width: 36
|
||||
height: 36
|
||||
name: statusChatInfoButton.title
|
||||
color: statusChatInfoButton.icon.color
|
||||
}
|
||||
image: statusChatInfoButton.image
|
||||
icon: statusChatInfoButton.icon
|
||||
name: statusChatInfoButton.title
|
||||
}
|
||||
|
||||
Item {
|
||||
@@ -161,6 +132,7 @@ Rectangle {
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
objectName: "mutedIcon"
|
||||
id: mutedIcon
|
||||
anchors.left: chatName.right
|
||||
anchors.leftMargin: 4
|
||||
@@ -206,15 +178,14 @@ Rectangle {
|
||||
+ divider.width + divider.anchors.leftMargin
|
||||
: 0
|
||||
|
||||
StatusBaseText {
|
||||
StatusSelectableText {
|
||||
id: chatType
|
||||
text: statusChatInfoButton.subTitle
|
||||
color: Theme.palette.baseColor1
|
||||
font.pixelSize: 12
|
||||
|
||||
elide: Text.ElideRight
|
||||
width: Math.min(parent.width - (pinIcon.visible ? divider.width + divider.anchors.leftMargin + pinIcon.width + pinIcon.anchors.leftMargin : 0),
|
||||
implicitWidth)
|
||||
onLinkActivated: statusChatInfoButton.linkActivated(link)
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
@@ -253,6 +224,7 @@ Rectangle {
|
||||
color: pinCountSensor.containsMouse ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
|
||||
MouseArea {
|
||||
objectName: "pinMessagesCounterSensor"
|
||||
id: pinCountSensor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
property string selectedColor
|
||||
property string label: "Color"
|
||||
property var model
|
||||
height: accountColorInput.height
|
||||
implicitWidth: 448
|
||||
|
||||
StatusSelect {
|
||||
id: accountColorInput
|
||||
bgColor: selectedColor
|
||||
label: root.label
|
||||
model: root.model
|
||||
|
||||
selectMenu.delegate: Component {
|
||||
MenuItem {
|
||||
property bool isFirstItem: index === 0
|
||||
property bool isLastItem: index === root.model.length - 1
|
||||
height: 52
|
||||
width: parent.width
|
||||
padding: 10
|
||||
onTriggered: function () {
|
||||
const selectedColor = root.model[index]
|
||||
root.selectedColor = selectedColor
|
||||
}
|
||||
background: Rectangle {
|
||||
color: root.model[index] || "transparent"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,14 +18,19 @@ Rectangle {
|
||||
return Theme.palette.directColor1;
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
return Theme.palette.primaryColor1;
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
return hovered ? Theme.palette.primaryColor1: Theme.palette.baseColor1;
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return hovered ? Theme.palette.primaryColor1: Theme.palette.directColor1;
|
||||
}
|
||||
}
|
||||
|
||||
property color disabledColor: {
|
||||
disabledColor: {
|
||||
switch(statusFlatRoundButton.type) {
|
||||
case StatusFlatRoundButton.Type.Secondary:
|
||||
return Theme.palette.baseColor1;
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return Theme.palette.baseColor1;
|
||||
}
|
||||
}
|
||||
@@ -35,6 +40,7 @@ Rectangle {
|
||||
|
||||
property alias hovered: sensor.containsMouse
|
||||
property alias tooltip: statusToolTip
|
||||
property alias backgroundHoverColor: backgroundSettings.hoverColor
|
||||
|
||||
property bool highlighted: false
|
||||
|
||||
@@ -47,7 +53,9 @@ Rectangle {
|
||||
|
||||
enum Type {
|
||||
Primary,
|
||||
Secondary
|
||||
Secondary,
|
||||
Tertiary,
|
||||
Quaternary
|
||||
}
|
||||
|
||||
/// Implementation
|
||||
@@ -59,6 +67,8 @@ Rectangle {
|
||||
switch(statusFlatRoundButton.type) {
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
case StatusFlatRoundButton.Type.Secondary:
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return "transparent";
|
||||
}
|
||||
}
|
||||
@@ -68,6 +78,8 @@ Rectangle {
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
return Theme.palette.primaryColor3;
|
||||
case StatusFlatRoundButton.Type.Secondary:
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return Theme.palette.baseColor2;
|
||||
}
|
||||
}
|
||||
@@ -76,6 +88,8 @@ Rectangle {
|
||||
switch(statusFlatRoundButton.type) {
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
case StatusFlatRoundButton.Type.Secondary:
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return "transparent";
|
||||
}
|
||||
}
|
||||
@@ -85,6 +99,8 @@ Rectangle {
|
||||
case StatusFlatRoundButton.Type.Primary:
|
||||
return Theme.palette.primaryColor3;
|
||||
case StatusFlatRoundButton.Type.Secondary:
|
||||
case StatusFlatRoundButton.Type.Tertiary:
|
||||
case StatusFlatRoundButton.Type.Quaternary:
|
||||
return Theme.palette.baseColor4;
|
||||
}
|
||||
}
|
||||
@@ -120,6 +136,7 @@ Rectangle {
|
||||
visible: !loading
|
||||
|
||||
icon: statusFlatRoundButton.icon.name
|
||||
source: statusFlatRoundButton.icon.source
|
||||
rotation: statusFlatRoundButton.icon.rotation
|
||||
|
||||
width: statusFlatRoundButton.icon.width
|
||||
|
||||
@@ -20,56 +20,20 @@ TabButton {
|
||||
|
||||
contentItem: Item {
|
||||
anchors.fill: parent
|
||||
|
||||
Loader {
|
||||
active: true
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
sourceComponent: statusIconTabButton.name !== "" && !icon.source.toString() ? letterIdenticon :
|
||||
!!icon.source.toString() ? imageIcon : defaultIcon
|
||||
}
|
||||
|
||||
Component {
|
||||
id: defaultIcon
|
||||
StatusIcon {
|
||||
icon: statusIconTabButton.icon.name
|
||||
height: statusIconTabButton.icon.height
|
||||
width: statusIconTabButton.icon.width
|
||||
color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: imageIcon
|
||||
Item {
|
||||
width: 28
|
||||
height: 28
|
||||
StatusRoundedImage {
|
||||
id: statusRoundImage
|
||||
showLoadingIndicator: true
|
||||
width: parent.width
|
||||
height: parent.height
|
||||
image.source: icon.source
|
||||
}
|
||||
Loader {
|
||||
sourceComponent:letterIdenticon
|
||||
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
active: statusRoundImage.image.status === Image.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: letterIdenticon
|
||||
StatusLetterIdenticon {
|
||||
width: 26
|
||||
height: 26
|
||||
letterSize: 15
|
||||
name: statusIconTabButton.name
|
||||
color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
|
||||
}
|
||||
image.source: statusIconTabButton.icon.source
|
||||
image.width: 28
|
||||
image.height: 28
|
||||
icon.height: statusIconTabButton.icon.height
|
||||
icon.width: statusIconTabButton.icon.width
|
||||
icon.name: statusIconTabButton.icon.name
|
||||
icon.color: (statusIconTabButton.hovered || highlighted || statusIconTabButton.checked) ? Theme.palette.primaryColor1 : statusIconTabButton.icon.color
|
||||
icon.isLetterIdenticon: statusIconTabButton.name !== "" && !statusIconTabButton.icon.source.toString()
|
||||
icon.letterSize: 15
|
||||
name: statusIconTabButton.name
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Backpressure 1.0
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Controls.Validators 0.1
|
||||
@@ -24,6 +25,7 @@ Item {
|
||||
|
||||
property alias input: statusBaseInput
|
||||
property alias valid: statusBaseInput.valid
|
||||
property alias pending: statusBaseInput.pending
|
||||
property alias text: statusBaseInput.text
|
||||
property string label: ""
|
||||
property string secondaryLabel: ""
|
||||
@@ -32,19 +34,25 @@ Item {
|
||||
property real leftPadding: 16
|
||||
property real rightPadding: 16
|
||||
property list<StatusValidator> validators
|
||||
property list<StatusAsyncValidator> asyncValidators
|
||||
property int validationMode: StatusInput.ValidationMode.OnlyWhenDirty
|
||||
property string validatedValue
|
||||
|
||||
property var pendingValidators: []
|
||||
|
||||
enum ValidationMode {
|
||||
OnlyWhenDirty, // validates input only after it has become dirty
|
||||
Always // validates input even before it has become dirty
|
||||
}
|
||||
|
||||
property var errors: ({})
|
||||
property var asyncErrors: ({})
|
||||
|
||||
function reset() {
|
||||
statusBaseInput.valid = false
|
||||
statusBaseInput.pristine = true
|
||||
statusBaseInput.text = ""
|
||||
errorMessage = ""
|
||||
root.errorMessage = ""
|
||||
}
|
||||
|
||||
function validate() {
|
||||
@@ -78,6 +86,43 @@ Item {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (asyncValidators.length && !Object.values(errors).length) {
|
||||
for (let idx in asyncValidators) {
|
||||
let asyncValidator = asyncValidators[idx]
|
||||
asyncValidator.validationComplete.connect(function (value, valid) {
|
||||
updateAsyncValidity(asyncValidator.name, value, valid)
|
||||
})
|
||||
root.pending = true
|
||||
pendingValidators.push(asyncValidator.name)
|
||||
asyncValidator.asyncOperationInternal(statusBaseInput.text)
|
||||
}
|
||||
} else if (!asyncValidators.length && !Object.values(errors).length) {
|
||||
root.validatedValue = root.text
|
||||
}
|
||||
}
|
||||
|
||||
function updateAsyncValidity(validatorName, value, result) {
|
||||
if (!asyncErrors) {
|
||||
asyncErrors = {}
|
||||
}
|
||||
|
||||
if (typeof result === "boolean" && result) {
|
||||
if (asyncErrors[validatorName] !== undefined) {
|
||||
delete asyncErrors[validatorName]
|
||||
}
|
||||
errorMessage.text = ""
|
||||
root.validatedValue = value
|
||||
} else {
|
||||
asyncErrors[validatorName] = result
|
||||
for (let idx in asyncValidators) {
|
||||
errorMessage.text = asyncValidators[idx].errorMessage || root.errorMessage
|
||||
break;
|
||||
}
|
||||
}
|
||||
pendingValidators = pendingValidators.filter(v => v !== validatorName)
|
||||
root.pending = pendingValidators.length > 0
|
||||
root.valid = Object.values(asyncErrors).length == 0
|
||||
}
|
||||
|
||||
Component.onCompleted: validate()
|
||||
|
||||
@@ -21,7 +21,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
property color disabledColor: {
|
||||
disabledColor: {
|
||||
switch(statusRoundButton.type) {
|
||||
case StatusRoundButton.Type.Primary:
|
||||
return Theme.palette.baseColor1;
|
||||
@@ -77,7 +77,7 @@ Rectangle {
|
||||
property color disabledColor: {
|
||||
switch(statusRoundButton.type) {
|
||||
case StatusRoundButton.Type.Primary:
|
||||
return Theme.palette.indirectColor1;
|
||||
return Theme.palette.baseColor2;
|
||||
case StatusRoundButton.Type.Secondary:
|
||||
return Theme.palette.baseColor1;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,175 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
Item {
|
||||
enum MenuAlignment {
|
||||
Left,
|
||||
Right,
|
||||
Center
|
||||
}
|
||||
property string label: ""
|
||||
readonly property bool hasLabel: label !== ""
|
||||
property color bgColor: Theme.palette.baseColor2
|
||||
readonly property int labelMargin: 7
|
||||
property var model
|
||||
property alias selectMenu: selectMenu
|
||||
property color bgColorHover: bgColor
|
||||
property alias selectedItemComponent: selectedItemContainer.children
|
||||
property int caretRightMargin: 16
|
||||
property alias select: inputRectangle
|
||||
property int menuAlignment: StatusSelect.MenuAlignment.Right
|
||||
property Item zeroItemsView: Item {}
|
||||
property string validationError: ""
|
||||
property alias validationErrorAlignment: validationErrorText.horizontalAlignment
|
||||
property int validationErrorTopMargin: 11
|
||||
implicitWidth: 448
|
||||
|
||||
id: root
|
||||
height: inputRectangle.height + (hasLabel ? inputLabel.height + labelMargin : 0) + (!!validationError ? (validationErrorText.height + validationErrorTopMargin) : 0)
|
||||
|
||||
StatusBaseText {
|
||||
id: inputLabel
|
||||
visible: hasLabel
|
||||
text: root.label
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 0
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 0
|
||||
font.pixelSize: 15
|
||||
color: root.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
property bool hovered: false
|
||||
id: inputRectangle
|
||||
height: 56
|
||||
color: hovered ? bgColorHover : bgColor
|
||||
radius: 8
|
||||
anchors.top: root.hasLabel ? inputLabel.bottom : parent.top
|
||||
anchors.topMargin: root.hasLabel ? root.labelMargin : 0
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
border.width: !!validationError ? 1 : 0
|
||||
border.color: Theme.palette.dangerColor1
|
||||
|
||||
Item {
|
||||
id: selectedItemContainer
|
||||
anchors.fill: parent
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: caret
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: caretRightMargin
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
width: 24
|
||||
height: 24
|
||||
icon: "chevron-down"
|
||||
color: Theme.palette.baseColor1
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: selectMenu.width
|
||||
height: selectMenu.height
|
||||
x: selectMenu.x
|
||||
y: selectMenu.y
|
||||
visible: selectMenu.opened
|
||||
color: Theme.palette.statusSelect.menuItemBackgroundColor
|
||||
radius: 8
|
||||
border.color: Theme.palette.baseColor2
|
||||
layer.enabled: true
|
||||
layer.effect: DropShadow {
|
||||
verticalOffset: 3
|
||||
radius: 8
|
||||
samples: 15
|
||||
fast: true
|
||||
cached: true
|
||||
color: Theme.palette.dropShadow
|
||||
}
|
||||
}
|
||||
|
||||
StatusPopupMenu {
|
||||
id: selectMenu
|
||||
closePolicy: Popup.CloseOnEscape | Popup.CloseOnPressOutsideParent
|
||||
width: parent.width
|
||||
clip: true
|
||||
|
||||
Repeater {
|
||||
id: menuItems
|
||||
model: root.model
|
||||
property int zeroItemsViewHeight
|
||||
delegate: selectMenu.delegate
|
||||
onItemAdded: {
|
||||
root.zeroItemsView.visible = false
|
||||
root.zeroItemsView.height = 0
|
||||
}
|
||||
onItemRemoved: {
|
||||
if (count === 0) {
|
||||
root.zeroItemsView.visible = true
|
||||
root.zeroItemsView.height = zeroItemsViewHeight
|
||||
}
|
||||
}
|
||||
Component.onCompleted: {
|
||||
zeroItemsViewHeight = root.zeroItemsView.height
|
||||
root.zeroItemsView.visible = count === 0
|
||||
root.zeroItemsView.height = count !== 0 ? 0 : root.zeroItemsView.height
|
||||
selectMenu.insertItem(0, root.zeroItemsView)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: validationErrorText
|
||||
visible: !!validationError
|
||||
text: validationError
|
||||
anchors.top: inputRectangle.bottom
|
||||
anchors.topMargin: validationErrorTopMargin
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
font.pixelSize: 12
|
||||
height: visible ? implicitHeight : 0
|
||||
color: Theme.palette.dangerColor1
|
||||
horizontalAlignment: TextEdit.AlignRight
|
||||
wrapMode: Text.WordWrap
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: mouseArea
|
||||
anchors.fill: inputRectangle
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: true
|
||||
onEntered: {
|
||||
inputRectangle.hovered = true
|
||||
}
|
||||
onExited: {
|
||||
inputRectangle.hovered = false
|
||||
}
|
||||
onClicked: {
|
||||
if (selectMenu.opened) {
|
||||
selectMenu.close()
|
||||
} else {
|
||||
const rightOffset = inputRectangle.width - selectMenu.width
|
||||
let offset = rightOffset
|
||||
switch (root.menuAlignment) {
|
||||
case StatusSelect.MenuAlignment.Left:
|
||||
offset = 0
|
||||
break
|
||||
case StatusSelect.MenuAlignment.Right:
|
||||
offset = rightOffset
|
||||
break
|
||||
case StatusSelect.MenuAlignment.Center:
|
||||
offset = rightOffset / 2
|
||||
}
|
||||
selectMenu.popup(inputRectangle.x + offset, inputRectangle.y + inputRectangle.height + 8)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
import QtQuick 2.14
|
||||
|
||||
import QtQuick.Controls 2.14 as QC
|
||||
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
|
||||
Item {
|
||||
id: statusSelectableText
|
||||
|
||||
property bool multiline: false
|
||||
property string text: ""
|
||||
property string hoveredLinkColor: Theme.palette.directColor1
|
||||
|
||||
property alias selectedText: edit.selectedText
|
||||
property alias selectedTextColor: edit.selectedTextColor
|
||||
property alias selectionStart: edit.selectionStart
|
||||
property alias selectionEnd: edit.selectionEnd
|
||||
property alias cursorPosition: edit.cursorPosition
|
||||
property alias hoveredLink: edit.hoveredLink
|
||||
property alias color: edit.color
|
||||
property alias font: edit.font
|
||||
property alias focussed: edit.activeFocus
|
||||
property alias verticalAlignmet: edit.verticalAlignment
|
||||
property alias horizontalAlignment: edit.horizontalAlignment
|
||||
|
||||
signal linkActivated(string link)
|
||||
|
||||
implicitWidth: multiline ? 0 : edit.implicitWidth
|
||||
implicitHeight: edit.implicitHeight
|
||||
|
||||
clip:true
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
enabled: !edit.activeFocus
|
||||
hoverEnabled: true
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.IBeamCursor
|
||||
onClicked: {
|
||||
edit.forceActiveFocus()
|
||||
}
|
||||
onExited: {
|
||||
flick.contentX = 0
|
||||
flick.contentY = 0
|
||||
}
|
||||
|
||||
Flickable {
|
||||
id: flick
|
||||
anchors.top: parent.top
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
contentWidth: edit.paintedWidth
|
||||
contentHeight: edit.paintedHeight
|
||||
boundsBehavior: Flickable.StopAtBounds
|
||||
QC.ScrollBar.vertical: QC.ScrollBar { interactive: multiline; enabled: multiline }
|
||||
function ensureVisible(r) {
|
||||
if (width-contentX >= r.x) {
|
||||
contentX = 0;
|
||||
}
|
||||
else if (contentX+width <= r.x+r.width) {
|
||||
contentX = r.x+r.width-width;
|
||||
}
|
||||
if (contentY >= r.y)
|
||||
contentY = r.y;
|
||||
else if (contentY+height <= r.y+r.height)
|
||||
contentY = r.y+r.height-height;
|
||||
}
|
||||
TextEdit {
|
||||
id: edit
|
||||
width: flick.width
|
||||
height: flick.height
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
readOnly: true
|
||||
selectByMouse: true
|
||||
selectionColor: Theme.palette.primaryColor2
|
||||
selectedTextColor: color
|
||||
focus: true
|
||||
font.pixelSize: 15
|
||||
font.family: Theme.palette.baseFont.name
|
||||
color: Theme.palette.directColor1
|
||||
textFormat: Text.RichText
|
||||
onCursorRectangleChanged: flick.ensureVisible(cursorRectangle)
|
||||
wrapMode: statusSelectableText.multiline ? Text.WrapAtWordBoundaryOrAnywhere : TextEdit.NoWrap
|
||||
|
||||
Keys.forwardTo: [statusSelectableText]
|
||||
|
||||
onFocusChanged: {
|
||||
if(!focus) {
|
||||
flick.contentX = 0
|
||||
flick.contentY = 0
|
||||
}
|
||||
}
|
||||
|
||||
onLinkActivated: statusSelectableText.linkActivated(link)
|
||||
|
||||
text: "<style>a:link { color: " + (!!hoveredLink ? statusSelectableText.hoveredLinkColor : Theme.palette.baseColor1) + "; }</style>" + statusSelectableText.text
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
import QtQuick 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
Item {
|
||||
id: root
|
||||
|
||||
property StatusIconSettings icon: StatusIconSettings {
|
||||
width: 24
|
||||
height: 24
|
||||
name: ""
|
||||
}
|
||||
|
||||
property bool highlighted: false
|
||||
property bool enabled: true
|
||||
|
||||
signal clicked(var mouse)
|
||||
|
||||
implicitWidth: 40
|
||||
implicitHeight: 40
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
enabled: root.enabled
|
||||
cursorShape: root.enabled ? Qt.PointingHandCursor : Qt.ArrowCursor
|
||||
anchors.fill: parent
|
||||
hoverEnabled: true
|
||||
onClicked: function (mouse) {
|
||||
root.clicked(mouse)
|
||||
}
|
||||
|
||||
StatusIcon {
|
||||
id: statusIcon
|
||||
width: root.icon.width
|
||||
height: root.icon.height
|
||||
icon: root.icon.name
|
||||
color: root.highlighted || sensor.containsMouse ? Theme.palette.primaryColor1 : Theme.palette.baseColor1
|
||||
anchors.centerIn: parent
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
visible: root.highlighted || sensor.containsMouse
|
||||
width: statusIcon.width
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
height: 2
|
||||
radius: 1
|
||||
color: Theme.palette.primaryColor1
|
||||
anchors.bottom: parent.bottom
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: control
|
||||
property bool selected: false
|
||||
icon.name: "filled-account"
|
||||
icon.width: 36
|
||||
icon.height: 36
|
||||
Rectangle {
|
||||
anchors.fill: parent
|
||||
color: control.hovered ? control.icon.color : "transparent"
|
||||
opacity: 0.1
|
||||
radius: 8
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
width: 16
|
||||
height: 16
|
||||
anchors.top: parent.top
|
||||
anchors.topMargin: 2
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 2
|
||||
visible: control.selected
|
||||
radius: width / 2
|
||||
color: Theme.palette.successColor1
|
||||
StatusIcon {
|
||||
icon: "tiny/checkmark"
|
||||
height: 12
|
||||
color: Theme.palette.white
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,61 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtQuick.Layouts 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
Item {
|
||||
id: control
|
||||
property string selectedColor
|
||||
property string label: "Account color"
|
||||
property var model
|
||||
property bool enabled: true
|
||||
|
||||
height: childrenRect.height
|
||||
implicitWidth: 480
|
||||
|
||||
StatusBaseText {
|
||||
id: label
|
||||
text: control.label
|
||||
anchors.left: parent.left
|
||||
anchors.top: parent.top
|
||||
font.pixelSize: 15
|
||||
color: control.enabled ? Theme.palette.directColor1 : Theme.palette.baseColor1
|
||||
}
|
||||
|
||||
RowLayout {
|
||||
id: colors
|
||||
spacing: 6
|
||||
anchors.top: label.bottom
|
||||
anchors.topMargin: 8
|
||||
anchors.left: parent.left
|
||||
anchors.right: parent.right
|
||||
Repeater {
|
||||
model: control.model
|
||||
StatusWalletColorButton {
|
||||
id: colorBtn
|
||||
icon.color: modelData
|
||||
selected: {
|
||||
const upperCaseColor = control.selectedColor.toUpperCase()
|
||||
const upperCaseModelDataColor = modelData.toString().toUpperCase()
|
||||
if (upperCaseColor === upperCaseModelDataColor) {
|
||||
return true
|
||||
}
|
||||
// Check the colors in the other theme
|
||||
const currentColor = Utils.getThemeAccountColor(upperCaseColor, Theme.palette.accountColors)
|
||||
if (!currentColor) {
|
||||
return false
|
||||
}
|
||||
|
||||
return currentColor === upperCaseModelDataColor
|
||||
}
|
||||
onClicked: {
|
||||
control.selectedColor = modelData.toUpperCase()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Core.Utils 0.1
|
||||
|
||||
StatusAsyncValidator {
|
||||
readonly property string uuid: Utils.uuid()
|
||||
|
||||
name: "asyncEns"
|
||||
|
||||
errorMessage: "ENS name could not be resolved in to an address"
|
||||
|
||||
validate: function (asyncResult) {
|
||||
return Utils.isValidAddress(asyncResult)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import QtQuick 2.13
|
||||
import StatusQ.Core.Backpressure 1.0
|
||||
|
||||
Item {
|
||||
id: statusAsyncValidator
|
||||
|
||||
property string name: ""
|
||||
property string errorMessage: "invalid input"
|
||||
signal asyncComplete(var result)
|
||||
signal validationComplete(var value, bool valid)
|
||||
|
||||
// Prevents firing async operations before time has elapsed. If multiple
|
||||
// calls are attempted, the timer resets each time.
|
||||
property int debounceTime: 600
|
||||
|
||||
property var validate: function (value) {
|
||||
return value === "async result"
|
||||
}
|
||||
property var asyncOperation: function(inputText) {
|
||||
// Do something with the input text. Once completed, fire the
|
||||
// `asyncComplete` signal
|
||||
asyncComplete("async result")
|
||||
}
|
||||
|
||||
readonly property var asyncOperationInternal: Backpressure.debounce(statusAsyncValidator, debounceTime, function(inputText) {
|
||||
statusAsyncValidator.asyncOperation(inputText)
|
||||
})
|
||||
|
||||
onAsyncComplete: function(result) {
|
||||
validationComplete(result, validate(result))
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import QtQuick 2.13
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
QtObject {
|
||||
id: statusValidator
|
||||
|
||||
@@ -2,6 +2,8 @@ module StatusQ.Controls.Validators
|
||||
|
||||
StatusAddressValidator 0.1 StatusAddressValidator.qml
|
||||
StatusAddressOrEnsValidator 0.1 StatusAddressOrEnsValidator.qml
|
||||
StatusValidator 0.1 StatusValidator.qml
|
||||
StatusAsyncValidator 0.1 StatusAsyncValidator.qml
|
||||
StatusAsyncEnsValidator 0.1 StatusAsyncEnsValidator.qml
|
||||
StatusMinLengthValidator 0.1 StatusMinLengthValidator.qml
|
||||
StatusMaxLengthValidator 0.1 StatusMaxLengthValidator.qml
|
||||
StatusValidator 0.1 StatusValidator.qml
|
||||
|
||||
@@ -1,9 +1,14 @@
|
||||
module StatusQ.Controls
|
||||
|
||||
StatusAccountSelector 0.1 StatusAccountSelector.qml
|
||||
StatusAssetSelector 0.1 StatusAssetSelector.qml
|
||||
StatusChatCommandButton 0.1 StatusChatCommandButton.qml
|
||||
StatusChatInfoButton 0.1 StatusChatInfoButton.qml
|
||||
StatusChatListCategoryItemButton 0.1 StatusChatListCategoryItemButton.qml
|
||||
StatusColorSelector 0.1 StatusColorSelector.qml
|
||||
StatusIconTabButton 0.1 StatusIconTabButton.qml
|
||||
StatusNavBarTabButton 0.1 StatusNavBarTabButton.qml
|
||||
StatusTabBarIconButton 0.1 StatusTabBarIconButton.qml
|
||||
StatusToolTip 0.1 StatusToolTip.qml
|
||||
StatusBaseButton 0.1 StatusBaseButton.qml
|
||||
StatusButton 0.1 StatusButton.qml
|
||||
@@ -14,8 +19,12 @@ StatusSwitch 0.1 StatusSwitch.qml
|
||||
StatusRadioButton 0.1 StatusRadioButton.qml
|
||||
StatusCheckBox 0.1 StatusCheckBox.qml
|
||||
StatusSlider 0.1 StatusSlider.qml
|
||||
StatusSelect 0.1 StatusSelect.qml
|
||||
StatusBaseInput 0.1 StatusBaseInput.qml
|
||||
StatusInput 0.1 StatusInput.qml
|
||||
StatusPickerButton 0.1 StatusPickerButton.qml
|
||||
StatusSwitchTabButton 0.1 StatusSwitchTabButton.qml
|
||||
StatusSwitchTabBar 0.1 StatusSwitchTabBar.qml
|
||||
StatusSelectableText 0.1 StatusSelectableText.qml
|
||||
StatusWalletColorButton 0.1 StatusWalletColorButton.qml
|
||||
StatusWalletColorSelect 0.1 StatusWalletColorSelect.qml
|
||||
|
||||
@@ -0,0 +1,123 @@
|
||||
pragma Singleton
|
||||
import QtQuick 2.0
|
||||
|
||||
Item {
|
||||
|
||||
id: backpressure
|
||||
|
||||
property var _timers: ({})
|
||||
property int _nextId: 0
|
||||
|
||||
function setTimeout(owner, timeout, callback) {
|
||||
var tid = ++_nextId;
|
||||
|
||||
var cleanup = function() {
|
||||
if (tid !== null) {
|
||||
clearTimeout(tid);
|
||||
}
|
||||
}
|
||||
|
||||
if (!owner) {
|
||||
owner = backpressure;
|
||||
}
|
||||
|
||||
owner.Component.destruction.connect(cleanup);
|
||||
|
||||
var obj = Qt.createQmlObject('import QtQuick 2.0; Timer {running: false; repeat: false; interval: ' + timeout + '}', backpressure, "setTimeout");
|
||||
obj.triggered.connect(function() {
|
||||
callback();
|
||||
obj.destroy();
|
||||
owner.Component.destruction.disconnect(cleanup);
|
||||
delete _timers[tid];
|
||||
});
|
||||
obj.running = true;
|
||||
_timers[tid] = obj;
|
||||
return tid;
|
||||
}
|
||||
|
||||
function clearTimeout(timerId) {
|
||||
if (!_timers.hasOwnProperty(timerId)) {
|
||||
return;
|
||||
}
|
||||
var timer = _timers[timerId];
|
||||
timer.stop();
|
||||
timer.destroy();
|
||||
delete _timers[timerId];
|
||||
}
|
||||
|
||||
function oneInTime(owner, duration, callback) {
|
||||
var pending = false;
|
||||
var timerId = null;
|
||||
|
||||
return function() {
|
||||
if (pending) {
|
||||
return;
|
||||
}
|
||||
pending = true;
|
||||
var args = arguments;
|
||||
callback.apply(null, args);
|
||||
timerId = setTimeout(owner, duration , function() {
|
||||
pending = false;
|
||||
}, duration);
|
||||
}
|
||||
}
|
||||
|
||||
function promisedOneInTime(owner, callback) {
|
||||
var q = priv.loadPromiseLib();
|
||||
var promise = null;
|
||||
|
||||
return function() {
|
||||
var args = arguments;
|
||||
if (promise !== null) {
|
||||
return q.rejected();
|
||||
}
|
||||
|
||||
promise = q.promise(function(fulfill, reject) {
|
||||
fulfill(callback.apply(null, args));
|
||||
});
|
||||
|
||||
promise.then(function() {
|
||||
promise = null;
|
||||
}, function() {
|
||||
promise = null;
|
||||
});
|
||||
return promise;
|
||||
};
|
||||
}
|
||||
|
||||
function debounce(owner, duration, callback) {
|
||||
var timerId = null;
|
||||
|
||||
return function() {
|
||||
var args = arguments;
|
||||
|
||||
if (timerId !== null) {
|
||||
clearTimeout(timerId);
|
||||
}
|
||||
|
||||
timerId = setTimeout(owner, duration, function() {
|
||||
timerId = null;
|
||||
callback.apply(null, args);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
QtObject {
|
||||
id: priv
|
||||
property var q: null
|
||||
|
||||
function loadPromiseLib() {
|
||||
if (q !== null) {
|
||||
return q.q;
|
||||
}
|
||||
|
||||
q = Qt.createQmlObject('import QtQuick 2.0; import QuickPromise 1.0; Item { property var q: Q;}', backpressure);
|
||||
if (q.hasOwnProperty("qmlErrors")) {
|
||||
console.error("Backpressure: Failed to load QuickPromise. Please check your installation.");
|
||||
}
|
||||
return q.q;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,201 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
@@ -0,0 +1,80 @@
|
||||
[](https://www.travis-ci.org/e-fever/backpressure)
|
||||
[](https://ci.appveyor.com/project/benlau/backpressure)
|
||||
|
||||
Backpressure
|
||||
============
|
||||
|
||||
Backpressure happens on a stream of data where you are not fast enough to process.
|
||||
This library is designed to provide a few mechanism to handle it.
|
||||
|
||||
Installation
|
||||
============
|
||||
|
||||
qpm install net.efever.backpressure
|
||||
|
||||
|
||||
API
|
||||
===
|
||||
|
||||
```
|
||||
import Backpressure 1.0
|
||||
```
|
||||
|
||||
|
||||
**Backpressure.oneInTime(owner, duration, callback)**
|
||||
|
||||
It will create a wrapper function of the callback. Whatever you have invoked the wrapper function, it will execute the callback immediately. Then it will be blocked within duration period. It could prevent to process the same event twice within the duration period.
|
||||
|
||||
Example:
|
||||
```
|
||||
|
||||
Item {
|
||||
id : item
|
||||
property var processClick : Backpressure.oneInTime(item, 500, function(value) {
|
||||
/* Callback */
|
||||
});
|
||||
|
||||
MouseArea {
|
||||
onClicked: {
|
||||
processClick(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
If the owner is destroyed, the callback will no longer be able to access.
|
||||
|
||||
**Backpressure.debounce(owner, duration, callback)**
|
||||
|
||||
If will create a wrapper function of the callback. Whatever you have invoked the wrapper function, it won't execute the callback until the duration period finished. If user invoked the wrapper function again within the period, then the previous call will be dropped, and the timer is restarted.
|
||||
|
||||
It will guarantee only the last function call and parameter will be passed to the callback.
|
||||
|
||||
Reference: [ReactiveX - Debounce operator](http://reactivex.io/documentation/operators/debounce.html)
|
||||
|
||||
**Backpressure.promisedOneInTime(owner, callback)**
|
||||
|
||||
This function is similar to oneInTime that will create a wrapper of the callback. But it does not take a timeout value as an argument of the construction function.
|
||||
|
||||
Instead, it will convert the return from the callback to a promise object. Then blocks successively calls until the promise is resolved/rejected.
|
||||
|
||||
The wrapper function returns a promise represents the result of the callback. If that is blocked, it will simply a rejected promise.
|
||||
|
||||
You must install QuickPromise in order to use this funciton.
|
||||
|
||||
Example
|
||||
```
|
||||
|
||||
var timeout = Backpressure.promisedOneInTime(anyItem, function(delay) {
|
||||
return Q.promise(function(fulfill, reject) {
|
||||
Q.setTimeout(function() {
|
||||
fulfill();
|
||||
}, delay);
|
||||
});
|
||||
});
|
||||
|
||||
var promise1 = timeout(1000); // Pending
|
||||
var promise2 = timeout(1000); // Rejected
|
||||
|
||||
```
|
||||
@@ -0,0 +1,3 @@
|
||||
module StatusQ.Core.Backpressure
|
||||
|
||||
singleton Backpressure 1.0 Backpressure.qml
|
||||
@@ -8,8 +8,10 @@ QtObject {
|
||||
property real width
|
||||
property real height
|
||||
property color color
|
||||
property color disabledColor
|
||||
property url source
|
||||
property int rotation
|
||||
property bool isLetterIdenticon
|
||||
property int letterSize
|
||||
property StatusIconBackgroundSettings background: StatusIconBackgroundSettings {}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ QtObject {
|
||||
property string subTitle
|
||||
property int titleElide: Text.ElideRight
|
||||
property int subTitleElide: Text.ElideRight
|
||||
property bool headerImageEditable: false
|
||||
property bool editable: false
|
||||
property Component popupMenu
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 40
|
||||
|
||||
@@ -146,6 +146,17 @@ ThemePalette {
|
||||
miscColor10: getColor('brown3')
|
||||
miscColor11: getColor('yellow2')
|
||||
|
||||
accountColors: [
|
||||
getColor('blue5'),
|
||||
getColor('yellow2'),
|
||||
"#E6ABFC",
|
||||
getColor('moss2'),
|
||||
"#FB8383",
|
||||
getColor('green4'),
|
||||
"#ADA3FF",
|
||||
getColor('brown3')
|
||||
]
|
||||
|
||||
property QtObject statusAppLayout: QtObject {
|
||||
property color backgroundColor: baseColor3
|
||||
property color rightPanelBackgroundColor: baseColor3
|
||||
@@ -205,5 +216,10 @@ ThemePalette {
|
||||
property QtObject statusSwitchTab: QtObject {
|
||||
property color backgroundColor: baseColor3
|
||||
}
|
||||
|
||||
property QtObject statusSelect: QtObject {
|
||||
property color menuItemBackgroundColor: baseColor2
|
||||
property color menuItemHoverBackgroundColor: directColor7
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -144,6 +144,17 @@ ThemePalette {
|
||||
miscColor10: getColor('brown')
|
||||
miscColor11: getColor('brown2')
|
||||
|
||||
accountColors: [
|
||||
getColor('blue'),
|
||||
getColor('brown2'),
|
||||
getColor('violet'),
|
||||
"#1D806F",
|
||||
getColor('red2'),
|
||||
getColor('green2'),
|
||||
getColor('purple'),
|
||||
getColor('brown')
|
||||
]
|
||||
|
||||
property QtObject statusAppLayout: QtObject {
|
||||
property color backgroundColor: white
|
||||
property color rightPanelBackgroundColor: white
|
||||
@@ -203,5 +214,10 @@ ThemePalette {
|
||||
property QtObject statusSwitchTab: QtObject {
|
||||
property color backgroundColor: white
|
||||
}
|
||||
|
||||
property QtObject statusSelect: QtObject {
|
||||
property color menuItemBackgroundColor: white
|
||||
property color menuItemHoverBackgroundColor: baseColor2
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -89,6 +89,8 @@ QtObject {
|
||||
property color miscColor10
|
||||
property color miscColor11
|
||||
|
||||
property var accountColors: []
|
||||
|
||||
property QtObject statusAppLayout: QtObject {
|
||||
property color backgroundColor
|
||||
property color rightPanelBackgroundColor
|
||||
@@ -150,6 +152,11 @@ QtObject {
|
||||
property color backgroundColor
|
||||
}
|
||||
|
||||
property QtObject statusSelect: QtObject {
|
||||
property color menuItemBackgroundColor
|
||||
property color menuItemHoeverBackgroundColor
|
||||
}
|
||||
|
||||
function alphaColor(color, alpha) {
|
||||
let actualColor = Qt.darker(color, 1)
|
||||
actualColor.a = alpha
|
||||
|
||||
@@ -26,6 +26,47 @@ QtObject {
|
||||
const isDomain = /(?:(?:(?<thld>[\w\-]*)(?:\.))?(?<sld>[\w\-]*))\.(?<tld>[\w\-]*)/.test(inputValue)
|
||||
return isEmail || isDomain || (inputValue.startsWith("@") && inputValue.length > 1)
|
||||
}
|
||||
|
||||
function uuid() {
|
||||
return Date.now().toString(36) + Math.random().toString(36).substr(2, 5)
|
||||
}
|
||||
|
||||
function getThemeAccountColor(c, accountColors) {
|
||||
const upperCaseColor = c.toUpperCase()
|
||||
let colorIndex = accountColors.indexOf(upperCaseColor)
|
||||
|
||||
if (colorIndex > -1) {
|
||||
return upperCaseColor
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
function findAssetBySymbol(assets, symbolToFind) {
|
||||
for(var i=0; i<assets.rowCount(); i++) {
|
||||
const symbol = assets.rowData(i, "symbol")
|
||||
if (symbol.toLowerCase() === symbolToFind.toLowerCase()) {
|
||||
return {
|
||||
name: assets.rowData(i, "name"),
|
||||
symbol,
|
||||
value: assets.rowData(i, "value"),
|
||||
fiatBalanceDisplay: assets.rowData(i, "fiatBalanceDisplay"),
|
||||
address: assets.rowData(i, "address"),
|
||||
fiatBalance: assets.rowData(i, "fiatBalance")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function stripTrailingZeros(strNumber) {
|
||||
if (!(typeof strNumber === "string")) {
|
||||
try {
|
||||
strNumber = strNumber.toString()
|
||||
} catch(e) {
|
||||
throw "[Utils.stripTrailingZeros] input parameter must be a string"
|
||||
}
|
||||
}
|
||||
return strNumber.replace(/(\.[0-9]*[1-9])0+$|\.0*$/,'$1')
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,129 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
import QtGraphicalEffects 1.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
|
||||
Rectangle {
|
||||
id: root
|
||||
property string chatId: ""
|
||||
property string name: "channelName"
|
||||
property string message: "My latest message\n with a return"
|
||||
property string identicon: ""
|
||||
|
||||
// TODO: what about dark theme?
|
||||
color: "#F7F7F7"
|
||||
width: 366
|
||||
height: 75
|
||||
|
||||
radius: 8
|
||||
|
||||
Loader {
|
||||
id: identicon
|
||||
sourceComponent: root.identicon === "" ? statusIdenticon : userOrChannelIdenticon
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 16
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
height: 40
|
||||
width: 40
|
||||
}
|
||||
|
||||
Component {
|
||||
id: userOrChannelIdenticon
|
||||
StatusSmartIdenticon {
|
||||
id: contactImage
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
image: StatusImageSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
source: root.identicon
|
||||
isIdenticon: true
|
||||
}
|
||||
icon: StatusIconSettings {
|
||||
width: 40
|
||||
height: 40
|
||||
letterSize: 15
|
||||
color: Theme.palette.miscColor5
|
||||
}
|
||||
name: root.name
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusIdenticon
|
||||
Image {
|
||||
source: "../../assets/img/status-logo-icon.svg"
|
||||
width: 40
|
||||
height: 40
|
||||
sourceSize.width: width * 2
|
||||
sourceSize.height: height * 2
|
||||
cache: true
|
||||
fillMode: Image.PreserveAspectFit
|
||||
}
|
||||
/* SVGImage { */
|
||||
/* source: Style.svg("status-logo-icon") */
|
||||
/* width: 40 */
|
||||
/* height: 40 */
|
||||
/* } */
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: name
|
||||
anchors.bottom: messagePreview.top
|
||||
anchors.bottomMargin: 2
|
||||
anchors.left: identicon.right
|
||||
anchors.leftMargin: 8
|
||||
anchors.right: openButton.left
|
||||
anchors.rightMargin: 8
|
||||
elide: Text.ElideRight
|
||||
text: root.name
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 15
|
||||
color: "#4b4b4b"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
id: messagePreview
|
||||
anchors.bottom: identicon.bottom
|
||||
anchors.bottomMargin: 2
|
||||
anchors.left: identicon.right
|
||||
anchors.leftMargin: 8
|
||||
anchors.right: openButton.left
|
||||
anchors.rightMargin: 16
|
||||
elide: Text.ElideRight
|
||||
clip: true // This is needed because emojis don't ellide correctly
|
||||
font.pixelSize: 14
|
||||
color: "#4b4b4b"
|
||||
text: root.message
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: openButton
|
||||
anchors.right: parent.right
|
||||
height: parent.height
|
||||
width: 85
|
||||
color: "transparent"
|
||||
|
||||
Rectangle {
|
||||
height: parent.height
|
||||
width: 1.2
|
||||
anchors.left: parent.left
|
||||
color: "#D9D9D9"
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
font.weight: Font.Medium
|
||||
font.pixelSize: 14
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
text: "Open"
|
||||
color: "black"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
module StatusQ.Platform
|
||||
|
||||
StatusMacTrafficLights 0.1 StatusMacTrafficLights.qml
|
||||
StatusMacNotification 0.1 StatusMacNotification.qml
|
||||
StatusWindowsTitleBar 0.1 StatusWindowsTitleBar.qml
|
||||
|
||||
|
||||
@@ -0,0 +1,193 @@
|
||||
import QtQuick 2.13
|
||||
import QtQuick.Controls 2.13
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
MenuItem {
|
||||
id: statusPopupMenuItem
|
||||
implicitWidth: parent ? parent.width : 0
|
||||
implicitHeight: action.enabled ? 38 : 0
|
||||
|
||||
property int subMenuIndex
|
||||
property var statusPopupMenu: null
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!!subMenu) {
|
||||
subMenuIndex = statusPopupMenu.menuItemCount
|
||||
statusPopupMenu.menuItemCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
action: StatusMenuItem {
|
||||
onTriggered: { statusPopupMenu.menuItemClicked(statusPopupMenuItem.subMenuIndex); }
|
||||
}
|
||||
|
||||
Component {
|
||||
id: indicatorComponent
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
StatusIcon {
|
||||
anchors.centerIn: parent
|
||||
width: {
|
||||
let width = statusPopupMenuItem.action && statusPopupMenuItem.action.icon.width ||
|
||||
statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.width
|
||||
return !!width ? width : 18
|
||||
}
|
||||
rotation: !!statusPopupMenuItem.action.iconRotation ? statusPopupMenuItem.action.iconRotation : 0
|
||||
icon: {
|
||||
if (statusPopupMenuItem.subMenu && !!statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] &&
|
||||
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon.toString() !== "") {
|
||||
return statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon;
|
||||
} else if (!!statusPopupMenuItem.action && statusPopupMenuItem.action.icon.name !== "") {
|
||||
return statusPopupMenuItem.action.icon.name;
|
||||
} else if (!!statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.name !== "") {
|
||||
return statusPopupMenuItem.action.iconSettings.name;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
color: {
|
||||
let c = !!statusPopupMenuItem.action.iconSettings && statusPopupMenuItem.action.iconSettings.color ||
|
||||
!!statusPopupMenuItem.action && statusPopupMenuItem.action.icon.color
|
||||
|
||||
if (!Qt.colorEqual(c, "transparent")) {
|
||||
return c
|
||||
}
|
||||
switch (statusPopupMenuItem.action.type) {
|
||||
case StatusMenuItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
break;
|
||||
default:
|
||||
return Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticonCmp
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
|
||||
StatusLetterIdenticon {
|
||||
anchors.centerIn: parent
|
||||
width: 16
|
||||
height: 16
|
||||
color: {
|
||||
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex]
|
||||
return subMenuItemIcon && subMenuItemIcon.color ? subMenuItemIcon.color : statusPopupMenuItem.action.iconSettings.background.color
|
||||
}
|
||||
name: statusPopupMenuItem.text
|
||||
letterSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundImageCmp
|
||||
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
StatusRoundedImage {
|
||||
anchors.centerIn: parent
|
||||
width: statusPopupMenuItem.action.image.width
|
||||
height: statusPopupMenuItem.action.image.height
|
||||
image.source: statusPopupMenuItem.subMenu ?
|
||||
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].source :
|
||||
statusPopupMenuItem.action.image.source
|
||||
border.width: (statusPopupMenuItem.subMenu && statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].isIdenticon) ||
|
||||
statusPopupMenuItem.action.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Loader {
|
||||
sourceComponent: {
|
||||
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons && statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]
|
||||
|
||||
if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) ||
|
||||
statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()) {
|
||||
return statusRoundImageCmp
|
||||
}
|
||||
|
||||
return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) ||
|
||||
(statusPopupMenuItem.action.iconsSettings && statusPopupMenuItem.action.iconSettings.isLetterIdenticon) ?
|
||||
statusLetterIdenticonCmp : indicatorComponent
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
active: {
|
||||
if (enabled) {
|
||||
let hasIconSettings = !!statusPopupMenuItem.action.icon.name ||
|
||||
(statusPopupMenuItem.action.iconSettings &&
|
||||
(!!statusPopupMenuItem.action.iconSettings.name || !!statusPopupMenuItem.action.iconSettings.isLetterIdenticon))
|
||||
|
||||
let hasImageSettings = statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()
|
||||
|
||||
return enabled && (parent.subMenu && !!statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]) || hasIconSettings || hasImageSettings
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.left: statusPopupMenuItem.indicator.right
|
||||
anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.leftMargin: 4
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: statusPopupMenuItem.text
|
||||
color: {
|
||||
switch (statusPopupMenuItem.action.type) {
|
||||
case StatusMenuItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
break;
|
||||
default:
|
||||
return Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
visible: statusPopupMenuItem.action.enabled
|
||||
}
|
||||
|
||||
arrow: StatusIcon {
|
||||
id: arrowIcon
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
height: 16
|
||||
visible: statusPopupMenuItem.subMenu
|
||||
icon: "next"
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: {
|
||||
if (statusPopupMenuItem.hovered) {
|
||||
return statusPopupMenuItem.action.type === StatusMenuItem.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
}
|
||||
return "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: statusPopupMenuItem.action.enabled
|
||||
onPressed: mouse.accepted = false
|
||||
}
|
||||
}
|
||||
@@ -20,6 +20,7 @@ QC.Popup {
|
||||
property bool showFooter: true
|
||||
|
||||
signal editButtonClicked()
|
||||
signal headerImageClicked()
|
||||
|
||||
parent: QC.Overlay.overlay
|
||||
|
||||
@@ -54,8 +55,11 @@ QC.Popup {
|
||||
image: header.image
|
||||
icon: header.icon
|
||||
popupMenu: header.popupMenu
|
||||
headerImageEditable: header.headerImageEditable
|
||||
editable: header.editable
|
||||
|
||||
onEditButtonClicked: statusModal.editButtonClicked()
|
||||
onHeaderImageClicked: statusModal.headerImageClicked()
|
||||
onClose: statusModal.close()
|
||||
}
|
||||
|
||||
@@ -63,7 +67,7 @@ QC.Popup {
|
||||
id: footerImpl
|
||||
anchors.bottom: parent.bottom
|
||||
width: visible ? parent.width : 0
|
||||
visible: statusModal.showFooter
|
||||
showFooter: statusModal.showFooter
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,7 +9,7 @@ import StatusQ.Popups 0.1
|
||||
|
||||
|
||||
Menu {
|
||||
id: statusPopupMenu
|
||||
id: root
|
||||
closePolicy: Popup.CloseOnPressOutside | Popup.CloseOnEscape
|
||||
topPadding: 8
|
||||
bottomPadding: 8
|
||||
@@ -38,190 +38,8 @@ Menu {
|
||||
}
|
||||
}
|
||||
|
||||
delegate: MenuItem {
|
||||
id: statusPopupMenuItem
|
||||
implicitWidth: parent ? parent.width : 0
|
||||
implicitHeight: action.enabled ? 38 : 0
|
||||
|
||||
property int subMenuIndex
|
||||
|
||||
Component.onCompleted: {
|
||||
if (!!subMenu) {
|
||||
subMenuIndex = statusPopupMenu.menuItemCount
|
||||
statusPopupMenu.menuItemCount += 1
|
||||
}
|
||||
}
|
||||
|
||||
action: StatusMenuItem {
|
||||
onTriggered: { statusPopupMenu.menuItemClicked(statusPopupMenuItem.subMenuIndex); }
|
||||
}
|
||||
|
||||
Component {
|
||||
id: indicatorComponent
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
StatusIcon {
|
||||
anchors.centerIn: parent
|
||||
width: {
|
||||
let width = statusPopupMenuItem.action.icon.width ||
|
||||
statusPopupMenuItem.action.iconSettings.width
|
||||
|
||||
return !!width ? width : 18
|
||||
}
|
||||
rotation: statusPopupMenuItem.action.iconRotation
|
||||
icon: {
|
||||
if (statusPopupMenuItem.subMenu && !!statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex] &&
|
||||
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon.toString() !== "") {
|
||||
return statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].icon;
|
||||
} else if (!!statusPopupMenuItem.action && statusPopupMenuItem.action.icon.name !== "") {
|
||||
return statusPopupMenuItem.action.icon.name;
|
||||
} else if (statusPopupMenuItem.action.iconSettings.name !== "") {
|
||||
return statusPopupMenuItem.action.iconSettings.name;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
color: {
|
||||
let c = statusPopupMenuItem.action.iconSettings.color ||
|
||||
statusPopupMenuItem.action.icon.color
|
||||
|
||||
if (!Qt.colorEqual(c, "transparent")) {
|
||||
return c
|
||||
}
|
||||
switch (statusPopupMenuItem.action.type) {
|
||||
case StatusMenuItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
break;
|
||||
default:
|
||||
return Theme.palette.primaryColor1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticonCmp
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
|
||||
StatusLetterIdenticon {
|
||||
anchors.centerIn: parent
|
||||
width: 16
|
||||
height: 16
|
||||
color: {
|
||||
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex]
|
||||
return subMenuItemIcon && subMenuItemIcon.color ? subMenuItemIcon.color : statusPopupMenuItem.action.iconSettings.background.color
|
||||
}
|
||||
name: statusPopupMenuItem.text
|
||||
letterSize: 11
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundImageCmp
|
||||
|
||||
Item {
|
||||
implicitWidth: 24
|
||||
implicitHeight: 24
|
||||
StatusRoundedImage {
|
||||
anchors.centerIn: parent
|
||||
width: statusPopupMenuItem.action.image.width
|
||||
height: statusPopupMenuItem.action.image.height
|
||||
image.source: statusPopupMenuItem.subMenu ?
|
||||
statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].source :
|
||||
statusPopupMenuItem.action.image.source
|
||||
border.width: (statusPopupMenuItem.subMenu && statusPopupMenu.subMenuItemIcons[statusPopupMenuItem.subMenuIndex].isIdenticon) ||
|
||||
statusPopupMenuItem.action.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
indicator: Loader {
|
||||
sourceComponent: {
|
||||
let subMenuItemIcon = statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]
|
||||
|
||||
if ((parent.subMenu && subMenuItemIcon && subMenuItemIcon.source) ||
|
||||
statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()) {
|
||||
return statusRoundImageCmp
|
||||
}
|
||||
|
||||
return (parent.subMenu && subMenuItemIcon && subMenuItemIcon.isLetterIdenticon) ||
|
||||
(statusPopupMenuItem.action.iconsSettings && statusPopupMenuItem.action.iconSettings.isLetterIdenticon) ?
|
||||
statusLetterIdenticonCmp : indicatorComponent
|
||||
}
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 8
|
||||
active: {
|
||||
if (enabled) {
|
||||
let hasIconSettings = !!statusPopupMenuItem.action.icon.name ||
|
||||
(statusPopupMenuItem.action.iconSettings &&
|
||||
(!!statusPopupMenuItem.action.iconSettings.name || !!statusPopupMenuItem.action.iconSettings.isLetterIdenticon))
|
||||
|
||||
let hasImageSettings = statusPopupMenuItem.action.image && !!statusPopupMenuItem.action.image.source.toString()
|
||||
|
||||
return enabled && (parent.subMenu && !!statusPopupMenu.subMenuItemIcons[parent.subMenuIndex]) || hasIconSettings || hasImageSettings
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
contentItem: StatusBaseText {
|
||||
anchors.left: statusPopupMenuItem.indicator.right
|
||||
anchors.right: arrowIcon.visible ? arrowIcon.left : arrowIcon.right
|
||||
anchors.rightMargin: 8
|
||||
anchors.leftMargin: 4
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: statusPopupMenuItem.text
|
||||
color: {
|
||||
switch (statusPopupMenuItem.action.type) {
|
||||
case StatusMenuItem.Type.Danger:
|
||||
return Theme.palette.dangerColor1
|
||||
break;
|
||||
default:
|
||||
return Theme.palette.directColor1
|
||||
}
|
||||
}
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
visible: statusPopupMenuItem.action.enabled
|
||||
}
|
||||
|
||||
arrow: StatusIcon {
|
||||
id: arrowIcon
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 8
|
||||
height: 16
|
||||
visible: statusPopupMenuItem.subMenu
|
||||
icon: "next"
|
||||
color: Theme.palette.directColor1
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: {
|
||||
if (statusPopupMenuItem.hovered) {
|
||||
return statusPopupMenuItem.action.type === StatusMenuItem.Type.Danger ? Theme.palette.dangerColor3 : Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
}
|
||||
return "transparent"
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
id: sensor
|
||||
anchors.fill: parent
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
hoverEnabled: statusPopupMenuItem.action.enabled
|
||||
onPressed: mouse.accepted = false
|
||||
}
|
||||
delegate: StatusMenuItemDelegate {
|
||||
statusPopupMenu: root
|
||||
}
|
||||
|
||||
background: Item {
|
||||
|
||||
@@ -113,11 +113,16 @@ StatusModal {
|
||||
property string primaryText: ""
|
||||
property string secondaryText: ""
|
||||
property StatusIconSettings iconSettings: StatusIconSettings {
|
||||
width: 16
|
||||
height: 16
|
||||
name: ""
|
||||
isLetterIdenticon: false
|
||||
letterSize: 11
|
||||
}
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 16
|
||||
height: 16
|
||||
source: ""
|
||||
isIdenticon: false
|
||||
}
|
||||
@@ -155,67 +160,17 @@ StatusModal {
|
||||
font.weight: Font.Medium
|
||||
}
|
||||
|
||||
Loader {
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
Layout.preferredWidth: active ? 16 : 0
|
||||
Layout.preferredHeight: 16
|
||||
image: searchOptionsMenuButton.image
|
||||
icon: searchOptionsMenuButton.iconSettings
|
||||
name: searchOptionsMenuButton.primaryText
|
||||
active: searchOptionsMenuButton.primaryText !== defaultSearchLocationText &&
|
||||
(searchOptionsMenuButton.iconSettings.name ||
|
||||
searchOptionsMenuButton.iconSettings.isLetterIdenticon ||
|
||||
!!searchOptionsMenuButton.image.source.toString())
|
||||
|
||||
sourceComponent: {
|
||||
if (!!searchOptionsMenuButton.image.source.toString()) {
|
||||
return statusRoundedImageCmp
|
||||
}
|
||||
if (!!searchOptionsMenuButton.iconSettings.isLetterIdenticon || !searchOptionsMenuButton.iconSettings.name) {
|
||||
return statusLetterIdenticonCmp
|
||||
}
|
||||
return statusIconCmp
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusIconCmp
|
||||
StatusIcon {
|
||||
width: 16
|
||||
icon: searchOptionsMenuButton.iconSettings.name
|
||||
color: searchOptionsMenuButton.iconSettings.color
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusRoundedImageCmp
|
||||
Item {
|
||||
width: 16
|
||||
height: 16
|
||||
StatusRoundedImage {
|
||||
id: statusRoundedImage
|
||||
implicitWidth: parent.width
|
||||
implicitHeight: parent.height
|
||||
image.source: searchOptionsMenuButton.image.source
|
||||
color: searchOptionsMenuButton.image.isIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
border.width: searchOptionsMenuButton.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: statusLetterIdenticonCmp
|
||||
active: statusRoundedImage.image.status === Image.Error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: statusLetterIdenticonCmp
|
||||
StatusLetterIdenticon {
|
||||
implicitWidth: 16
|
||||
implicitHeight: 16
|
||||
letterSize: 11
|
||||
color: searchOptionsMenuButton.iconSettings.color
|
||||
name: searchOptionsMenuButton.primaryText
|
||||
}
|
||||
}
|
||||
|
||||
StatusBaseText {
|
||||
@@ -301,7 +256,7 @@ StatusModal {
|
||||
radius: 0
|
||||
statusListItemSubTitle.height: model.content !== "" ? 20 : 0
|
||||
statusListItemSubTitle.elide: Text.ElideRight
|
||||
statusListItemSubTitle.color: Theme.palette.black
|
||||
statusListItemSubTitle.color: Theme.palette.directColor1
|
||||
icon.isLetterIdenticon: (model.image === "")
|
||||
icon.background.color: model.color
|
||||
titleAsideText: root.formatTimestampFn(model.time)
|
||||
|
||||
@@ -22,7 +22,8 @@ MenuItem {
|
||||
isLetterIdenticon: (root.image.source.toString() === ""
|
||||
&& root.iconSettings.name.toString() === "")
|
||||
background: StatusIconBackgroundSettings {}
|
||||
color: "transparent"
|
||||
color: (name === "channel") ? Theme.palette.directColor1 : "transparent"
|
||||
letterSize: 11
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
@@ -32,30 +33,17 @@ MenuItem {
|
||||
contentItem: RowLayout {
|
||||
anchors.left: parent.left
|
||||
anchors.leftMargin: 12
|
||||
StatusIcon {
|
||||
Layout.preferredWidth: visible ? root.iconSettings.width : 0
|
||||
Layout.preferredHeight: visible ? root.iconSettings.height : 0
|
||||
Item {
|
||||
Layout.preferredWidth: root.iconSettings.width
|
||||
Layout.preferredHeight: root.iconSettings.height
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: !!root.iconSettings.name && !root.image.source.toString()
|
||||
icon: root.iconSettings.name
|
||||
color: (icon === "channel")? Theme.palette.directColor1 : root.iconSettings.color
|
||||
}
|
||||
StatusRoundedImage {
|
||||
Layout.preferredWidth: visible ? root.image.width : 0
|
||||
Layout.preferredHeight: visible ? root.image.height : 0
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
visible: root.image.source.toString() !== ""
|
||||
image.source: root.image.source
|
||||
border.width: root.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
}
|
||||
StatusLetterIdenticon {
|
||||
Layout.preferredWidth: visible ? root.iconSettings.width : 0
|
||||
Layout.preferredHeight: visible ? root.iconSettings.height : 0
|
||||
visible: root.iconSettings.isLetterIdenticon && !root.iconSettings.name && !root.image.source.toString()
|
||||
color: root.iconSettings.color
|
||||
name: root.text
|
||||
letterSize: 11
|
||||
StatusSmartIdenticon {
|
||||
id: identicon
|
||||
anchors.centerIn: parent
|
||||
image: root.image
|
||||
icon: root.iconSettings
|
||||
name: root.text
|
||||
}
|
||||
}
|
||||
StatusBaseText {
|
||||
Layout.fillWidth: true
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
import QtQuick 2.14
|
||||
import QtQuick.Controls 2.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
|
||||
StatusPopupMenu {
|
||||
id: root
|
||||
|
||||
property alias suggestions: suggestionsMenu.model
|
||||
|
||||
signal addToUserDict()
|
||||
signal disableSpellchecking()
|
||||
|
||||
Column {
|
||||
|
||||
Repeater {
|
||||
id: suggestionsMenu
|
||||
|
||||
delegate: MenuItem {
|
||||
id: variants
|
||||
implicitWidth: parent ? parent.width : 0
|
||||
implicitHeight: 38
|
||||
contentItem: StatusBaseText {
|
||||
rightPadding: 8
|
||||
leftPadding: 4
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: modelData
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: variants.hovered ? Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
root.menuItemClicked(index)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusMenuSeparator { visible: !!suggestionsMenu.model && suggestionsMenu.model.length !== 0}
|
||||
|
||||
MenuItem {
|
||||
id: ignoreWord
|
||||
implicitWidth: parent ? parent.width : 0
|
||||
implicitHeight: 38
|
||||
contentItem: StatusBaseText {
|
||||
rightPadding: 8
|
||||
leftPadding: 4
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: qsTr("Add to dictionary")
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
background: Rectangle {
|
||||
color: ignoreWord.hovered ? Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
root.addToUserDict()
|
||||
}
|
||||
}
|
||||
|
||||
MenuItem {
|
||||
id: disableSpellchecking
|
||||
implicitWidth: parent ? parent.width : 0
|
||||
implicitHeight: 38
|
||||
contentItem: StatusBaseText {
|
||||
rightPadding: 8
|
||||
leftPadding: 4
|
||||
|
||||
horizontalAlignment: Text.AlignLeft
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
|
||||
text: qsTr("Disable Spellchecking")
|
||||
color: Theme.palette.directColor1
|
||||
font.pixelSize: 13
|
||||
elide: Text.ElideRight
|
||||
}
|
||||
|
||||
|
||||
background: Rectangle {
|
||||
color: disableSpellchecking.hovered ? Theme.palette.statusPopupMenu.hoverBackgroundColor
|
||||
: "transparent"
|
||||
}
|
||||
|
||||
onTriggered: {
|
||||
root.disableSpellchecking()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -3,9 +3,11 @@ module StatusQ.Popups
|
||||
StatusMenuSeparator 0.1 StatusMenuSeparator.qml
|
||||
StatusPopupMenu 0.1 StatusPopupMenu.qml
|
||||
StatusMenuItem 0.1 StatusMenuItem.qml
|
||||
StatusMenuItemDelegate 0.1 StatusMenuItemDelegate.qml
|
||||
StatusMenuHeadline 0.1 StatusMenuHeadline.qml
|
||||
StatusModal 0.1 StatusModal.qml
|
||||
StatusSearchPopup 0.1 StatusSearchPopup.qml
|
||||
StatusModalDivider 0.1 StatusModalDivider.qml
|
||||
StatusSearchPopupMenuItem 0.1 StatusSearchPopupMenuItem.qml
|
||||
StatusSearchLocationMenu 0.1 StatusSearchLocationMenu.qml
|
||||
StatusSpellcheckingMenuItems 0.1 StatusSpellcheckingMenuItems.qml
|
||||
|
||||
@@ -12,8 +12,10 @@ Row {
|
||||
property int titleElide: Text.ElideRight
|
||||
property int subTitleElide: Text.ElideRight
|
||||
property bool editable: false
|
||||
property bool headerImageEditable: false
|
||||
|
||||
signal editButtonClicked
|
||||
signal headerImageClicked
|
||||
|
||||
property StatusImageSettings image: StatusImageSettings {
|
||||
width: 40
|
||||
@@ -39,7 +41,7 @@ Row {
|
||||
}
|
||||
return statusRoundedImageCmp
|
||||
}
|
||||
active: statusImageWithTitle.icon.isLetterIdenticon ||
|
||||
active: statusImageWithTitle.icon.isLetterIdenticon ||
|
||||
!!statusImageWithTitle.image.source.toString()
|
||||
}
|
||||
|
||||
@@ -60,16 +62,56 @@ Row {
|
||||
height: statusImageWithTitle.image.height
|
||||
StatusRoundedImage {
|
||||
id: statusRoundedImage
|
||||
objectName: "headerImage"
|
||||
image.source: statusImageWithTitle.image.source
|
||||
width: statusImageWithTitle.image.width
|
||||
height: statusImageWithTitle.image.height
|
||||
color: statusImageWithTitle.image.isIdenticon ?
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
Theme.palette.statusRoundedImage.backgroundColor :
|
||||
"transparent"
|
||||
border.width: statusImageWithTitle.image.isIdenticon ? 1 : 0
|
||||
border.color: Theme.palette.directColor7
|
||||
showLoadingIndicator: true
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
id: editAvatarIcon
|
||||
|
||||
objectName: "editAvatarImage"
|
||||
anchors.right: parent.right
|
||||
anchors.bottom: parent.bottom
|
||||
anchors.bottomMargin: -3
|
||||
anchors.rightMargin: -2
|
||||
width: 18
|
||||
height: 18
|
||||
radius: width / 2
|
||||
|
||||
visible: statusImageWithTitle.headerImageEditable
|
||||
|
||||
color: Theme.palette.primaryColor1;
|
||||
border.color: Theme.palette.indirectColor1
|
||||
border.width: Theme.palette.name === "light" ? 1 : 0
|
||||
|
||||
StatusIcon {
|
||||
anchors.centerIn: parent
|
||||
width: 11
|
||||
color: Theme.palette.indirectColor1
|
||||
icon: "tiny/edit"
|
||||
}
|
||||
}
|
||||
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
|
||||
cursorShape: enabled ? Qt.PointingHandCursor
|
||||
: Qt.ArrowCursor
|
||||
enabled: statusImageWithTitle.headerImageEditable
|
||||
|
||||
onClicked: {
|
||||
statusImageWithTitle.headerImageClicked()
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
sourceComponent: statusLetterIdenticon
|
||||
active: statusRoundedImage.image.status === Image.Error
|
||||
@@ -80,23 +122,25 @@ Row {
|
||||
Column {
|
||||
id: textLayout
|
||||
width: !iconOrImage.active ? parent.width :
|
||||
parent.width - iconOrImage.width - parent.spacing
|
||||
parent.width - iconOrImage.width - parent.spacing
|
||||
Row {
|
||||
id: headerTitleRow
|
||||
width: parent.width
|
||||
spacing: 4
|
||||
StatusBaseText {
|
||||
id: headerTitle
|
||||
objectName: "headerTitle"
|
||||
font.family: Theme.palette.baseFont.name
|
||||
font.pixelSize: 17
|
||||
font.bold: true
|
||||
elide: statusImageWithTitle.titleElide
|
||||
color: Theme.palette.directColor1
|
||||
width: !editButton.visible ? parent.width :
|
||||
parent.width - editButton.width - parent.spacing
|
||||
width: !editButton.visible ? parent.width :
|
||||
parent.width - editButton.width - parent.spacing
|
||||
}
|
||||
StatusFlatRoundButton {
|
||||
id: editButton
|
||||
objectName: "editAvatarbButton"
|
||||
visible: statusImageWithTitle.editable
|
||||
anchors.bottom: headerTitle.bottom
|
||||
anchors.bottomMargin: -1
|
||||
@@ -114,6 +158,7 @@ Row {
|
||||
|
||||
StatusBaseText {
|
||||
id: headerSubTitle
|
||||
objectName: "headerSubTitle"
|
||||
font.family: Theme.palette.baseFont.name
|
||||
font.pixelSize: 15
|
||||
color:Theme.palette.baseColor1
|
||||
|
||||
@@ -13,6 +13,7 @@ Rectangle {
|
||||
|
||||
property list<Item> leftButtons
|
||||
property list<StatusBaseButton> rightButtons
|
||||
property bool showFooter: true
|
||||
|
||||
radius: 8
|
||||
|
||||
@@ -30,7 +31,7 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
implicitHeight: visible ? rootLayout.implicitHeight + 30 : 0
|
||||
implicitHeight: rootLayout.implicitHeight + 30
|
||||
|
||||
RowLayout {
|
||||
id: rootLayout
|
||||
@@ -43,6 +44,7 @@ Rectangle {
|
||||
Row {
|
||||
id: leftButtonsLayout
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignLeft
|
||||
visible: statusModalFooter.showFooter
|
||||
|
||||
spacing: 16
|
||||
}
|
||||
@@ -55,9 +57,9 @@ Rectangle {
|
||||
Row {
|
||||
id: rightButtonsLayout
|
||||
Layout.alignment: Qt.AlignVCenter | Qt.AlignRight
|
||||
visible: statusModalFooter.showFooter
|
||||
|
||||
spacing: 16
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,9 +18,11 @@ Rectangle {
|
||||
property alias image: imageWithTitle.image
|
||||
property alias icon: imageWithTitle.icon
|
||||
property bool editable: false
|
||||
property alias headerImageEditable: imageWithTitle.headerImageEditable
|
||||
property Component popupMenu
|
||||
|
||||
signal editButtonClicked
|
||||
signal headerImageClicked
|
||||
signal close
|
||||
|
||||
implicitHeight: visible? Math.max(closeButton.height, imageWithTitle.implicitHeight) + 32 : 0
|
||||
@@ -36,6 +38,18 @@ Rectangle {
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: parent.radius
|
||||
color: parent.color
|
||||
|
||||
StatusModalDivider {
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
StatusImageWithTitle {
|
||||
id: imageWithTitle
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -46,6 +60,7 @@ Rectangle {
|
||||
editable: statusModalHeader.editable
|
||||
titleElide: statusModalHeader.titleElide
|
||||
subTitleElide: statusModalHeader.subTitleElide
|
||||
onHeaderImageClicked: statusModalHeader.headerImageClicked()
|
||||
onEditButtonClicked: statusModalHeader.editButtonClicked()
|
||||
}
|
||||
|
||||
@@ -60,6 +75,7 @@ Rectangle {
|
||||
|
||||
Loader {
|
||||
id: actionButtonLoader
|
||||
objectName: "actionButtonloader"
|
||||
anchors.right: closeButton.left
|
||||
anchors.rightMargin: 8
|
||||
anchors.top: parent.top
|
||||
@@ -68,6 +84,7 @@ Rectangle {
|
||||
|
||||
StatusFlatRoundButton {
|
||||
id: closeButton
|
||||
objectName: "headerClosebutton"
|
||||
anchors.right: parent.right
|
||||
anchors.rightMargin: 20
|
||||
anchors.top: parent.top
|
||||
@@ -83,18 +100,6 @@ Rectangle {
|
||||
onClicked: statusModalHeader.close()
|
||||
}
|
||||
|
||||
Rectangle {
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
height: parent.radius
|
||||
color: parent.color
|
||||
|
||||
StatusModalDivider {
|
||||
anchors.bottom: parent.bottom
|
||||
width: parent.width
|
||||
}
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: popupMenuSlot
|
||||
active: !!statusModalHeader.popupMenu
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
<svg width="16" height="17" viewBox="0 0 16 17" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M2.76413 10.1901L8.32479 4.77888C8.70676 4.40717 9.32476 4.40591 9.71111 4.78187C10.0948 5.15523 10.0968 5.75861 9.71418 6.13093L3.45575 12.2211C3.26582 12.406 3.01753 12.4992 2.76838 12.5C2.51183 12.4981 2.26284 12.4063 2.07584 12.2244L0.284232 10.5078C-0.0959013 10.1379 -0.0957078 9.53795 0.290638 9.16199C0.674309 8.78863 1.29863 8.79084 1.67363 9.15576L2.76413 10.1901Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.76413 10.1901L14.3248 4.77888C14.7068 4.40717 15.3248 4.40591 15.7111 4.78187C16.0948 5.15523 16.0968 5.75861 15.7142 6.13093L9.45576 12.2211C9.26582 12.406 9.01753 12.4992 8.76838 12.5C8.51183 12.4981 8.26284 12.4063 8.07584 12.2244L6.28423 10.5078L7.67363 9.15576L8.76413 10.1901Z" fill="black"/>
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M22.8641 4.42199C23.2087 4.65176 23.3019 5.11741 23.0721 5.46206L13.1981 19.4222C13.0734 19.6091 12.8715 19.7303 12.6479 19.7525C12.4243 19.7746 12.2026 19.6953 12.0437 19.5365L6.04369 13.5365C5.7508 13.2436 5.7508 12.7687 6.04369 12.4758C6.33658 12.1829 6.81146 12.1829 7.10435 12.4758L12.4575 17.8289L21.824 4.63C22.0538 4.28536 22.5194 4.19223 22.8641 4.42199Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.8556 4.38365C18.1927 4.6244 18.2707 5.09281 18.03 5.42988L12.0525 13.7986C11.8117 14.1357 11.3433 14.2137 11.0063 13.973C10.6692 13.7322 10.5911 13.2638 10.8319 12.9268L16.8094 4.55803C17.0501 4.22097 17.5185 4.1429 17.8556 4.38365Z" fill="black"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M1.0194 12.4798C1.3111 12.1857 1.78597 12.1838 2.08005 12.4755L8.09766 18.4444C8.39174 18.7361 8.39367 19.211 8.10197 19.505C7.81027 19.7991 7.3354 19.801 7.04132 19.5093L1.02371 13.5404C0.729628 13.2487 0.727699 12.7738 1.0194 12.4798Z" fill="black"/>
|
||||
</svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 894 B After Width: | Height: | Size: 1.1 KiB |
@@ -0,0 +1,6 @@
|
||||
<svg width="20" height="20" viewBox="0 0 20 20" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M16 1.5H4C2.61929 1.5 1.5 2.61929 1.5 4V16C1.5 17.3807 2.61929 18.5 4 18.5H16C17.3807 18.5 18.5 17.3807 18.5 16V4C18.5 2.61929 17.3807 1.5 16 1.5ZM4 0C1.79086 0 0 1.79086 0 4V16C0 18.2091 1.79086 20 4 20H16C18.2091 20 20 18.2091 20 16V4C20 1.79086 18.2091 0 16 0H4Z" fill="#939BA1"/>
|
||||
<path d="M8.72261 11.4868V10.4133C8.72261 9.99528 8.38061 9.65328 7.96261 9.65328H6.22411C5.90111 9.65328 5.64461 9.90978 5.64461 10.2328C5.64461 10.5748 5.90111 10.8313 6.22411 10.8313H7.37361V11.5913C7.11711 11.8288 6.58511 12.0758 6.02461 12.0758C4.87511 12.0758 4.03911 11.1923 4.03911 9.99528C4.03911 8.79828 4.87511 7.91478 6.02461 7.91478C6.50911 7.91478 6.98411 8.12378 7.34511 8.47528C7.46861 8.59878 7.63961 8.66528 7.80111 8.66528C8.13361 8.66528 8.43761 8.38978 8.43761 8.05728C8.43761 7.91478 8.38061 7.76278 8.27611 7.64878C7.78211 7.11678 7.05061 6.71778 6.02461 6.71778C4.17211 6.71778 2.65211 7.99078 2.65211 9.99528C2.65211 11.9903 4.17211 13.2823 6.02461 13.2823C7.30711 13.2823 8.72261 12.6363 8.72261 11.4868Z" fill="#939BA1"/>
|
||||
<path d="M11.4392 12.5603V7.43978C11.4392 7.07878 11.1352 6.77478 10.7742 6.77478C10.3942 6.77478 10.0902 7.07878 10.0902 7.43978V12.5603C10.0902 12.9213 10.3942 13.2253 10.7552 13.2253C11.1352 13.2253 11.4392 12.9213 11.4392 12.5603Z" fill="#939BA1"/>
|
||||
<path d="M17.3479 7.43029C17.3479 7.09778 17.0819 6.83179 16.7684 6.83179H13.5669C13.1489 6.83179 12.8069 7.17379 12.8069 7.59179V12.5603C12.8069 12.9213 13.1109 13.2253 13.4719 13.2253C13.8519 13.2253 14.1559 12.9213 14.1559 12.5603V11.0463C14.1559 10.7701 14.3797 10.5463 14.6559 10.5463H16.2425C16.556 10.5463 16.822 10.2803 16.822 9.95728C16.822 9.62478 16.556 9.35879 16.2425 9.35879H14.6559C14.3797 9.35879 14.1559 9.13493 14.1559 8.85879V8.51929C14.1559 8.24314 14.3797 8.01929 14.6559 8.01929H16.7684C17.0819 8.01929 17.3479 7.75329 17.3479 7.43029Z" fill="#939BA1"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.85145 4.58361L7.3077 0.871991C7.19383 0.598227 6.80602 0.598227 6.69215 0.871991L5.1484 4.58361L1.1414 4.90485C0.845844 4.92854 0.726003 5.29738 0.951182 5.49027L4.0041 8.10542L3.07138 12.0156C3.00259 12.304 3.31634 12.5319 3.56937 12.3774L6.99993 10.282L10.4305 12.3774C10.6835 12.5319 10.9973 12.304 10.9285 12.0156L9.99575 8.10542L13.0487 5.49027C13.2738 5.29738 13.154 4.92854 12.8585 4.90485L8.85145 4.58361ZM10.8765 6.03425C10.9891 5.93781 10.9292 5.75339 10.7814 5.74154L8.77154 5.58041C8.39775 5.55045 8.07214 5.31388 7.92813 4.96764L7.15381 3.10596C7.09688 2.96908 6.90297 2.96908 6.84604 3.10596L6.07172 4.96764C5.92771 5.31388 5.6021 5.55045 5.22831 5.58041L3.21848 5.74154C3.0707 5.75339 3.01078 5.93781 3.12337 6.03425L4.65465 7.34596C4.93944 7.58991 5.06381 7.97269 4.97681 8.33744L4.50897 10.2987C4.47458 10.4429 4.63145 10.5569 4.75797 10.4796L6.47867 9.42861C6.79869 9.23315 7.20116 9.23315 7.52118 9.42861L9.24188 10.4796C9.3684 10.5569 9.52527 10.4429 9.49088 10.2987L9.02304 8.33744C8.93604 7.97269 9.06041 7.58991 9.3452 7.34596L10.8765 6.03425Z" fill="#FFCA0F"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
@@ -0,0 +1,3 @@
|
||||
<svg width="14" height="13" viewBox="0 0 14 13" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M8.85169 4.58361L7.30794 0.871991C7.19408 0.598227 6.80626 0.598227 6.6924 0.871991L5.14865 4.58361L1.14164 4.90485C0.846088 4.92854 0.726247 5.29738 0.951426 5.49027L4.00434 8.10542L3.07163 12.0156C3.00283 12.304 3.31658 12.5319 3.56961 12.3774L7.00017 10.282L10.4307 12.3774C10.6838 12.5319 10.9975 12.304 10.9287 12.0156L9.996 8.10542L13.0489 5.49027C13.2741 5.29738 13.1543 4.92854 12.8587 4.90485L8.85169 4.58361Z" fill="#FFCA0F"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 589 B |
@@ -0,0 +1,107 @@
|
||||
<svg width="1024" height="1024" viewBox="0 0 1024 1024" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<g filter="url(#filter0_d)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M924 356.628C924 346.845 924.004 337.062 923.944 327.279C923.895 319.039 923.8 310.8 923.576 302.562C923.092 284.61 922.033 266.503 918.84 248.75C915.602 230.741 910.314 213.98 901.981 197.617C893.789 181.534 883.088 166.817 870.32 154.057C857.555 141.298 842.834 130.605 826.746 122.417C810.366 114.083 793.587 108.796 775.558 105.56C757.803 102.371 739.691 101.314 721.738 100.829C713.495 100.607 705.253 100.512 697.008 100.461C687.22 100.402 677.432 100.406 667.644 100.406L553.997 100H468.997L357.361 100.407C347.554 100.407 337.747 100.402 327.94 100.461C319.679 100.512 311.42 100.607 303.161 100.829C285.167 101.315 267.014 102.373 249.217 105.564C231.164 108.801 214.36 114.085 197.958 122.414C181.835 130.601 167.083 141.296 154.291 154.057C141.501 166.816 130.78 181.529 122.573 197.61C114.218 213.981 108.919 230.751 105.673 248.771C102.477 266.516 101.418 284.618 100.931 302.562C100.709 310.801 100.613 319.039 100.563 327.279C100.503 337.063 100 349.217 100 359L100.003 469.09L100 555L100.508 667.428C100.508 677.224 100.504 687.02 100.563 696.816C100.613 705.069 100.709 713.319 100.932 721.568C101.418 739.544 102.479 757.676 105.678 775.454C108.923 793.487 114.22 810.271 122.569 826.656C130.777 842.761 141.5 857.498 154.291 870.275C167.082 883.051 181.83 893.759 197.95 901.959C214.362 910.304 231.174 915.597 249.238 918.838C267.027 922.032 285.174 923.09 303.161 923.576C311.42 923.798 319.679 923.893 327.941 923.944C337.748 924.003 347.554 924 357.361 924L470.006 924.003H555.217L667.644 923.999C677.432 923.999 687.22 924.003 697.008 923.944C705.253 923.893 713.495 923.798 721.738 923.576C739.698 923.089 757.816 922.03 775.579 918.835C793.597 915.593 810.368 910.302 826.739 901.961C842.831 893.763 857.554 883.053 870.32 870.275C883.086 857.5 893.786 842.765 901.978 826.663C910.316 810.27 915.604 793.477 918.844 775.432C922.034 757.663 923.092 739.537 923.577 721.568C923.8 713.318 923.895 705.068 923.944 696.816C924.005 687.02 924 677.224 924 667.428C924 667.428 923.994 556.985 923.994 555V469C923.994 467.534 924 356.628 924 356.628Z" fill="#3B59DE"/>
|
||||
</g>
|
||||
<g clip-path="url(#clip0)">
|
||||
<g filter="url(#filter1_f)">
|
||||
<circle cx="512" cy="100" r="521" fill="white" fill-opacity="0.1"/>
|
||||
</g>
|
||||
</g>
|
||||
<g filter="url(#filter2_ddiii)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M429.746 739.525C365.19 743.172 300.676 704.222 297.172 641.018C293.727 578.889 342.227 537.325 422.283 532.812C481.376 529.482 518.419 542.937 577.513 539.598C592.165 538.795 606.72 536.719 621.015 533.395C612.306 640.178 534.949 733.597 429.746 739.525Z" fill="url(#paint0_radial)"/>
|
||||
</g>
|
||||
<g filter="url(#filter3_ddiii)">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M595.412 506.135C533.72 509.69 495.058 495.319 433.357 498.883C418.055 499.742 402.858 501.96 387.946 505.51C397.053 391.409 477.806 291.595 587.616 285.251C655.003 281.362 722.357 322.968 726.01 390.51C729.605 456.894 678.988 501.306 595.42 506.127L595.412 506.135Z" fill="url(#paint1_radial)"/>
|
||||
</g>
|
||||
<defs>
|
||||
<filter id="filter0_d" x="89" y="89.0002" width="854" height="854.003" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dx="4" dy="4"/>
|
||||
<feGaussianBlur stdDeviation="7.5"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect1_dropShadow" result="shape"/>
|
||||
</filter>
|
||||
<filter id="filter1_f" x="-213" y="-625" width="1450" height="1450" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="BackgroundImageFix" result="shape"/>
|
||||
<feGaussianBlur stdDeviation="102" result="effect1_foregroundBlur"/>
|
||||
</filter>
|
||||
<filter id="filter2_ddiii" x="222" y="487.277" width="474.015" height="357.483" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="30"/>
|
||||
<feGaussianBlur stdDeviation="37.5"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="13"/>
|
||||
<feGaussianBlur stdDeviation="13.5"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="-38"/>
|
||||
<feGaussianBlur stdDeviation="61"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect3_innerShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-10" dy="-33"/>
|
||||
<feGaussianBlur stdDeviation="20"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.262745 0 0 0 0 0.376471 0 0 0 0 0.87451 0 0 0 0.17 0"/>
|
||||
<feBlend mode="normal" in2="effect3_innerShadow" result="effect4_innerShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="10" dy="24"/>
|
||||
<feGaussianBlur stdDeviation="32"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="effect4_innerShadow" result="effect5_innerShadow"/>
|
||||
</filter>
|
||||
<filter id="filter3_ddiii" x="312.946" y="240" width="488.244" height="371.705" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
|
||||
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="30"/>
|
||||
<feGaussianBlur stdDeviation="37.5"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0"/>
|
||||
<feBlend mode="normal" in2="BackgroundImageFix" result="effect1_dropShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
|
||||
<feOffset dy="13"/>
|
||||
<feGaussianBlur stdDeviation="13.5"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.3 0"/>
|
||||
<feBlend mode="normal" in2="effect1_dropShadow" result="effect2_dropShadow"/>
|
||||
<feBlend mode="normal" in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dy="-38"/>
|
||||
<feGaussianBlur stdDeviation="61"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
|
||||
<feBlend mode="normal" in2="shape" result="effect3_innerShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="-10" dy="-33"/>
|
||||
<feGaussianBlur stdDeviation="20"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 0.262745 0 0 0 0 0.376471 0 0 0 0 0.87451 0 0 0 0.17 0"/>
|
||||
<feBlend mode="normal" in2="effect3_innerShadow" result="effect4_innerShadow"/>
|
||||
<feColorMatrix in="SourceAlpha" type="matrix" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
|
||||
<feOffset dx="10" dy="24"/>
|
||||
<feGaussianBlur stdDeviation="32"/>
|
||||
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
|
||||
<feColorMatrix type="matrix" values="0 0 0 0 1 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0"/>
|
||||
<feBlend mode="normal" in2="effect4_innerShadow" result="effect5_innerShadow"/>
|
||||
</filter>
|
||||
<radialGradient id="paint0_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(360.545 542.122) rotate(45.3201) scale(237.198 346.271)">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0.8"/>
|
||||
</radialGradient>
|
||||
<radialGradient id="paint1_radial" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(454.281 295.52) rotate(45.988) scale(250.586 365.62)">
|
||||
<stop stop-color="white"/>
|
||||
<stop offset="1" stop-color="white" stop-opacity="0.8"/>
|
||||
</radialGradient>
|
||||
<clipPath id="clip0">
|
||||
<rect x="100" y="100" width="824" height="824.003" rx="184" fill="white"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.2 KiB |
+47
@@ -18,8 +18,10 @@
|
||||
<file>src/StatusQ/Popups/StatusMenuSeparator.qml</file>
|
||||
<file>src/StatusQ/Popups/StatusMenuHeadline.qml</file>
|
||||
<file>src/StatusQ/Popups/StatusMenuItem.qml</file>
|
||||
<file>src/StatusQ/Popups/StatusMenuItemDelegate.qml</file>
|
||||
<file>src/StatusQ/Popups/StatusModalDivider.qml</file>
|
||||
<file>src/StatusQ/Components/qmldir</file>
|
||||
<file>src/StatusQ/Components/StatusAddress.qml</file>
|
||||
<file>src/StatusQ/Components/StatusChatListItem.qml</file>
|
||||
<file>src/StatusQ/Components/StatusChatListAndCategories.qml</file>
|
||||
<file>src/StatusQ/Components/StatusChatInfoToolBar.qml</file>
|
||||
@@ -37,9 +39,12 @@
|
||||
<file>src/StatusQ/Components/StatusLoadingIndicator.qml</file>
|
||||
<file>src/StatusQ/Platform/qmldir</file>
|
||||
<file>src/StatusQ/Platform/StatusMacTrafficLights.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusAssetSelector.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusIconTabButton.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusChatInfoButton.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusColorSelector.qml</file>
|
||||
<file>src/StatusQ/Controls/qmldir</file>
|
||||
<file>src/StatusQ/Controls/StatusAccountSelector.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusSlider.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusRoundButton.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusNavBarTabButton.qml</file>
|
||||
@@ -50,6 +55,7 @@
|
||||
<file>src/StatusQ/Controls/StatusSwitch.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusCheckBox.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusButton.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusSelect.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusToolTip.qml</file>
|
||||
<file>src/StatusQ/Controls/Validators/StatusValidator.qml</file>
|
||||
<file>src/StatusQ/Controls/Validators/StatusMinLengthValidator.qml</file>
|
||||
@@ -268,5 +274,46 @@
|
||||
<file>src/StatusQ/Controls/StatusSwitchTabBar.qml</file>
|
||||
<file>src/StatusQ/Components/StatusExpandableItem.qml</file>
|
||||
<file>src/assets/img/icons/snt.svg</file>
|
||||
<file>src/StatusQ/Popups/StatusSpellcheckingMenuItems.qml</file>
|
||||
<file>src/StatusQ/Controls/StatusSelectableText.qml</file>
|
||||
<file>src/assets/img/icons/tiny/add.svg</file>
|
||||
<file>src/assets/img/icons/tiny/arrow-down.svg</file>
|
||||
<file>src/assets/img/icons/tiny/channel-white.svg</file>
|
||||
<file>src/assets/img/icons/tiny/channel.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chat.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chatbot.svg</file>
|
||||
<file>src/assets/img/icons/tiny/checkmark.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chevron-down.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chevron-left.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chevron-right.svg</file>
|
||||
<file>src/assets/img/icons/tiny/chevron-up.svg</file>
|
||||
<file>src/assets/img/icons/tiny/clear.svg</file>
|
||||
<file>src/assets/img/icons/tiny/community-1.svg</file>
|
||||
<file>src/assets/img/icons/tiny/community.svg</file>
|
||||
<file>src/assets/img/icons/tiny/contact.svg</file>
|
||||
<file>src/assets/img/icons/tiny/double-checkmark.svg</file>
|
||||
<file>src/assets/img/icons/tiny/edit.svg</file>
|
||||
<file>src/assets/img/icons/tiny/external.svg</file>
|
||||
<file>src/assets/img/icons/tiny/group-white.svg</file>
|
||||
<file>src/assets/img/icons/tiny/group.svg</file>
|
||||
<file>src/assets/img/icons/tiny/more.svg</file>
|
||||
<file>src/assets/img/icons/tiny/message/delivered.svg</file>
|
||||
<file>src/assets/img/icons/tiny/message/pending.svg</file>
|
||||
<file>src/assets/img/icons/tiny/message/sent.svg</file>
|
||||
<file>src/assets/img/icons/tiny/message/warning.svg</file>
|
||||
<file>src/assets/img/icons/tiny/muted-white.svg</file>
|
||||
<file>src/assets/img/icons/tiny/muted.svg</file>
|
||||
<file>src/assets/img/icons/tiny/not-secure.svg</file>
|
||||
<file>src/assets/img/icons/tiny/pending.svg</file>
|
||||
<file>src/assets/img/icons/tiny/pin.svg</file>
|
||||
<file>src/assets/img/icons/tiny/public-chat-white.svg</file>
|
||||
<file>src/assets/img/icons/tiny/public-chat.svg</file>
|
||||
<file>src/assets/img/icons/tiny/reply.svg</file>
|
||||
<file>src/assets/img/icons/tiny/secure.svg</file>
|
||||
<file>src/assets/img/icons/tiny/settings.svg</file>
|
||||
<file>src/assets/img/icons/tiny/SNT.svg</file>
|
||||
<file>src/assets/img/icons/tiny/time.svg</file>
|
||||
<file>src/assets/img/icons/tiny/tribute-to-talk.svg</file>
|
||||
<file>src/assets/img/icons/tiny/warning.svg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
Reference in New Issue
Block a user