├── .circleci └── config.yml ├── .github └── workflows │ └── build.yml ├── .gitignore ├── .qmake.conf ├── .travis.yml ├── .travis ├── install.sh ├── release.sh └── script.sh ├── LICENSE.md ├── README.md ├── pegasus-metaed.pro ├── src ├── AndroidHelpers.cpp ├── AndroidHelpers.h ├── Api.cpp ├── Api.h ├── FolderListModel.cpp ├── FolderListModel.h ├── frontend │ ├── AboutDialog.qml │ ├── CollectionEditor.qml │ ├── CollectionEditorRuleset.qml │ ├── EntryEditHelpText.qml │ ├── GameEditor.qml │ ├── LoadDialog.qml │ ├── ModelBox.qml │ ├── SaveAsDialog.qml │ ├── StringListEditor.qml │ ├── WelcomeText.qml │ ├── components │ │ ├── BigLabel.qml │ │ ├── CommandVarsHelp.qml │ │ ├── CommandVarsLabel.qml │ │ ├── FancyToolButton.qml │ │ ├── FlatButton.qml │ │ ├── InputArea.qml │ │ ├── InputLine.qml │ │ ├── InputLineNarrow.qml │ │ ├── MessageDialog.qml │ │ ├── Panel.qml │ │ ├── TinyLabel.qml │ │ └── TinyMonoLabel.qml │ ├── icons │ │ └── fa │ │ │ ├── ellipsis-v.svg │ │ │ ├── file.svg │ │ │ ├── folder-open.svg │ │ │ ├── folder.svg │ │ │ ├── save.svg │ │ │ └── search.svg │ ├── main.qml │ └── qml.qrc ├── main.cpp ├── metaformat │ ├── Metafile.cpp │ ├── Metafile.h │ ├── Metaformat.cpp │ ├── Metaformat.h │ ├── MetaformatAssets.cpp │ ├── MetaformatAssets.h │ ├── MetaformatCollections.cpp │ ├── MetaformatCollections.h │ ├── MetaformatErrorCB.h │ ├── MetaformatGames.cpp │ ├── MetaformatGames.h │ ├── MetaformatUtils.cpp │ ├── MetaformatUtils.h │ └── metaformat.pri ├── model │ ├── Model.cpp │ ├── Model.h │ ├── ModelData.cpp │ ├── ModelData.h │ └── model.pri ├── platform │ ├── android │ │ ├── AndroidManifest.xml │ │ ├── res │ │ │ ├── drawable-hdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-ldpi │ │ │ │ └── icon.png │ │ │ ├── drawable-mdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-xhdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-xxhdpi │ │ │ │ └── icon.png │ │ │ ├── drawable-xxxhdpi │ │ │ │ └── icon.png │ │ │ └── drawable │ │ │ │ └── banner.png │ │ └── src │ │ │ └── org │ │ │ └── pegasus_frontend │ │ │ └── metaed │ │ │ └── MainActivity.java │ ├── macos │ │ ├── Info.plist.in │ │ └── appicons.icns │ └── windows │ │ └── app_icon.ico ├── src.pro └── utils │ ├── MoveOnly.h │ ├── StdHelpers.h │ ├── StringListModel.cpp │ ├── StringListModel.h │ └── utils.pri └── thirdparty ├── QtQmlTricks ├── LICENSE.md ├── QQmlObjectListModel.cpp ├── QQmlObjectListModel.h ├── QtQmlTricks.pri └── README.md ├── README.md ├── SortFilterProxyModel ├── .gitignore ├── CMakeLists.txt ├── LICENSE ├── README.md ├── SortFilterProxyModel.pri ├── docs │ ├── index.html │ ├── qml-allof-members.html │ ├── qml-allof.html │ ├── qml-anyof-members.html │ ├── qml-anyof.html │ ├── qml-expressionfilter-members.html │ ├── qml-expressionfilter.html │ ├── qml-expressionrole-members.html │ ├── qml-expressionrole.html │ ├── qml-expressionsorter-members.html │ ├── qml-expressionsorter.html │ ├── qml-filter-members.html │ ├── qml-filter.html │ ├── qml-filterrole-members.html │ ├── qml-filterrole.html │ ├── qml-filtersorter-members.html │ ├── qml-filtersorter.html │ ├── qml-indexfilter-members.html │ ├── qml-indexfilter.html │ ├── qml-joinrole-members.html │ ├── qml-joinrole.html │ ├── qml-proxyrole-members.html │ ├── qml-proxyrole.html │ ├── qml-rangefilter-members.html │ ├── qml-rangefilter.html │ ├── qml-regexpfilter-members.html │ ├── qml-regexpfilter.html │ ├── qml-regexprole-members.html │ ├── qml-regexprole.html │ ├── qml-rolefilter-members.html │ ├── qml-rolefilter.html │ ├── qml-rolesorter-members.html │ ├── qml-rolesorter.html │ ├── qml-singlerole-members.html │ ├── qml-singlerole.html │ ├── qml-sorter-members.html │ ├── qml-sorter.html │ ├── qml-sortfilterproxymodel-members.html │ ├── qml-sortfilterproxymodel.html │ ├── qml-stringsorter-members.html │ ├── qml-stringsorter.html │ ├── qml-switchrole-members.html │ ├── qml-switchrole.html │ ├── qml-valuefilter-members.html │ ├── qml-valuefilter.html │ ├── sortfilterproxymodel.index │ └── style │ │ └── offline.css ├── filters │ ├── alloffilter.cpp │ ├── alloffilter.h │ ├── anyoffilter.cpp │ ├── anyoffilter.h │ ├── expressionfilter.cpp │ ├── expressionfilter.h │ ├── filter.cpp │ ├── filter.h │ ├── filtercontainer.cpp │ ├── filtercontainer.h │ ├── filtercontainerfilter.cpp │ ├── filtercontainerfilter.h │ ├── filtersqmltypes.cpp │ ├── filtersqmltypes.h │ ├── indexfilter.cpp │ ├── indexfilter.h │ ├── rangefilter.cpp │ ├── rangefilter.h │ ├── regexpfilter.cpp │ ├── regexpfilter.h │ ├── rolefilter.cpp │ ├── rolefilter.h │ ├── valuefilter.cpp │ └── valuefilter.h ├── proxyroles │ ├── expressionrole.cpp │ ├── expressionrole.h │ ├── filterrole.cpp │ ├── filterrole.h │ ├── joinrole.cpp │ ├── joinrole.h │ ├── proxyrole.cpp │ ├── proxyrole.h │ ├── proxyrolecontainer.cpp │ ├── proxyrolecontainer.h │ ├── proxyrolesqmltypes.cpp │ ├── proxyrolesqmltypes.h │ ├── regexprole.cpp │ ├── regexprole.h │ ├── singlerole.cpp │ ├── singlerole.h │ ├── switchrole.cpp │ └── switchrole.h ├── qpm.json ├── qqmlsortfilterproxymodel.cpp ├── qqmlsortfilterproxymodel.h ├── sorters │ ├── expressionsorter.cpp │ ├── expressionsorter.h │ ├── filtersorter.cpp │ ├── filtersorter.h │ ├── rolesorter.cpp │ ├── rolesorter.h │ ├── sorter.cpp │ ├── sorter.h │ ├── sortercontainer.cpp │ ├── sortercontainer.h │ ├── sortersqmltypes.cpp │ ├── sortersqmltypes.h │ ├── stringsorter.cpp │ └── stringsorter.h ├── sortfilterproxymodel.qdocconf └── tests │ ├── SortFilterProxyModel.pro │ ├── indexsorter.cpp │ ├── indexsorter.h │ ├── testroles.cpp │ ├── testroles.h │ ├── tst_builtins.qml │ ├── tst_expressionrole.qml │ ├── tst_filtercontainers.qml │ ├── tst_filterrole.qml │ ├── tst_filtersorter.qml │ ├── tst_helpers.qml │ ├── tst_indexfilter.qml │ ├── tst_joinrole.qml │ ├── tst_proxyroles.qml │ ├── tst_rangefilter.qml │ ├── tst_regexprole.qml │ ├── tst_rolesorter.qml │ ├── tst_sorters.qml │ ├── tst_sortfilterproxymodel.cpp │ ├── tst_sourceroles.qml │ ├── tst_stringsorter.qml │ └── tst_switchrole.qml └── thirdparty.pri /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | android: 4 | docker: 5 | - image: mmatyas/pegasus-qt-android 6 | environment: 7 | TOOLS_URL: https://github.com/mmatyas/pegasus-frontend/releases/download/alpha1 8 | QT_TARGET: qt5156_android 9 | ANDROID_SDK_ROOT: /opt/android-sdk 10 | ANDROID_NDK_ROOT: /opt/android-sdk/ndk/21.4.7075529 11 | steps: 12 | - run: git clone https://github.com/mmatyas/pegasus-metadata-editor . 13 | - run: git checkout -qf ${CIRCLE_SHA1} 14 | - run: git submodule update --init --recursive 15 | - run: sed -i "s/android:versionName=\"devel\"/android:versionName=\"$(git describe --always)\"/" src/platform/android/AndroidManifest.xml 16 | - run: sed -i "s/android:versionCode=\"1\"/android:versionCode=\"$(git rev-list --count HEAD)\"/" src/platform/android/AndroidManifest.xml 17 | - run: curl -L ${TOOLS_URL}/${QT_TARGET}.tar.xz | tar xJf - -C /opt/ 18 | - run: curl -L ${TOOLS_URL}/openssl-111d_android.tar.xz | tar xJf - -C /opt/ 19 | - run: /opt/${QT_TARGET}/bin/qmake . 20 | - run: make 21 | - run: make install INSTALL_ROOT=${PWD}/installdir 22 | - run: /opt/${QT_TARGET}/bin/androiddeployqt 23 | --input src/android-pegasus-metaed-deployment-settings.json 24 | --output ${PWD}/installdir 25 | --android-platform android-30 26 | --gradle 27 | # Deploy 28 | - run: mkdir dist 29 | - run: cp 30 | installdir/build/outputs/apk/debug/installdir-debug.apk 31 | dist/pegasus-metadata-editor_$(git describe --always)_android.apk 32 | - run: curl -L -O https://github.com/mmatyas/uploadtool/raw/circleci/upload.sh 33 | - run: bash ./upload.sh dist/*.apk 34 | mingw: 35 | docker: 36 | - image: mmatyas/pegasus-qt-mingw 37 | environment: 38 | TOOLS_URL: https://github.com/mmatyas/pegasus-frontend/releases/download/alpha1 39 | QT_TARGET: qt5156_win32-mingw-static 40 | steps: 41 | - run: git clone https://github.com/mmatyas/pegasus-metadata-editor . 42 | - run: git checkout -qf ${CIRCLE_SHA1} 43 | - run: git submodule update --init --recursive 44 | - run: curl -L ${TOOLS_URL}/${QT_TARGET}.tar.xz | tar xJf - -C /opt/ 45 | - run: curl -L ${TOOLS_URL}/openssl-111d_mingw.tar.xz | tar xJf - -C /opt/ 46 | - run: /opt/${QT_TARGET}_hosttools/bin/qmake . 47 | - run: make 48 | - run: make install INSTALL_ROOT=${PWD}/installdir 49 | - run: i686-w64-mingw32-objdump -p installdir/home/build/project/src/C:/pegasus-metadata-editor/pegasus-metaed.exe | grep 'DLL Name' | sort 50 | # Deploy 51 | - run: mkdir -p dist/pegasus-metadata-editor 52 | - run: cp 53 | installdir/home/build/project/src/C:/pegasus-metadata-editor/pegasus-metaed.exe 54 | README.md 55 | LICENSE.md 56 | dist/pegasus-metadata-editor/ 57 | - run: cd dist && zip -r 58 | pegasus-metadata-editor_$(git describe --always)_win-mingw-static.zip 59 | pegasus-metadata-editor 60 | - run: curl -L -O https://github.com/mmatyas/uploadtool/raw/circleci/upload.sh 61 | - run: bash ./upload.sh dist/*.zip 62 | workflows: 63 | version: 2 64 | all: 65 | jobs: 66 | - android 67 | - mingw 68 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: [push, workflow_dispatch] 4 | 5 | env: 6 | QT_VER: "5.15.6" 7 | 8 | 9 | jobs: 10 | x11-static: 11 | runs-on: ubuntu-20.04 12 | env: 13 | TARGET: x11-static 14 | steps: 15 | - uses: actions/checkout@v2 16 | - run: .travis/install.sh 17 | - run: .travis/script.sh 18 | - uses: actions/upload-artifact@v2 19 | with: 20 | name: pme-x11-static 21 | path: dist 22 | 23 | macos-static: 24 | runs-on: macos-10.15 25 | env: 26 | TARGET: macos-static 27 | steps: 28 | - uses: actions/checkout@v2 29 | - run: .travis/install.sh 30 | - run: .travis/script.sh 31 | - uses: actions/upload-artifact@v2 32 | with: 33 | name: pme-macos-static 34 | path: dist 35 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ignore build dirs 2 | build*/ 3 | 4 | # ignore IDE project files 5 | *.pro.user* 6 | *.autosave 7 | *.kdev4 8 | *.workspace 9 | 10 | # ignore Qt generated files 11 | *.qmlc 12 | *.jsc 13 | -------------------------------------------------------------------------------- /.qmake.conf: -------------------------------------------------------------------------------- 1 | TOP_SRCDIR=$$PWD 2 | TOP_BUILDDIR=$$shadowed($$PWD) 3 | 4 | GIT_REVISION = $$system(git \ 5 | --git-dir $${TOP_SRCDIR}/.git \ 6 | --work-tree $${TOP_SRCDIR} \ 7 | describe \ 8 | --always --dirty) 9 | 10 | GIT_DATE = $$system(git \ 11 | --git-dir $${TOP_SRCDIR}/.git \ 12 | --work-tree $${TOP_SRCDIR} \ 13 | log \ 14 | -1 \ 15 | --format=%cd \ 16 | --date=short) 17 | 18 | GIT_COMMIT_CNT = $$system(git \ 19 | --git-dir $${TOP_SRCDIR}/.git \ 20 | --work-tree $${TOP_SRCDIR} \ 21 | rev-list \ 22 | --count HEAD) 23 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: cpp 2 | 3 | sudo: required 4 | dist: xenial 5 | 6 | branches: 7 | only: 8 | - master 9 | 10 | env: 11 | global: 12 | - QT_VER=5.12.5 13 | 14 | 15 | install: ./.travis/install.sh 16 | script: ./.travis/script.sh 17 | deploy: 18 | - provider: pages 19 | github-token: $GITHUB_TOKEN 20 | local-dir: dist 21 | repo: mmatyas/pegasus-metadata-editor-staging 22 | target-branch: continuous-$TARGET 23 | skip-cleanup: true 24 | 25 | 26 | jobs: 27 | include: 28 | - env: TARGET=x11-static 29 | - env: TARGET=rpi1-static 30 | - env: TARGET=rpi2-static 31 | - env: TARGET=rpi3-static 32 | 33 | - env: TARGET=macos-static QT_VER=5.12.3 34 | os: osx 35 | osx_image: xcode9.2 36 | 37 | - stage: deploy 38 | install: skip 39 | script: ./.travis/release.sh 40 | deploy: null 41 | 42 | services: 43 | - xvfb 44 | -------------------------------------------------------------------------------- /.travis/install.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | if [[ -z ${QT_VER-} || -z ${TARGET-} ]]; then 7 | echo "Please define QT_VER and TARGET first" 8 | exit 1 9 | fi 10 | set -o xtrace 11 | 12 | 13 | # Native dependencies 14 | 15 | if [[ $TARGET = x11* ]]; then 16 | sudo apt-add-repository -y ppa:brightbox/ruby-ng 17 | sudo apt-get -qq update 18 | sudo apt-get install -y \ 19 | libgl1-mesa-dev \ 20 | libudev-dev \ 21 | libx11-xcb-dev \ 22 | libxcb-glx0-dev \ 23 | libxcb-icccm4-dev \ 24 | libxcb-image0-dev \ 25 | libxcb-keysyms1-dev \ 26 | libxcb-randr0-dev \ 27 | libxcb-render-util0-dev \ 28 | libxcb-shape0-dev \ 29 | libxcb-sync-dev \ 30 | libxcb-util-dev \ 31 | libxcb-xfixes0-dev \ 32 | libxcb-xinerama0-dev \ 33 | libxi-dev \ 34 | libxkbcommon-dev \ 35 | libxkbcommon-x11-dev \ 36 | libzstd-dev 37 | fi 38 | 39 | if [[ $TARGET = rpi* ]]; then 40 | sudo apt-get -qq update 41 | sudo apt-get install -y \ 42 | g++-aarch64-linux-gnu \ 43 | g++-arm-linux-gnueabihf 44 | fi 45 | 46 | 47 | # Toolchains 48 | 49 | TOOLS_URL=https://github.com/mmatyas/pegasus-frontend/releases/download/alpha1 50 | 51 | pushd /tmp 52 | wget ${TOOLS_URL}/qt${QT_VER//./}_${TARGET}.tar.xz 53 | 54 | if [[ $TARGET = rpi* ]]; then 55 | if [[ $TARGET = rpi4* ]]; then 56 | wget ${TOOLS_URL}/rpi-sysroot_buster_mesa.tar.xz 57 | else 58 | wget ${TOOLS_URL}/rpi-sysroot_buster_brcm.tar.xz 59 | fi 60 | fi 61 | 62 | if [[ $TARGET == macos* ]]; then OUTDIR=/usr/local; else OUTDIR=/opt; fi 63 | for f in *.tar.xz; do sudo tar xJf ${f} -C ${OUTDIR}/; done 64 | popd 65 | -------------------------------------------------------------------------------- /.travis/release.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | if [[ $TRAVIS_EVENT_TYPE = pull_request ]]; then 7 | echo "Skipping deployment for pull requests" 8 | exit 0 9 | fi 10 | 11 | 12 | STAGING_REPO=https://github.com/mmatyas/pegasus-metadata-editor-staging.git 13 | GIT_REV=$(git describe --always) 14 | TARGETS='x11-static rpi1-static rpi2-static rpi3-static macos-static' 15 | EXPECTED_FILE_CNT=5 16 | 17 | 18 | # Collect 19 | 20 | FILE_CNT=0 21 | NEXT_SLEEP_SEC=0 22 | 23 | while [[ $FILE_CNT -ne $EXPECTED_FILE_CNT ]]; do 24 | if [[ $NEXT_SLEEP_SEC -ne 0 ]]; then echo Retrying in $NEXT_SLEEP_SEC seconds...; fi 25 | sleep $NEXT_SLEEP_SEC 26 | NEXT_SLEEP_SEC=20 27 | 28 | for target in $TARGETS; do 29 | rm -rf dist-${target}; 30 | git clone ${STAGING_REPO} -b continuous-${target} dist-${target}; 31 | done; 32 | 33 | FILES=$(find ./ -maxdepth 2 -name "*${GIT_REV}*.zip"); 34 | FILE_CNT=$(echo $FILES | wc -w); 35 | echo "Available files:" 36 | echo ${FILES} 37 | echo "(${FILE_CNT} out of ${EXPECTED_FILE_CNT})"; 38 | done 39 | 40 | 41 | # Deploy 42 | 43 | wget https://github.com/mmatyas/uploadtool/raw/master/upload.sh; 44 | bash ./upload.sh $FILES 45 | -------------------------------------------------------------------------------- /.travis/script.sh: -------------------------------------------------------------------------------- 1 | #! /bin/bash 2 | 3 | set -o errexit 4 | set -o nounset 5 | 6 | if [[ -z ${QT_VER-} || -z ${TARGET-} ]]; then 7 | echo "Please define QT_VER and TARGET first" 8 | exit 1 9 | fi 10 | set -o xtrace 11 | 12 | 13 | # Platform settings - Qt dir 14 | if [[ $TARGET == macos* ]]; then 15 | QT_HOSTDIR=/usr/local/Qt-${QT_VER} 16 | elif [[ $TARGET == x11* ]]; then 17 | QT_HOSTDIR=/opt/qt${QT_VER//./}_${TARGET} 18 | else 19 | QT_HOSTDIR=/opt/qt${QT_VER//./}_${TARGET}_hosttools 20 | fi 21 | # Platform settings - Cross prefix 22 | if [[ $TARGET == rpi1* ]]; then 23 | CROSS=/opt/rpi-toolchain/arm-bcm2708/arm-linux-gnueabihf/bin/arm-linux-gnueabihf- 24 | elif [[ $TARGET == rpi* ]]; then 25 | CROSS=/opt/linaro/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabihf/bin/arm-linux-gnueabihf- 26 | fi 27 | # Platform settings - install path 28 | if [[ $TARGET == macos* ]]; then 29 | INSTALLED_FILE=usr/local/pegasus-metadata-editor/Pegasus\ Metadata\ Editor.app 30 | INSTALLED_BINARY=${INSTALLED_FILE}/Contents/MacOS/pegasus-metaed 31 | else 32 | INSTALLED_FILE=opt/pegasus-metadata-editor/pegasus-metaed 33 | INSTALLED_BINARY=${INSTALLED_FILE} 34 | fi 35 | 36 | 37 | # Lint 38 | find . -name *.qml -exec ${QT_HOSTDIR}/bin/qmllint {} \; 39 | 40 | 41 | # Build 42 | mkdir build && pushd build 43 | ${QT_HOSTDIR}/bin/qmake .. 44 | make 45 | make install INSTALL_ROOT=$PWD/../installoc 46 | popd 47 | 48 | 49 | # Check deps 50 | ${CROSS-}objdump -p "installoc/${INSTALLED_BINARY}" | grep NEEDED | sort 51 | 52 | 53 | # Create artifacts 54 | mkdir dist && pushd dist 55 | DISTDIR=pegasus-metadata-editor 56 | mkdir $DISTDIR 57 | cp -r "../installoc/${INSTALLED_FILE}" ../README.md ../LICENSE.md $DISTDIR/ 58 | zip -r pegasus-metadata-editor_$(git describe --always)_${TARGET}.zip $DISTDIR 59 | rm -rf $DISTDIR 60 | popd 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Pegasus Metadata Editor 2 | 3 | A simple editor for the metadata files of [Pegasus](http://pegasus-frontend.org). 4 | 5 | ![screenshot](https://snipboard.io/jvemLa.jpg) 6 | ![screenshot](https://snipboard.io/nKNWkt.jpg) 7 | 8 | You can download it [**from here**](https://github.com/mmatyas/pegasus-metadata-editor/releases). 9 | 10 | Also avaliable from AUR! Look for [`pegasus-metadata-editor-git`](https://aur.archlinux.org/packages/pegasus-metadata-editor-git/). 11 | -------------------------------------------------------------------------------- /pegasus-metaed.pro: -------------------------------------------------------------------------------- 1 | lessThan(QT_MAJOR_VERSION, 5) | lessThan(QT_MINOR_VERSION, 12) { 2 | error("This project requires Qt 5.12 or later") 3 | } 4 | 5 | TEMPLATE = subdirs 6 | SUBDIRS += src 7 | -------------------------------------------------------------------------------- /src/AndroidHelpers.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "AndroidHelpers.h" 19 | 20 | #include 21 | #include 22 | #include 23 | 24 | 25 | namespace android { 26 | 27 | constexpr const char* jni_classname() { 28 | return "org/pegasus_frontend/metaed/MainActivity"; 29 | } 30 | 31 | QString primary_storage_path() 32 | { 33 | // should be the same as storage_paths().front(), but perhaps faster 34 | return QStandardPaths::standardLocations(QStandardPaths::GenericDataLocation).constFirst(); 35 | } 36 | 37 | QStringList storage_paths() 38 | { 39 | static constexpr auto JNI_METHOD = "sdcardPaths"; 40 | static constexpr auto JNI_SIGNATURE = "()[Ljava/lang/String;"; 41 | 42 | QAndroidJniEnvironment jni_env; 43 | const auto jni_path_arr_raw = QAndroidJniObject::callStaticObjectMethod(jni_classname(), JNI_METHOD, JNI_SIGNATURE); 44 | const auto jni_path_arr = jni_path_arr_raw.object(); 45 | const jsize path_count = jni_env->GetArrayLength(jni_path_arr); 46 | 47 | QStringList out; 48 | out.reserve(static_cast(path_count)); 49 | 50 | for (jsize i = 0; i < path_count; i++) { 51 | const auto jni_path_raw = QAndroidJniObject(jni_env->GetObjectArrayElement(jni_path_arr, i)); 52 | out.append(jni_path_raw.toString()); 53 | } 54 | 55 | if (out.empty()) 56 | out.append(primary_storage_path()); 57 | 58 | return out; 59 | } 60 | 61 | } // namespace android 62 | -------------------------------------------------------------------------------- /src/AndroidHelpers.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | 23 | namespace android { 24 | 25 | constexpr const char* jni_classname(); 26 | QString primary_storage_path(); 27 | QStringList storage_paths(); 28 | 29 | } // namespace android 30 | -------------------------------------------------------------------------------- /src/Api.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "model/Model.h" 21 | 22 | #include "QtQmlTricks/QQmlObjectListModel.h" 23 | #include 24 | 25 | 26 | class Api: public QObject { 27 | Q_OBJECT 28 | 29 | Q_PROPERTY(QString errorLog READ errorLog NOTIFY errorLogChanged) 30 | Q_PROPERTY(QString filePath READ filePath NOTIFY filePathChanged) 31 | Q_PROPERTY(bool hasDocument READ hasDocument NOTIFY hasDocumentChanged) 32 | QML_OBJMODEL_PROPERTY(model::Collection, collections) 33 | QML_OBJMODEL_PROPERTY(model::Game, games) 34 | 35 | Q_PROPERTY(QString gitRevision MEMBER m_git_revision CONSTANT) 36 | Q_PROPERTY(QString gitDate MEMBER m_git_date CONSTANT) 37 | 38 | public: 39 | explicit Api(QObject* parent = nullptr); 40 | 41 | Q_INVOKABLE void newDocument(); 42 | Q_INVOKABLE void openFile(QString path); 43 | Q_INVOKABLE void save(); 44 | Q_INVOKABLE void saveAs(QString path); 45 | 46 | Q_INVOKABLE void newCollection(); 47 | Q_INVOKABLE void newGame(); 48 | 49 | const QString& errorLog() const { return m_error_log; } 50 | const QString& filePath() const { return m_file_path; } 51 | bool hasDocument() const { return m_has_document; } 52 | 53 | signals: 54 | void errorLogChanged(); 55 | void filePathChanged(); 56 | void hasDocumentChanged(); 57 | 58 | void openSuccess(); 59 | void openFail(); 60 | void saveSuccess(); 61 | void saveFail(); 62 | 63 | private: 64 | static const QString m_git_revision; 65 | static const QString m_git_date; 66 | 67 | QString m_error_log; 68 | QString m_file_path; 69 | bool m_has_document; 70 | }; 71 | -------------------------------------------------------------------------------- /src/FolderListModel.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "utils/MoveOnly.h" 21 | 22 | #include 23 | #include 24 | 25 | 26 | struct FolderListEntry { 27 | QString name; 28 | bool is_dir; 29 | 30 | FolderListEntry(QString name, bool is_dir); 31 | MOVE_ONLY(FolderListEntry) 32 | }; 33 | 34 | 35 | class FolderListModel : public QAbstractListModel { 36 | Q_OBJECT 37 | Q_PROPERTY(QString folder READ folder NOTIFY folderChanged) 38 | Q_PROPERTY(QStringList files 39 | READ filenames WRITE setFilenames 40 | NOTIFY filenamesChanged) 41 | Q_PROPERTY(QStringList extensions 42 | READ extensions WRITE setExtensions 43 | NOTIFY extensionsChanged) 44 | 45 | public: 46 | explicit FolderListModel(QObject* parent = nullptr); 47 | 48 | enum Roles { 49 | EntryName = Qt::UserRole + 1, 50 | EntryIsDir, 51 | }; 52 | 53 | int rowCount(const QModelIndex& parent = QModelIndex()) const override; 54 | QVariant data(const QModelIndex& index, int role) const override; 55 | QHash roleNames() const override { return m_role_names; } 56 | 57 | Q_INVOKABLE void cd(const QString&); 58 | Q_INVOKABLE bool fileExists(QString path) const; 59 | 60 | QString folder() const { return m_dir_path; } 61 | const QStringList& filenames() const { return m_filenames; } 62 | const QStringList& extensions() const { return m_extensions; } 63 | void setFilenames(QStringList); 64 | void setExtensions(QStringList); 65 | 66 | signals: 67 | void folderChanged(); 68 | void filenamesChanged(); 69 | void extensionsChanged(); 70 | 71 | private: 72 | QDir m_dir; 73 | QString m_dir_path; 74 | std::vector m_files; 75 | QStringList m_filenames; 76 | QStringList m_extensions; 77 | 78 | const QStringList m_drives_cache; 79 | const QHash m_role_names; 80 | }; 81 | -------------------------------------------------------------------------------- /src/frontend/AboutDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | 4 | Dialog { 5 | width: parent.width * 0.45 6 | anchors.centerIn: parent 7 | 8 | modal: true 9 | standardButtons: Dialog.Ok 10 | 11 | Label { 12 | anchors.fill: parent 13 | text: "

