added available levels model

This commit is contained in:
Andrei Yankovich 2021-08-15 12:47:44 +03:00
parent ce75c0c5ee
commit 2a376488c8
10 changed files with 482 additions and 126 deletions

View File

@ -26,5 +26,6 @@
<file>CrawlModule/particles/Wint.qml</file>
<file>CrawlModule/PreviewControl.qml</file>
<file>CrawlModule/StoreView.qml</file>
<file>CrawlModule/SelectLevelView.qml</file>
</qresource>
</RCC>

View File

@ -0,0 +1,64 @@
import QtQuick
import ViewSolutionsModule
import QtQuick.Controls
import QtQuick.Controls.Material
import QtQuick.Layouts
Page {
id: store
property var model: null;
visible: model && model.visible
ColumnLayout {
anchors.fill: parent
ListView {
id: listView
Layout.fillHeight: true
Layout.fillWidth: true
model: store.model
delegate: delegateRow
Component {
id: delegateRow
Rectangle {
anchors.fill: parent
color: (itemId == currentLevel) ? "#ffaf2c": "#00000000"
RowLayout {
width: listView.width
height: 100
Image {
id: img
fillMode: Image.PreserveAspectCrop
source: itemImage
Layout.fillHeight: true
Layout.preferredWidth: height * 2
}
Label {
text: itemName
Layout.fillHeight: true
}
Label {
text: itemDescription
Layout.fillWidth: true
Layout.fillHeight: true
}
Button {
text: qsTr("Select");
visible: !itemWasBuy
onClicked: () => {
if (store.model)
store.model.select(itemId);
}
}
}
}
}
}
}
}

View File

@ -0,0 +1,45 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "availablelevelsmodel.h"
#include "user.h"
#include <Crawl/iitem.h>
namespace CRAWL {
AvailableLevelsModel::AvailableLevelsModel() {
}
void AvailableLevelsModel::setAllLevels(const QList<const IItem *> &newAllLevels) {
_allLevels = newAllLevels;
QList<int> keys;
for (auto level: qAsConst(_allLevels)) {
keys += level->itemId();
}
setKeys(keys);
}
int AvailableLevelsModel::getCurrentLevel() const {
return currentLevel;
}
void AvailableLevelsModel::setCurrentLevel(int newCurrentLevel) {
if (currentLevel == newCurrentLevel)
return;
currentLevel = newCurrentLevel;
emit currentLevelChanged();
}
void AvailableLevelsModel::select(int levelId) {
if (getUser()->isUnlocked(levelId)) {
emit sigUserSelectLevel(levelId);
}
}
}

View File

@ -0,0 +1,88 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef AVAILABLELEVELSMODEL_H
#define AVAILABLELEVELSMODEL_H
#include "baseuserlistmodel.h"
namespace CRAWL {
class User;
class IItem;
/**
* @brief The AvailableLevelsModel class is model of the available levels qml view.
* This model just show available levels of the current user.
*/
class AvailableLevelsModel: public BaseUserListModel
{
Q_OBJECT
/**
* @brief currentLevel This property contains id of the loaded level.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
Q_PROPERTY(int currentLevel READ getCurrentLevel WRITE setCurrentLevel NOTIFY currentLevelChanged)
public:
AvailableLevelsModel();
/**
* @brief setAllLevels This method sets list of the available levels in game.
* @param newAllLevels This is new value of thge availabel games list.
*/
void setAllLevels(const QList<const IItem *> &newAllLevels);
/**
* @brief getCurrentLevel This method return value of the curernt level property
* @return value of the curernt level property
* @see AvailableLevelsModel::currentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
int getCurrentLevel() const;
/**
* @brief setCurrentLevel This method sets new current level.
* @param newCurrentLevel This is new value of the current level.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::currentLevel
* @see AvailableLevelsModel::currentLevelChanged
*/
void setCurrentLevel(int newCurrentLevel);
/**
* @brief select This method select new level of user.
* @param levelId This is id of the selected level.
*/
Q_INVOKABLE void select(int levelId);
signals:
/**
* @brief currentLevelChanged This signal emited when the currentLevel propertye is changed.
* @see AvailableLevelsModel::getCurrentLevel
* @see AvailableLevelsModel::setCurrentLevel
* @see AvailableLevelsModel::currentLevel
*/
void currentLevelChanged();
/**
* @brief sigUserSelectLevel This signal emited when user select new level.
* @param level This is level id that user selected.
*/
void sigUserSelectLevel(int level);
private:
QList<const IItem*> _allLevels;
int currentLevel = -1;
};
}
#endif // AVAILABLELEVELSMODEL_H

