parent
10684c22a0
commit
8e39d761dc
|
@ -28,21 +28,34 @@ add_executable(
|
||||||
main.cpp
|
main.cpp
|
||||||
cachecleaner.cpp cachecleaner.h
|
cachecleaner.cpp cachecleaner.h
|
||||||
directorieswatcher.cpp directorieswatcher.h
|
directorieswatcher.cpp directorieswatcher.h
|
||||||
|
figmadecoratormodel.cpp figmadecoratormodel.h
|
||||||
|
figmaio.cpp figmaio.h
|
||||||
|
figmalinks.cpp figmalinks.h
|
||||||
|
figmalinksmodel.cpp figmalinksmodel.h
|
||||||
|
figmalinkssource.cpp figmalinkssource.h
|
||||||
|
modelutils.cpp modelutils.h
|
||||||
sectionsdecoratormodel.cpp sectionsdecoratormodel.h
|
sectionsdecoratormodel.cpp sectionsdecoratormodel.h
|
||||||
${QML_FILES} main.qml PagesModel.qml
|
${QML_FILES} main.qml PagesModel.qml
|
||||||
${JS_FILES}
|
${JS_FILES}
|
||||||
|
figma.json
|
||||||
)
|
)
|
||||||
|
|
||||||
target_compile_definitions(${PROJECT_NAME}
|
target_compile_definitions(${PROJECT_NAME}
|
||||||
PRIVATE QML_IMPORT_ROOT="${CMAKE_CURRENT_LIST_DIR}")
|
PRIVATE QML_IMPORT_ROOT="${CMAKE_CURRENT_LIST_DIR}")
|
||||||
|
|
||||||
target_link_libraries(
|
target_link_libraries(
|
||||||
${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 SortFilterProxyModel)
|
${PROJECT_NAME} PRIVATE Qt5::Core Qt5::Quick Qt5::QuickControls2 SortFilterProxyModel)
|
||||||
|
|
||||||
enable_testing()
|
enable_testing()
|
||||||
add_executable(SectionsDecoratorModelTest tests/tst_SectionsDecoratorModel.cpp sectionsdecoratormodel.cpp)
|
add_executable(SectionsDecoratorModelTest tests/tst_SectionsDecoratorModel.cpp sectionsdecoratormodel.cpp modelutils.cpp)
|
||||||
add_test(NAME SectionsDecoratorModelTest COMMAND SectionsDecoratorModelTest)
|
add_test(NAME SectionsDecoratorModelTest COMMAND SectionsDecoratorModelTest)
|
||||||
target_link_libraries(SectionsDecoratorModelTest PRIVATE Qt5::Test)
|
target_link_libraries(SectionsDecoratorModelTest PRIVATE Qt5::Test)
|
||||||
|
|
||||||
|
add_executable(FigmaDecoratorModelTest tests/tst_FigmaDecoratorModel.cpp figmadecoratormodel.cpp figmalinkssource.cpp
|
||||||
|
figmalinks.cpp figmaio.cpp modelutils.cpp figmalinksmodel.cpp)
|
||||||
|
add_test(NAME FigmaModelTest COMMAND FigmaModelTest)
|
||||||
|
target_link_libraries(FigmaDecoratorModelTest PRIVATE Qt5::Test Qt5::Qml)
|
||||||
|
|
||||||
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/StatusQ/src")
|
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/StatusQ/src")
|
||||||
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/app")
|
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/app")
|
||||||
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/imports")
|
list(APPEND QML_DIRS "${CMAKE_SOURCE_DIR}/../ui/imports")
|
||||||
|
|
|
@ -3,39 +3,10 @@ import QtQuick 2.14
|
||||||
ListModel {
|
ListModel {
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "ProfileDialogView"
|
title: "ProfileDialogView"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=733%3A12552"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A15078"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17655"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17087"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23525"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23932"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Views"
|
section: "Views"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "CommunitiesPortalLayout"
|
title: "CommunitiesPortalLayout"
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415655"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415935"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Views"
|
section: "Views"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
|
@ -44,67 +15,22 @@ ListModel {
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "LoginView"
|
title: "LoginView"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=1080%3A313192"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Views"
|
section: "Views"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "AboutView"
|
title: "AboutView"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1159%3A114479"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1684%3A127762"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Views"
|
section: "Views"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "StatusCommunityCard"
|
title: "StatusCommunityCard"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416159"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416160"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Panels"
|
section: "Panels"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "CommunityProfilePopupInviteFriendsPanel"
|
title: "CommunityProfilePopupInviteFriendsPanel"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A343592"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2990%3A353179"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A344073"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Panels"
|
section: "Panels"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "CommunityProfilePopupInviteMessagePanel"
|
title: "CommunityProfilePopupInviteMessagePanel"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4291%3A385536"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4295%3A385958"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Panels"
|
section: "Panels"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
|
@ -113,86 +39,22 @@ ListModel {
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "InviteFriendsToCommunityPopup"
|
title: "InviteFriendsToCommunityPopup"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A343592"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2990%3A353179"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A344073"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4291%3A385536"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4295%3A385958"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Popups"
|
section: "Popups"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "CreateChannelPopup"
|
title: "CreateChannelPopup"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488608"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488256"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2903%3A348301"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488848"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A489237"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A489607"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A492910"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Popups"
|
section: "Popups"
|
||||||
}
|
}
|
||||||
|
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "MembersSelector"
|
title: "MembersSelector"
|
||||||
section: "Components"
|
section: "Components"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "BrowserSettings"
|
title: "BrowserSettings"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=448%3A36296"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1573%3A296338"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Settings"
|
section: "Settings"
|
||||||
}
|
}
|
||||||
ListElement {
|
ListElement {
|
||||||
title: "LanguageCurrencySettings"
|
title: "LanguageCurrencySettings"
|
||||||
|
|
||||||
figma: [
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=701%3A74776"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1592%3A112840"
|
|
||||||
},
|
|
||||||
ListElement {
|
|
||||||
link: "https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=701%3A75345"
|
|
||||||
}
|
|
||||||
]
|
|
||||||
section: "Settings"
|
section: "Settings"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
{
|
||||||
|
"ProfileDialogView": [
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=733%3A12552",
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A15078",
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17655",
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=682%3A17087",
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23525",
|
||||||
|
"https://www.figma.com/file/ibJOTPlNtIxESwS96vJb06/%F0%9F%91%A4-Profile-%7C-Desktop?node-id=4%3A23932"
|
||||||
|
],
|
||||||
|
"CommunitiesPortalLayout": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415655",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A415935"
|
||||||
|
],
|
||||||
|
"LoginView": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=1080%3A313192"
|
||||||
|
],
|
||||||
|
"AboutView": [
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1159%3A114479",
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1684%3A127762"
|
||||||
|
],
|
||||||
|
"StatusCommunityCard": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416159",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=8159%3A416160"
|
||||||
|
],
|
||||||
|
"CommunityProfilePopupInviteFriendsPanel": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A343592",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2990%3A353179",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A344073"
|
||||||
|
],
|
||||||
|
"CommunityProfilePopupInviteMessagePanel": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4291%3A385536",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4295%3A385958"
|
||||||
|
],
|
||||||
|
"InviteFriendsToCommunityPopup": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A343592",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2990%3A353179",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2927%3A344073",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4291%3A385536",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=4295%3A385958"
|
||||||
|
],
|
||||||
|
"CreateChannelPopup": [
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488608",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488256",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2903%3A348301",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A488848",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A489237",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A489607",
|
||||||
|
"https://www.figma.com/file/17fc13UBFvInrLgNUKJJg5/Kuba%E2%8E%9CDesktop?node-id=2975%3A492910"
|
||||||
|
],
|
||||||
|
"BrowserSettings": [
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=448%3A36296",
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1573%3A296338"
|
||||||
|
],
|
||||||
|
"LanguageCurrencySettings": [
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=701%3A74776",
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=1592%3A112840",
|
||||||
|
"https://www.figma.com/file/idUoxN7OIW2Jpp3PMJ1Rl8/%E2%9A%99%EF%B8%8F-Settings-%7C-Desktop?node-id=701%3A75345"
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,94 @@
|
||||||
|
#include "figmadecoratormodel.h"
|
||||||
|
|
||||||
|
#include "figmalinks.h"
|
||||||
|
#include "figmalinksmodel.h"
|
||||||
|
#include "modelutils.h"
|
||||||
|
|
||||||
|
FigmaDecoratorModel::FigmaDecoratorModel(QObject *parent)
|
||||||
|
: QIdentityProxyModel{parent}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> FigmaDecoratorModel::roleNames() const
|
||||||
|
{
|
||||||
|
auto roles = QIdentityProxyModel::roleNames();
|
||||||
|
roles.insert(FigmaRole, QByteArrayLiteral("figma"));
|
||||||
|
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant FigmaDecoratorModel::data(const QModelIndex &proxyIndex, int role) const
|
||||||
|
{
|
||||||
|
if (!checkIndex(proxyIndex, CheckIndexOption::IndexIsValid))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
if (role == FigmaRole) {
|
||||||
|
static FigmaLinksModel empty({});
|
||||||
|
|
||||||
|
if (!m_titleRole)
|
||||||
|
return QVariant::fromValue(&empty);
|
||||||
|
|
||||||
|
const auto title = data(proxyIndex, m_titleRole.value()).toString();
|
||||||
|
auto it = m_submodels.find(title);
|
||||||
|
|
||||||
|
if (it == m_submodels.end()) {
|
||||||
|
QStringList links;
|
||||||
|
|
||||||
|
if (m_figmaLinks)
|
||||||
|
links = m_figmaLinks->getLinksMap().value(title, {});
|
||||||
|
|
||||||
|
auto linksModel = new FigmaLinksModel(
|
||||||
|
links, const_cast<FigmaDecoratorModel*>(this));
|
||||||
|
it = m_submodels.insert(title, linksModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return QVariant::fromValue(it.value());
|
||||||
|
}
|
||||||
|
|
||||||
|
return QIdentityProxyModel::data(proxyIndex, role);
|
||||||
|
}
|
||||||
|
|
||||||
|
FigmaLinks* FigmaDecoratorModel::getFigmaLinks() const
|
||||||
|
{
|
||||||
|
return m_figmaLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaDecoratorModel::setFigmaLinks(FigmaLinks *figmaLinks)
|
||||||
|
{
|
||||||
|
if (figmaLinks == m_figmaLinks)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_figmaLinks = figmaLinks;
|
||||||
|
const auto& linksMap = m_figmaLinks
|
||||||
|
? m_figmaLinks->getLinksMap()
|
||||||
|
: QMap<QString, QStringList>{};
|
||||||
|
|
||||||
|
auto linksIt = linksMap.constBegin();
|
||||||
|
while (linksIt != linksMap.constEnd()) {
|
||||||
|
if (m_submodels.contains(linksIt.key()))
|
||||||
|
m_submodels.value(linksIt.key())->setContent(linksIt.value());
|
||||||
|
++linksIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto submodelsIt = m_submodels.constBegin();
|
||||||
|
while (submodelsIt != m_submodels.constEnd()) {
|
||||||
|
if (!linksMap.contains(submodelsIt.key()))
|
||||||
|
submodelsIt.value()->setContent({});
|
||||||
|
++submodelsIt;
|
||||||
|
}
|
||||||
|
|
||||||
|
emit figmaLinksChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaDecoratorModel::setSourceModel(QAbstractItemModel *sourceModel)
|
||||||
|
{
|
||||||
|
qDeleteAll(m_submodels);
|
||||||
|
m_submodels.clear();
|
||||||
|
|
||||||
|
m_titleRole = ModelUtils::findRole(QByteArrayLiteral("title"), sourceModel);
|
||||||
|
|
||||||
|
if(!m_titleRole)
|
||||||
|
qWarning("The source model is missing title role!");
|
||||||
|
|
||||||
|
QIdentityProxyModel::setSourceModel(sourceModel);
|
||||||
|
}
|
|
@ -0,0 +1,33 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QIdentityProxyModel>
|
||||||
|
|
||||||
|
class FigmaLinks;
|
||||||
|
class FigmaLinksModel;
|
||||||
|
|
||||||
|
class FigmaDecoratorModel : public QIdentityProxyModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(FigmaLinks* figmaLinks READ getFigmaLinks
|
||||||
|
WRITE setFigmaLinks NOTIFY figmaLinksChanged)
|
||||||
|
public:
|
||||||
|
static constexpr auto FigmaRole = Qt::UserRole + 100;
|
||||||
|
|
||||||
|
explicit FigmaDecoratorModel(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
QVariant data(const QModelIndex &proxyIndex, int role) const override;
|
||||||
|
|
||||||
|
FigmaLinks* getFigmaLinks() const;
|
||||||
|
void setFigmaLinks(FigmaLinks *figmaLinks);
|
||||||
|
|
||||||
|
void setSourceModel(QAbstractItemModel *sourceModel) override;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void figmaLinksChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::optional<int> m_titleRole;
|
||||||
|
FigmaLinks* m_figmaLinks = nullptr;
|
||||||
|
mutable QMap<QString, FigmaLinksModel*> m_submodels;
|
||||||
|
};
|
|
@ -0,0 +1,49 @@
|
||||||
|
#include "figmaio.h"
|
||||||
|
|
||||||
|
#include <QDebug>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QJsonArray>
|
||||||
|
#include <QJsonDocument>
|
||||||
|
#include <QJsonObject>
|
||||||
|
|
||||||
|
QMap<QString, QStringList> FigmaIO::read(const QString &file)
|
||||||
|
{
|
||||||
|
QFile f(file);
|
||||||
|
if (!f.open(QIODevice::ReadOnly | QIODevice::Text)) {
|
||||||
|
qWarning() << "FigmaIO::read - failed to open file:" << file;
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QJsonParseError error;
|
||||||
|
auto jsonDoc = QJsonDocument::fromJson(f.readAll(), &error);
|
||||||
|
|
||||||
|
if (error.error != QJsonParseError::NoError) {
|
||||||
|
qWarning() << "FigmaIO::read - error parsing json file:" << file
|
||||||
|
<< "->" << error.errorString();
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
QMap<QString, QStringList> mapping;
|
||||||
|
|
||||||
|
if (jsonDoc.isObject()) {
|
||||||
|
auto rootObject = jsonDoc.object();
|
||||||
|
|
||||||
|
auto i = rootObject.constBegin();
|
||||||
|
while (i != rootObject.constEnd()) {
|
||||||
|
QJsonValue val = i.value();
|
||||||
|
QJsonArray links = val.toArray();
|
||||||
|
|
||||||
|
QStringList linksList;
|
||||||
|
linksList.reserve(links.size());
|
||||||
|
|
||||||
|
for (const QJsonValue &link : qAsConst(links))
|
||||||
|
if (link.isString())
|
||||||
|
linksList << link.toString();
|
||||||
|
|
||||||
|
mapping.insert(i.key(), linksList);
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return mapping;
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class FigmaIO
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static QMap<QString, QStringList> read(const QString &file);
|
||||||
|
};
|
|
@ -0,0 +1,11 @@
|
||||||
|
#include "figmalinks.h"
|
||||||
|
|
||||||
|
FigmaLinks::FigmaLinks(const QMap<QString, QStringList>& linksMap, QObject *parent)
|
||||||
|
: m_linksMap{linksMap}, QObject{parent}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
const QMap<QString, QStringList>& FigmaLinks::getLinksMap() const
|
||||||
|
{
|
||||||
|
return m_linksMap;
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QMap>
|
||||||
|
|
||||||
|
class FigmaLinks : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
explicit FigmaLinks(const QMap<QString, QStringList>& mapping,
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
const QMap<QString, QStringList>& getLinksMap() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QMap<QString, QStringList> m_linksMap;
|
||||||
|
};
|
|
@ -0,0 +1,42 @@
|
||||||
|
#include "figmalinksmodel.h"
|
||||||
|
|
||||||
|
FigmaLinksModel::FigmaLinksModel(const QStringList &links, QObject *parent)
|
||||||
|
: QAbstractListModel{parent}, m_links{links}
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int FigmaLinksModel::rowCount(const QModelIndex &parent) const
|
||||||
|
{
|
||||||
|
return m_links.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant FigmaLinksModel::data(const QModelIndex &index, int role) const
|
||||||
|
{
|
||||||
|
if (!checkIndex(index, CheckIndexOption::IndexIsValid))
|
||||||
|
return {};
|
||||||
|
|
||||||
|
const int row = index.row();
|
||||||
|
return m_links.at(row);
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> FigmaLinksModel::roleNames() const
|
||||||
|
{
|
||||||
|
static QHash<int, QByteArray> roles(
|
||||||
|
{{LinkRole, QByteArrayLiteral("link")}});
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaLinksModel::setContent(const QStringList &links)
|
||||||
|
{
|
||||||
|
if (m_links == links)
|
||||||
|
return;
|
||||||
|
|
||||||
|
const auto oldCount = m_links.size();
|
||||||
|
|
||||||
|
beginResetModel();
|
||||||
|
m_links = links;
|
||||||
|
endResetModel();
|
||||||
|
|
||||||
|
if (m_links.size() != oldCount)
|
||||||
|
emit countChanged();
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QAbstractListModel>
|
||||||
|
|
||||||
|
class FigmaLinksModel : public QAbstractListModel
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(int count READ rowCount NOTIFY countChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto LinkRole = 0;
|
||||||
|
|
||||||
|
explicit FigmaLinksModel(const QStringList &links,
|
||||||
|
QObject *parent = nullptr);
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override;
|
||||||
|
QHash<int, QByteArray> roleNames() const override;
|
||||||
|
|
||||||
|
void setContent(const QStringList &links);
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void countChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
QStringList m_links;
|
||||||
|
};
|
|
@ -0,0 +1,71 @@
|
||||||
|
#include "figmalinkssource.h"
|
||||||
|
|
||||||
|
#include <QQmlEngine>
|
||||||
|
|
||||||
|
#include "figmaio.h"
|
||||||
|
#include "figmalinks.h"
|
||||||
|
|
||||||
|
FigmaLinksSource::FigmaLinksSource(QObject *parent)
|
||||||
|
: QObject{parent}
|
||||||
|
{
|
||||||
|
connect(&m_watcher, &QFileSystemWatcher::fileChanged,
|
||||||
|
this, [this](const QString &path) {
|
||||||
|
this->readFile();
|
||||||
|
|
||||||
|
if (!this->m_watcher.files().contains(path))
|
||||||
|
this->m_watcher.addPath(path);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
const QUrl& FigmaLinksSource::getFilePath() const
|
||||||
|
{
|
||||||
|
return m_filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaLinksSource::setFilePath(const QUrl& path)
|
||||||
|
{
|
||||||
|
if (path == m_filePath)
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_filePath = path;
|
||||||
|
readFile();
|
||||||
|
setupWatcher();
|
||||||
|
emit filePathChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
FigmaLinks* FigmaLinksSource::getFigmaLinks() const
|
||||||
|
{
|
||||||
|
return m_figmaLinks;
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaLinksSource::updateFigmaLinks(const QMap<QString, QStringList>& map)
|
||||||
|
{
|
||||||
|
FigmaLinks *mapping = new FigmaLinks(map, this);
|
||||||
|
|
||||||
|
if (m_figmaLinks && qjsEngine(m_figmaLinks)) {
|
||||||
|
m_figmaLinks->setParent(nullptr);
|
||||||
|
QQmlEngine::setObjectOwnership(m_figmaLinks, QQmlEngine::JavaScriptOwnership);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_figmaLinks = mapping;
|
||||||
|
emit figmaLinksChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaLinksSource::readFile()
|
||||||
|
{
|
||||||
|
QMap<QString, QStringList> figmaLinks = FigmaIO::read(m_filePath.path());
|
||||||
|
updateFigmaLinks(figmaLinks);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FigmaLinksSource::setupWatcher()
|
||||||
|
{
|
||||||
|
auto currentlyWatched = m_watcher.files();
|
||||||
|
|
||||||
|
if (!currentlyWatched.isEmpty())
|
||||||
|
m_watcher.removePaths(currentlyWatched);
|
||||||
|
|
||||||
|
if (m_filePath.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_watcher.addPath(m_filePath.path());
|
||||||
|
}
|
|
@ -0,0 +1,34 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <QObject>
|
||||||
|
#include <QFileSystemWatcher>
|
||||||
|
#include <QUrl>
|
||||||
|
|
||||||
|
class FigmaLinks;
|
||||||
|
|
||||||
|
class FigmaLinksSource : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
Q_PROPERTY(QUrl filePath READ getFilePath WRITE setFilePath NOTIFY filePathChanged)
|
||||||
|
Q_PROPERTY(FigmaLinks* figmaLinks READ getFigmaLinks NOTIFY figmaLinksChanged)
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit FigmaLinksSource(QObject *parent = nullptr);
|
||||||
|
|
||||||
|
const QUrl& getFilePath() const;
|
||||||
|
void setFilePath(const QUrl& path);
|
||||||
|
FigmaLinks* getFigmaLinks() const;
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void filePathChanged();
|
||||||
|
void figmaLinksChanged();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void updateFigmaLinks(const QMap<QString, QStringList>& map);
|
||||||
|
void readFile();
|
||||||
|
void setupWatcher();
|
||||||
|
|
||||||
|
FigmaLinks *m_figmaLinks = nullptr;
|
||||||
|
QUrl m_filePath;
|
||||||
|
QFileSystemWatcher m_watcher;
|
||||||
|
};
|
|
@ -3,6 +3,9 @@
|
||||||
|
|
||||||
#include "cachecleaner.h"
|
#include "cachecleaner.h"
|
||||||
#include "directorieswatcher.h"
|
#include "directorieswatcher.h"
|
||||||
|
#include "figmadecoratormodel.h"
|
||||||
|
#include "figmalinks.h"
|
||||||
|
#include "figmalinkssource.h"
|
||||||
#include "sectionsdecoratormodel.h"
|
#include "sectionsdecoratormodel.h"
|
||||||
|
|
||||||
int main(int argc, char *argv[])
|
int main(int argc, char *argv[])
|
||||||
|
@ -35,6 +38,9 @@ int main(int argc, char *argv[])
|
||||||
engine.addImportPath(path);
|
engine.addImportPath(path);
|
||||||
|
|
||||||
qmlRegisterType<SectionsDecoratorModel>("Storybook", 1, 0, "SectionsDecoratorModel");
|
qmlRegisterType<SectionsDecoratorModel>("Storybook", 1, 0, "SectionsDecoratorModel");
|
||||||
|
qmlRegisterType<FigmaDecoratorModel>("Storybook", 1, 0, "FigmaDecoratorModel");
|
||||||
|
qmlRegisterType<FigmaLinksSource>("Storybook", 1, 0, "FigmaLinksSource");
|
||||||
|
qmlRegisterUncreatableType<FigmaLinks>("Storybook", 1, 0, "FigmaLinks", "");
|
||||||
|
|
||||||
auto watcherFactory = [additionalImportPaths](QQmlEngine*, QJSEngine*) {
|
auto watcherFactory = [additionalImportPaths](QQmlEngine*, QJSEngine*) {
|
||||||
auto watcher = new DirectoriesWatcher();
|
auto watcher = new DirectoriesWatcher();
|
||||||
|
|
|
@ -18,6 +18,23 @@ ApplicationWindow {
|
||||||
|
|
||||||
font.pixelSize: 13
|
font.pixelSize: 13
|
||||||
|
|
||||||
|
PagesModel {
|
||||||
|
id: pagesModel
|
||||||
|
}
|
||||||
|
|
||||||
|
FigmaLinksSource {
|
||||||
|
id: figmaLinksSource
|
||||||
|
|
||||||
|
filePath: "figma.json"
|
||||||
|
}
|
||||||
|
|
||||||
|
FigmaDecoratorModel {
|
||||||
|
id: figmaModel
|
||||||
|
|
||||||
|
sourceModel: pagesModel
|
||||||
|
figmaLinks: figmaLinksSource.figmaLinks
|
||||||
|
}
|
||||||
|
|
||||||
HotReloader {
|
HotReloader {
|
||||||
id: reloader
|
id: reloader
|
||||||
|
|
||||||
|
@ -26,10 +43,6 @@ ApplicationWindow {
|
||||||
onReloaded: hotReloaderControls.notifyReload()
|
onReloaded: hotReloaderControls.notifyReload()
|
||||||
}
|
}
|
||||||
|
|
||||||
PagesModel {
|
|
||||||
id: pagesModel
|
|
||||||
}
|
|
||||||
|
|
||||||
SplitView {
|
SplitView {
|
||||||
anchors.fill: parent
|
anchors.fill: parent
|
||||||
|
|
||||||
|
@ -125,13 +138,13 @@ ApplicationWindow {
|
||||||
|
|
||||||
title: `pages/${root.currentPage}Page.qml`
|
title: `pages/${root.currentPage}Page.qml`
|
||||||
figmaPagesCount: currentPageModelItem.object
|
figmaPagesCount: currentPageModelItem.object
|
||||||
? currentPageModelItem.object.figmaCount : 0
|
? currentPageModelItem.object.figma.count : 0
|
||||||
|
|
||||||
Instantiator {
|
Instantiator {
|
||||||
id: currentPageModelItem
|
id: currentPageModelItem
|
||||||
|
|
||||||
model: SingleItemProxyModel {
|
model: SingleItemProxyModel {
|
||||||
sourceModel: pagesModel
|
sourceModel: figmaModel
|
||||||
roleName: "title"
|
roleName: "title"
|
||||||
value: root.currentPage
|
value: root.currentPage
|
||||||
}
|
}
|
||||||
|
@ -139,7 +152,6 @@ ApplicationWindow {
|
||||||
delegate: QtObject {
|
delegate: QtObject {
|
||||||
readonly property string title: model.title
|
readonly property string title: model.title
|
||||||
readonly property var figma: model.figma
|
readonly property var figma: model.figma
|
||||||
readonly property int figmaCount: figma ? figma.count : 0
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
#include "modelutils.h"
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
std::optional<int> ModelUtils::findRole(const QByteArray &role,
|
||||||
|
const QAbstractItemModel *model)
|
||||||
|
{
|
||||||
|
if (model == nullptr)
|
||||||
|
return std::nullopt;
|
||||||
|
|
||||||
|
const auto roleNames = model->roleNames();
|
||||||
|
|
||||||
|
auto it = std::find_if(roleNames.constKeyValueBegin(),
|
||||||
|
roleNames.constKeyValueEnd(), [&role](auto entry) {
|
||||||
|
return entry.second == role;
|
||||||
|
});
|
||||||
|
|
||||||
|
return it == roleNames.constKeyValueEnd()
|
||||||
|
? std::nullopt : std::make_optional((*it).first);
|
||||||
|
}
|
|
@ -0,0 +1,13 @@
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
class QAbstractItemModel;
|
||||||
|
|
||||||
|
struct ModelUtils
|
||||||
|
{
|
||||||
|
static std::optional<int> findRole(const QByteArray &role,
|
||||||
|
const QAbstractItemModel *model);
|
||||||
|
};
|
|
@ -1,5 +1,7 @@
|
||||||
#include "sectionsdecoratormodel.h"
|
#include "sectionsdecoratormodel.h"
|
||||||
|
|
||||||
|
#include "modelutils.h"
|
||||||
|
|
||||||
#include <QScopeGuard>
|
#include <QScopeGuard>
|
||||||
|
|
||||||
SectionsDecoratorModel::SectionsDecoratorModel(QObject *parent)
|
SectionsDecoratorModel::SectionsDecoratorModel(QObject *parent)
|
||||||
|
@ -121,20 +123,6 @@ void SectionsDecoratorModel::calculateOffsets()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
std::optional<int> SectionsDecoratorModel::findSectionRole() const
|
|
||||||
{
|
|
||||||
const auto roleNames = m_sourceModel->roleNames();
|
|
||||||
auto i = roleNames.constBegin();
|
|
||||||
|
|
||||||
while (i != roleNames.constEnd()) {
|
|
||||||
if (i.value() == QStringLiteral("section"))
|
|
||||||
return i.key();
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
|
|
||||||
return std::nullopt;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SectionsDecoratorModel::initialize()
|
void SectionsDecoratorModel::initialize()
|
||||||
{
|
{
|
||||||
beginResetModel();
|
beginResetModel();
|
||||||
|
@ -142,7 +130,8 @@ void SectionsDecoratorModel::initialize()
|
||||||
|
|
||||||
m_rowsMetadata.clear();
|
m_rowsMetadata.clear();
|
||||||
|
|
||||||
const auto sectionRoleOpt = findSectionRole();
|
const auto sectionRoleOpt = ModelUtils::findRole(
|
||||||
|
QByteArrayLiteral("section"), m_sourceModel);
|
||||||
|
|
||||||
if (!sectionRoleOpt) {
|
if (!sectionRoleOpt) {
|
||||||
qWarning("Section role not found!");
|
qWarning("Section role not found!");
|
||||||
|
|
|
@ -36,7 +36,6 @@ private:
|
||||||
int count = 0;
|
int count = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
std::optional<int> findSectionRole() const;
|
|
||||||
void initialize();
|
void initialize();
|
||||||
void calculateOffsets();
|
void calculateOffsets();
|
||||||
|
|
||||||
|
|
|
@ -1,30 +1,47 @@
|
||||||
import QtQuick 2.14
|
import QtQuick 2.14
|
||||||
|
|
||||||
ListModel {
|
ListModel {
|
||||||
|
id: root
|
||||||
|
|
||||||
/* required */ property FigmaLinksCache figmaLinksCache
|
/* required */ property FigmaLinksCache figmaLinksCache
|
||||||
property alias sourceModel: d.model
|
property alias sourceModel: d.model
|
||||||
|
|
||||||
readonly property Instantiator _d: Instantiator {
|
readonly property Instantiator _d: Instantiator {
|
||||||
id: d
|
id: d
|
||||||
|
|
||||||
|
property int idCounter: 0
|
||||||
|
|
||||||
model: 0
|
model: 0
|
||||||
|
|
||||||
delegate: QtObject {
|
delegate: QtObject {
|
||||||
id: delegate
|
id: delegate
|
||||||
|
|
||||||
|
property int uniqueId
|
||||||
|
|
||||||
Component.onCompleted: {
|
Component.onCompleted: {
|
||||||
append({
|
append({
|
||||||
rawLink: model.link,
|
rawLink: model.link,
|
||||||
imageLink: ""
|
imageLink: "",
|
||||||
|
uniqueId: d.idCounter
|
||||||
})
|
})
|
||||||
|
|
||||||
|
uniqueId = d.idCounter
|
||||||
|
d.idCounter++
|
||||||
|
|
||||||
figmaLinksCache.getImageUrl(model.link, link => {
|
figmaLinksCache.getImageUrl(model.link, link => {
|
||||||
if (delegate)
|
if (delegate)
|
||||||
setProperty(model.index, "imageLink", link)
|
root.setProperty(model.index, "imageLink", link)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
onObjectRemoved: console.warn("FigmaImagesProxyModel: removing items from the source model is not supported!")
|
onObjectRemoved: {
|
||||||
|
for (let i = 0; i < root.count; i++) {
|
||||||
|
if (root.get(i).uniqueId === object.uniqueId) {
|
||||||
|
root.remove(i)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,7 +17,7 @@ ColumnLayout {
|
||||||
|
|
||||||
RoundButton {
|
RoundButton {
|
||||||
text: "⬅"
|
text: "⬅"
|
||||||
enabled: root.currentIndex !== 0
|
enabled: root.currentIndex !== 0 && root.currentIndex !== -1
|
||||||
onClicked: root.left()
|
onClicked: root.left()
|
||||||
}
|
}
|
||||||
RoundButton {
|
RoundButton {
|
||||||
|
|
|
@ -0,0 +1,321 @@
|
||||||
|
#include <QSignalSpy>
|
||||||
|
#include <QTest>
|
||||||
|
#include <QTemporaryFile>
|
||||||
|
#include <QStringListModel>
|
||||||
|
|
||||||
|
#include "figmadecoratormodel.h"
|
||||||
|
#include "figmalinks.h"
|
||||||
|
#include "figmalinksmodel.h"
|
||||||
|
#include "figmalinkssource.h"
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
auto constexpr sampleJson1 = R"(
|
||||||
|
{
|
||||||
|
"Component_1": [
|
||||||
|
"link_1", "link_2"
|
||||||
|
],
|
||||||
|
"Component_2": [
|
||||||
|
"link_3", "link_4"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
auto constexpr sampleJson2 = R"(
|
||||||
|
{
|
||||||
|
"Component_1": [
|
||||||
|
"link_1"
|
||||||
|
],
|
||||||
|
"Component_2": [
|
||||||
|
"link_3", "link_5"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
)";
|
||||||
|
|
||||||
|
class TestSourceModel : public QAbstractListModel {
|
||||||
|
|
||||||
|
public:
|
||||||
|
static constexpr auto TitleRole = 0;
|
||||||
|
|
||||||
|
TestSourceModel(int count = 1) : m_count(count) {}
|
||||||
|
|
||||||
|
int rowCount(const QModelIndex &parent = QModelIndex()) const override {
|
||||||
|
return m_count;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant data(const QModelIndex &index, int role) const override {
|
||||||
|
if (!index.isValid())
|
||||||
|
return {};
|
||||||
|
|
||||||
|
return QString("title_%1").arg(index.row());
|
||||||
|
}
|
||||||
|
|
||||||
|
QHash<int, QByteArray> roleNames() const override {
|
||||||
|
QHash<int, QByteArray> roles;
|
||||||
|
roles.insert(TitleRole, QByteArrayLiteral("title"));
|
||||||
|
return roles;
|
||||||
|
}
|
||||||
|
|
||||||
|
int m_count;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // unnamed namespace
|
||||||
|
|
||||||
|
class FigmaDecoratorModelTest: public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
private slots:
|
||||||
|
void readingFigmaFileTest() {
|
||||||
|
FigmaLinksSource figmaLinksSource;
|
||||||
|
|
||||||
|
QSignalSpy spy(&figmaLinksSource, &FigmaLinksSource::figmaLinksChanged);
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksSource.getFigmaLinks(), nullptr);
|
||||||
|
|
||||||
|
QTemporaryFile file;
|
||||||
|
if (file.open()) {
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream << sampleJson1;
|
||||||
|
}
|
||||||
|
|
||||||
|
figmaLinksSource.setFilePath(file.fileName());
|
||||||
|
|
||||||
|
QVERIFY(figmaLinksSource.getFigmaLinks() != nullptr);
|
||||||
|
|
||||||
|
const FigmaLinks *links = figmaLinksSource.getFigmaLinks();
|
||||||
|
|
||||||
|
QCOMPARE(links->getLinksMap(), (QMap<QString, QStringList> {
|
||||||
|
{{"Component_1"}, {"link_1", "link_2"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_4"}}}));
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
|
||||||
|
QTemporaryFile file2;
|
||||||
|
if (file2.open()) {
|
||||||
|
QTextStream stream(&file2);
|
||||||
|
stream << sampleJson2;
|
||||||
|
}
|
||||||
|
|
||||||
|
figmaLinksSource.setFilePath(file2.fileName());
|
||||||
|
|
||||||
|
QVERIFY(figmaLinksSource.getFigmaLinks() != nullptr);
|
||||||
|
|
||||||
|
const FigmaLinks *links2 = figmaLinksSource.getFigmaLinks();
|
||||||
|
|
||||||
|
QCOMPARE(links2->getLinksMap(), (QMap<QString, QStringList> {
|
||||||
|
{{"Component_1"}, {"link_1"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_5"}}}));
|
||||||
|
QCOMPARE(spy.count(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
void readingAfterFigmaFileChangedTest() {
|
||||||
|
|
||||||
|
FigmaLinksSource figmaLinksSource;
|
||||||
|
|
||||||
|
QSignalSpy spy(&figmaLinksSource, &FigmaLinksSource::figmaLinksChanged);
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksSource.getFigmaLinks(), nullptr);
|
||||||
|
|
||||||
|
QTemporaryFile file;
|
||||||
|
if (file.open()) {
|
||||||
|
QTextStream stream(&file);
|
||||||
|
stream << sampleJson1;
|
||||||
|
}
|
||||||
|
|
||||||
|
figmaLinksSource.setFilePath(file.fileName());
|
||||||
|
|
||||||
|
QVERIFY(figmaLinksSource.getFigmaLinks() != nullptr);
|
||||||
|
|
||||||
|
const FigmaLinks *links = figmaLinksSource.getFigmaLinks();
|
||||||
|
|
||||||
|
QCOMPARE(links->getLinksMap(), (QMap<QString, QStringList> {
|
||||||
|
{{"Component_1"}, {"link_1", "link_2"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_4"}}}));
|
||||||
|
|
||||||
|
QCOMPARE(spy.count(), 1);
|
||||||
|
|
||||||
|
if (QFile f(file.fileName());
|
||||||
|
f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
QTextStream stream(&f);
|
||||||
|
stream << sampleJson2;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(spy.wait());
|
||||||
|
QCOMPARE(spy.count(), 2);
|
||||||
|
|
||||||
|
const FigmaLinks *links2 = figmaLinksSource.getFigmaLinks();
|
||||||
|
|
||||||
|
QCOMPARE(links2->getLinksMap(), (QMap<QString, QStringList> {
|
||||||
|
{{"Component_1"}, {"link_1"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_5"}}}));
|
||||||
|
|
||||||
|
|
||||||
|
if (QFile f(file.fileName());
|
||||||
|
f.open(QIODevice::WriteOnly | QIODevice::Truncate)) {
|
||||||
|
QTextStream stream(&f);
|
||||||
|
stream << sampleJson1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVERIFY(spy.wait());
|
||||||
|
QCOMPARE(spy.count(), 3);
|
||||||
|
|
||||||
|
const FigmaLinks *links3 = figmaLinksSource.getFigmaLinks();
|
||||||
|
|
||||||
|
QCOMPARE(links3->getLinksMap(), (QMap<QString, QStringList> {
|
||||||
|
{{"Component_1"}, {"link_1", "link_2"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_4"}}}));
|
||||||
|
}
|
||||||
|
|
||||||
|
void emptyFigmaModelTest() {
|
||||||
|
FigmaDecoratorModel model;
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QVERIFY(model.roleNames().contains(FigmaDecoratorModel::FigmaRole));
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
FigmaDecoratorModel::FigmaRole), QStringLiteral("figma"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void figmaModelWithoutSourceModel() {
|
||||||
|
FigmaLinks links({
|
||||||
|
{{"Component_1"}, {"link_1", "link_2"}},
|
||||||
|
{{"Component_2"}, {"link_3", "link_4"}}
|
||||||
|
});
|
||||||
|
|
||||||
|
FigmaDecoratorModel model;
|
||||||
|
model.setFigmaLinks(&links);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 0);
|
||||||
|
QVERIFY(model.roleNames().contains(FigmaDecoratorModel::FigmaRole));
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
FigmaDecoratorModel::FigmaRole), QStringLiteral("figma"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void figmaModelWithIncompatibleSourceModel() {
|
||||||
|
QStringListModel stringsModel({"s1", "s2"});
|
||||||
|
FigmaDecoratorModel model;
|
||||||
|
|
||||||
|
QTest::ignoreMessage(QtWarningMsg,
|
||||||
|
"The source model is missing title role!");
|
||||||
|
model.setSourceModel(&stringsModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 2);
|
||||||
|
QVERIFY(model.roleNames().contains(FigmaDecoratorModel::FigmaRole));
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
FigmaDecoratorModel::FigmaRole), QStringLiteral("figma"));
|
||||||
|
|
||||||
|
QCOMPARE(model.data(
|
||||||
|
model.index(0, 0),
|
||||||
|
FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>()->rowCount(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void figmaModelWithoutLinksTest() {
|
||||||
|
TestSourceModel sourceModel;
|
||||||
|
FigmaDecoratorModel model;
|
||||||
|
|
||||||
|
model.setSourceModel(&sourceModel);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 1);
|
||||||
|
QCOMPARE(model.roleNames().count(), 2);
|
||||||
|
QVERIFY(model.roleNames().contains(FigmaDecoratorModel::FigmaRole));
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
FigmaDecoratorModel::FigmaRole), QStringLiteral("figma"));
|
||||||
|
|
||||||
|
QCOMPARE(model.data(
|
||||||
|
model.index(0, 0),
|
||||||
|
FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>()->rowCount(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void figmaModelTest() {
|
||||||
|
TestSourceModel sourceModel{2};
|
||||||
|
FigmaLinks links({
|
||||||
|
{{"title_0"}, {"link_1", "link_2"}},
|
||||||
|
{{"title_x"}, {"link_3", "link_4"}}
|
||||||
|
});
|
||||||
|
|
||||||
|
FigmaDecoratorModel model;
|
||||||
|
|
||||||
|
QSignalSpy spy(&model, &FigmaDecoratorModel::dataChanged);
|
||||||
|
|
||||||
|
model.setSourceModel(&sourceModel);
|
||||||
|
|
||||||
|
QCOMPARE(spy.size(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(model.rowCount(), 2);
|
||||||
|
QCOMPARE(model.roleNames().count(), 2);
|
||||||
|
QVERIFY(model.roleNames().contains(FigmaDecoratorModel::FigmaRole));
|
||||||
|
QVERIFY(model.roleNames().contains(TestSourceModel::TitleRole));
|
||||||
|
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
FigmaDecoratorModel::FigmaRole), QStringLiteral("figma"));
|
||||||
|
QCOMPARE(model.roleNames().value(
|
||||||
|
TestSourceModel::TitleRole), QStringLiteral("title"));
|
||||||
|
|
||||||
|
QCOMPARE(model.data(model.index(0, 0),
|
||||||
|
TestSourceModel::TitleRole).toString(), "title_0");
|
||||||
|
QCOMPARE(model.data(model.index(1, 0),
|
||||||
|
TestSourceModel::TitleRole).toString(), "title_1");
|
||||||
|
|
||||||
|
auto figmaLinksModel1 = model.data(model.index(0, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>();
|
||||||
|
|
||||||
|
QVERIFY(figmaLinksModel1 != nullptr);
|
||||||
|
QCOMPARE(figmaLinksModel1->rowCount(), 0);
|
||||||
|
|
||||||
|
auto figmaLinksModel2 = model.data(model.index(1, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>();
|
||||||
|
|
||||||
|
QVERIFY(figmaLinksModel2 != nullptr);
|
||||||
|
QCOMPARE(figmaLinksModel2->rowCount(), 0);
|
||||||
|
|
||||||
|
QSignalSpy linksModelspy1(figmaLinksModel1,
|
||||||
|
&QAbstractItemModel::modelReset);
|
||||||
|
QSignalSpy linksModelspy2(figmaLinksModel2,
|
||||||
|
&QAbstractItemModel::modelReset);
|
||||||
|
|
||||||
|
model.setFigmaLinks(&links);
|
||||||
|
|
||||||
|
QCOMPARE(spy.size(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(linksModelspy1.size(), 1);
|
||||||
|
QCOMPARE(linksModelspy2.size(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>(), figmaLinksModel1);
|
||||||
|
QCOMPARE(model.data(model.index(1, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>(), figmaLinksModel2);
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksModel1->rowCount(), 2);
|
||||||
|
QCOMPARE(figmaLinksModel2->rowCount(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(model.data(model.index(0, 0),
|
||||||
|
TestSourceModel::TitleRole).toString(), "title_0");
|
||||||
|
QCOMPARE(model.data(model.index(1, 0),
|
||||||
|
TestSourceModel::TitleRole).toString(), "title_1");
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksModel1->roleNames().size(), 1);
|
||||||
|
QCOMPARE(figmaLinksModel2->roleNames().size(), 1);
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksModel1->data(figmaLinksModel1->index(0, 0),
|
||||||
|
FigmaLinksModel::LinkRole).toString(), "link_1");
|
||||||
|
QCOMPARE(figmaLinksModel1->data(figmaLinksModel1->index(1, 0),
|
||||||
|
FigmaLinksModel::LinkRole).toString(), "link_2");
|
||||||
|
|
||||||
|
model.setFigmaLinks(nullptr);
|
||||||
|
|
||||||
|
QCOMPARE(spy.size(), 0);
|
||||||
|
QCOMPARE(linksModelspy1.size(), 2);
|
||||||
|
QCOMPARE(linksModelspy2.size(), 0);
|
||||||
|
|
||||||
|
QCOMPARE(model.data(model.index(0, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>(), figmaLinksModel1);
|
||||||
|
QCOMPARE(model.data(model.index(1, 0), FigmaDecoratorModel::FigmaRole)
|
||||||
|
.value<QAbstractItemModel*>(), figmaLinksModel2);
|
||||||
|
|
||||||
|
QCOMPARE(figmaLinksModel1->rowCount(), 0);
|
||||||
|
QCOMPARE(figmaLinksModel2->rowCount(), 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
QTEST_MAIN(FigmaDecoratorModelTest)
|
||||||
|
#include "tst_FigmaDecoratorModel.moc"
|
Loading…
Reference in New Issue