Pegasus Metadata Editor

" 14 | + "
A graphical editor for the Metadata files of the Pegasus frontend." 15 | + "
Visit us at https://pegasus-frontend.org!" 16 | + "

Version %1 (%2)".arg(Api.gitRevision).arg(Api.gitDate) 17 | + "
Copyright \xa9 2019 Mátyás Mustoha" 18 | + "

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE." 19 | wrapMode: Text.Wrap 20 | horizontalAlignment: Text.AlignJustify 21 | onLinkActivated: Qt.openUrlExternally(link) 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/frontend/CollectionEditorRuleset.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | import "components" 5 | 6 | 7 | ColumnLayout { 8 | property alias header: mHeader.text 9 | property alias extensionsText: mExtDesc.text 10 | property alias filesText: mFileDesc.text 11 | property alias regexText: mRegexDesc.text 12 | property var cdata 13 | 14 | anchors.left: parent.left 15 | anchors.right: parent.right 16 | 17 | spacing: 10 18 | 19 | 20 | Label { 21 | id: mHeader 22 | 23 | font.pointSize: 17 24 | font.capitalization: Font.AllUppercase 25 | 26 | topPadding: font.pixelSize * 2.5 27 | } 28 | 29 | Item { width: 1; height: 1 } 30 | 31 | Label { 32 | id: mExtDesc 33 | Layout.fillWidth: true 34 | wrapMode: Text.Wrap 35 | } 36 | StringListEditor { 37 | Layout.fillWidth: true 38 | model: cdata ? cdata.extensions : 0 39 | } 40 | 41 | Item { width: 1; height: 1 } 42 | 43 | Label { 44 | id: mFileDesc 45 | Layout.fillWidth: true 46 | wrapMode: Text.Wrap 47 | } 48 | StringListEditor { 49 | Layout.fillWidth: true 50 | model: cdata ? cdata.files : 0 51 | } 52 | 53 | Item { width: 1; height: 1 } 54 | 55 | Label { 56 | id: mRegexDesc 57 | Layout.fillWidth: true 58 | wrapMode: Text.Wrap 59 | } 60 | InputLineNarrow { 61 | text: cdata ? cdata.regex : "" 62 | placeholderText: "regular expression..." 63 | onTextEdited: if (cdata) cdata.regex = text; 64 | Layout.fillWidth: true 65 | } 66 | } 67 | -------------------------------------------------------------------------------- /src/frontend/EntryEditHelpText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | 5 | Label { 6 | text: "Select an item from the left to edit.\n" 7 | + "Use the + button to add a new item.\n" 8 | + "Use the \xd7 button to delete an item." 9 | font.pointSize: 12 10 | opacity: 0.6 11 | 12 | horizontalAlignment: Text.AlignHCenter 13 | verticalAlignment: Text.AlignVCenter 14 | 15 | Layout.fillWidth: true 16 | Layout.fillHeight: true 17 | } 18 | -------------------------------------------------------------------------------- /src/frontend/StringListEditor.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | import "components" 5 | 6 | 7 | ColumnLayout { 8 | property alias model: mList.model 9 | 10 | spacing: 0 11 | 12 | 13 | Rectangle { 14 | Layout.fillWidth: true 15 | Layout.minimumHeight: mList.contentHeight 16 | 17 | color: "transparent" 18 | border.color: "#40000000" 19 | border.width: 1 20 | 21 | ListView { 22 | id: mList 23 | 24 | anchors.fill: parent 25 | 26 | delegate: mListDelegate 27 | } 28 | } 29 | FlatButton { 30 | Layout.fillWidth: true 31 | text: "+" 32 | onPressed: model.create() 33 | } 34 | 35 | 36 | Component { 37 | id: mListDelegate 38 | 39 | InputLineNarrow { 40 | id: inputLine 41 | 42 | width: ListView.view.width 43 | background: Item {} 44 | 45 | text: display 46 | onTextEdited: edit = text 47 | placeholderText: "(enter value)" 48 | 49 | font.pointSize: 10 50 | topPadding: font.pixelSize * 0.6 51 | 52 | Label { 53 | id: delBtn 54 | 55 | width: height * 1.25 56 | anchors.right: parent.right 57 | anchors.verticalCenter: parent.verticalCenter 58 | 59 | text: "\xd7" 60 | font.pointSize: 16 61 | visible: parent.hovered 62 | horizontalAlignment: Text.AlignHCenter 63 | font.italic: false 64 | 65 | MouseArea { 66 | anchors.fill: parent 67 | cursorShape: Qt.ArrowCursor 68 | onClicked: inputLine.ListView.view.model.remove(index) 69 | } 70 | } 71 | } 72 | } 73 | } 74 | -------------------------------------------------------------------------------- /src/frontend/WelcomeText.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Column { 5 | anchors.centerIn: parent 6 | opacity: 0.7 7 | spacing: 6 8 | 9 | readonly property int imgSize: 20 10 | readonly property int textSizePt: 13 11 | 12 | Label { 13 | text: "Welcome to the Pegasus Metadata Editor!" 14 | font.bold: true 15 | anchors.horizontalCenter: parent.horizontalCenter 16 | font.pointSize: textSizePt * 1.17 17 | bottomPadding: font.pixelSize * 0.9 18 | } 19 | Label { 20 | text: "You can use the toolbar buttons at the top to" 21 | anchors.horizontalCenter: parent.horizontalCenter 22 | font.pointSize: textSizePt 23 | } 24 | Grid { 25 | columns: 2 26 | columnSpacing: 10 27 | verticalItemAlignment: Grid.AlignVCenter 28 | anchors.horizontalCenter: parent.horizontalCenter 29 | 30 | Image { sourceSize { width: imgSize; height: imgSize} asynchronous: true; source: "qrc:///icons/fa/folder-open.svg" } 31 | Label { text: "Open"; font.pointSize: textSizePt } 32 | Image { sourceSize { width: imgSize; height: imgSize} asynchronous: true; source: "qrc:///icons/fa/save.svg" } 33 | Label { text: "Save"; font.pointSize: textSizePt } 34 | Image { sourceSize { width: imgSize; height: imgSize} asynchronous: true; source: "qrc:///icons/fa/file.svg" } 35 | Label { text: "Create New"; font.pointSize: textSizePt } 36 | } 37 | Label { 38 | text: "metadata files. Happy editing!" 39 | anchors.horizontalCenter: parent.horizontalCenter 40 | font.pointSize: textSizePt 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/frontend/components/BigLabel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Label { 5 | font.pointSize: 17 6 | font.capitalization: Font.AllUppercase 7 | wrapMode: Text.Wrap 8 | 9 | topPadding: font.pixelSize * 2 10 | bottomPadding: font.pixelSize * 0.25 11 | } 12 | -------------------------------------------------------------------------------- /src/frontend/components/CommandVarsHelp.qml: -------------------------------------------------------------------------------- 1 | import QtQuick.Layouts 1.12 2 | 3 | 4 | GridLayout { 5 | columns: 2 6 | columnSpacing: 32 7 | anchors.leftMargin: 16 8 | anchors.left: parent.left 9 | anchors.right: parent.right 10 | 11 | TinyMonoLabel { text: "{file.path}" } 12 | TinyLabel { text: "Absolute path to the launched file" } 13 | TinyMonoLabel { text: "{file.name}" } 14 | TinyLabel { text: "The file name part of the path" } 15 | TinyMonoLabel { text: "{file.basename}" } 16 | TinyLabel { text: "The file name without extension" } 17 | TinyMonoLabel { text: "{file.dir}" } 18 | TinyLabel { text: "The directory where the file is located" } 19 | TinyMonoLabel { text: "{file.uri}" } 20 | TinyLabel { text: "Absolute path in URI format (mainly for Android)" } 21 | TinyMonoLabel { text: "{env.MYVAR}" } 22 | TinyLabel { text: "The value of the environment variable MYVAR, if defined" } 23 | } 24 | -------------------------------------------------------------------------------- /src/frontend/components/CommandVarsLabel.qml: -------------------------------------------------------------------------------- 1 | TinyLabel { 2 | text: "The launch command is a single value, but you can break " 3 | + "it up to multiple lines for better readability. You can use " 4 | + "the following variables in it:" 5 | anchors.left: parent.left 6 | anchors.right: parent.right 7 | } 8 | -------------------------------------------------------------------------------- /src/frontend/components/FancyToolButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Controls.Material 2.12 4 | import QtQuick.Layouts 1.12 5 | 6 | ToolButton { 7 | leftPadding: 12 8 | rightPadding: leftPadding 9 | Layout.fillHeight: true 10 | 11 | background: Rectangle { 12 | anchors.fill: parent 13 | visible: parent.hovered 14 | color: parent.Material.rippleColor 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /src/frontend/components/FlatButton.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Rectangle { 5 | id: root 6 | 7 | property alias text: mText.text 8 | 9 | signal pressed() 10 | 11 | width: mText.width * 2 12 | height: mText.height 13 | 14 | color: mMouse.containsMouse ? "#50000000" : "#28000000" 15 | 16 | 17 | Label { 18 | id: mText 19 | padding: 6.5 20 | anchors.centerIn: parent 21 | } 22 | 23 | MouseArea { 24 | id: mMouse 25 | anchors.fill: parent 26 | hoverEnabled: true 27 | cursorShape: Qt.PointingHandCursor 28 | onClicked: root.pressed() 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/frontend/components/InputArea.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Controls.Material 2.12 4 | 5 | 6 | TextArea { 7 | property alias label: mLabel.text 8 | property string tooltipText: "" 9 | 10 | readonly property color mAccentColor: activeFocus 11 | ? Material.accentColor 12 | : (hovered ? Material.primaryTextColor : Material.hintTextColor) 13 | 14 | height: Math.max(font.pixelSize * 5.5, implicitHeight) 15 | 16 | anchors.left: parent.left 17 | anchors.right: parent.right 18 | 19 | leftPadding: mLabel.leftPadding 20 | rightPadding: leftPadding 21 | topPadding: mLabel.height 22 | bottomPadding: font.pixelSize * 0.25 23 | 24 | selectByMouse: true 25 | background: Rectangle { 26 | color: "#10000000" 27 | } 28 | 29 | wrapMode: Text.Wrap 30 | 31 | ToolTip.text: tooltipText 32 | ToolTip.visible: tooltipText ? hovered : false 33 | ToolTip.delay: 500 34 | 35 | Label { 36 | id: mLabel 37 | font.pointSize: 10 38 | padding: font.pixelSize * 0.5 39 | color: mAccentColor 40 | font.family: "Roboto" 41 | } 42 | 43 | Rectangle { 44 | anchors.bottom: parent.bottom 45 | width: parent.width 46 | height: parent.activeFocus || parent.hovered ? 2 : 1 47 | color: mAccentColor 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/frontend/components/InputLine.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Controls.Material 2.12 4 | 5 | 6 | TextField { 7 | property alias label: mLabel.text 8 | property string tooltipText: "" 9 | 10 | readonly property color mAccentColor: activeFocus 11 | ? Material.accentColor 12 | : (hovered ? Material.primaryTextColor : Material.hintTextColor) 13 | 14 | anchors.left: parent.left 15 | anchors.right: parent.right 16 | 17 | leftPadding: mLabel.leftPadding 18 | rightPadding: leftPadding 19 | topPadding: mLabel.height * 1.1 20 | bottomPadding: font.pixelSize * 0.25 21 | 22 | selectByMouse: true 23 | background: Rectangle { 24 | color: "#10000000" 25 | } 26 | 27 | ToolTip.text: tooltipText 28 | ToolTip.visible: tooltipText ? hovered : false 29 | ToolTip.delay: 500 30 | 31 | Label { 32 | id: mLabel 33 | font.pointSize: 10 34 | padding: font.pixelSize * 0.5 35 | bottomPadding: 0 36 | color: mAccentColor 37 | font.family: "Roboto" 38 | } 39 | 40 | Rectangle { 41 | anchors.bottom: parent.bottom 42 | width: parent.width 43 | height: parent.activeFocus || parent.hovered ? 2 : 1 44 | color: mAccentColor 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/frontend/components/InputLineNarrow.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Controls.Material 2.12 4 | import QtQuick.Layouts 1.12 5 | 6 | 7 | TextField { 8 | Layout.fillWidth: true 9 | 10 | topPadding: font.pixelSize * 0.3 11 | bottomPadding: topPadding 12 | leftPadding: font.pixelSize * 0.6 13 | rightPadding: leftPadding 14 | 15 | font.italic: !text 16 | 17 | selectByMouse: true 18 | background: Rectangle { 19 | color: "#10000000" 20 | } 21 | 22 | Rectangle { 23 | anchors.bottom: parent.bottom 24 | width: parent.width 25 | height: parent.activeFocus || parent.hovered ? 2 : 1 26 | color: parent.activeFocus 27 | ? Material.accentColor 28 | : (parent.hovered ? Material.primaryTextColor : Material.hintTextColor) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /src/frontend/components/MessageDialog.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Dialog { 5 | id: root 6 | 7 | property alias text: mText.text 8 | 9 | width: parent.width * 0.4 10 | anchors.centerIn: parent 11 | 12 | modal: true 13 | standardButtons: Dialog.Ok 14 | 15 | Label { 16 | id: mText 17 | width: root.width - root.leftPadding - root.rightPadding 18 | wrapMode: Text.Wrap 19 | horizontalAlignment: Text.AlignJustify 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /src/frontend/components/Panel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQuick.Controls 2.12 3 | import QtQuick.Layouts 1.12 4 | 5 | 6 | Frame { 7 | Layout.fillWidth: true 8 | 9 | leftPadding: 0 10 | rightPadding: 0 11 | topPadding: 0 12 | bottomPadding: 0 13 | 14 | background: Rectangle { 15 | color: '#fff' 16 | border.color: '#28000000' 17 | border.width: 1 18 | radius: 5 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/frontend/components/TinyLabel.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.12 2 | import QtQuick.Controls 2.12 3 | 4 | Label { 5 | font.pointSize: 10 6 | wrapMode: Text.Wrap 7 | } 8 | -------------------------------------------------------------------------------- /src/frontend/components/TinyMonoLabel.qml: -------------------------------------------------------------------------------- 1 | TinyLabel { 2 | font.family: "Monospace" 3 | } 4 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/ellipsis-v.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/file.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/folder-open.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/folder.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/save.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/frontend/icons/fa/search.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/frontend/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | main.qml 4 | ModelBox.qml 5 | CollectionEditor.qml 6 | icons/fa/search.svg 7 | icons/fa/file.svg 8 | icons/fa/folder.svg 9 | icons/fa/folder-open.svg 10 | icons/fa/ellipsis-v.svg 11 | icons/fa/save.svg 12 | components/Panel.qml 13 | components/InputLine.qml 14 | components/InputArea.qml 15 | components/InputLineNarrow.qml 16 | CollectionEditorRuleset.qml 17 | components/TinyLabel.qml 18 | components/FlatButton.qml 19 | GameEditor.qml 20 | components/BigLabel.qml 21 | StringListEditor.qml 22 | components/FancyToolButton.qml 23 | LoadDialog.qml 24 | SaveAsDialog.qml 25 | AboutDialog.qml 26 | WelcomeText.qml 27 | components/MessageDialog.qml 28 | EntryEditHelpText.qml 29 | components/TinyMonoLabel.qml 30 | components/CommandVarsHelp.qml 31 | components/CommandVarsLabel.qml 32 | 33 | 34 | -------------------------------------------------------------------------------- /src/main.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "Api.h" 19 | #include "FolderListModel.h" 20 | 21 | #include 22 | #include 23 | #include 24 | #include 25 | 26 | 27 | int main(int argc, char *argv[]) 28 | { 29 | QGuiApplication::setAttribute(Qt::AA_EnableHighDpiScaling); 30 | QGuiApplication app(argc, argv); 31 | 32 | 33 | Api api; 34 | qmlRegisterType("Pegasus.FolderListModel", 1, 0, "FolderListModel"); 35 | 36 | 37 | QQuickStyle::setStyle(QStringLiteral("Material")); 38 | 39 | QQmlApplicationEngine engine; 40 | engine.rootContext()->setContextProperty(QStringLiteral("Api"), &api); 41 | engine.load(QUrl(QStringLiteral("qrc:/main.qml"))); 42 | if (engine.rootObjects().isEmpty()) 43 | return -1; 44 | 45 | return app.exec(); 46 | } 47 | -------------------------------------------------------------------------------- /src/metaformat/Metafile.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "utils/MoveOnly.h" 21 | 22 | #include 23 | #include 24 | #include 25 | 26 | class QFile; 27 | class QTextStream; 28 | 29 | 30 | namespace metafile { 31 | 32 | struct Entry { 33 | size_t line; 34 | QString key; 35 | std::vector values; 36 | 37 | void reset(); 38 | MOVE_ONLY(Entry) 39 | }; 40 | struct Error { 41 | size_t line; 42 | QString message; 43 | 44 | MOVE_ONLY(Error) 45 | }; 46 | 47 | 48 | void read_stream(QTextStream& stream, 49 | const std::function& onAttributeFound, 50 | const std::function& onError); 51 | 52 | bool read_file(const QString& path, 53 | const std::function& onAttributeFound, 54 | const std::function& onError); 55 | 56 | void read_file(QFile& file, 57 | const std::function& onAttributeFound, 58 | const std::function& onError); 59 | 60 | } // namespace metafile 61 | -------------------------------------------------------------------------------- /src/metaformat/Metaformat.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "MetaformatErrorCB.h" 21 | #include "model/ModelData.h" 22 | 23 | #include 24 | #include 25 | 26 | 27 | namespace metaformat { 28 | struct Entries { 29 | std::vector games; 30 | std::vector collections; 31 | }; 32 | struct EntryRefs { 33 | std::vector games; 34 | std::vector collections; 35 | }; 36 | 37 | bool parse(const QString&, Entries&, ParseErrorCB); 38 | bool write(const QString&, const EntryRefs&, WriteErrorCB); 39 | } // namespace metaformat 40 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatAssets.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "MetaformatAssets.h" 19 | 20 | #include "MetaformatUtils.h" 21 | 22 | 23 | namespace { 24 | static const auto ASSET_PREFIX(QStringLiteral("assets.")); 25 | 26 | bool is_multiasset(const QString& asset_key) 27 | { 28 | return asset_key == QLatin1String("video") 29 | || asset_key == QLatin1String("videos") 30 | || asset_key == QLatin1String("screenshot") 31 | || asset_key == QLatin1String("screenshots"); 32 | } 33 | } // namespace 34 | 35 | 36 | namespace metaformat { 37 | bool parse_asset_entry_maybe(const metafile::Entry& entry, QVariantMap& assets, ParseErrorCB error_cb) 38 | { 39 | if (!entry.key.startsWith(ASSET_PREFIX)) 40 | return false; 41 | 42 | QString asset_key = entry.key.mid(ASSET_PREFIX.length()); 43 | QString asset_val; 44 | 45 | if (is_multiasset(asset_key)) { 46 | // TODO: reserve 47 | // join 48 | asset_val = entry.values.front(); 49 | for (auto it = ++entry.values.cbegin(); it != entry.values.cend(); ++it) { 50 | asset_val += QChar('\n'); 51 | asset_val += *it; 52 | } 53 | // pluralize 54 | if (!asset_key.endsWith(QChar('s'))) 55 | asset_key += QChar('s'); 56 | } 57 | else { 58 | asset_val = first_line_of(entry, error_cb); 59 | } 60 | 61 | assets.insert(asset_key, asset_val); 62 | return true; 63 | } 64 | 65 | QStringList render_assets(const QVariantMap& map) 66 | { 67 | QStringList out; 68 | 69 | for (auto it = map.cbegin(); it != map.cend(); ++it) 70 | out.append(ASSET_PREFIX + it.key() + QStringLiteral(": ") + it.value().toString()); 71 | 72 | return out; 73 | } 74 | } // namespace metaformat 75 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatAssets.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "Metafile.h" 21 | #include "MetaformatErrorCB.h" 22 | 23 | #include 24 | 25 | 26 | namespace metaformat { 27 | bool parse_asset_entry_maybe(const metafile::Entry&, QVariantMap&, ParseErrorCB); 28 | QStringList render_assets(const QVariantMap&); 29 | } // namespace metaformat 30 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatCollections.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "Metafile.h" 21 | #include "MetaformatErrorCB.h" 22 | #include "model/ModelData.h" 23 | 24 | 25 | namespace metaformat { 26 | modeldata::Collection new_collection(const metafile::Entry&, ParseErrorCB); 27 | void parse_collection_entry(const metafile::Entry&, modeldata::Collection&, ParseErrorCB); 28 | QString render_collection(const modeldata::Collection&, WriteErrorCB); 29 | } // namespace metaformat 30 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatErrorCB.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | 24 | namespace metaformat { 25 | using ParseErrorCB = const std::function&; 26 | using WriteErrorCB = const std::function&; 27 | } // namespace metaformat 28 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatGames.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "Metafile.h" 21 | #include "MetaformatErrorCB.h" 22 | #include "model/ModelData.h" 23 | 24 | 25 | namespace metaformat { 26 | modeldata::Game new_game(const metafile::Entry&, ParseErrorCB); 27 | void parse_game_entry(const metafile::Entry&, modeldata::Game&, ParseErrorCB); 28 | QString render_game(const modeldata::Game&, WriteErrorCB); 29 | } // namespace metaformat 30 | -------------------------------------------------------------------------------- /src/metaformat/MetaformatUtils.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "MetaformatUtils.h" 19 | 20 | #include 21 | 22 | 23 | namespace { 24 | int qstrlen_accumulator(const int acc, const QString& str) 25 | { 26 | return acc + str.length(); 27 | } 28 | } // namespace 29 | 30 | 31 | namespace metaformat { 32 | QString first_line_of(const metafile::Entry& entry, ParseErrorCB error_cb) { 33 | Q_ASSERT(!entry.key.isEmpty()); 34 | Q_ASSERT(!entry.values.empty()); 35 | 36 | if (entry.values.size() > 1) { 37 | error_cb(entry.line, 38 | QStringLiteral("expected single line value for `%1` but got more. " 39 | "The rest of the lines will be ignored.").arg(entry.key)); 40 | } 41 | 42 | return entry.values.front(); 43 | }; 44 | 45 | QString join(const std::vector& vec) 46 | { 47 | if (vec.empty()) 48 | return QString(); 49 | 50 | const int newline_cnt = static_cast(vec.size()) - 1; 51 | const int out_len = std::accumulate(vec.cbegin(), vec.cend(), newline_cnt, qstrlen_accumulator); 52 | 53 | QString out(vec.front()); 54 | out.reserve(out_len); 55 | 56 | for (auto it = ++vec.cbegin(); it != vec.cend(); ++it) { 57 | out.append(QChar('\n')); 58 | out.append(*it); 59 | } 60 | 61 | return out; 62 | } 63 | } // namespace metaformat 64 | -------------------------------------------------------------------------------- /src/metaformat/metaformat.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/Metafile.h \ 3 | $$PWD/Metaformat.h \ 4 | $$PWD/MetaformatAssets.h \ 5 | $$PWD/MetaformatCollections.h \ 6 | $$PWD/MetaformatErrorCB.h \ 7 | $$PWD/MetaformatGames.h \ 8 | $$PWD/MetaformatUtils.h 9 | 10 | SOURCES += \ 11 | $$PWD/Metafile.cpp \ 12 | $$PWD/Metaformat.cpp \ 13 | $$PWD/MetaformatAssets.cpp \ 14 | $$PWD/MetaformatCollections.cpp \ 15 | $$PWD/MetaformatGames.cpp \ 16 | $$PWD/MetaformatUtils.cpp 17 | -------------------------------------------------------------------------------- /src/model/Model.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "Model.h" 19 | 20 | 21 | #define BIND_MODEL_PTR(field) \ 22 | connect(&m_##field, &StringListModel::dataChanged, \ 23 | this, [this](){ m_data->field = m_##field.stringList(); }); \ 24 | connect(&m_##field, &StringListModel::rowsRemoved, \ 25 | this, [this](){ m_data->field = m_##field.stringList(); }); 26 | 27 | #define BIND_MODEL(field) \ 28 | connect(&m_##field, &StringListModel::dataChanged, \ 29 | this, [this](){ m_data.field = m_##field.stringList(); }); \ 30 | connect(&m_##field, &StringListModel::rowsRemoved, \ 31 | this, [this](){ m_data.field = m_##field.stringList(); }); 32 | 33 | 34 | namespace model { 35 | 36 | CollectionFilter::CollectionFilter(modeldata::CollectionFilter* const data, QObject* parent) 37 | : QObject(parent) 38 | , m_data(data) 39 | , m_extensions(m_data->extensions) 40 | , m_files(m_data->files) 41 | { 42 | Q_ASSERT(m_data); 43 | BIND_MODEL_PTR(extensions) 44 | BIND_MODEL_PTR(files) 45 | } 46 | 47 | 48 | Collection::Collection(modeldata::Collection data, QObject* parent) 49 | : QObject(parent) 50 | , m_data(std::move(data)) 51 | , m_directories(m_data.directories) 52 | , m_include(&m_data.include) 53 | , m_exclude(&m_data.exclude) 54 | { 55 | BIND_MODEL(directories) 56 | } 57 | 58 | 59 | Game::Game(modeldata::Game data, QObject* parent) 60 | : QObject(parent) 61 | , m_data(std::move(data)) 62 | , m_developers(m_data.developers) 63 | , m_publishers(m_data.publishers) 64 | , m_genres(m_data.genres) 65 | , m_files(m_data.files) 66 | { 67 | BIND_MODEL(developers) 68 | BIND_MODEL(publishers) 69 | BIND_MODEL(genres) 70 | BIND_MODEL(files) 71 | } 72 | 73 | } // namespace model 74 | -------------------------------------------------------------------------------- /src/model/ModelData.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "ModelData.h" 19 | 20 | 21 | namespace modeldata { 22 | 23 | CollectionFilter::CollectionFilter() = default; 24 | Collection::Collection() = default; 25 | 26 | Game::Game() 27 | : rating(0.0) 28 | , max_players(1) 29 | , release_year(0) 30 | , release_month(0) 31 | , release_day(0) 32 | {} 33 | 34 | } // namespace modeldata 35 | -------------------------------------------------------------------------------- /src/model/ModelData.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include "utils/MoveOnly.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | 28 | namespace modeldata { 29 | 30 | struct CollectionFilter { 31 | QStringList extensions; 32 | QStringList files; 33 | QString regex; 34 | 35 | CollectionFilter(); 36 | MOVE_ONLY(CollectionFilter) 37 | }; 38 | 39 | struct Collection { 40 | QString name; 41 | QString shortname; 42 | QString summary; 43 | QString description; 44 | QString sortby; 45 | 46 | QStringList directories; 47 | CollectionFilter include; 48 | CollectionFilter exclude; 49 | 50 | QString launch_cmd; 51 | QString launch_workdir; 52 | 53 | QVariantMap assets; 54 | QVariantMap extra; 55 | 56 | Collection(); 57 | MOVE_ONLY(Collection) 58 | }; 59 | 60 | struct Game { 61 | QString title; 62 | QString summary; 63 | QString description; 64 | QString sortby; 65 | 66 | QString launch_cmd; 67 | QString launch_workdir; 68 | 69 | float rating; 70 | int max_players; 71 | int release_year; 72 | int release_month; 73 | int release_day; 74 | 75 | QStringList developers; 76 | QStringList publishers; 77 | QStringList genres; 78 | 79 | QStringList files; 80 | QVariantMap assets; 81 | QVariantMap extra; 82 | 83 | Game(); 84 | MOVE_ONLY(Game) 85 | }; 86 | 87 | } // namespace modeldata 88 | -------------------------------------------------------------------------------- /src/model/model.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/Model.h \ 3 | $$PWD/ModelData.h \ 4 | 5 | SOURCES += \ 6 | $$PWD/Model.cpp \ 7 | $$PWD/ModelData.cpp \ 8 | -------------------------------------------------------------------------------- /src/platform/android/res/drawable-hdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-hdpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable-ldpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-ldpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable-mdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-mdpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable-xhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-xhdpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable-xxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-xxhdpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable-xxxhdpi/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable-xxxhdpi/icon.png -------------------------------------------------------------------------------- /src/platform/android/res/drawable/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/android/res/drawable/banner.png -------------------------------------------------------------------------------- /src/platform/android/src/org/pegasus_frontend/metaed/MainActivity.java: -------------------------------------------------------------------------------- 1 | package org.pegasus_frontend.metaed; 2 | 3 | import android.content.Context; 4 | import java.io.File; 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | 9 | public class MainActivity extends org.qtproject.qt5.android.bindings.QtActivity { 10 | private static Context m_context; 11 | 12 | @Override 13 | protected void onStart() { 14 | super.onStart(); 15 | m_context = this; 16 | } 17 | 18 | public static String[] sdcardPaths() { 19 | final String android_subdir = "/Android/data/"; 20 | 21 | ArrayList paths = new ArrayList(); 22 | for (File file : m_context.getExternalFilesDirs(null)) { 23 | if (file == null) 24 | continue; 25 | 26 | final String abs_full_path = file.getAbsolutePath(); 27 | final int substr_until = abs_full_path.indexOf(android_subdir); 28 | if (substr_until < 0) 29 | continue; 30 | 31 | final String abs_path = abs_full_path.substring(0, substr_until); 32 | paths.add(abs_path); 33 | } 34 | return paths.toArray(new String[paths.size()]); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/platform/macos/Info.plist.in: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleExecutable${EXECUTABLE_NAME} 6 | CFBundleGetInfoStringCreated by Qt/QMake 7 | CFBundleIconFile${ASSETCATALOG_COMPILER_APPICON_NAME} 8 | CFBundleIdentifierorg.pegasus-frontend.metaed.macos 9 | CFBundlePackageTypeAPPL 10 | CFBundleSignature${QMAKE_PKGINFO_TYPEINFO} 11 | LSMinimumSystemVersion${MACOSX_DEPLOYMENT_TARGET} 12 | LSApplicationCategoryTypepublic.app-category.games 13 | LSUIPresentationMode4 14 | NSPrincipalClassNSApplication 15 | NSHumanReadableCopyrightCopyright (c) 2017-2019 Mátyás Mustoha 16 | NSSupportsAutomaticGraphicsSwitching 17 | NSHighResolutionCapable 18 | 19 | 20 | -------------------------------------------------------------------------------- /src/platform/macos/appicons.icns: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/macos/appicons.icns -------------------------------------------------------------------------------- /src/platform/windows/app_icon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/mmatyas/pegasus-metadata-editor/c09792dc910574eaf3397a9e9837d0eb0d75fdee/src/platform/windows/app_icon.ico -------------------------------------------------------------------------------- /src/src.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = pegasus-metaed 3 | 4 | QT += quick quickcontrols2 svg 5 | CONFIG += c++11 qtquickcompiler warn_on 6 | 7 | DEFINES += \ 8 | QT_DEPRECATED_WARNINGS \ 9 | QT_DISABLE_DEPRECATED_BEFORE=0x050C00 \ 10 | QT_NO_CAST_TO_ASCII \ 11 | GIT_REVISION=\\\"$${GIT_REVISION}\\\" \ 12 | GIT_DATE=\\\"$${GIT_DATE}\\\" 13 | 14 | HEADERS += \ 15 | Api.h \ 16 | FolderListModel.h \ 17 | 18 | SOURCES += \ 19 | Api.cpp \ 20 | main.cpp \ 21 | FolderListModel.cpp \ 22 | 23 | RESOURCES += frontend/qml.qrc 24 | OTHER_FILES += ../.qmake.conf 25 | 26 | 27 | include(utils/utils.pri) 28 | include(model/model.pri) 29 | include(metaformat/metaformat.pri) 30 | include(../thirdparty/thirdparty.pri) 31 | 32 | 33 | LONGNAME=pegasus-metadata-editor 34 | 35 | unix:!android:!macx { 36 | target.path = /opt/$${LONGNAME}/ 37 | } 38 | android { 39 | QT += androidextras 40 | 41 | SOURCES += AndroidHelpers.cpp 42 | HEADERS += AndroidHelpers.h 43 | 44 | OTHER_FILES += \ 45 | platform/android/AndroidManifest.xml \ 46 | platform/android/res/drawable/banner.png \ 47 | platform/android/res/drawable-ldpi/icon.png \ 48 | platform/android/res/drawable-mdpi/icon.png \ 49 | platform/android/res/drawable-hdpi/icon.png \ 50 | platform/android/res/drawable-xhdpi/icon.png \ 51 | platform/android/res/drawable-xxhdpi/icon.png \ 52 | platform/android/res/drawable-xxxhdpi/icon.png \ 53 | platform/android/src/org/pegasus_frontend/metaed/MainActivity.java \ 54 | 55 | ANDROID_PACKAGE_SOURCE_DIR = $$PWD/platform/android 56 | } 57 | win32 { 58 | QMAKE_TARGET_PRODUCT = "pegasus-metadata-editor" 59 | QMAKE_TARGET_COMPANY = "pegasus-frontend.org" 60 | QMAKE_TARGET_DESCRIPTION = "Metadata Editor for the Pegasus frontend" 61 | QMAKE_TARGET_COPYRIGHT = "Copyright (c) 2017-2019 Matyas Mustoha" 62 | RC_ICONS = platform/windows/app_icon.ico 63 | OTHER_FILES += $${RC_ICONS} 64 | 65 | target.path = C:/$${LONGNAME}/ 66 | } 67 | macx { 68 | ICON = platform/macos/appicons.icns 69 | QMAKE_APPLICATION_BUNDLE_NAME = "Pegasus Metadata Editor" 70 | QMAKE_TARGET_BUNDLE_PREFIX = org.pegasus-frontend 71 | QMAKE_INFO_PLIST = platform/macos/Info.plist.in 72 | 73 | target.path = /usr/local/$${LONGNAME}/ 74 | } 75 | 76 | !isEmpty(target.path): INSTALLS += target 77 | -------------------------------------------------------------------------------- /src/utils/MoveOnly.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #define MOVE_ONLY(T) \ 21 | T(const T&) = delete; \ 22 | T& operator=(const T&) = delete; \ 23 | T(T&&) = default; \ 24 | T& operator=(T&&) = default; 25 | -------------------------------------------------------------------------------- /src/utils/StdHelpers.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include 21 | #include 22 | 23 | 24 | #define VEC_SORT(vec) \ 25 | std::sort(vec.begin(), vec.end()) 26 | 27 | #define VEC_REMOVE_DUPLICATES(vec) \ 28 | VEC_SORT(vec); \ 29 | vec.erase(std::unique(vec.begin(), vec.end()), vec.end()) 30 | 31 | #define VEC_REMOVE_VALUE(vec, val) \ 32 | vec.erase(std::remove(vec.begin(), vec.end(), val), vec.end()) 33 | 34 | #define VEC_CONTAINS(vec, val) \ 35 | (std::find(vec.cbegin(), vec.cend(), val) != vec.cend()) 36 | 37 | 38 | template 39 | typename List1::iterator vec_append_move(List1& dest, List2&& src) 40 | { 41 | typename List1::iterator result = dest.insert( 42 | dest.end(), 43 | std::make_move_iterator(src.begin()), 44 | std::make_move_iterator(src.end())); 45 | src.clear(); 46 | return result; 47 | } 48 | 49 | template 50 | typename List1::iterator vec_append_copy(List1& dest, const List2& src) 51 | { 52 | return dest.insert(dest.end(), src.cbegin(), src.cend()); 53 | } 54 | -------------------------------------------------------------------------------- /src/utils/StringListModel.cpp: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #include "StringListModel.h" 19 | 20 | 21 | StringListModel::StringListModel(const QStringList& data, QObject *parent) 22 | : QStringListModel(data, parent) 23 | {} 24 | 25 | void StringListModel::create() 26 | { 27 | insertRow(rowCount()); 28 | } 29 | 30 | void StringListModel::append(QString str) 31 | { 32 | create(); 33 | const QModelIndex idx = index(rowCount() - 1); 34 | setData(idx, str); 35 | } 36 | 37 | void StringListModel::remove(int idx) 38 | { 39 | removeRow(idx); 40 | } 41 | -------------------------------------------------------------------------------- /src/utils/StringListModel.h: -------------------------------------------------------------------------------- 1 | // Pegasus Metadata Editor 2 | // Copyright (C) 2017-2019 Mátyás Mustoha 3 | // 4 | // This program is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | // 9 | // This program is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | // 14 | // You should have received a copy of the GNU General Public License 15 | // along with this program. If not, see . 16 | 17 | 18 | #pragma once 19 | 20 | #include 21 | 22 | 23 | class StringListModel : public QStringListModel { 24 | Q_OBJECT 25 | 26 | public: 27 | explicit StringListModel(const QStringList& data, QObject* parent = nullptr); 28 | 29 | Q_INVOKABLE void create(); 30 | Q_INVOKABLE void append(QString str); 31 | Q_INVOKABLE void remove(int idx); 32 | }; 33 | -------------------------------------------------------------------------------- /src/utils/utils.pri: -------------------------------------------------------------------------------- 1 | HEADERS += \ 2 | $$PWD/MoveOnly.h \ 3 | $$PWD/StdHelpers.h \ 4 | $$PWD/StringListModel.h \ 5 | 6 | SOURCES += \ 7 | $$PWD/StringListModel.cpp \ 8 | -------------------------------------------------------------------------------- /thirdparty/QtQmlTricks/LICENSE.md: -------------------------------------------------------------------------------- 1 | How can I use this ? 2 | 3 | Well, license here is pretty "super-open", not even copy-left or copy-right, 4 | basically its close to the WTFPL, just use it as you want, 5 | as it's the most practical to you : 6 | 7 | * if you want to use it as GIT submodule and compile it in your app, do it ; 8 | * if you prefer separate project as a shared library, do it ; 9 | * if you need to modify the project to be able to integrate in you app (opensource or not), do it ; 10 | * if you want to share you work on the library, thanks a lot, but if you don't, no problem ; 11 | * if you think about some weird case I didn't talk about, well, do whatever you want, I don't need to know about it ; 12 | * if you like it so much you want to spread the word, thank you, you're welcome. 13 | 14 | Enjoy ! -------------------------------------------------------------------------------- /thirdparty/QtQmlTricks/QtQmlTricks.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | 3 | HEADERS += $$PWD/QQmlObjectListModel.h 4 | SOURCES += $$PWD/QQmlObjectListModel.cpp 5 | -------------------------------------------------------------------------------- /thirdparty/QtQmlTricks/README.md: -------------------------------------------------------------------------------- 1 | Qt QML Models 2 | ============= 3 | 4 | Additional data models aimed to bring more power to QML applications by using useful C++ models in back-end. 5 | 6 | * `QQmlObjectListModel` : a much nicer way to expose C++ list to QML than the quick & dirty `QList` property . Supports all the strong model features of `QAbstractListModel` while showing the simple and well know API of QList. 7 | 8 | * `QQmlVariantListModel` : a dead-simple way to create a dynamic C++ list of any type and expose it to QML, way better than using a `QVariantList` property. 9 | 10 | > NOTE : If you want to donate, use this link : [![Flattr this](http://api.flattr.com/button/flattr-badge-large.png)](https://flattr.com/submit/auto?user_id=thebootroo&url=http://gitlab.unique-conception.org/qt-qml-tricks/qt-qml-models) 11 | -------------------------------------------------------------------------------- /thirdparty/README.md: -------------------------------------------------------------------------------- 1 | # Third-party libraries 2 | 3 | - **QtQmlTricks**: the SmartDataModels component, based on `http://gitlab.unique-conception.org/qt-qml-tricks/qt-qml-models`, commit `abd8617e` 4 | - **SortFilterProxyModel**: based on `https://github.com/oKcerG/SortFilterProxyModel` 5 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/.gitignore: -------------------------------------------------------------------------------- 1 | # This file is used to ignore files which are generated 2 | # ---------------------------------------------------------------------------- 3 | 4 | *~ 5 | *.autosave 6 | *.a 7 | *.core 8 | *.moc 9 | *.o 10 | *.obj 11 | *.orig 12 | *.rej 13 | *.so 14 | *.so.* 15 | *_pch.h.cpp 16 | *_resource.rc 17 | *.qm 18 | .#* 19 | *.*# 20 | core 21 | !core/ 22 | tags 23 | .DS_Store 24 | .directory 25 | *.debug 26 | Makefile* 27 | *.prl 28 | *.app 29 | moc_*.cpp 30 | ui_*.h 31 | qrc_*.cpp 32 | *.qmlc 33 | Thumbs.db 34 | *.res 35 | *.rc 36 | /.qmake.cache 37 | /.qmake.stash 38 | 39 | # qtcreator generated files 40 | *.pro.user* 41 | 42 | # qtcreator shadow builds 43 | build-SortFilterProxyModel-* 44 | 45 | # xemacs temporary files 46 | *.flc 47 | 48 | # Vim temporary files 49 | .*.swp 50 | 51 | # Visual Studio generated files 52 | *.ib_pdb_index 53 | *.idb 54 | *.ilk 55 | *.pdb 56 | *.sln 57 | *.suo 58 | *.vcproj 59 | *vcproj.*.*.user 60 | *.ncb 61 | *.sdf 62 | *.opensdf 63 | *.vcxproj 64 | *vcxproj.* 65 | 66 | # MinGW generated files 67 | *.Debug 68 | *.Release 69 | 70 | # Python byte code 71 | *.pyc 72 | 73 | # Binaries 74 | # -------- 75 | *.dll 76 | *.exe 77 | 78 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.1) 2 | 3 | set(CMAKE_CXX_STANDARD 11) 4 | 5 | find_package(Qt5 REQUIRED 6 | Core 7 | Qml 8 | ) 9 | 10 | set(CMAKE_AUTOMOC ON) 11 | set(CMAKE_INCLUDE_CURRENT_DIR ON) # This is to find generated *.moc and *.h files in build dir 12 | 13 | add_library(SortFilterProxyModel OBJECT 14 | qqmlsortfilterproxymodel.cpp 15 | filters/filter.cpp 16 | filters/filtercontainer.cpp 17 | filters/rolefilter.cpp 18 | filters/valuefilter.cpp 19 | filters/indexfilter.cpp 20 | filters/regexpfilter.cpp 21 | filters/rangefilter.cpp 22 | filters/expressionfilter.cpp 23 | filters/filtercontainerfilter.cpp 24 | filters/anyoffilter.cpp 25 | filters/alloffilter.cpp 26 | filters/filtersqmltypes.cpp 27 | sorters/sorter.cpp 28 | sorters/sortercontainer.cpp 29 | sorters/rolesorter.cpp 30 | sorters/stringsorter.cpp 31 | sorters/expressionsorter.cpp 32 | sorters/sortersqmltypes.cpp 33 | proxyroles/proxyrole.cpp 34 | proxyroles/proxyrolecontainer.cpp 35 | proxyroles/joinrole.cpp 36 | proxyroles/switchrole.cpp 37 | proxyroles/expressionrole.cpp 38 | proxyroles/proxyrolesqmltypes.cpp 39 | proxyroles/singlerole.cpp 40 | proxyroles/regexprole.cpp 41 | sorters/filtersorter.cpp 42 | proxyroles/filterrole.cpp 43 | ) 44 | 45 | target_include_directories(SortFilterProxyModel PUBLIC 46 | ${CMAKE_CURRENT_LIST_DIR} 47 | $ 48 | $ 49 | ) 50 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | Copyright (c) 2016 Pierre-Yves Siret 3 | 4 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 5 | 6 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 7 | 8 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/SortFilterProxyModel.pri: -------------------------------------------------------------------------------- 1 | !contains( CONFIG, c\+\+1[14] ): warning("SortFilterProxyModel needs at least c++11, add CONFIG += c++11 to your .pro") 2 | 3 | INCLUDEPATH += $$PWD 4 | 5 | HEADERS += $$PWD/qqmlsortfilterproxymodel.h \ 6 | $$PWD/filters/filter.h \ 7 | $$PWD/filters/filtercontainer.h \ 8 | $$PWD/filters/rolefilter.h \ 9 | $$PWD/filters/valuefilter.h \ 10 | $$PWD/filters/indexfilter.h \ 11 | $$PWD/filters/regexpfilter.h \ 12 | $$PWD/filters/rangefilter.h \ 13 | $$PWD/filters/expressionfilter.h \ 14 | $$PWD/filters/filtercontainerfilter.h \ 15 | $$PWD/filters/filtersqmltypes.h \ 16 | $$PWD/filters/anyoffilter.h \ 17 | $$PWD/filters/alloffilter.h \ 18 | $$PWD/sorters/sorter.h \ 19 | $$PWD/sorters/sortercontainer.h \ 20 | $$PWD/sorters/rolesorter.h \ 21 | $$PWD/sorters/stringsorter.h \ 22 | $$PWD/sorters/expressionsorter.h \ 23 | $$PWD/sorters/sortersqmltypes.h \ 24 | $$PWD/proxyroles/proxyrole.h \ 25 | $$PWD/proxyroles/proxyrolecontainer.h \ 26 | $$PWD/proxyroles/joinrole.h \ 27 | $$PWD/proxyroles/switchrole.h \ 28 | $$PWD/proxyroles/expressionrole.h \ 29 | $$PWD/proxyroles/singlerole.h \ 30 | $$PWD/proxyroles/regexprole.h \ 31 | $$PWD/sorters/filtersorter.h \ 32 | $$PWD/proxyroles/filterrole.h \ 33 | $$PWD/proxyroles/proxyrolesqmltypes.h 34 | 35 | SOURCES += $$PWD/qqmlsortfilterproxymodel.cpp \ 36 | $$PWD/filters/filter.cpp \ 37 | $$PWD/filters/filtercontainer.cpp \ 38 | $$PWD/filters/rolefilter.cpp \ 39 | $$PWD/filters/valuefilter.cpp \ 40 | $$PWD/filters/indexfilter.cpp \ 41 | $$PWD/filters/regexpfilter.cpp \ 42 | $$PWD/filters/rangefilter.cpp \ 43 | $$PWD/filters/expressionfilter.cpp \ 44 | $$PWD/filters/filtercontainerfilter.cpp \ 45 | $$PWD/filters/anyoffilter.cpp \ 46 | $$PWD/filters/alloffilter.cpp \ 47 | $$PWD/filters/filtersqmltypes.cpp \ 48 | $$PWD/sorters/sorter.cpp \ 49 | $$PWD/sorters/sortercontainer.cpp \ 50 | $$PWD/sorters/rolesorter.cpp \ 51 | $$PWD/sorters/stringsorter.cpp \ 52 | $$PWD/sorters/expressionsorter.cpp \ 53 | $$PWD/sorters/sortersqmltypes.cpp \ 54 | $$PWD/proxyroles/proxyrole.cpp \ 55 | $$PWD/proxyroles/proxyrolecontainer.cpp \ 56 | $$PWD/proxyroles/joinrole.cpp \ 57 | $$PWD/proxyroles/switchrole.cpp \ 58 | $$PWD/proxyroles/expressionrole.cpp \ 59 | $$PWD/proxyroles/proxyrolesqmltypes.cpp \ 60 | $$PWD/proxyroles/singlerole.cpp \ 61 | $$PWD/proxyroles/regexprole.cpp \ 62 | $$PWD/sorters/filtersorter.cpp \ 63 | $$PWD/proxyroles/filterrole.cpp 64 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-allof-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for AllOf | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for AllOf

