feat(CommunityPermissions): Dropdown for channels selection added
This commit is contained in:
parent
c980b52c3b
commit
d58dd3331b
|
@ -0,0 +1,13 @@
|
|||
import StatusQ.Core.Theme 0.1
|
||||
|
||||
CommunityListItem {
|
||||
implicitHeight: 34
|
||||
|
||||
statusListItemTitle.font.pixelSize: 12
|
||||
statusListItemTitle.color: Theme.palette.baseColor1
|
||||
|
||||
checkBox.visible: false
|
||||
|
||||
asset.isLetterIdenticon: false
|
||||
asset.isImage: false
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
import QtQuick 2.14
|
||||
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
|
||||
StatusListItem {
|
||||
property alias checked: checkBox.checked
|
||||
property alias checkState: checkBox.checkState
|
||||
readonly property alias checkBox: checkBox
|
||||
|
||||
implicitHeight: 44
|
||||
leftPadding: 8
|
||||
rightPadding: 3
|
||||
statusListItemTitle.font.pixelSize: 13
|
||||
|
||||
statusListItemTitleArea.anchors.leftMargin: 8
|
||||
|
||||
asset.bgWidth: 32
|
||||
asset.bgHeight: 32
|
||||
|
||||
asset.isLetterIdenticon: true
|
||||
asset.letterSize: 12
|
||||
asset.isImage: model.icon.includes("data")
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
|
||||
components: [
|
||||
StatusCheckBox {
|
||||
id: checkBox
|
||||
|
||||
size: StatusCheckBox.Size.Small
|
||||
rightPadding: 0
|
||||
}
|
||||
]
|
||||
|
||||
// using MouseArea instead of build-in 'clicked' signal to avoid
|
||||
// intercepting event by the StatusCheckBox
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
checkBox.toggle()
|
||||
checkBox.toggled()
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
|
@ -0,0 +1,376 @@
|
|||
import QtQuick 2.14
|
||||
import QtQuick.Layouts 1.14
|
||||
|
||||
import StatusQ.Core 0.1
|
||||
import StatusQ.Core.Theme 0.1
|
||||
import StatusQ.Components 0.1
|
||||
import StatusQ.Controls 0.1
|
||||
import StatusQ.Popups 0.1
|
||||
|
||||
import shared.controls 1.0
|
||||
|
||||
import SortFilterProxyModel 0.2
|
||||
|
||||
StatusDropdown {
|
||||
id: root
|
||||
|
||||
property string communityName
|
||||
property string communityImage
|
||||
property color communityColor
|
||||
|
||||
property var model
|
||||
|
||||
property int acceptMode: InDropdown.AcceptMode.Add
|
||||
|
||||
enum AcceptMode {
|
||||
Add, Update
|
||||
}
|
||||
|
||||
width: 289
|
||||
padding: 8
|
||||
|
||||
// force keeping within the bounds of the enclosing window
|
||||
margins: 0
|
||||
|
||||
signal addChannelClicked
|
||||
signal communitySelected
|
||||
signal channelsSelected(var channels)
|
||||
|
||||
function setSelectedChannels(channels) {
|
||||
d.setSelectedChannels(channels)
|
||||
}
|
||||
|
||||
onAboutToHide: searcher.text = ""
|
||||
onAboutToShow: scrollView.Layout.preferredHeight = Math.min(
|
||||
scrollView.implicitHeight, 420)
|
||||
|
||||
QtObject {
|
||||
id: d
|
||||
|
||||
readonly property var selectedChannels: new Map()
|
||||
|
||||
signal setSelectedChannels(var channels)
|
||||
|
||||
function search(text, searcherText) {
|
||||
return text.toLowerCase().includes(searcherText.toLowerCase())
|
||||
}
|
||||
|
||||
function resolveEmoji(emoji) {
|
||||
return !!emoji ? emoji : ""
|
||||
}
|
||||
|
||||
function resolveColor(color, colorId) {
|
||||
return !!color ? color : Theme.palette.userCustomizationColors[colorId]
|
||||
}
|
||||
|
||||
function addToSelectedChannels(model) {
|
||||
selectedChannels.set(model.itemId, {
|
||||
itemId: model.itemId,
|
||||
name: model.name,
|
||||
color: d.resolveColor(model.color, model.colorId),
|
||||
emoji: d.resolveEmoji(model.emoji)
|
||||
})
|
||||
}
|
||||
|
||||
function removeFromSelectedChannels(model) {
|
||||
selectedChannels.delete(model.itemId)
|
||||
}
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
anchors.top: parent.top
|
||||
anchors.right: parent.right
|
||||
anchors.left: parent.left
|
||||
|
||||
spacing: 0
|
||||
|
||||
SearchBox {
|
||||
id: searcher
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
topPadding: 0
|
||||
bottomPadding: 0
|
||||
minimumHeight: 36
|
||||
maximumHeight: 36
|
||||
}
|
||||
|
||||
StatusListItem {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 9
|
||||
Layout.preferredHeight: 44
|
||||
|
||||
|
||||
title: root.communityName
|
||||
subTitle: qsTr("Community")
|
||||
|
||||
asset.name: root.communityImage
|
||||
asset.color: root.communityColor
|
||||
asset.isImage: true
|
||||
asset.width: 32
|
||||
asset.height: 32
|
||||
asset.isLetterIdenticon: !asset.name
|
||||
asset.charactersLen: 2
|
||||
asset.letterSize: 15
|
||||
|
||||
leftPadding: 8
|
||||
rightPadding: 6
|
||||
|
||||
statusListItemTitleArea.anchors.leftMargin: 8
|
||||
statusListItemTitle.font.pixelSize: 13
|
||||
statusListItemTitle.font.weight: Font.Medium
|
||||
|
||||
statusListItemSubTitle.font.pixelSize: 12
|
||||
|
||||
components: [
|
||||
StatusRadioButton {
|
||||
id: radioButton
|
||||
|
||||
size: StatusRadioButton.Size.Small
|
||||
rightPadding: 0
|
||||
}
|
||||
]
|
||||
|
||||
// using MouseArea instead of build-in 'clicked' signal to avoid
|
||||
// intercepting event by the StatusRadioButton
|
||||
MouseArea {
|
||||
anchors.fill: parent
|
||||
onClicked: {
|
||||
radioButton.toggle()
|
||||
radioButton.toggled()
|
||||
}
|
||||
cursorShape: Qt.PointingHandCursor
|
||||
}
|
||||
}
|
||||
|
||||
StatusMenuSeparator {
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: 4 - implicitHeight / 2
|
||||
Layout.bottomMargin: 4 - implicitHeight / 2
|
||||
}
|
||||
|
||||
StatusScrollView {
|
||||
id: scrollView
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.bottomMargin: 9
|
||||
|
||||
padding: 0
|
||||
|
||||
ColumnLayout {
|
||||
id: scollableColumn
|
||||
|
||||
spacing: 0
|
||||
width: scrollView.width
|
||||
|
||||
StatusIconTextButton {
|
||||
Layout.preferredHeight: 36
|
||||
|
||||
leftPadding: 8
|
||||
spacing: 8
|
||||
statusIcon: "add"
|
||||
icon.width: 16
|
||||
icon.height: 16
|
||||
iconRotation: 0
|
||||
text: qsTr("Add channel")
|
||||
onClicked: root.addChannelClicked()
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: topRepeater
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
id: topLevelModel
|
||||
|
||||
sourceModel: root.model
|
||||
|
||||
sorters: [
|
||||
RoleSorter { roleName: "isCategory" },
|
||||
RoleSorter { roleName: "position" }
|
||||
]
|
||||
}
|
||||
|
||||
ColumnLayout {
|
||||
id: column
|
||||
|
||||
Layout.fillWidth: true
|
||||
spacing: 0
|
||||
|
||||
readonly property var topModel: model
|
||||
readonly property alias checkBox: loader.item
|
||||
property int checkedCount: 0
|
||||
|
||||
visible: {
|
||||
if (!model.isCategory)
|
||||
return d.search(model.name, searcher.text)
|
||||
|| checkBox.checked
|
||||
|
||||
if (checkedCount > 0)
|
||||
return true
|
||||
|
||||
const subItemsCount = subItemsRepeater.count
|
||||
|
||||
for (let i = 0; i < subItemsCount; i++)
|
||||
if (subItemsRepeater.itemAt(i).show)
|
||||
return true
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Loader {
|
||||
id: loader
|
||||
|
||||
Layout.fillWidth: true
|
||||
Layout.topMargin: model.isCategory ? 9 : 0
|
||||
|
||||
sourceComponent: model.isCategory
|
||||
? communityCategoryDelegate
|
||||
: communityDelegate
|
||||
|
||||
Connections {
|
||||
target: radioButton
|
||||
|
||||
function onToggled() {
|
||||
const checkBox = loader.item.checkBox
|
||||
checkBox.checked = false
|
||||
checkBox.onToggled()
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityDelegate
|
||||
|
||||
CommunityListItem {
|
||||
id: communityItem
|
||||
|
||||
title: "#" + model.name
|
||||
|
||||
asset.name: model.icon
|
||||
asset.emoji: d.resolveEmoji(model.emoji)
|
||||
asset.color: d.resolveColor(model.color,
|
||||
model.colorId)
|
||||
|
||||
checkBox.onToggled: {
|
||||
if (checked)
|
||||
radioButton.checked = false
|
||||
}
|
||||
|
||||
checkBox.onCheckedChanged: {
|
||||
if (checkBox.checked)
|
||||
d.addToSelectedChannels(model)
|
||||
else
|
||||
d.removeFromSelectedChannels(model)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: d
|
||||
|
||||
function onSetSelectedChannels(channels) {
|
||||
communityItem.checked = channels.includes(
|
||||
model.itemId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Component {
|
||||
id: communityCategoryDelegate
|
||||
|
||||
CommunityCategoryListItem {
|
||||
title: model.name
|
||||
|
||||
checkState: {
|
||||
if (checkedCount === model.subItems.count)
|
||||
return Qt.Checked
|
||||
else if (checkedCount === 0)
|
||||
return Qt.Unchecked
|
||||
|
||||
return Qt.PartiallyChecked
|
||||
}
|
||||
|
||||
checkBox.onToggled: {
|
||||
if (checked)
|
||||
radioButton.checked = false
|
||||
|
||||
subItemsRepeater.setAll(checkState)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Repeater {
|
||||
id: subItemsRepeater
|
||||
|
||||
model: SortFilterProxyModel {
|
||||
sourceModel: topModel.isCategory ? topModel.subItems : null
|
||||
sorters: RoleSorter { roleName: "position" }
|
||||
}
|
||||
|
||||
function setAll(checkState) {
|
||||
const subItemsCount = count
|
||||
|
||||
for (let i = 0; i < subItemsCount; i++) {
|
||||
itemAt(i).checkState = checkState
|
||||
}
|
||||
}
|
||||
|
||||
CommunityListItem {
|
||||
id: communitySubItem
|
||||
|
||||
Layout.fillWidth: true
|
||||
|
||||
readonly property bool show: d.search(model.name, searcher.text)
|
||||
|| checked
|
||||
|
||||
visible: show
|
||||
|
||||
title: "#" + model.name
|
||||
|
||||
asset.name: model.icon
|
||||
asset.emoji: d.resolveEmoji(model.emoji)
|
||||
asset.color: d.resolveColor(model.color,
|
||||
model.colorId)
|
||||
|
||||
onCheckedChanged: {
|
||||
if (checked) {
|
||||
radioButton.checked = false
|
||||
d.addToSelectedChannels(model)
|
||||
} else {
|
||||
d.removeFromSelectedChannels(model)
|
||||
}
|
||||
|
||||
Qt.callLater(() => checkedCount += checked ? 1 : -1)
|
||||
}
|
||||
|
||||
Connections {
|
||||
target: d
|
||||
|
||||
function onSetSelectedChannels(channels) {
|
||||
communitySubItem.checked = channels.includes(
|
||||
model.itemId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StatusButton {
|
||||
Layout.fillWidth: true
|
||||
text: root.acceptMode === InDropdown.AcceptMode.Add
|
||||
? qsTr("Add") : qsTr("Update")
|
||||
|
||||
onClicked: {
|
||||
if (radioButton.checked) {
|
||||
root.communitySelected()
|
||||
return
|
||||
}
|
||||
|
||||
root.channelsSelected(Array.from(d.selectedChannels.values()))
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,3 +1,6 @@
|
|||
HoldingsDropdown 1.0 HoldingsDropdown.qml
|
||||
CommunityCategoryListItem 1.0 CommunityCategoryListItem.qml
|
||||
CommunityListItem 1.0 CommunityListItem.qml
|
||||
HoldingTypes 1.0 HoldingTypes.qml
|
||||
HoldingsDropdown 1.0 HoldingsDropdown.qml
|
||||
InDropdown 1.0 InDropdown.qml
|
||||
PermissionItem 1.0 PermissionItem.qml
|
||||
|
|
Loading…
Reference in New Issue