View File

@ -0,0 +1,144 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#include "baseuserlistmodel.h"
#include "user.h"
#include <Crawl/iitem.h>
namespace CRAWL {
BaseUserListModel::BaseUserListModel() {
}
void BaseUserListModel::setUser(User *newUser) {
if (_user) {
disconnect(_user, &User::sigDropped,
this, &BaseUserListModel::handleDroppedItem);
disconnect(_user, &User::sigUnlcoked,
this, &BaseUserListModel::handleUnlockedItem);
disconnect(_user, &User::sigUlockedItemsChanged,
this, &BaseUserListModel::handleUnlockedItemsListChanged);
}
_user = newUser;
if (_user) {
connect(_user, &User::sigDropped,
this, &BaseUserListModel::handleDroppedItem);
connect(_user, &User::sigUnlcoked,
this, &BaseUserListModel::handleUnlockedItem);
connect(_user, &User::sigUlockedItemsChanged,
this, &BaseUserListModel::handleUnlockedItemsListChanged);
}
}
int BaseUserListModel::getIndexById(int id) const {
return _keysIndexes.value(id, -1);
}
const QList<int> &BaseUserListModel::keys() const {
return _keys;
}
void BaseUserListModel::setKeys(const QList<int> &visibleKeysList) {
int diff = visibleKeysList.size() - _keys.size();
auto update = [this](const QList<int> & list) {
_keys = list;
for (int index = 0; index < _keys.size(); ++index) {
_keysIndexes[_keys[index]] = index;
}
};
if (diff > 0) {
beginInsertRows({}, _keys.size(), visibleKeysList.size() - 1);
update(visibleKeysList);
endInsertRows();
} else if (diff == 0) {
emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1));
} else {
beginRemoveRows({}, visibleKeysList.size(), _keys.size() - 1);
update(visibleKeysList);
endRemoveRows();
}
}
int BaseUserListModel::rowCount(const QModelIndex &) const {
return _keys.size();
}
int BaseUserListModel::columnCount(const QModelIndex &) const {
return 1;
}
QVariant BaseUserListModel::data(const QModelIndex &index, int role) const {
if (index.row() >= rowCount()) {
return {};
}
int id = _keys.at(index.row());
const IItem* item = getItem(id);
if (!item)
return {};
switch (role) {
case ItemId: return id;
case ItemName: return item->itemName();
case ItemImage: return item->image();
case ItemDescription: return item->description();
case ItemWasBuy: return getUser() && getUser()->isUnlocked(id);
default:
return {};
}
}
QHash<int, QByteArray> BaseUserListModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[ItemId] = "itemId";
roles[ItemName] = "itemName";
roles[ItemDescription] = "itemDescription";
roles[ItemImage] = "itemImage";
roles[ItemWasBuy] = "itemWasBuy";
return roles;
}
User *BaseUserListModel::getUser() const {
return _user;
}
void BaseUserListModel::handleUnlockedItem(int item) {
int idx = _keysIndexes.value(item, -1);
if (idx >= 0) {
emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy});
}
}
void BaseUserListModel::handleDroppedItem(int item) {
int idx = _keysIndexes.value(item, -1);
if (idx >= 0) {
emit dataChanged(index(idx,0), index(idx, 0), {ItemWasBuy});
}
}
void BaseUserListModel::handleUnlockedItemsListChanged(const QSet<int> &) {
emit dataChanged(index(0,0), index(_keys.size() - 1, 0), {ItemWasBuy});
}
}

View File