13 |

This is the complete list of members for AllOf, including inherited members.

14 |

The following members are inherited from Filter.

15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-allof.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | AllOf QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 19 |

AllOf QML Type

20 | 21 | 22 |

Filter container accepting rows accepted by all its child filters More...

23 | 24 |
25 |
Import Statement: import .
Inherits:

Filter

26 |
29 | 30 | 31 |

Detailed Description

32 |

The AllOf type is a Filter container that accepts rows if all of its contained (and enabled) filters accept them, or if it has no filter.

33 |

Using it as a top level filter has the same effect as putting all its child filters as top level filters. It can however be usefull to use an AllOf filter when nested in an AnyOf filter.

34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-anyof-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for AnyOf | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for AnyOf

13 |

This is the complete list of members for AnyOf, including inherited members.

14 |

The following members are inherited from Filter.

15 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-anyof.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | AnyOf QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 19 |

AnyOf QML Type

20 | 21 | 22 |

Filter container accepting rows accepted by at least one of its child filters More...

23 | 24 |
25 |
Import Statement: import .
Inherits:

Filter

26 |
29 | 30 | 31 |

Detailed Description

32 |

The AnyOf type is a Filter container that accepts rows if any of its contained (and enabled) filters accept them.

33 |

In the following example, only the rows where the firstName role or the lastName role match the text entered in the nameTextField will be accepted :

34 |
TextField {
35 |   id: nameTextField
36 | }
37 | 
38 | SortFilterProxyModel {
39 |   sourceModel: contactModel
40 |   filters: AnyOf {
41 |       RegExpFilter {
42 |           roleName: "lastName"
43 |           pattern: nameTextField.text
44 |           caseSensitivity: Qt.CaseInsensitive
45 |       }
46 |       RegExpFilter {
47 |           roleName: "firstName"
48 |           pattern: nameTextField.text
49 |           caseSensitivity: Qt.CaseInsensitive
50 |       }
51 |   }
52 | }
53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-expressionfilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for ExpressionFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for ExpressionFilter

13 |

This is the complete list of members for ExpressionFilter, including inherited members.

14 | 17 |

The following members are inherited from Filter.

18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-expressionrole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for ExpressionRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for ExpressionRole

13 |

This is the complete list of members for ExpressionRole, including inherited members.

14 | 17 |

The following members are inherited from SingleRole.

18 |
    19 |
  • name : string
  • 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-expressionsorter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for ExpressionSorter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for ExpressionSorter

13 |

This is the complete list of members for ExpressionSorter, including inherited members.

14 | 17 |

The following members are inherited from Sorter.

18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-filter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for Filter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for Filter

13 |

This is the complete list of members for Filter, including inherited members.

14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-filterrole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for FilterRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for FilterRole

13 |

This is the complete list of members for FilterRole, including inherited members.

14 | 17 |

The following members are inherited from SingleRole.

18 |
    19 |
  • name : string
  • 20 |
21 | 22 | 23 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-filterrole.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FilterRole QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 20 |

FilterRole QML Type

21 | 22 | 23 |

A role resolving to true for rows matching all its filters More...

24 | 25 |
26 |
Import Statement: import .
Inherits:

SingleRole

27 |
30 | 31 |

Properties

32 | 35 | 36 | 37 |

Detailed Description

38 |

A FilterRole is a ProxyRole that returns true for rows matching all its filters.

39 |

In the following example, the isAdult role will be equal to true if the age role is superior or equal to 18.

40 |
SortFilterProxyModel {
41 |     sourceModel: personModel
42 |     proxyRoles: FilterRole {
43 |         name: "isAdult"
44 |         RangeFilter { roleName: "age"; minimumValue: 18; minimumInclusive: true }
45 |     }
46 | }
47 | 48 |

Property Documentation

49 | 50 |
51 |
52 | 53 | 55 |

54 | filters : string

56 |

This property holds the list of filters for this filter role. The data of this role will be equal to the true if all its filters match the model row, false otherwise.

57 |

See also Filter.

58 |
59 |
60 | 61 | 62 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-filtersorter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for FilterSorter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for FilterSorter

13 |

This is the complete list of members for FilterSorter, including inherited members.

14 | 17 |

The following members are inherited from Sorter.

18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-filtersorter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | FilterSorter QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 20 |

FilterSorter QML Type

21 | 22 | 23 |

Sorts rows based on if they match filters More...

24 | 25 |
26 |
Import Statement: import .
Inherits:

Sorter

27 |
30 | 31 |

Properties

32 | 35 | 36 | 37 |

Detailed Description

38 |

A FilterSorter is a Sorter that orders row matching its filters before the rows not matching the filters.

39 |

In the following example, rows with their favorite role set to true will be ordered at the beginning :

40 |
SortFilterProxyModel {
41 |     sourceModel: contactModel
42 |     sorters: FilterSorter {
43 |         ValueFilter { roleName: "favorite"; value: true }
44 |     }
45 | }
46 | 47 |

Property Documentation

48 | 49 |
50 |
51 | 52 | 54 |

53 | filters : string

55 |

This property holds the list of filters for this filter sorter. If a row match all this FilterSorter's filters, it will be ordered before rows not matching all the filters.

56 |

See also Filter.

57 |
58 |
59 | 60 | 61 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-indexfilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for IndexFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for IndexFilter

13 |

This is the complete list of members for IndexFilter, including inherited members.

14 | 18 |

The following members are inherited from Filter.

19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-joinrole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for JoinRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for JoinRole

13 |

This is the complete list of members for JoinRole, including inherited members.

14 | 18 |

The following members are inherited from SingleRole.

19 |
    20 |
  • name : string
  • 21 |
22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-proxyrole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for ProxyRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for ProxyRole

13 |

This is the complete list of members for ProxyRole, including inherited members.

14 | 15 | 16 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-proxyrole.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | ProxyRole QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 19 |

ProxyRole QML Type

20 | 21 | 22 |

Base type for the SortFilterProxyModel proxy roles More...

23 | 24 |
25 |
Import Statement: import .
Inherited By:

RegExpRole and SingleRole

26 |
29 | 30 | 31 |

Detailed Description

32 |

The ProxyRole type cannot be used directly in a QML file. It exists to provide a set of common properties and methods, available across all the other proxy role types that inherit from it. Attempting to use the ProxyRole type directly will result in an error.

33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-rangefilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for RangeFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for RangeFilter

13 |

This is the complete list of members for RangeFilter, including inherited members.

14 | 21 |

The following members are inherited from Filter.

22 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-regexpfilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for RegExpFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for RegExpFilter

13 |

This is the complete list of members for RegExpFilter, including inherited members.

14 | 20 |

The following members are inherited from Filter.

21 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-regexprole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for RegExpRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for RegExpRole

13 |

This is the complete list of members for RegExpRole, including inherited members.

14 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-rolefilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for RoleFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for RoleFilter

13 |

This is the complete list of members for RoleFilter, including inherited members.

14 | 17 |

The following members are inherited from Filter.

18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-rolefilter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | RoleFilter QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 20 |

RoleFilter QML Type

21 | 22 | 23 |

Base type for filters based on a source model role More...

24 | 25 |
26 |
Import Statement: import .
Inherits:

Filter

27 |
Inherited By:

RangeFilter, RegExpFilter, and ValueFilter

28 |
31 | 32 |

Properties

33 | 36 | 37 | 38 |

Detailed Description

39 |

The RoleFilter type cannot be used directly in a QML file. It exists to provide a set of common properties and methods, available across all the other filter types that inherit from it. Attempting to use the RoleFilter type directly will result in an error.

40 | 41 |

Property Documentation

42 | 43 |
44 |
45 | 46 | 48 |

47 | roleName : string

49 |

This property holds the role name that the filter is using to query the source model's data when filtering items.

50 |
51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-rolesorter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for RoleSorter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for RoleSorter

13 |

This is the complete list of members for RoleSorter, including inherited members.

14 | 17 |

The following members are inherited from Sorter.

18 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-rolesorter.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | RoleSorter QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 20 |

RoleSorter QML Type

21 | 22 | 23 |

Sorts rows based on a source model role More...

24 | 25 |
26 |
Import Statement: import .
Inherits:

Sorter

27 |
Inherited By:

StringSorter

28 |
31 | 32 |

Properties

33 | 36 | 37 | 38 |

Detailed Description

39 |

A RoleSorter is a simple Sorter that sorts rows based on a source model role.

40 |

In the following example, rows with be sorted by their lastName role :

41 |
SortFilterProxyModel {
42 |    sourceModel: contactModel
43 |    sorters: RoleSorter { roleName: "lastName" }
44 | }
45 | 46 |

Property Documentation

47 | 48 |
49 |
50 | 51 | 53 |

52 | roleName : string

54 |

This property holds the role name that the sorter is using to query the source model's data when sorting items.

55 |
56 |
57 | 58 | 59 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-singlerole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for SingleRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for SingleRole

13 |

This is the complete list of members for SingleRole, including inherited members.

14 |
    15 |
  • name : string
  • 16 |
17 | 18 | 19 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-singlerole.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | SingleRole QML Type | SortFilterProxyModel 8 | 9 | 10 | 11 | 20 |

SingleRole QML Type

21 | 22 | 23 |

Base type for the SortFilterProxyModel proxy roles defining a single role More...

24 | 25 |
26 |
Import Statement: import .
Inherits:

ProxyRole

27 |
Inherited By:

ExpressionRole, FilterRole, JoinRole, and SwitchRole

28 |
31 | 32 |

Properties

33 |
    34 |
  • name : string
  • 35 |
36 | 37 | 38 |

Detailed Description

39 |

SingleRole is a convenience base class for proxy roles who define a single role. It cannot be used directly in a QML file. It exists to provide a set of common properties and methods, available across all the other proxy role types that inherit from it. Attempting to use the SingleRole type directly will result in an error.

40 | 41 |

Property Documentation

42 | 43 |
44 |
45 | 46 | 48 |

47 | name : string

49 |

This property holds the role name of the proxy role.