@ -0,0 +1,107 @@
//#
//# Copyright (C) 2021-2021 QuasarApp.
//# Distributed under the GPLv3 software license, see the accompanying
//# Everyone is permitted to copy and distribute verbatim copies
//# of this license document, but changing it is not allowed.
//#
#ifndef BASEUSERLISTMODEL_H
#define BASEUSERLISTMODEL_H
#include <QAbstractListModel>
namespace CRAWL {
class User;
class IItem;
/**
* @brief The BaseUserListModel class This is base class wint implementation methods for working with user object.
*/
class BaseUserListModel: public QAbstractListModel
{
Q_OBJECT
public:
BaseUserListModel();
/**
* @brief setUser This method update user pointer
* @param user This is new pointer to current user.
*/
void setUser(User *newUser);
/**
* @brief keys This method retutn curent visible items list.
* @return visible items list.
* @see BaseUserListModel::setKeys
*/
const QList<int> &keys() const;
/**
* @brief setKeys This method sets lsit of the keys for view.
* @param visibleKeysList This is new valud of the visible keys list.
* @see BaseUserListModel::keys
*/
void setKeys(const QList<int>& visibleKeysList);
int rowCount(const QModelIndex &parent = {}) const override;
int columnCount(const QModelIndex &parent = {}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
protected:
/**
* @brief getUser This method return pointer to current user.
* @return pointer to current user.
*/
User* getUser() const;
/**
* @brief handleUnlockedItem This slot invoked when emited the User::unclokItem signal.
* @param item This is id of the unlocked item
*/
virtual void handleUnlockedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::droppItem signal.
* @param item This is id of the dropped item
*/
virtual void handleDroppedItem(int item);
/**
* @brief handleUnlockedItem This slot invoked when emited the User::setUnlockedItems signal.
* @param item This is new list of the unclod items.
*/
virtual void handleUnlockedItemsListChanged(const QSet<int>& newSet);
/**
* @brief getItem This method should be return the item by id. Override this method for correct works this model.
* @param id This is item id
* @return const pointer to item object.
*/
virtual const IItem* getItem(int id) const = 0;
/**
* @brief getIndexById This method return index of the item by id.
* @param id This is id of the needed item
* @return index of the needed item. If the item with id not exists then return -1
*/
int getIndexById(int id) const;
private:
enum ViewItemRoles {
ItemId,
ItemName,
ItemImage,
ItemDescription,
ItemWasBuy
};
User * _user = nullptr;
QList<int> _keys;
QHash<int, int> _keysIndexes;
};
}
#endif // BASEUSERLISTMODEL_H

View File

@ -10,95 +10,10 @@ StoreViewModel::StoreViewModel() {
}
int StoreViewModel::rowCount(const QModelIndex &) const {
return _keys.size();
}
int StoreViewModel::columnCount(const QModelIndex &) const {
return 1;
}
QVariant StoreViewModel::data(const QModelIndex &index, int role) const {
if (!_store)
return {};
if (index.row() >= rowCount()) {
return {};
}
int id = _keys.at(index.row());
const IItem* item = _store->getItemById(id);
if (!item)
return {};
switch (role) {
case ItemId: return id;
case ItemName: return item->itemName();
case ItemImage: return item->image();
case ItemDescription: return item->description();
case ItemWasBuy: return _currentUser && _currentUser->isUnlocked(id);
default:
return {};
}
}
QHash<int, QByteArray> StoreViewModel::roleNames() const {
QHash<int, QByteArray> roles;
roles[ItemId] = "itemId";
roles[ItemName] = "itemName";
roles[ItemDescription] = "itemDescription";
roles[ItemImage] = "itemImage";
roles[ItemWasBuy] = "itemWasBuy";
return roles;
}
void StoreViewModel::init(Store *store, User *user) {
setUser(user);
int diff = store->size() - _keys.size();
auto update = [this](Store *store) {
_store = store;
_keys = store->keysList();
for (int index = 0; index < _keys.size(); ++index) {
_keysIndexes[index] = _keys[index];
}
};
if (diff > 0) {
beginInsertRows({}, _keys.size(), store->size() - 1);
update(store);
endInsertRows();
} else if (diff == 0) {
emit dataChanged(index(0,0), index(rowCount() - 1, columnCount() - 1));
} else {
beginRemoveRows({}, store->size(), _keys.size() - 1);
update(store);
endRemoveRows();
}
}
void StoreViewModel::setUser(User *user) {
if (_currentUser) {
disconnect(_currentUser, &User::sigItemsUlocked,
this, &StoreViewModel::handleItemsUnlocked);
}
_currentUser = user;
if (_currentUser) {
connect(_currentUser, &User::sigItemsUlocked,
this, &StoreViewModel::handleItemsUnlocked);
handleItemsUnlocked(_currentUser->unlockedItems());
}
setKeys(store->keysList());
_store = store;
}
bool StoreViewModel::visible() const {
@ -113,15 +28,16 @@ void StoreViewModel::setVisible(bool newVisible) {
}
void StoreViewModel::buy(int item) {
if (_store && _currentUser) {
_store->buy(*_currentUser, item);
if (_store && getUser()) {
_store->buy(*getUser(), item);
}
}
void StoreViewModel::handleItemsUnlocked (const QSet<int> & ) {
emit dataChanged(index(0,0), index(_keys.size() - 1, 0), {ItemWasBuy});
const IItem *StoreViewModel::getItem(int id) const {
if (!_store)
return nullptr;
return _store->getItemById(id);
}
}

View File

@ -8,7 +8,7 @@
#ifndef STOREVIEWMODEL_H
#define STOREVIEWMODEL_H
#include <QAbstractListModel>
#include "baseuserlistmodel.h"
namespace CRAWL {
@ -18,7 +18,7 @@ class User;
/**
* @brief The StoreViewModel class This is view model of the store. The object of this class should be initialized it he Store class.
*/
class StoreViewModel: public QAbstractListModel
class StoreViewModel: public BaseUserListModel
{
Q_OBJECT
/**
@ -29,11 +29,6 @@ class StoreViewModel: public QAbstractListModel
public:
StoreViewModel();
int rowCount(const QModelIndex &parent = {}) const override;
int columnCount(const QModelIndex &parent = {}) const override;
QVariant data(const QModelIndex &index, int role) const override;
QHash<int, QByteArray> roleNames() const override;
/**
* @brief init This method initialize data of the view model.
* @param _store This is poiter to store that contains all inforamtion about store items.
@ -42,12 +37,6 @@ public:
*/
void init(Store * store, User* user);
/**
* @brief setUser This method update user pointer
* @param user This is new pointer to current user.
*/
void setUser(User* user);
/**
* @brief visible This method return true if the store view is visible.
* @return true if the store view is visible.
@ -66,33 +55,20 @@ public:
*/
Q_INVOKABLE void buy(int item);
// BaseUserListModel interface
protected:
const IItem *getItem(int id) const;
signals:
/**
* @brief visibleChanged This slot emited when store visibel changed
*/
void visibleChanged();
private slots:
void handleItemsUnlocked(const QSet<int> &);
private:
void updateView();
enum StoreRoles {
ItemId,
ItemName,
ItemImage,
ItemDescription,
ItemWasBuy
};
Store *_store = nullptr;
QList<int> _keys;
QHash<int, int> _keysIndexes;
User* _currentUser = nullptr;
bool _visible = false;
};
}

View File

@ -60,16 +60,17 @@ bool User::isUnlocked(int item) const {
void User::unclokItem(int item) {
_unlockedItems.insert(item);
emit sigItemsUlocked({item});
emit sigUnlcoked(item);
}
void User::droppItem(int item) {
_unlockedItems.remove(item);
emit sigDropped(item);
}
void User::setUnlockedItems(const QSet<int> &newUnlockedItems) {
_unlockedItems = newUnlockedItems;
emit sigItemsUlocked(newUnlockedItems);
emit sigUlockedItemsChanged(newUnlockedItems);
}
int User::recalcTier() {

View File

@ -145,10 +145,24 @@ signals:
void xpChanged();
/**
* @brief sigItemsUlocked This signal emited when user unlocked item.
* @brief sigUlockedItemsChanged This signal emited when users list of unclode items is changed..
* @param unclokedItems This is unlocked items set. Each items in the set is id of the unclocked item.
*/
void sigItemsUlocked(const QSet<int> & unclokedItems);
void sigUlockedItemsChanged(const QSet<int> & unclokedItems);
/**
* @brief sigUnlcoked This signal emmited when user unlock one item.
* @param item This is unlocked item id.
* @see User::unclokItem
*/
void sigUnlcoked(int item);
/**
* @brief sigDropped This signal emmited when user dropped one item.
* @param item This is dpopped item id.
* @see User::droppItem
*/
void sigDropped(int item);
protected:
/**