50 |
51 |
52 | 53 | 54 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-sorter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for Sorter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for Sorter

13 |

This is the complete list of members for Sorter, including inherited members.

14 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-sortfilterproxymodel-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for SortFilterProxyModel | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for SortFilterProxyModel

13 |

This is the complete list of members for SortFilterProxyModel, including inherited members.

14 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-stringsorter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for StringSorter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for StringSorter

13 |

This is the complete list of members for StringSorter, including inherited members.

14 | 20 |

The following members are inherited from RoleSorter.

21 | 24 |

The following members are inherited from Sorter.

25 | 29 | 30 | 31 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-switchrole-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for SwitchRole | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for SwitchRole

13 |

This is the complete list of members for SwitchRole, including inherited members.

14 | 20 |

The following members are inherited from SingleRole.

21 |
    22 |
  • name : string
  • 23 |
24 | 25 | 26 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/docs/qml-valuefilter-members.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | List of All Members for ValueFilter | SortFilterProxyModel 8 | 9 | 10 | 11 | 12 |

List of All Members for ValueFilter

13 |

This is the complete list of members for ValueFilter, including inherited members.

14 | 18 |

The following members are inherited from Filter.

19 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/alloffilter.cpp: -------------------------------------------------------------------------------- 1 | #include "alloffilter.h" 2 | 3 | namespace qqsfpm { 4 | 5 | /*! 6 | \qmltype AllOf 7 | \inherits Filter 8 | \inqmlmodule SortFilterProxyModel 9 | \brief Filter container accepting rows accepted by all its child filters 10 | 11 | The AllOf type is a \l Filter container that accepts rows if all of its contained (and enabled) filters accept them, or if it has no filter. 12 | 13 | Using it as a top level filter has the same effect as putting all its child filters as top level filters. It can however be usefull to use an AllOf filter when nested in an AnyOf filter. 14 | */ 15 | bool AllOfFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 16 | { 17 | //return true if all filters return false, or if there is no filter. 18 | return std::all_of(m_filters.begin(), m_filters.end(), 19 | [&sourceIndex, &proxyModel] (Filter* filter) { 20 | return filter->filterAcceptsRow(sourceIndex, proxyModel); 21 | } 22 | ); 23 | } 24 | 25 | } 26 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/alloffilter.h: -------------------------------------------------------------------------------- 1 | #ifndef ALLOFFILTER_H 2 | #define ALLOFFILTER_H 3 | 4 | #include "filtercontainerfilter.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class AllOfFilter : public FilterContainerFilter { 9 | Q_OBJECT 10 | 11 | public: 12 | using FilterContainerFilter::FilterContainerFilter; 13 | 14 | protected: 15 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 16 | }; 17 | 18 | } 19 | 20 | #endif // ALLOFFILTER_H 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/anyoffilter.cpp: -------------------------------------------------------------------------------- 1 | #include "anyoffilter.h" 2 | 3 | namespace qqsfpm { 4 | 5 | /*! 6 | \qmltype AnyOf 7 | \inherits Filter 8 | \inqmlmodule SortFilterProxyModel 9 | \brief Filter container accepting rows accepted by at least one of its child filters 10 | 11 | The AnyOf type is a \l Filter container that accepts rows if any of its contained (and enabled) filters accept them. 12 | 13 | In the following example, only the rows where the \c firstName role or the \c lastName role match the text entered in the \c nameTextField will be accepted : 14 | \code 15 | TextField { 16 | id: nameTextField 17 | } 18 | 19 | SortFilterProxyModel { 20 | sourceModel: contactModel 21 | filters: AnyOf { 22 | RegExpFilter { 23 | roleName: "lastName" 24 | pattern: nameTextField.text 25 | caseSensitivity: Qt.CaseInsensitive 26 | } 27 | RegExpFilter { 28 | roleName: "firstName" 29 | pattern: nameTextField.text 30 | caseSensitivity: Qt.CaseInsensitive 31 | } 32 | } 33 | } 34 | \endcode 35 | */ 36 | bool AnyOfFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 37 | { 38 | //return true if any of the enabled filters return true 39 | return std::any_of(m_filters.begin(), m_filters.end(), 40 | [&sourceIndex, &proxyModel] (Filter* filter) { 41 | return filter->enabled() && filter->filterAcceptsRow(sourceIndex, proxyModel); 42 | } 43 | ); 44 | } 45 | 46 | } 47 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/anyoffilter.h: -------------------------------------------------------------------------------- 1 | #ifndef ANYOFFILTER_H 2 | #define ANYOFFILTER_H 3 | 4 | #include "filtercontainerfilter.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class AnyOfFilter : public FilterContainerFilter { 9 | Q_OBJECT 10 | 11 | public: 12 | using FilterContainerFilter::FilterContainerFilter; 13 | 14 | protected: 15 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 16 | }; 17 | 18 | } 19 | 20 | #endif // ANYOFFILTER_H 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/expressionfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSIONFILTER_H 2 | #define EXPRESSIONFILTER_H 3 | 4 | #include "filter.h" 5 | #include 6 | 7 | class QQmlExpression; 8 | 9 | namespace qqsfpm { 10 | 11 | class ExpressionFilter : public Filter 12 | { 13 | Q_OBJECT 14 | Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged) 15 | 16 | public: 17 | using Filter::Filter; 18 | 19 | const QQmlScriptString& expression() const; 20 | void setExpression(const QQmlScriptString& scriptString); 21 | 22 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 23 | 24 | protected: 25 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 26 | 27 | Q_SIGNALS: 28 | void expressionChanged(); 29 | 30 | private: 31 | void updateContext(const QQmlSortFilterProxyModel& proxyModel); 32 | void updateExpression(); 33 | 34 | QQmlScriptString m_scriptString; 35 | QQmlExpression* m_expression = nullptr; 36 | QQmlContext* m_context = nullptr; 37 | }; 38 | 39 | } 40 | 41 | #endif // EXPRESSIONFILTER_H 42 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filter.cpp: -------------------------------------------------------------------------------- 1 | #include "filter.h" 2 | #include "qqmlsortfilterproxymodel.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype Filter 8 | \inqmlmodule SortFilterProxyModel 9 | \brief Base type for the \l SortFilterProxyModel filters 10 | 11 | The Filter type cannot be used directly in a QML file. 12 | It exists to provide a set of common properties and methods, 13 | available across all the other filter types that inherit from it. 14 | Attempting to use the Filter type directly will result in an error. 15 | */ 16 | 17 | Filter::Filter(QObject *parent) : QObject(parent) 18 | { 19 | } 20 | 21 | /*! 22 | \qmlproperty bool Filter::enabled 23 | 24 | This property holds whether the filter is enabled. 25 | A disabled filter will accept every rows unconditionally (even if it's inverted). 26 | 27 | By default, filters are enabled. 28 | */ 29 | bool Filter::enabled() const 30 | { 31 | return m_enabled; 32 | } 33 | 34 | void Filter::setEnabled(bool enabled) 35 | { 36 | if (m_enabled == enabled) 37 | return; 38 | 39 | m_enabled = enabled; 40 | Q_EMIT enabledChanged(); 41 | Q_EMIT invalidated(); 42 | } 43 | 44 | /*! 45 | \qmlproperty bool Filter::inverted 46 | 47 | This property holds whether the filter is inverted. 48 | When a filter is inverted, a row normally accepted would be rejected, and vice-versa. 49 | 50 | By default, filters are not inverted. 51 | */ 52 | bool Filter::inverted() const 53 | { 54 | return m_inverted; 55 | } 56 | 57 | void Filter::setInverted(bool inverted) 58 | { 59 | if (m_inverted == inverted) 60 | return; 61 | 62 | m_inverted = inverted; 63 | Q_EMIT invertedChanged(); 64 | invalidate(); 65 | } 66 | 67 | bool Filter::filterAcceptsRow(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 68 | { 69 | return !m_enabled || filterRow(sourceIndex, proxyModel) ^ m_inverted; 70 | } 71 | 72 | void Filter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) 73 | { 74 | Q_UNUSED(proxyModel) 75 | } 76 | 77 | void Filter::invalidate() 78 | { 79 | if (m_enabled) 80 | Q_EMIT invalidated(); 81 | } 82 | 83 | } 84 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filter.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTER_H 2 | #define FILTER_H 3 | 4 | #include 5 | 6 | namespace qqsfpm { 7 | 8 | class QQmlSortFilterProxyModel; 9 | 10 | class Filter : public QObject 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) 14 | Q_PROPERTY(bool inverted READ inverted WRITE setInverted NOTIFY invertedChanged) 15 | 16 | public: 17 | explicit Filter(QObject *parent = nullptr); 18 | virtual ~Filter() = default; 19 | 20 | bool enabled() const; 21 | void setEnabled(bool enabled); 22 | 23 | bool inverted() const; 24 | void setInverted(bool inverted); 25 | 26 | bool filterAcceptsRow(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const; 27 | 28 | virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel); 29 | 30 | Q_SIGNALS: 31 | void enabledChanged(); 32 | void invertedChanged(); 33 | void invalidated(); 34 | 35 | protected: 36 | virtual bool filterRow(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const = 0; 37 | void invalidate(); 38 | 39 | private: 40 | bool m_enabled = true; 41 | bool m_inverted = false; 42 | }; 43 | 44 | } 45 | 46 | #endif // FILTER_H 47 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtercontainer.cpp: -------------------------------------------------------------------------------- 1 | #include "filtercontainer.h" 2 | 3 | namespace qqsfpm { 4 | 5 | FilterContainer::~FilterContainer() 6 | { 7 | 8 | } 9 | 10 | QList FilterContainer::filters() const 11 | { 12 | return m_filters; 13 | } 14 | 15 | void FilterContainer::appendFilter(Filter* filter) 16 | { 17 | m_filters.append(filter); 18 | onFilterAppended(filter); 19 | } 20 | 21 | void FilterContainer::removeFilter(Filter* filter) 22 | { 23 | m_filters.removeOne(filter); 24 | onFilterRemoved(filter); 25 | } 26 | 27 | void FilterContainer::clearFilters() 28 | { 29 | m_filters.clear(); 30 | onFiltersCleared(); 31 | } 32 | 33 | QQmlListProperty FilterContainer::filtersListProperty() 34 | { 35 | return QQmlListProperty(reinterpret_cast(this), &m_filters, 36 | &FilterContainer::append_filter, 37 | &FilterContainer::count_filter, 38 | &FilterContainer::at_filter, 39 | &FilterContainer::clear_filters); 40 | } 41 | 42 | void FilterContainer::append_filter(QQmlListProperty* list, Filter* filter) 43 | { 44 | if (!filter) 45 | return; 46 | 47 | FilterContainer* that = reinterpret_cast(list->object); 48 | that->appendFilter(filter); 49 | } 50 | 51 | int FilterContainer::count_filter(QQmlListProperty* list) 52 | { 53 | QList* filters = static_cast*>(list->data); 54 | return filters->count(); 55 | } 56 | 57 | Filter* FilterContainer::at_filter(QQmlListProperty* list, int index) 58 | { 59 | QList* filters = static_cast*>(list->data); 60 | return filters->at(index); 61 | } 62 | 63 | void FilterContainer::clear_filters(QQmlListProperty *list) 64 | { 65 | FilterContainer* that = reinterpret_cast(list->object); 66 | that->clearFilters(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtercontainer.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERCONTAINER_H 2 | #define FILTERCONTAINER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class Filter; 10 | class QQmlSortFilterProxyModel; 11 | 12 | class FilterContainer { 13 | public: 14 | virtual ~FilterContainer(); 15 | 16 | QList filters() const; 17 | void appendFilter(Filter* filter); 18 | void removeFilter(Filter* filter); 19 | void clearFilters(); 20 | 21 | QQmlListProperty filtersListProperty(); 22 | 23 | protected: 24 | QList m_filters; 25 | 26 | private: 27 | virtual void onFilterAppended(Filter* filter) = 0; 28 | virtual void onFilterRemoved(Filter* filter) = 0; 29 | virtual void onFiltersCleared() = 0; 30 | 31 | static void append_filter(QQmlListProperty* list, Filter* filter); 32 | static int count_filter(QQmlListProperty* list); 33 | static Filter* at_filter(QQmlListProperty* list, int index); 34 | static void clear_filters(QQmlListProperty* list); 35 | }; 36 | 37 | } 38 | 39 | #define FilterContainer_iid "fr.grecko.SortFilterProxyModel.FilterContainer" 40 | Q_DECLARE_INTERFACE(qqsfpm::FilterContainer, FilterContainer_iid) 41 | 42 | #endif // FILTERCONTAINER_H 43 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtercontainerfilter.cpp: -------------------------------------------------------------------------------- 1 | #include "filtercontainerfilter.h" 2 | 3 | namespace qqsfpm { 4 | 5 | void FilterContainerFilter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) 6 | { 7 | for (Filter* filter : m_filters) 8 | filter->proxyModelCompleted(proxyModel); 9 | } 10 | 11 | void FilterContainerFilter::onFilterAppended(Filter* filter) 12 | { 13 | connect(filter, &Filter::invalidated, this, &FilterContainerFilter::invalidate); 14 | invalidate(); 15 | } 16 | 17 | void FilterContainerFilter::onFilterRemoved(Filter* filter) 18 | { 19 | Q_UNUSED(filter) 20 | invalidate(); 21 | } 22 | 23 | void qqsfpm::FilterContainerFilter::onFiltersCleared() 24 | { 25 | invalidate(); 26 | } 27 | 28 | } 29 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtercontainerfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERCONTAINERFILTER_H 2 | #define FILTERCONTAINERFILTER_H 3 | 4 | #include "filter.h" 5 | #include "filtercontainer.h" 6 | 7 | namespace qqsfpm { 8 | 9 | class FilterContainerFilter : public Filter, public FilterContainer { 10 | Q_OBJECT 11 | Q_INTERFACES(qqsfpm::FilterContainer) 12 | Q_PROPERTY(QQmlListProperty filters READ filtersListProperty NOTIFY filtersChanged) 13 | Q_CLASSINFO("DefaultProperty", "filters") 14 | 15 | public: 16 | using Filter::Filter; 17 | 18 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 19 | 20 | Q_SIGNALS: 21 | void filtersChanged(); 22 | 23 | private: 24 | void onFilterAppended(Filter* filter) override; 25 | void onFilterRemoved(Filter* filter) override; 26 | void onFiltersCleared() override; 27 | }; 28 | 29 | } 30 | 31 | #endif // FILTERCONTAINERFILTER_H 32 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtersqmltypes.cpp: -------------------------------------------------------------------------------- 1 | #include "filter.h" 2 | #include "valuefilter.h" 3 | #include "indexfilter.h" 4 | #include "regexpfilter.h" 5 | #include "rangefilter.h" 6 | #include "expressionfilter.h" 7 | #include "anyoffilter.h" 8 | #include "alloffilter.h" 9 | #include 10 | #include 11 | 12 | namespace qqsfpm { 13 | 14 | void registerFiltersTypes() { 15 | qmlRegisterUncreatableType("SortFilterProxyModel", 0, 2, "Filter", "Filter is an abstract class"); 16 | qmlRegisterType("SortFilterProxyModel", 0, 2, "ValueFilter"); 17 | qmlRegisterType("SortFilterProxyModel", 0, 2, "IndexFilter"); 18 | qmlRegisterType("SortFilterProxyModel", 0, 2, "RegExpFilter"); 19 | qmlRegisterType("SortFilterProxyModel", 0, 2, "RangeFilter"); 20 | qmlRegisterType("SortFilterProxyModel", 0, 2, "ExpressionFilter"); 21 | qmlRegisterType("SortFilterProxyModel", 0, 2, "AnyOf"); 22 | qmlRegisterType("SortFilterProxyModel", 0, 2, "AllOf"); 23 | } 24 | 25 | Q_COREAPP_STARTUP_FUNCTION(registerFiltersTypes) 26 | 27 | } 28 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/filtersqmltypes.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERSQMLTYPES_H 2 | #define FILTERSQMLTYPES_H 3 | 4 | namespace qqsfpm { 5 | 6 | void registerFiltersTypes(); 7 | 8 | } 9 | 10 | #endif // FILTERSQMLTYPES_H 11 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/indexfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef INDEXFILTER_H 2 | #define INDEXFILTER_H 3 | 4 | #include "filter.h" 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class IndexFilter: public Filter { 10 | Q_OBJECT 11 | Q_PROPERTY(QVariant minimumIndex READ minimumIndex WRITE setMinimumIndex NOTIFY minimumIndexChanged) 12 | Q_PROPERTY(QVariant maximumIndex READ maximumIndex WRITE setMaximumIndex NOTIFY maximumIndexChanged) 13 | 14 | public: 15 | using Filter::Filter; 16 | 17 | const QVariant& minimumIndex() const; 18 | void setMinimumIndex(const QVariant& minimumIndex); 19 | 20 | const QVariant& maximumIndex() const; 21 | void setMaximumIndex(const QVariant& maximumIndex); 22 | 23 | protected: 24 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 25 | 26 | Q_SIGNALS: 27 | void minimumIndexChanged(); 28 | void maximumIndexChanged(); 29 | 30 | private: 31 | QVariant m_minimumIndex; 32 | QVariant m_maximumIndex; 33 | }; 34 | 35 | } 36 | 37 | #endif // INDEXFILTER_H 38 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/rangefilter.h: -------------------------------------------------------------------------------- 1 | #ifndef RANGEFILTER_H 2 | #define RANGEFILTER_H 3 | 4 | #include "rolefilter.h" 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class RangeFilter : public RoleFilter 10 | { 11 | Q_OBJECT 12 | Q_PROPERTY(QVariant minimumValue READ minimumValue WRITE setMinimumValue NOTIFY minimumValueChanged) 13 | Q_PROPERTY(bool minimumInclusive READ minimumInclusive WRITE setMinimumInclusive NOTIFY minimumInclusiveChanged) 14 | Q_PROPERTY(QVariant maximumValue READ maximumValue WRITE setMaximumValue NOTIFY maximumValueChanged) 15 | Q_PROPERTY(bool maximumInclusive READ maximumInclusive WRITE setMaximumInclusive NOTIFY maximumInclusiveChanged) 16 | 17 | public: 18 | using RoleFilter::RoleFilter; 19 | 20 | QVariant minimumValue() const; 21 | void setMinimumValue(QVariant minimumValue); 22 | bool minimumInclusive() const; 23 | void setMinimumInclusive(bool minimumInclusive); 24 | 25 | QVariant maximumValue() const; 26 | void setMaximumValue(QVariant maximumValue); 27 | bool maximumInclusive() const; 28 | void setMaximumInclusive(bool maximumInclusive); 29 | 30 | protected: 31 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 32 | 33 | Q_SIGNALS: 34 | void minimumValueChanged(); 35 | void minimumInclusiveChanged(); 36 | void maximumValueChanged(); 37 | void maximumInclusiveChanged(); 38 | 39 | private: 40 | QVariant m_minimumValue; 41 | bool m_minimumInclusive = true; 42 | QVariant m_maximumValue; 43 | bool m_maximumInclusive = true; 44 | }; 45 | 46 | } 47 | 48 | #endif // RANGEFILTER_H 49 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/regexpfilter.h: -------------------------------------------------------------------------------- 1 | #ifndef REGEXPFILTER_H 2 | #define REGEXPFILTER_H 3 | 4 | #include "rolefilter.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class RegExpFilter : public RoleFilter { 9 | Q_OBJECT 10 | Q_PROPERTY(QString pattern READ pattern WRITE setPattern NOTIFY patternChanged) 11 | Q_PROPERTY(PatternSyntax syntax READ syntax WRITE setSyntax NOTIFY syntaxChanged) 12 | Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged) 13 | 14 | public: 15 | enum PatternSyntax { 16 | RegExp = QRegExp::RegExp, 17 | Wildcard = QRegExp::Wildcard, 18 | FixedString = QRegExp::FixedString, 19 | RegExp2 = QRegExp::RegExp2, 20 | WildcardUnix = QRegExp::WildcardUnix, 21 | W3CXmlSchema11 = QRegExp::W3CXmlSchema11 }; 22 | Q_ENUMS(PatternSyntax) 23 | 24 | using RoleFilter::RoleFilter; 25 | 26 | QString pattern() const; 27 | void setPattern(const QString& pattern); 28 | 29 | PatternSyntax syntax() const; 30 | void setSyntax(PatternSyntax syntax); 31 | 32 | Qt::CaseSensitivity caseSensitivity() const; 33 | void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); 34 | 35 | protected: 36 | bool filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 37 | 38 | Q_SIGNALS: 39 | void patternChanged(); 40 | void syntaxChanged(); 41 | void caseSensitivityChanged(); 42 | 43 | private: 44 | QRegExp m_regExp; 45 | Qt::CaseSensitivity m_caseSensitivity = m_regExp.caseSensitivity(); 46 | PatternSyntax m_syntax = static_cast(m_regExp.patternSyntax()); 47 | QString m_pattern = m_regExp.pattern(); 48 | }; 49 | 50 | } 51 | 52 | #endif // REGEXPFILTER_H 53 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/rolefilter.cpp: -------------------------------------------------------------------------------- 1 | #include "rolefilter.h" 2 | #include "qqmlsortfilterproxymodel.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype RoleFilter 8 | \qmlabstract 9 | \inherits Filter 10 | \inqmlmodule SortFilterProxyModel 11 | \brief Base type for filters based on a source model role 12 | 13 | The RoleFilter type cannot be used directly in a QML file. 14 | It exists to provide a set of common properties and methods, 15 | available across all the other filter types that inherit from it. 16 | Attempting to use the RoleFilter type directly will result in an error. 17 | */ 18 | 19 | /*! 20 | \qmlproperty string RoleFilter::roleName 21 | 22 | This property holds the role name that the filter is using to query the source model's data when filtering items. 23 | */ 24 | const QString& RoleFilter::roleName() const 25 | { 26 | return m_roleName; 27 | } 28 | 29 | void RoleFilter::setRoleName(const QString& roleName) 30 | { 31 | if (m_roleName == roleName) 32 | return; 33 | 34 | m_roleName = roleName; 35 | Q_EMIT roleNameChanged(); 36 | invalidate(); 37 | } 38 | 39 | QVariant RoleFilter::sourceData(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 40 | { 41 | return proxyModel.sourceData(sourceIndex, m_roleName); 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/rolefilter.h: -------------------------------------------------------------------------------- 1 | #ifndef ROLEFILTER_H 2 | #define ROLEFILTER_H 3 | 4 | #include "filter.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class RoleFilter : public Filter 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY roleNameChanged) 12 | 13 | public: 14 | using Filter::Filter; 15 | 16 | const QString& roleName() const; 17 | void setRoleName(const QString& roleName); 18 | 19 | Q_SIGNALS: 20 | void roleNameChanged(); 21 | 22 | protected: 23 | QVariant sourceData(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const; 24 | 25 | private: 26 | QString m_roleName; 27 | }; 28 | 29 | } 30 | 31 | #endif // ROLEFILTER_H 32 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/valuefilter.cpp: -------------------------------------------------------------------------------- 1 | #include "valuefilter.h" 2 | 3 | namespace qqsfpm { 4 | 5 | /*! 6 | \qmltype ValueFilter 7 | \inherits RoleFilter 8 | \inqmlmodule SortFilterProxyModel 9 | \brief Filters rows matching exactly a value 10 | 11 | A ValueFilter is a simple \l RoleFilter that accepts rows matching exactly the filter's value 12 | 13 | In the following example, only rows with their \c favorite role set to \c true will be accepted when the checkbox is checked : 14 | \code 15 | CheckBox { 16 | id: showOnlyFavoriteCheckBox 17 | } 18 | 19 | SortFilterProxyModel { 20 | sourceModel: contactModel 21 | filters: ValueFilter { 22 | roleName: "favorite" 23 | value: true 24 | enabled: showOnlyFavoriteCheckBox.checked 25 | } 26 | } 27 | \endcode 28 | 29 | */ 30 | 31 | /*! 32 | \qmlproperty variant ValueFilter::value 33 | 34 | This property holds the value used to filter the contents of the source model. 35 | */ 36 | const QVariant &ValueFilter::value() const 37 | { 38 | return m_value; 39 | } 40 | 41 | void ValueFilter::setValue(const QVariant& value) 42 | { 43 | if (m_value == value) 44 | return; 45 | 46 | m_value = value; 47 | Q_EMIT valueChanged(); 48 | invalidate(); 49 | } 50 | 51 | bool ValueFilter::filterRow(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 52 | { 53 | return !m_value.isValid() || m_value == sourceData(sourceIndex, proxyModel); 54 | } 55 | 56 | } 57 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/filters/valuefilter.h: -------------------------------------------------------------------------------- 1 | #ifndef VALUEFILTER_H 2 | #define VALUEFILTER_H 3 | 4 | #include "rolefilter.h" 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class ValueFilter : public RoleFilter { 10 | Q_OBJECT 11 | Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) 12 | 13 | public: 14 | using RoleFilter::RoleFilter; 15 | 16 | const QVariant& value() const; 17 | void setValue(const QVariant& value); 18 | 19 | protected: 20 | bool filterRow(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const override; 21 | 22 | Q_SIGNALS: 23 | void valueChanged(); 24 | 25 | private: 26 | QVariant m_value; 27 | }; 28 | 29 | } 30 | 31 | #endif // VALUEFILTER_H 32 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/expressionrole.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSIONROLE_H 2 | #define EXPRESSIONROLE_H 3 | 4 | #include "singlerole.h" 5 | #include 6 | 7 | class QQmlExpression; 8 | 9 | namespace qqsfpm { 10 | 11 | class ExpressionRole : public SingleRole 12 | { 13 | Q_OBJECT 14 | Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged) 15 | 16 | public: 17 | using SingleRole::SingleRole; 18 | 19 | const QQmlScriptString& expression() const; 20 | void setExpression(const QQmlScriptString& scriptString); 21 | 22 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 23 | 24 | Q_SIGNALS: 25 | void expressionChanged(); 26 | 27 | private: 28 | QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override; 29 | void updateContext(const QQmlSortFilterProxyModel& proxyModel); 30 | void updateExpression(); 31 | 32 | QQmlScriptString m_scriptString; 33 | QQmlExpression* m_expression = nullptr; 34 | QQmlContext* m_context = nullptr; 35 | }; 36 | 37 | } 38 | 39 | #endif // EXPRESSIONROLE_H 40 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/filterrole.cpp: -------------------------------------------------------------------------------- 1 | #include "filterrole.h" 2 | #include "filters/filter.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype FilterRole 8 | \inherits SingleRole 9 | \inqmlmodule SortFilterProxyModel 10 | \brief A role resolving to \c true for rows matching all its filters 11 | 12 | A FilterRole is a \l ProxyRole that returns \c true for rows matching all its filters. 13 | 14 | In the following example, the \c isAdult role will be equal to \c true if the \c age role is superior or equal to 18. 15 | \code 16 | SortFilterProxyModel { 17 | sourceModel: personModel 18 | proxyRoles: FilterRole { 19 | name: "isAdult" 20 | RangeFilter { roleName: "age"; minimumValue: 18; minimumInclusive: true } 21 | } 22 | } 23 | \endcode 24 | */ 25 | 26 | /*! 27 | \qmlproperty string FilterRole::filters 28 | 29 | This property holds the list of filters for this filter role. 30 | The data of this role will be equal to the \c true if all its filters match the model row, \c false otherwise. 31 | 32 | \sa Filter 33 | */ 34 | 35 | void FilterRole::onFilterAppended(Filter* filter) 36 | { 37 | connect(filter, &Filter::invalidated, this, &FilterRole::invalidate); 38 | invalidate(); 39 | } 40 | 41 | void FilterRole::onFilterRemoved(Filter* filter) 42 | { 43 | disconnect(filter, &Filter::invalidated, this, &FilterRole::invalidate); 44 | invalidate(); 45 | } 46 | 47 | void FilterRole::onFiltersCleared() 48 | { 49 | invalidate(); 50 | } 51 | 52 | QVariant FilterRole::data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) 53 | { 54 | return std::all_of(m_filters.begin(), m_filters.end(), 55 | [&] (Filter* filter) { 56 | return filter->filterAcceptsRow(sourceIndex, proxyModel); 57 | } 58 | ); 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/filterrole.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERROLE_H 2 | #define FILTERROLE_H 3 | 4 | #include "singlerole.h" 5 | #include "filters/filtercontainer.h" 6 | 7 | namespace qqsfpm { 8 | 9 | class FilterRole : public SingleRole, public FilterContainer 10 | { 11 | Q_OBJECT 12 | Q_INTERFACES(qqsfpm::FilterContainer) 13 | Q_PROPERTY(QQmlListProperty filters READ filtersListProperty) 14 | Q_CLASSINFO("DefaultProperty", "filters") 15 | 16 | public: 17 | using SingleRole::SingleRole; 18 | 19 | private: 20 | void onFilterAppended(Filter* filter) override; 21 | void onFilterRemoved(Filter* filter) override; 22 | void onFiltersCleared() override; 23 | 24 | QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override; 25 | }; 26 | 27 | } 28 | 29 | #endif // FILTERROLE_H 30 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/joinrole.cpp: -------------------------------------------------------------------------------- 1 | #include "joinrole.h" 2 | #include "qqmlsortfilterproxymodel.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype JoinRole 8 | \inherits SingleRole 9 | \inqmlmodule SortFilterProxyModel 10 | \brief a role made from concatenating other roles 11 | 12 | A JoinRole is a simple \l ProxyRole that concatenates other roles. 13 | 14 | In the following example, the \c fullName role is computed by the concatenation of the \c firstName role and the \c lastName role separated by a space : 15 | \code 16 | SortFilterProxyModel { 17 | sourceModel: contactModel 18 | proxyRoles: JoinRole { 19 | name: "fullName" 20 | roleNames: ["firstName", "lastName"] 21 | } 22 | } 23 | \endcode 24 | 25 | */ 26 | 27 | /*! 28 | \qmlproperty list JoinRole::roleNames 29 | 30 | This property holds the role names that are joined by this role. 31 | */ 32 | QStringList JoinRole::roleNames() const 33 | { 34 | return m_roleNames; 35 | } 36 | 37 | void JoinRole::setRoleNames(const QStringList& roleNames) 38 | { 39 | if (m_roleNames == roleNames) 40 | return; 41 | 42 | m_roleNames = roleNames; 43 | Q_EMIT roleNamesChanged(); 44 | invalidate(); 45 | } 46 | 47 | /*! 48 | \qmlproperty string JoinRole::separator 49 | 50 | This property holds the separator that is used to join the roles specified in \l roleNames. 51 | 52 | By default, it's a space. 53 | */ 54 | QString JoinRole::separator() const 55 | { 56 | return m_separator; 57 | } 58 | 59 | void JoinRole::setSeparator(const QString& separator) 60 | { 61 | if (m_separator == separator) 62 | return; 63 | 64 | m_separator = separator; 65 | Q_EMIT separatorChanged(); 66 | invalidate(); 67 | } 68 | 69 | QVariant JoinRole::data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel& proxyModel) 70 | { 71 | QString result; 72 | 73 | for (const QString& roleName : m_roleNames) 74 | result += proxyModel.sourceData(sourceIndex, roleName).toString() + m_separator; 75 | 76 | if (!m_roleNames.isEmpty()) 77 | result.chop(m_separator.length()); 78 | 79 | return result; 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/joinrole.h: -------------------------------------------------------------------------------- 1 | #ifndef JOINROLE_H 2 | #define JOINROLE_H 3 | 4 | #include "singlerole.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class JoinRole : public SingleRole 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QStringList roleNames READ roleNames WRITE setRoleNames NOTIFY roleNamesChanged) 12 | Q_PROPERTY(QString separator READ separator WRITE setSeparator NOTIFY separatorChanged) 13 | 14 | public: 15 | using SingleRole::SingleRole; 16 | 17 | QStringList roleNames() const; 18 | void setRoleNames(const QStringList& roleNames); 19 | 20 | QString separator() const; 21 | void setSeparator(const QString& separator); 22 | 23 | Q_SIGNALS: 24 | void roleNamesChanged(); 25 | 26 | void separatorChanged(); 27 | 28 | private: 29 | QStringList m_roleNames; 30 | QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override; 31 | QString m_separator = " "; 32 | }; 33 | 34 | } 35 | 36 | #endif // JOINROLE_H 37 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrole.cpp: -------------------------------------------------------------------------------- 1 | #include "proxyrole.h" 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include "filters/filter.h" 9 | #include "qqmlsortfilterproxymodel.h" 10 | 11 | namespace qqsfpm { 12 | 13 | /*! 14 | \qmltype ProxyRole 15 | \inqmlmodule SortFilterProxyModel 16 | \brief Base type for the \l SortFilterProxyModel proxy roles 17 | 18 | The ProxyRole type cannot be used directly in a QML file. 19 | It exists to provide a set of common properties and methods, 20 | available across all the other proxy role types that inherit from it. 21 | Attempting to use the ProxyRole type directly will result in an error. 22 | */ 23 | 24 | QVariant ProxyRole::roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel, const QString &name) 25 | { 26 | if (m_mutex.tryLock()) { 27 | QVariant result = data(sourceIndex, proxyModel, name); 28 | m_mutex.unlock(); 29 | return result; 30 | } else { 31 | return {}; 32 | } 33 | } 34 | 35 | void ProxyRole::proxyModelCompleted(const QQmlSortFilterProxyModel &proxyModel) 36 | { 37 | Q_UNUSED(proxyModel) 38 | } 39 | 40 | void ProxyRole::invalidate() 41 | { 42 | Q_EMIT invalidated(); 43 | } 44 | 45 | } 46 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrole.h: -------------------------------------------------------------------------------- 1 | #ifndef PROXYROLE_H 2 | #define PROXYROLE_H 3 | 4 | #include 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class QQmlSortFilterProxyModel; 10 | 11 | class ProxyRole : public QObject 12 | { 13 | Q_OBJECT 14 | 15 | public: 16 | using QObject::QObject; 17 | virtual ~ProxyRole() = default; 18 | 19 | QVariant roleData(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel, const QString& name); 20 | virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel); 21 | 22 | virtual QStringList names() = 0; 23 | 24 | protected: 25 | void invalidate(); 26 | 27 | Q_SIGNALS: 28 | void invalidated(); 29 | void namesAboutToBeChanged(); 30 | void namesChanged(); 31 | 32 | private: 33 | virtual QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel, const QString& name) = 0; 34 | 35 | QMutex m_mutex; 36 | }; 37 | 38 | } 39 | 40 | #endif // PROXYROLE_H 41 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrolecontainer.cpp: -------------------------------------------------------------------------------- 1 | #include "proxyrolecontainer.h" 2 | 3 | namespace qqsfpm { 4 | 5 | ProxyRoleContainer::~ProxyRoleContainer() 6 | { 7 | 8 | } 9 | 10 | QList ProxyRoleContainer::proxyRoles() const 11 | { 12 | return m_proxyRoles; 13 | } 14 | 15 | void ProxyRoleContainer::appendProxyRole(ProxyRole* proxyRole) 16 | { 17 | m_proxyRoles.append(proxyRole); 18 | onProxyRoleAppended(proxyRole); 19 | } 20 | 21 | void ProxyRoleContainer::removeProxyRole(ProxyRole* proxyRole) 22 | { 23 | m_proxyRoles.removeOne(proxyRole); 24 | onProxyRoleRemoved(proxyRole); 25 | } 26 | 27 | void ProxyRoleContainer::clearProxyRoles() 28 | { 29 | m_proxyRoles.clear(); 30 | onProxyRolesCleared(); 31 | } 32 | 33 | QQmlListProperty ProxyRoleContainer::proxyRolesListProperty() 34 | { 35 | return QQmlListProperty(reinterpret_cast(this), &m_proxyRoles, 36 | &ProxyRoleContainer::append_proxyRole, 37 | &ProxyRoleContainer::count_proxyRole, 38 | &ProxyRoleContainer::at_proxyRole, 39 | &ProxyRoleContainer::clear_proxyRoles); 40 | } 41 | 42 | void ProxyRoleContainer::append_proxyRole(QQmlListProperty* list, ProxyRole* proxyRole) 43 | { 44 | if (!proxyRole) 45 | return; 46 | 47 | ProxyRoleContainer* that = reinterpret_cast(list->object); 48 | that->appendProxyRole(proxyRole); 49 | } 50 | 51 | int ProxyRoleContainer::count_proxyRole(QQmlListProperty* list) 52 | { 53 | QList* ProxyRoles = static_cast*>(list->data); 54 | return ProxyRoles->count(); 55 | } 56 | 57 | ProxyRole* ProxyRoleContainer::at_proxyRole(QQmlListProperty* list, int index) 58 | { 59 | QList* ProxyRoles = static_cast*>(list->data); 60 | return ProxyRoles->at(index); 61 | } 62 | 63 | void ProxyRoleContainer::clear_proxyRoles(QQmlListProperty *list) 64 | { 65 | ProxyRoleContainer* that = reinterpret_cast(list->object); 66 | that->clearProxyRoles(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrolecontainer.h: -------------------------------------------------------------------------------- 1 | #ifndef PROXYROLECONTAINER_H 2 | #define PROXYROLECONTAINER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class ProxyRole; 10 | class QQmlSortFilterProxyModel; 11 | 12 | class ProxyRoleContainer { 13 | public: 14 | virtual ~ProxyRoleContainer(); 15 | 16 | QList proxyRoles() const; 17 | void appendProxyRole(ProxyRole* proxyRole); 18 | void removeProxyRole(ProxyRole* proxyRole); 19 | void clearProxyRoles(); 20 | 21 | QQmlListProperty proxyRolesListProperty(); 22 | 23 | protected: 24 | QList m_proxyRoles; 25 | 26 | private: 27 | virtual void onProxyRoleAppended(ProxyRole* proxyRole) = 0; 28 | virtual void onProxyRoleRemoved(ProxyRole* proxyRole) = 0; 29 | virtual void onProxyRolesCleared() = 0; 30 | 31 | static void append_proxyRole(QQmlListProperty* list, ProxyRole* proxyRole); 32 | static int count_proxyRole(QQmlListProperty* list); 33 | static ProxyRole* at_proxyRole(QQmlListProperty* list, int index); 34 | static void clear_proxyRoles(QQmlListProperty* list); 35 | }; 36 | 37 | } 38 | 39 | #define ProxyRoleContainer_iid "fr.grecko.SortFilterProxyModel.ProxyRoleContainer" 40 | Q_DECLARE_INTERFACE(qqsfpm::ProxyRoleContainer, ProxyRoleContainer_iid) 41 | 42 | #endif // PROXYROLECONTAINER_H 43 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrolesqmltypes.cpp: -------------------------------------------------------------------------------- 1 | #include "proxyrole.h" 2 | #include "joinrole.h" 3 | #include "switchrole.h" 4 | #include "expressionrole.h" 5 | #include "regexprole.h" 6 | #include "filterrole.h" 7 | #include 8 | #include 9 | 10 | namespace qqsfpm { 11 | 12 | void registerProxyRoleTypes() { 13 | qmlRegisterUncreatableType("SortFilterProxyModel", 0, 2, "ProxyRole", "ProxyRole is an abstract class"); 14 | qmlRegisterType("SortFilterProxyModel", 0, 2, "JoinRole"); 15 | qmlRegisterType("SortFilterProxyModel", 0, 2, "SwitchRole"); 16 | qmlRegisterType("SortFilterProxyModel", 0, 2, "ExpressionRole"); 17 | qmlRegisterType("SortFilterProxyModel", 0, 2, "RegExpRole"); 18 | qmlRegisterType("SortFilterProxyModel", 0, 2, "FilterRole"); 19 | } 20 | 21 | Q_COREAPP_STARTUP_FUNCTION(registerProxyRoleTypes) 22 | 23 | } 24 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/proxyrolesqmltypes.h: -------------------------------------------------------------------------------- 1 | #ifndef PROXYROLESQMLTYPES_H 2 | #define PROXYROLESQMLTYPES_H 3 | 4 | namespace qqsfpm { 5 | 6 | void registerProxyRoleTypes(); 7 | 8 | } 9 | 10 | #endif // PROXYROLESQMLTYPES_H 11 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/regexprole.h: -------------------------------------------------------------------------------- 1 | #ifndef REGEXPROLE_H 2 | #define REGEXPROLE_H 3 | 4 | #include "proxyrole.h" 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class RegExpRole : public ProxyRole 10 | { 11 | Q_OBJECT 12 | Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY roleNameChanged) 13 | Q_PROPERTY(QString pattern READ pattern WRITE setPattern NOTIFY patternChanged) 14 | Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged) 15 | 16 | public: 17 | using ProxyRole::ProxyRole; 18 | 19 | QString roleName() const; 20 | void setRoleName(const QString& roleName); 21 | 22 | QString pattern() const; 23 | void setPattern(const QString& pattern); 24 | 25 | Qt::CaseSensitivity caseSensitivity() const; 26 | void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); 27 | 28 | QStringList names() override; 29 | 30 | Q_SIGNALS: 31 | void roleNameChanged(); 32 | void patternChanged(); 33 | void caseSensitivityChanged(); 34 | 35 | private: 36 | QString m_roleName; 37 | QRegularExpression m_regularExpression; 38 | QVariant data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel, const QString &name) override; 39 | }; 40 | 41 | } 42 | 43 | #endif // REGEXPROLE_H 44 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/singlerole.cpp: -------------------------------------------------------------------------------- 1 | #include "singlerole.h" 2 | #include 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype SingleRole 8 | \inherits ProxyRole 9 | \inqmlmodule SortFilterProxyModel 10 | \brief Base type for the \l SortFilterProxyModel proxy roles defining a single role 11 | 12 | SingleRole is a convenience base class for proxy roles who define a single role. 13 | It cannot be used directly in a QML file. 14 | It exists to provide a set of common properties and methods, 15 | available across all the other proxy role types that inherit from it. 16 | Attempting to use the SingleRole type directly will result in an error. 17 | */ 18 | /*! 19 | \qmlproperty string SingleRole::name 20 | 21 | This property holds the role name of the proxy role. 22 | */ 23 | QString SingleRole::name() const 24 | { 25 | return m_name; 26 | } 27 | 28 | void SingleRole::setName(const QString& name) 29 | { 30 | if (m_name == name) 31 | return; 32 | 33 | Q_EMIT namesAboutToBeChanged(); 34 | m_name = name; 35 | Q_EMIT nameChanged(); 36 | Q_EMIT namesChanged(); 37 | } 38 | 39 | QStringList SingleRole::names() 40 | { 41 | return QStringList { m_name }; 42 | } 43 | 44 | QVariant SingleRole::data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel, const QString &name) 45 | { 46 | Q_UNUSED(name); 47 | return data(sourceIndex, proxyModel); 48 | } 49 | 50 | } 51 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/singlerole.h: -------------------------------------------------------------------------------- 1 | #ifndef SINGLEROLE_H 2 | #define SINGLEROLE_H 3 | 4 | #include "proxyrole.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class SingleRole : public ProxyRole 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QString name READ name WRITE setName NOTIFY nameChanged) 12 | 13 | public: 14 | using ProxyRole::ProxyRole; 15 | 16 | QString name() const; 17 | void setName(const QString& name); 18 | 19 | QStringList names() override; 20 | 21 | Q_SIGNALS: 22 | void nameChanged(); 23 | 24 | private: 25 | QString m_name; 26 | 27 | private: 28 | QVariant data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel, const QString &name) final; 29 | virtual QVariant data(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel) = 0; 30 | }; 31 | 32 | } 33 | 34 | #endif // SINGLEROLE_H 35 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/proxyroles/switchrole.h: -------------------------------------------------------------------------------- 1 | #ifndef SWITCHROLE_H 2 | #define SWITCHROLE_H 3 | 4 | #include "singlerole.h" 5 | #include "filters/filtercontainer.h" 6 | #include 7 | 8 | namespace qqsfpm { 9 | 10 | class SwitchRoleAttached : public QObject 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) 14 | public: 15 | SwitchRoleAttached(QObject* parent); 16 | 17 | QVariant value() const; 18 | void setValue(QVariant value); 19 | 20 | Q_SIGNALS: 21 | void valueChanged(); 22 | 23 | private: 24 | QVariant m_value; 25 | }; 26 | 27 | class SwitchRole : public SingleRole, public FilterContainer 28 | { 29 | Q_OBJECT 30 | Q_INTERFACES(qqsfpm::FilterContainer) 31 | Q_PROPERTY(QString defaultRoleName READ defaultRoleName WRITE setDefaultRoleName NOTIFY defaultRoleNameChanged) 32 | Q_PROPERTY(QVariant defaultValue READ defaultValue WRITE setDefaultValue NOTIFY defaultValueChanged) 33 | Q_PROPERTY(QQmlListProperty filters READ filtersListProperty) 34 | Q_CLASSINFO("DefaultProperty", "filters") 35 | 36 | public: 37 | using SingleRole::SingleRole; 38 | 39 | QString defaultRoleName() const; 40 | void setDefaultRoleName(const QString& defaultRoleName); 41 | 42 | QVariant defaultValue() const; 43 | void setDefaultValue(const QVariant& defaultValue); 44 | 45 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 46 | 47 | static SwitchRoleAttached* qmlAttachedProperties(QObject* object); 48 | 49 | Q_SIGNALS: 50 | void defaultRoleNameChanged(); 51 | void defaultValueChanged(); 52 | 53 | private: 54 | QVariant data(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) override; 55 | 56 | void onFilterAppended(Filter *filter) override; 57 | void onFilterRemoved(Filter *filter) override; 58 | void onFiltersCleared() override; 59 | 60 | QString m_defaultRoleName; 61 | QVariant m_defaultValue; 62 | }; 63 | 64 | } 65 | 66 | QML_DECLARE_TYPEINFO(qqsfpm::SwitchRole, QML_HAS_ATTACHED_PROPERTIES) 67 | 68 | #endif // SWITCHROLE_H 69 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/qpm.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "fr.grecko.sortfilterproxymodel", 3 | "description": "A nicely exposed QSortFilterProxyModel for QML", 4 | "author": { 5 | "name": "Pierre-Yves Siret", 6 | "email": "gr3cko@gmail.com" 7 | }, 8 | "repository": { 9 | "type": "GITHUB", 10 | "url": "https://github.com/oKcerG/SortFilterProxyModel.git" 11 | }, 12 | "version": { 13 | "label": "0.1.0", 14 | "revision": "", 15 | "fingerprint": "" 16 | }, 17 | "dependencies": [ 18 | ], 19 | "license": "MIT", 20 | "pri_filename": "SortFilterProxyModel.pri", 21 | "webpage": "" 22 | } -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/expressionsorter.h: -------------------------------------------------------------------------------- 1 | #ifndef EXPRESSIONSORTER_H 2 | #define EXPRESSIONSORTER_H 3 | 4 | #include "sorter.h" 5 | #include 6 | 7 | class QQmlExpression; 8 | 9 | namespace qqsfpm { 10 | 11 | class QQmlSortFilterProxyModel; 12 | 13 | class ExpressionSorter : public Sorter 14 | { 15 | Q_OBJECT 16 | Q_PROPERTY(QQmlScriptString expression READ expression WRITE setExpression NOTIFY expressionChanged) 17 | 18 | public: 19 | using Sorter::Sorter; 20 | 21 | const QQmlScriptString& expression() const; 22 | void setExpression(const QQmlScriptString& scriptString); 23 | 24 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 25 | 26 | Q_SIGNALS: 27 | void expressionChanged(); 28 | 29 | protected: 30 | int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const override; 31 | 32 | private: 33 | void updateContext(const QQmlSortFilterProxyModel& proxyModel); 34 | void updateExpression(); 35 | 36 | QQmlScriptString m_scriptString; 37 | QQmlExpression* m_expression = nullptr; 38 | QQmlContext* m_context = nullptr; 39 | }; 40 | 41 | } 42 | 43 | #endif // EXPRESSIONSORTER_H 44 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/filtersorter.cpp: -------------------------------------------------------------------------------- 1 | #include "filtersorter.h" 2 | #include "filters/filter.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype FilterSorter 8 | \inherits Sorter 9 | \inqmlmodule SortFilterProxyModel 10 | \brief Sorts rows based on if they match filters 11 | 12 | A FilterSorter is a \l Sorter that orders row matching its filters before the rows not matching the filters. 13 | 14 | In the following example, rows with their \c favorite role set to \c true will be ordered at the beginning : 15 | \code 16 | SortFilterProxyModel { 17 | sourceModel: contactModel 18 | sorters: FilterSorter { 19 | ValueFilter { roleName: "favorite"; value: true } 20 | } 21 | } 22 | \endcode 23 | */ 24 | 25 | /*! 26 | \qmlproperty string FilterSorter::filters 27 | 28 | This property holds the list of filters for this filter sorter. 29 | If a row match all this FilterSorter's filters, it will be ordered before rows not matching all the filters. 30 | 31 | \sa Filter 32 | */ 33 | 34 | int FilterSorter::compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel &proxyModel) const 35 | { 36 | bool leftIsAccepted = indexIsAccepted(sourceLeft, proxyModel); 37 | bool rightIsAccepted = indexIsAccepted(sourceRight, proxyModel); 38 | 39 | if (leftIsAccepted == rightIsAccepted) 40 | return 0; 41 | 42 | return leftIsAccepted ? -1 : 1; 43 | } 44 | 45 | void FilterSorter::proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) 46 | { 47 | for (Filter* filter : m_filters) 48 | filter->proxyModelCompleted(proxyModel); 49 | } 50 | 51 | void FilterSorter::onFilterAppended(Filter* filter) 52 | { 53 | connect(filter, &Filter::invalidated, this, &FilterSorter::invalidate); 54 | invalidate(); 55 | } 56 | 57 | void FilterSorter::onFilterRemoved(Filter* filter) 58 | { 59 | disconnect(filter, &Filter::invalidated, this, &FilterSorter::invalidate); 60 | invalidate(); 61 | } 62 | 63 | void FilterSorter::onFiltersCleared() 64 | { 65 | invalidate(); 66 | } 67 | 68 | bool FilterSorter::indexIsAccepted(const QModelIndex& sourceIndex, const QQmlSortFilterProxyModel& proxyModel) const 69 | { 70 | return std::all_of(m_filters.begin(), m_filters.end(), 71 | [&] (Filter* filter) { 72 | return filter->filterAcceptsRow(sourceIndex, proxyModel); 73 | } 74 | ); 75 | } 76 | 77 | } 78 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/filtersorter.h: -------------------------------------------------------------------------------- 1 | #ifndef FILTERSORTER_H 2 | #define FILTERSORTER_H 3 | 4 | #include "sorter.h" 5 | #include "filters/filtercontainer.h" 6 | 7 | namespace qqsfpm { 8 | 9 | class FilterSorter : public Sorter, public FilterContainer 10 | { 11 | Q_OBJECT 12 | Q_INTERFACES(qqsfpm::FilterContainer) 13 | Q_PROPERTY(QQmlListProperty filters READ filtersListProperty) 14 | Q_CLASSINFO("DefaultProperty", "filters") 15 | 16 | public: 17 | using Sorter::Sorter; 18 | 19 | protected: 20 | int compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const QQmlSortFilterProxyModel &proxyModel) const override; 21 | 22 | private: 23 | void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel) override; 24 | void onFilterAppended(Filter *filter) override; 25 | void onFilterRemoved(Filter *filter) override; 26 | void onFiltersCleared() override; 27 | 28 | bool indexIsAccepted(const QModelIndex &sourceIndex, const QQmlSortFilterProxyModel &proxyModel) const; 29 | }; 30 | 31 | } 32 | 33 | #endif // FILTERSORTER_H 34 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/rolesorter.cpp: -------------------------------------------------------------------------------- 1 | #include "rolesorter.h" 2 | #include "qqmlsortfilterproxymodel.h" 3 | 4 | namespace qqsfpm { 5 | 6 | /*! 7 | \qmltype RoleSorter 8 | \inherits Sorter 9 | \inqmlmodule SortFilterProxyModel 10 | \brief Sorts rows based on a source model role 11 | 12 | A RoleSorter is a simple \l Sorter that sorts rows based on a source model role. 13 | 14 | In the following example, rows with be sorted by their \c lastName role : 15 | \code 16 | SortFilterProxyModel { 17 | sourceModel: contactModel 18 | sorters: RoleSorter { roleName: "lastName" } 19 | } 20 | \endcode 21 | */ 22 | 23 | /*! 24 | \qmlproperty string RoleSorter::roleName 25 | 26 | This property holds the role name that the sorter is using to query the source model's data when sorting items. 27 | */ 28 | const QString& RoleSorter::roleName() const 29 | { 30 | return m_roleName; 31 | } 32 | 33 | void RoleSorter::setRoleName(const QString& roleName) 34 | { 35 | if (m_roleName == roleName) 36 | return; 37 | 38 | m_roleName = roleName; 39 | Q_EMIT roleNameChanged(); 40 | invalidate(); 41 | } 42 | 43 | QPair RoleSorter::sourceData(const QModelIndex &sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const 44 | { 45 | QPair pair; 46 | int role = proxyModel.roleForName(m_roleName); 47 | 48 | if (role == -1) 49 | return pair; 50 | 51 | pair.first = proxyModel.sourceData(sourceLeft, role); 52 | pair.second = proxyModel.sourceData(sourceRight, role); 53 | return pair; 54 | } 55 | 56 | int RoleSorter::compare(const QModelIndex &sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const 57 | { 58 | QPair pair = sourceData(sourceLeft, sourceRight, proxyModel); 59 | QVariant leftValue = pair.first; 60 | QVariant rightValue = pair.second; 61 | if (leftValue < rightValue) 62 | return -1; 63 | if (leftValue > rightValue) 64 | return 1; 65 | return 0; 66 | } 67 | 68 | } 69 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/rolesorter.h: -------------------------------------------------------------------------------- 1 | #ifndef ROLESORTER_H 2 | #define ROLESORTER_H 3 | 4 | #include "sorter.h" 5 | 6 | namespace qqsfpm { 7 | 8 | class RoleSorter : public Sorter 9 | { 10 | Q_OBJECT 11 | Q_PROPERTY(QString roleName READ roleName WRITE setRoleName NOTIFY roleNameChanged) 12 | 13 | public: 14 | using Sorter::Sorter; 15 | 16 | const QString& roleName() const; 17 | void setRoleName(const QString& roleName); 18 | 19 | Q_SIGNALS: 20 | void roleNameChanged(); 21 | 22 | protected: 23 | QPair sourceData(const QModelIndex &sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const; 24 | int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const override; 25 | 26 | private: 27 | QString m_roleName; 28 | }; 29 | 30 | } 31 | 32 | #endif // ROLESORTER_H 33 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/sorter.h: -------------------------------------------------------------------------------- 1 | #ifndef SORTER_H 2 | #define SORTER_H 3 | 4 | #include 5 | 6 | namespace qqsfpm { 7 | 8 | class QQmlSortFilterProxyModel; 9 | 10 | class Sorter : public QObject 11 | { 12 | Q_OBJECT 13 | Q_PROPERTY(bool enabled READ enabled WRITE setEnabled NOTIFY enabledChanged) 14 | Q_PROPERTY(bool ascendingOrder READ ascendingOrder WRITE setAscendingOrder NOTIFY sortOrderChanged) 15 | Q_PROPERTY(Qt::SortOrder sortOrder READ sortOrder WRITE setSortOrder NOTIFY sortOrderChanged) 16 | 17 | public: 18 | Sorter(QObject* parent = nullptr); 19 | virtual ~Sorter() = 0; 20 | 21 | bool enabled() const; 22 | void setEnabled(bool enabled); 23 | 24 | bool ascendingOrder() const; 25 | void setAscendingOrder(bool ascendingOrder); 26 | 27 | Qt::SortOrder sortOrder() const; 28 | void setSortOrder(Qt::SortOrder sortOrder); 29 | 30 | int compareRows(const QModelIndex& source_left, const QModelIndex& source_right, const QQmlSortFilterProxyModel& proxyModel) const; 31 | 32 | virtual void proxyModelCompleted(const QQmlSortFilterProxyModel& proxyModel); 33 | 34 | Q_SIGNALS: 35 | void enabledChanged(); 36 | void sortOrderChanged(); 37 | 38 | void invalidated(); 39 | 40 | protected: 41 | virtual int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const; 42 | virtual bool lessThan(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const; 43 | void invalidate(); 44 | 45 | private: 46 | bool m_enabled = true; 47 | Qt::SortOrder m_sortOrder = Qt::AscendingOrder; 48 | }; 49 | 50 | } 51 | 52 | #endif // SORTER_H 53 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/sortercontainer.cpp: -------------------------------------------------------------------------------- 1 | #include "sortercontainer.h" 2 | 3 | namespace qqsfpm { 4 | 5 | SorterContainer::~SorterContainer() 6 | { 7 | 8 | } 9 | 10 | QList SorterContainer::sorters() const 11 | { 12 | return m_sorters; 13 | } 14 | 15 | void SorterContainer::appendSorter(Sorter* sorter) 16 | { 17 | m_sorters.append(sorter); 18 | onSorterAppended(sorter); 19 | } 20 | 21 | void SorterContainer::removeSorter(Sorter *sorter) 22 | { 23 | m_sorters.removeOne(sorter); 24 | onSorterRemoved(sorter); 25 | } 26 | 27 | void SorterContainer::clearSorters() 28 | { 29 | m_sorters.clear(); 30 | onSortersCleared(); 31 | } 32 | 33 | QQmlListProperty SorterContainer::sortersListProperty() 34 | { 35 | return QQmlListProperty(reinterpret_cast(this), &m_sorters, 36 | &SorterContainer::append_sorter, 37 | &SorterContainer::count_sorter, 38 | &SorterContainer::at_sorter, 39 | &SorterContainer::clear_sorters); 40 | } 41 | 42 | void SorterContainer::append_sorter(QQmlListProperty* list, Sorter* sorter) 43 | { 44 | if (!sorter) 45 | return; 46 | 47 | SorterContainer* that = reinterpret_cast(list->object); 48 | that->appendSorter(sorter); 49 | } 50 | 51 | int SorterContainer::count_sorter(QQmlListProperty* list) 52 | { 53 | QList* sorters = static_cast*>(list->data); 54 | return sorters->count(); 55 | } 56 | 57 | Sorter* SorterContainer::at_sorter(QQmlListProperty* list, int index) 58 | { 59 | QList* sorters = static_cast*>(list->data); 60 | return sorters->at(index); 61 | } 62 | 63 | void SorterContainer::clear_sorters(QQmlListProperty *list) 64 | { 65 | SorterContainer* that = reinterpret_cast(list->object); 66 | that->clearSorters(); 67 | } 68 | 69 | } 70 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/sortercontainer.h: -------------------------------------------------------------------------------- 1 | #ifndef SORTERSSORTERCONTAINER_H 2 | #define SORTERSSORTERCONTAINER_H 3 | 4 | #include 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class Sorter; 10 | class QQmlSortFilterProxyModel; 11 | 12 | class SorterContainer { 13 | public: 14 | virtual ~SorterContainer(); 15 | 16 | QList sorters() const; 17 | void appendSorter(Sorter* sorter); 18 | void removeSorter(Sorter* sorter); 19 | void clearSorters(); 20 | 21 | QQmlListProperty sortersListProperty(); 22 | 23 | protected: 24 | QList m_sorters; 25 | 26 | private: 27 | virtual void onSorterAppended(Sorter* sorter) = 0; 28 | virtual void onSorterRemoved(Sorter* sorter) = 0; 29 | virtual void onSortersCleared() = 0; 30 | 31 | static void append_sorter(QQmlListProperty* list, Sorter* sorter); 32 | static int count_sorter(QQmlListProperty* list); 33 | static Sorter* at_sorter(QQmlListProperty* list, int index); 34 | static void clear_sorters(QQmlListProperty* list); 35 | }; 36 | 37 | } 38 | 39 | #define SorterContainer_iid "fr.grecko.SortFilterProxyModel.SorterContainer" 40 | Q_DECLARE_INTERFACE(qqsfpm::SorterContainer, SorterContainer_iid) 41 | 42 | #endif // SORTERSSORTERCONTAINER_H 43 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/sortersqmltypes.cpp: -------------------------------------------------------------------------------- 1 | #include "sorter.h" 2 | #include "rolesorter.h" 3 | #include "stringsorter.h" 4 | #include "filtersorter.h" 5 | #include "expressionsorter.h" 6 | #include 7 | #include 8 | 9 | namespace qqsfpm { 10 | 11 | void registerSorterTypes() { 12 | qmlRegisterUncreatableType("SortFilterProxyModel", 0, 2, "Sorter", "Sorter is an abstract class"); 13 | qmlRegisterType("SortFilterProxyModel", 0, 2, "RoleSorter"); 14 | qmlRegisterType("SortFilterProxyModel", 0, 2, "StringSorter"); 15 | qmlRegisterType("SortFilterProxyModel", 0, 2, "FilterSorter"); 16 | qmlRegisterType("SortFilterProxyModel", 0, 2, "ExpressionSorter"); 17 | } 18 | 19 | Q_COREAPP_STARTUP_FUNCTION(registerSorterTypes) 20 | 21 | } 22 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/sortersqmltypes.h: -------------------------------------------------------------------------------- 1 | #ifndef SORTERSQMLTYPES_H 2 | #define SORTERSQMLTYPES_H 3 | 4 | namespace qqsfpm { 5 | 6 | void registerSorterTypes(); 7 | 8 | } 9 | 10 | #endif // SORTERSQMLTYPES_H 11 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sorters/stringsorter.h: -------------------------------------------------------------------------------- 1 | #ifndef STRINGSORTER_H 2 | #define STRINGSORTER_H 3 | 4 | #include "rolesorter.h" 5 | #include 6 | 7 | namespace qqsfpm { 8 | 9 | class StringSorter : public RoleSorter 10 | { 11 | Q_OBJECT 12 | Q_PROPERTY(Qt::CaseSensitivity caseSensitivity READ caseSensitivity WRITE setCaseSensitivity NOTIFY caseSensitivityChanged) 13 | Q_PROPERTY(bool ignorePunctation READ ignorePunctation WRITE setIgnorePunctation NOTIFY ignorePunctationChanged) 14 | Q_PROPERTY(QLocale locale READ locale WRITE setLocale NOTIFY localeChanged) 15 | Q_PROPERTY(bool numericMode READ numericMode WRITE setNumericMode NOTIFY numericModeChanged) 16 | 17 | public: 18 | using RoleSorter::RoleSorter; 19 | 20 | Qt::CaseSensitivity caseSensitivity() const; 21 | void setCaseSensitivity(Qt::CaseSensitivity caseSensitivity); 22 | 23 | bool ignorePunctation() const; 24 | void setIgnorePunctation(bool ignorePunctation); 25 | 26 | QLocale locale() const; 27 | void setLocale(const QLocale& locale); 28 | 29 | bool numericMode() const; 30 | void setNumericMode(bool numericMode); 31 | 32 | Q_SIGNALS: 33 | void caseSensitivityChanged(); 34 | void ignorePunctationChanged(); 35 | void localeChanged(); 36 | void numericModeChanged(); 37 | 38 | protected: 39 | int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const QQmlSortFilterProxyModel& proxyModel) const override; 40 | 41 | private: 42 | QCollator m_collator; 43 | }; 44 | 45 | } 46 | 47 | #endif // STRINGSORTER_H 48 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/sortfilterproxymodel.qdocconf: -------------------------------------------------------------------------------- 1 | project = SortFilterProxyModel 2 | description = lol 3 | 4 | sourcedirs = . 5 | 6 | sources.fileextensions = "*.cpp *.qdoc *.qml" 7 | headers.fileextensions = "*.h" 8 | 9 | outputdir = docs/ 10 | 11 | HTML.templatedir = . 12 | HTML.stylesheets = "D:\\coding\\Qt\\Docs\\Qt-5.8\\global\\template\\style\\offline.css" 13 | 14 | HTML.headerstyles = \ 15 | " \n" 16 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/SortFilterProxyModel.pro: -------------------------------------------------------------------------------- 1 | TEMPLATE = app 2 | TARGET = tst_sortfilterproxymodel 3 | QT += qml quick 4 | CONFIG += c++11 warn_on qmltestcase qml_debug no_keywords 5 | 6 | include(../SortFilterProxyModel.pri) 7 | 8 | HEADERS += \ 9 | indexsorter.h \ 10 | testroles.h 11 | 12 | SOURCES += \ 13 | tst_sortfilterproxymodel.cpp \ 14 | indexsorter.cpp \ 15 | testroles.cpp 16 | 17 | OTHER_FILES += \ 18 | tst_rangefilter.qml \ 19 | tst_indexfilter.qml \ 20 | tst_sourceroles.qml \ 21 | tst_sorters.qml \ 22 | tst_helpers.qml \ 23 | tst_builtins.qml \ 24 | tst_rolesorter.qml \ 25 | tst_stringsorter.qml \ 26 | tst_proxyroles.qml \ 27 | tst_joinrole.qml \ 28 | tst_switchrole.qml \ 29 | tst_expressionrole.qml 30 | 31 | DISTFILES += \ 32 | tst_filtercontainers.qml \ 33 | tst_regexprole.qml \ 34 | tst_filtersorter.qml \ 35 | tst_filterrole.qml 36 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/indexsorter.cpp: -------------------------------------------------------------------------------- 1 | #include "indexsorter.h" 2 | #include 3 | 4 | int IndexSorter::compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const 5 | { 6 | Q_UNUSED(proxyModel) 7 | return sourceLeft.row() - sourceRight.row(); 8 | } 9 | 10 | int ReverseIndexSorter::compare(const QModelIndex &sourceLeft, const QModelIndex &sourceRight, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const 11 | { 12 | Q_UNUSED(proxyModel) 13 | return sourceRight.row() - sourceLeft.row(); 14 | } 15 | 16 | void registerIndexSorterTypes() { 17 | qmlRegisterType("SortFilterProxyModel.Test", 0, 2, "IndexSorter"); 18 | qmlRegisterType("SortFilterProxyModel.Test", 0, 2, "ReverseIndexSorter"); 19 | } 20 | 21 | Q_COREAPP_STARTUP_FUNCTION(registerIndexSorterTypes) 22 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/indexsorter.h: -------------------------------------------------------------------------------- 1 | #ifndef INDEXSORTER_H 2 | #define INDEXSORTER_H 3 | 4 | #include "sorters/sorter.h" 5 | 6 | class IndexSorter : public qqsfpm::Sorter 7 | { 8 | public: 9 | using qqsfpm::Sorter::Sorter; 10 | int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const override; 11 | }; 12 | 13 | class ReverseIndexSorter : public qqsfpm::Sorter 14 | { 15 | public: 16 | using qqsfpm::Sorter::Sorter; 17 | int compare(const QModelIndex& sourceLeft, const QModelIndex& sourceRight, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) const override; 18 | }; 19 | 20 | #endif // INDEXSORTER_H 21 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/testroles.cpp: -------------------------------------------------------------------------------- 1 | #include "testroles.h" 2 | #include 3 | 4 | QVariant StaticRole::value() const 5 | { 6 | return m_value; 7 | } 8 | 9 | void StaticRole::setValue(const QVariant& value) 10 | { 11 | if (m_value == value) 12 | return; 13 | 14 | m_value = value; 15 | Q_EMIT valueChanged(); 16 | invalidate(); 17 | } 18 | 19 | QVariant StaticRole::data(const QModelIndex& sourceIndex, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) 20 | { 21 | Q_UNUSED(sourceIndex) 22 | Q_UNUSED(proxyModel) 23 | return m_value; 24 | } 25 | 26 | QVariant SourceIndexRole::data(const QModelIndex& sourceIndex, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) 27 | { 28 | Q_UNUSED(proxyModel) 29 | return sourceIndex.row(); 30 | } 31 | 32 | QStringList MultiRole::names() 33 | { 34 | return {"role1", "role2"}; 35 | } 36 | 37 | QVariant MultiRole::data(const QModelIndex&, const qqsfpm::QQmlSortFilterProxyModel&, const QString& name) 38 | { 39 | return "data for " + name; 40 | } 41 | 42 | void registerTestRolesTypes() { 43 | qmlRegisterType("SortFilterProxyModel.Test", 0, 2, "StaticRole"); 44 | qmlRegisterType("SortFilterProxyModel.Test", 0, 2, "SourceIndexRole"); 45 | qmlRegisterType("SortFilterProxyModel.Test", 0, 2, "MultiRole"); 46 | } 47 | 48 | Q_COREAPP_STARTUP_FUNCTION(registerTestRolesTypes) 49 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/testroles.h: -------------------------------------------------------------------------------- 1 | #ifndef TESTROLES_H 2 | #define TESTROLES_H 3 | 4 | #include "proxyroles/singlerole.h" 5 | #include 6 | 7 | class StaticRole : public qqsfpm::SingleRole 8 | { 9 | Q_OBJECT 10 | Q_PROPERTY(QVariant value READ value WRITE setValue NOTIFY valueChanged) 11 | public: 12 | using qqsfpm::SingleRole::SingleRole; 13 | 14 | QVariant value() const; 15 | void setValue(const QVariant& value); 16 | 17 | Q_SIGNALS: 18 | void valueChanged(); 19 | 20 | protected: 21 | 22 | private: 23 | QVariant data(const QModelIndex& sourceIndex, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) override; 24 | QVariant m_value; 25 | }; 26 | 27 | class SourceIndexRole : public qqsfpm::SingleRole 28 | { 29 | public: 30 | using qqsfpm::SingleRole::SingleRole; 31 | 32 | private: 33 | QVariant data(const QModelIndex& sourceIndex, const qqsfpm::QQmlSortFilterProxyModel& proxyModel) override; 34 | }; 35 | 36 | class MultiRole : public qqsfpm::ProxyRole 37 | { 38 | public: 39 | using qqsfpm::ProxyRole::ProxyRole; 40 | 41 | QStringList names() override; 42 | 43 | private: 44 | QVariant data(const QModelIndex &sourceIndex, const qqsfpm::QQmlSortFilterProxyModel &proxyModel, const QString &name) override; 45 | }; 46 | 47 | #endif // TESTROLES_H 48 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_builtins.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | 6 | Item { 7 | ListModel { 8 | id: testModel 9 | ListElement{role1: 1; role2: 1} 10 | ListElement{role1: 2; role2: 1} 11 | ListElement{role1: 3; role2: 2} 12 | ListElement{role1: 4; role2: 2} 13 | } 14 | ListModel { 15 | id: noRolesFirstTestModel 16 | function initModel() { 17 | noRolesFirstTestModel.append({role1: 1, role2: 1 }) 18 | noRolesFirstTestModel.append({role1: 2, role2: 1 }) 19 | noRolesFirstTestModel.append({role1: 3, role2: 2 }) 20 | noRolesFirstTestModel.append({role1: 4, role2: 2 }) 21 | } 22 | } 23 | SortFilterProxyModel { 24 | id: testProxyModel 25 | property string tag: "testProxyModel" 26 | sourceModel: testModel 27 | filterRoleName: "role2" 28 | filterValue: 2 29 | property var expectedData: ([{role1: 3, role2: 2}, {role1: 4, role2: 2}]) 30 | } 31 | SortFilterProxyModel { 32 | id: noRolesFirstTestProxyModel 33 | property string tag: "noRolesFirstTestProxyModel" 34 | sourceModel: noRolesFirstTestModel 35 | filterRoleName: "role2" 36 | filterValue: 2 37 | property var expectedData: ([{role1: 3, role2: 2}, {role1: 4, role2: 2}]) 38 | } 39 | TestCase { 40 | name: "BuiltinsFilterTests" 41 | function test_filterValue_data() { 42 | return [testProxyModel, noRolesFirstTestProxyModel]; 43 | } 44 | 45 | function test_filterValue(proxyModel) { 46 | if (proxyModel.sourceModel.initModel) 47 | proxyModel.sourceModel.initModel() 48 | var data = []; 49 | for (var i = 0; i < proxyModel.count; i++) 50 | data.push(proxyModel.get(i)); 51 | compare(data, proxyModel.expectedData); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_expressionrole.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import QtQml 2.2 6 | 7 | Item { 8 | property int c: 0 9 | ListModel { 10 | id: listModel 11 | ListElement { a: 1; b: 2 } 12 | } 13 | 14 | SortFilterProxyModel { 15 | id: testModel 16 | sourceModel: listModel 17 | 18 | proxyRoles: ExpressionRole { 19 | name: "expressionRole" 20 | expression: a + model.b + c 21 | } 22 | } 23 | 24 | Instantiator { 25 | id: instantiator 26 | model: testModel 27 | QtObject { 28 | property string expressionRole: model.expressionRole 29 | } 30 | } 31 | 32 | TestCase { 33 | name: "ExpressionRole" 34 | 35 | function test_expressionRole() { 36 | fuzzyCompare(instantiator.object.expressionRole, 3, 1e-7); 37 | listModel.setProperty(0, "b", 9); 38 | fuzzyCompare(instantiator.object.expressionRole, 10, 1e-7); 39 | c = 1327; 40 | fuzzyCompare(instantiator.object.expressionRole, 1337, 1e-7); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_filterrole.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import QtQml 2.2 6 | 7 | Item { 8 | ListModel { 9 | id: listModel 10 | ListElement { name: "1"; age: 18 } 11 | ListElement { name: "2"; age: 22 } 12 | ListElement { name: "3"; age: 45 } 13 | ListElement { name: "4"; age: 10 } 14 | } 15 | 16 | SortFilterProxyModel { 17 | id: testModel 18 | sourceModel: listModel 19 | 20 | proxyRoles: FilterRole { 21 | name: "isOldEnough" 22 | RangeFilter { 23 | id: ageFilter 24 | roleName: "age" 25 | minimumInclusive: true 26 | minimumValue: 18 27 | } 28 | } 29 | } 30 | TestCase { 31 | name: "FilterRole" 32 | 33 | function test_filterRole() { 34 | compare(testModel.get(0, "isOldEnough"), true); 35 | compare(testModel.get(1, "isOldEnough"), true); 36 | compare(testModel.get(2, "isOldEnough"), true); 37 | compare(testModel.get(3, "isOldEnough"), false); 38 | 39 | ageFilter.minimumValue = 21; 40 | 41 | compare(testModel.get(0, "isOldEnough"), false); 42 | compare(testModel.get(1, "isOldEnough"), true); 43 | compare(testModel.get(2, "isOldEnough"), true); 44 | compare(testModel.get(3, "isOldEnough"), false); 45 | } 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_filtersorter.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import QtQml 2.2 6 | 7 | Item { 8 | ListModel { 9 | id: listModel 10 | ListElement { name: "1"; favorite: true } 11 | ListElement { name: "2"; favorite: false } 12 | ListElement { name: "3"; favorite: false } 13 | ListElement { name: "4"; favorite: true } 14 | } 15 | 16 | SortFilterProxyModel { 17 | id: testModel 18 | sourceModel: listModel 19 | 20 | sorters: FilterSorter { 21 | ValueFilter { 22 | id: favoriteFilter 23 | roleName: "favorite" 24 | value: true 25 | } 26 | } 27 | } 28 | TestCase { 29 | name: "FilterSorter" 30 | 31 | function test_filterSorter() { 32 | compare(testModel.get(0, "name"), "1"); 33 | compare(testModel.get(1, "name"), "4"); 34 | compare(testModel.get(2, "name"), "2"); 35 | compare(testModel.get(3, "name"), "3"); 36 | 37 | favoriteFilter.value = false; 38 | 39 | compare(testModel.get(0, "name"), "2"); 40 | compare(testModel.get(1, "name"), "3"); 41 | compare(testModel.get(2, "name"), "1"); 42 | compare(testModel.get(3, "name"), "4"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_joinrole.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import QtQml 2.2 6 | 7 | Item { 8 | ListModel { 9 | id: listModel 10 | ListElement { firstName: "Justin"; lastName: "Timberlake" } 11 | } 12 | 13 | SortFilterProxyModel { 14 | id: testModel 15 | sourceModel: listModel 16 | 17 | proxyRoles: JoinRole { 18 | id: joinRole 19 | name: "fullName" 20 | roleNames: ["firstName", "lastName"] 21 | } 22 | } 23 | 24 | Instantiator { 25 | id: instantiator 26 | model: testModel 27 | QtObject { 28 | property string fullName: model.fullName 29 | } 30 | } 31 | 32 | TestCase { 33 | name: "JoinRole" 34 | 35 | function test_joinRole() { 36 | compare(instantiator.object.fullName, "Justin Timberlake"); 37 | listModel.setProperty(0, "lastName", "Bieber"); 38 | compare(instantiator.object.fullName, "Justin Bieber"); 39 | joinRole.roleNames = ["lastName", "firstName"]; 40 | compare(instantiator.object.fullName, "Bieber Justin"); 41 | joinRole.separator = " - "; 42 | compare(instantiator.object.fullName, "Bieber - Justin"); 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_proxyroles.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import SortFilterProxyModel.Test 0.2 6 | import QtQml 2.2 7 | 8 | Item { 9 | ListModel { 10 | id: listModel 11 | ListElement { test: "first"; keep: true } 12 | ListElement { test: "second"; keep: true } 13 | ListElement { test: "third"; keep: true } 14 | } 15 | 16 | SortFilterProxyModel { 17 | id: testModel 18 | sourceModel: listModel 19 | filters: [ 20 | ValueFilter { 21 | roleName: "keep" 22 | value: true 23 | }, 24 | ValueFilter { 25 | inverted: true 26 | roleName: "staticRole" 27 | value: "filterMe" 28 | } 29 | ] 30 | 31 | proxyRoles: [ 32 | StaticRole { 33 | id: staticRole 34 | name: "staticRole" 35 | value: "foo" 36 | }, 37 | StaticRole { 38 | id: renameRole 39 | name: "renameMe" 40 | value: "test" 41 | }, 42 | SourceIndexRole { 43 | name: "sourceIndexRole" 44 | }, 45 | MultiRole {} 46 | ] 47 | } 48 | 49 | Instantiator { 50 | id: instantiator 51 | model: testModel 52 | QtObject { 53 | property string staticRole: model.staticRole 54 | property int sourceIndexRole: model.sourceIndexRole 55 | } 56 | } 57 | 58 | TestCase { 59 | name: "ProxyRoles" 60 | 61 | function test_resetAfterNameChange() { 62 | var oldObject = instantiator.object; 63 | renameRole.name = "foobarRole"; 64 | var newObject = instantiator.object; 65 | verify(newObject !== oldObject, "Instantiator object should have been reinstantiated"); 66 | } 67 | 68 | function test_proxyRoleInvalidation() { 69 | compare(instantiator.object.staticRole, "foo"); 70 | staticRole.value = "bar"; 71 | compare(instantiator.object.staticRole, "bar"); 72 | } 73 | 74 | function test_proxyRoleGetDataFromSource() { 75 | compare(instantiator.object.sourceIndexRole, 0); 76 | compare(testModel.get(1, "sourceIndexRole"), 1); 77 | listModel.setProperty(1, "keep", false); 78 | compare(testModel.get(1, "sourceIndexRole"), 2); 79 | } 80 | 81 | function test_filterFromProxyRole() { 82 | staticRole.value = "filterMe"; 83 | compare(testModel.count, 0); 84 | staticRole.value = "foo"; 85 | } 86 | 87 | function test_multiRole() { 88 | compare(testModel.get(0, "role1"), "data for role1"); 89 | compare(testModel.get(0, "role2"), "data for role2"); 90 | } 91 | } 92 | } 93 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_regexprole.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtQml 2.2 3 | import QtTest 1.1 4 | import SortFilterProxyModel 0.2 5 | import QtQml 2.2 6 | 7 | Item { 8 | ListModel { 9 | id: listModel 10 | ListElement { dummyRole: false; compoundRole: "0 - zero"; unusedRole: "" } 11 | ListElement { dummyRole: false; compoundRole: "1 - one"; unusedRole: "" } 12 | ListElement { dummyRole: false; compoundRole: "2 - two"; unusedRole: "" } 13 | ListElement { dummyRole: false; compoundRole: "3 - three"; unusedRole: "" } 14 | ListElement { dummyRole: false; compoundRole: "four"; unusedRole: "" } 15 | } 16 | 17 | SortFilterProxyModel { 18 | id: testModel 19 | sourceModel: listModel 20 | 21 | proxyRoles: [ 22 | RegExpRole { 23 | id: regExpRole 24 | roleName: "compoundRole" 25 | pattern: "(?\\d+) - (?.+)" 26 | }, 27 | RegExpRole { 28 | id: caseSensitiveRole 29 | roleName: "compoundRole" 30 | pattern: "\\d+ - (?[A-Z]+)" 31 | caseSensitivity: Qt.CaseSensitive 32 | }, 33 | RegExpRole { 34 | id: caseInsensitiveRole 35 | roleName: "compoundRole" 36 | pattern: "\\d+ - (?[A-Z]+)" 37 | caseSensitivity: Qt.CaseInsensitive 38 | } 39 | ] 40 | } 41 | 42 | TestCase { 43 | name: "RegExpRole" 44 | 45 | function test_regExpRole() { 46 | compare(testModel.get(0, "id"), "0"); 47 | compare(testModel.get(1, "id"), "1"); 48 | compare(testModel.get(0, "name"), "zero"); 49 | compare(testModel.get(4, "id"), undefined); 50 | compare(testModel.get(0, "nameCS"), undefined); 51 | compare(testModel.get(0, "nameCIS"), "zero"); 52 | } 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_rolesorter.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import SortFilterProxyModel 0.2 3 | import QtQml.Models 2.2 4 | import QtTest 1.1 5 | 6 | Item { 7 | property list sorters: [ 8 | RoleSorter { 9 | property string tag: "intRole" 10 | property var expectedValues: [1, 2, 3, 4, 5] 11 | roleName: "intRole" 12 | }, 13 | RoleSorter { 14 | property string tag: "intRoleDescending" 15 | property var expectedValues: [5, 4, 3, 2, 1] 16 | roleName: "intRole" 17 | sortOrder: Qt.DescendingOrder 18 | }, 19 | RoleSorter { 20 | property string tag: "stringRole" 21 | property var expectedValues: ["a", "b", "c", "d", "e"] 22 | roleName: "stringRole" 23 | }, 24 | RoleSorter { 25 | property string tag: "stringRoleDescending" 26 | property var expectedValues: ["e", "d", "c", "b", "a"] 27 | roleName: "stringRole" 28 | sortOrder: Qt.DescendingOrder 29 | }, 30 | RoleSorter { 31 | property string tag: "mixedCaseStringRole" 32 | property var expectedValues: ["A", "b", "C", "D", "e"] 33 | roleName: "mixedCaseStringRole" 34 | } 35 | ] 36 | 37 | ListModel { 38 | id: dataModel 39 | ListElement { intRole: 5; stringRole: "c"; mixedCaseStringRole: "C" } 40 | ListElement { intRole: 3; stringRole: "e"; mixedCaseStringRole: "e" } 41 | ListElement { intRole: 1; stringRole: "d"; mixedCaseStringRole: "D" } 42 | ListElement { intRole: 2; stringRole: "a"; mixedCaseStringRole: "A" } 43 | ListElement { intRole: 4; stringRole: "b"; mixedCaseStringRole: "b" } 44 | } 45 | 46 | SortFilterProxyModel { 47 | id: testModel 48 | sourceModel: dataModel 49 | } 50 | 51 | TestCase { 52 | name: "RoleSorterTests" 53 | 54 | function test_roleSorters_data() { 55 | return sorters; 56 | } 57 | 58 | function test_roleSorters(sorter) { 59 | testModel.sorters = sorter; 60 | 61 | verify(testModel.count === sorter.expectedValues.length, 62 | "Expected count " + sorter.expectedValues.length + ", actual count: " + testModel.count); 63 | for (var i = 0; i < testModel.count; i++) 64 | { 65 | var modelValue = testModel.get(i, sorter.roleName); 66 | verify(modelValue === sorter.expectedValues[i], 67 | "Expected testModel value " + sorter.expectedValues[i] + ", actual: " + modelValue); 68 | } 69 | } 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_sortfilterproxymodel.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | QUICK_TEST_MAIN(SortFilterProxyModel) 3 | -------------------------------------------------------------------------------- /thirdparty/SortFilterProxyModel/tests/tst_sourceroles.qml: -------------------------------------------------------------------------------- 1 | import QtQuick 2.0 2 | import QtTest 1.1 3 | import QtQml 2.2 4 | import SortFilterProxyModel 0.2 5 | 6 | Item { 7 | ListModel { 8 | id: nonEmptyFirstModel 9 | ListElement { 10 | test: "test" 11 | } 12 | } 13 | SortFilterProxyModel { 14 | id: nonEmptyFirstProxyModel 15 | sourceModel: nonEmptyFirstModel 16 | } 17 | Instantiator { 18 | id: nonEmptyFirstInstantiator 19 | model: nonEmptyFirstProxyModel 20 | QtObject { property var test: model.test } 21 | } 22 | 23 | ListModel { 24 | id: emptyFirstModel 25 | } 26 | SortFilterProxyModel { 27 | id: emptyFirstProxyModel 28 | sourceModel: emptyFirstModel 29 | } 30 | Instantiator { 31 | id: emptyFirstInstantiator 32 | model: emptyFirstProxyModel 33 | QtObject { property var test: model.test } 34 | } 35 | 36 | TestCase { 37 | name: "RoleTests" 38 | 39 | function test_nonEmptyFirst() { 40 | compare(nonEmptyFirstInstantiator.object.test, "test"); 41 | } 42 | 43 | function test_emptyFirst() { 44 | emptyFirstModel.append({test: "test"}); 45 | compare(emptyFirstProxyModel.get(0), {test: "test"}); 46 | compare(emptyFirstInstantiator.object.test, "test"); 47 | } 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /thirdparty/thirdparty.pri: -------------------------------------------------------------------------------- 1 | INCLUDEPATH += $$PWD 2 | 3 | include(QtQmlTricks/QtQmlTricks.pri) 4 | include(SortFilterProxyModel/SortFilterProxyModel.pri) 5 | --------------------------------------------------------------------------------