Skip to content
  • 0 Votes
    5 Posts
    2k Views
    E

    Like in your example as of now I think I'd make one tree model.

    I had considered creating a tree model, but I have some reservations. Store, Department, and Employee have additional responsibilities beyond being simple data containers, and I worry that either I end up decoupling the data from the logic (which goes against OOP principles), or I have to subclass the three classes from a common class, override functions, and therefore haven't achieved clear separation of UI and business logic.

    To my mind at least, it makes sense to design this as if it were a command line application, and then throw some code on top to interface with a GUI. Maybe that's not the right way to think about things, but I don't like the idea of the GUI framework I'm using dictating how I should structure my data.

    Aren't you describing a use case for a database and thus Qt's SQL module and its models ?

    Truthfully, the application has nothing to do with stores, departments, or employees. I changed the names to make the problem easier to reason with. I don't think the data layout is so complex that it justifies introducing relational databases. And besides, with the very frequent live updates coming over the network I can see latency issues arising.

  • 0 Votes
    8 Posts
    705 Views
    H

    The issue was solved Add child model in parent repeater's Compoenet.onCompleted.

    Repeater { id: repeater1 model: backend.graphModel Component.onCompleted: { repeater2.model = model.GraphMaximumCount } } Repeater { id: repeater2 }
  • 0 Votes
    2 Posts
    404 Views
    JonBJ

    @Babs
    I presume that if you don't use d&d it's just a question of intercepting the keypresses in the list view and acting as desired on them, e.g. move an item at one index in the model to another index.

  • 0 Votes
    12 Posts
    2k Views
    T

    @fcarney I put the QAbstractItemModelTester in both my model, and my proxy model, and... no errors. I also swapped it to FailureReportingMode::Fatal to double check, and nothing. The endless calls to data from VXYModelMapper continue.

  • 0 Votes
    2 Posts
    445 Views
    E

    Still not sure what's the best design here.

  • 0 Votes
    3 Posts
    771 Views
    Q

    @VRonin said in How to propagate changes in SingleTon type custom QAbstractListModel on QML ListView?:

    @qml.newbie said in How to propagate changes in SingleTon type custom QAbstractListModel on QML ListView?:

    m_hackNewsList.append(HackNews{id, deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});

    You need to call beginInsertRows/endInsertRows before/after m_hackNewsList.append(HackNews{id, deleted, type, by, time, text, dead, parentId, pollId, kidsIdList, url, score, title, partsIdList, descendantCount});

    I have now added these lines but even now it's not working. Could be down to something I did wrong in the main.cpp where I'm registering the model for qml? The main cpp file is as below.

    #include <QGuiApplication> #include <QQmlApplicationEngine> #include "NetworkRequestMaker.h" #include "HackNewsModel.h" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); NetworkRequestMaker testRequestMaker; qmlRegisterType<HackNewsModel>("Hacknews", 1, 0, "HackNewsModel"); QQmlApplicationEngine engine; const QUrl url(QStringLiteral("qrc:/main.qml")); QObject::connect(&engine, &QQmlApplicationEngine::objectCreated, &app, [url](QObject *obj, const QUrl &objUrl) { if (!obj && url == objUrl) QCoreApplication::exit(-1); }, Qt::QueuedConnection); engine.load(url); return app.exec(); }
  • 0 Votes
    5 Posts
    3k Views
    C

    @SGaist

    When I remove the dataChanged(index,index) no update gets recognized.
    When I manually set the role vector to dataChanged(index, index, role) it behaves the same way as without the role specification (updates the current element, not the other ones).

    As per https://forum.qt.io/topic/39357/solved-qabstractitemmodel-datachanged-question/6 , I noticed that the other elements have to get a "recompute" signal and tried the following:

    bool setData(const QModelIndex & index, const QVariant & value, int role) override { // ... QModelIndex toIndex(createIndex(rowCount() - 1, index.column())); qDebug() << toIndex.row() << ',' << toIndex.column(); emit dataChanged(index, toIndex); }

    Which should've helped and would've made sense as it helped in the other thread, but it didn't trigger a recomputation :( I found this blogpost which discusses the problem at hand, but solves it in QML only because he would use the dataChanged signal in C++.

    EDIT: Marking this question as solved as my solution with the resetModel() worked. I had to implement a similar functionality with the same model, which was also dependent on the dataChanged signal, but it worked without resetModel. The only difference was that this functionality was encapsulated in a single "Item", e.g (color choose dialog -> change multiple textfields in the same "row").

  • 0 Votes
    3 Posts
    565 Views
    K

    @SGaist

    Thanks for pointing into that direction. It does work.

  • 0 Votes
    8 Posts
    3k Views
    VRoninV

    @milan said in How to implement checkstate for QAbstractItemModel or QAbstractListModel:

    I cannot hide the checkboxes

    if you return QVariant() for the CheckStateRole the checkbox will not appear in the default delegate (QStyledItemDelegate)

  • 0 Votes
    4 Posts
    600 Views
    Christian EhrlicherC

    Once again: When you add the role to your debug output you will for sure notice that the data for Qt::ToolTipRole is requested (and maybe Qt::BackgroundRole / TextRole because the item is repainted)

  • 0 Votes
    2 Posts
    3k Views
    romsharkovR

    After hours of google, trial and error I'm proud to finally have solved it myself as I am still pretty new to Qt!

    To help people with a similar problem I'll quickly sum up all I had to do to make it work:

    turn the internal QList<Message> into a QList<QSharedPointer<Message>>

    define a QMap<QString, QSharedPointer<Message>> to hold index ids to the individual messages

    when inserting, insert in the indexMap as well

    define a method in the QAbstractListModel derived MessageList which simply returns a QVariantMap

    P.S. Below is the new working version of the example app, in case anyone notices any misconceptions, please let me know

    MessageList.hpp:

    #ifndef MESSAGELIST_HPP #define MESSAGELIST_HPP #include "Message.hpp" #include <QObject> #include <QAbstractListModel> #include <QModelIndex> #include <QList> #include <QHash> #include <QVariant> #include <QMap> #include <QSharedPointer> class MessageList : public QAbstractListModel { Q_OBJECT public: typedef QSharedPointer<Message> MessagePointer; typedef QList<MessagePointer> MessagePointerList; typedef QMap<QString, MessagePointer> IndexMap; enum Roles { IdentifierRole, TitleRole, MessageRole, }; protected: MessagePointerList _list; IndexMap _indexMap; public: MessageList(); int rowCount(const QModelIndex& parent) const; QHash<int, QByteArray> roleNames() const; QVariant data(const QModelIndex& index, int role) const; bool insert( const QList<Message>& messages, int position = 0 ); bool reset(); Q_INVOKABLE QVariantMap get(const QString& identifier) const; const Message& at(int index) const; }; #endif // MESSAGELIST_HPP

    MessageList.cpp:

    #include "MessageList.hpp" #include <QObject> #include <QModelIndex> #include <QVariant> #include <QHash> #include <QByteArray> MessageList::MessageList() : QAbstractListModel(nullptr) { } int MessageList::rowCount(const QModelIndex& parent) const { Q_UNUSED(parent) return _list.size(); } QHash<int, QByteArray> MessageList::roleNames() const { QHash<int, QByteArray> roles; roles[IdentifierRole] = "identifier"; roles[TitleRole] = "title"; roles[MessageRole] = "message"; return roles; } QVariant MessageList::data(const QModelIndex& index, int role) const { if(!index.isValid() || index.row() >= _list.size() || index.row() < 0 ) { return QVariant(); } switch(role) { case IdentifierRole: return _list.at(index.row())->identifier(); break; case TitleRole: return _list.at(index.row())->title(); break; case MessageRole: return _list.at(index.row())->message(); break; default: return QVariant(); } } bool MessageList::insert( const QList<Message>& messages, int position ) { beginInsertRows(QModelIndex(), position, position + messages.size() - 1); for(int row = 0; row < messages.size(); ++row) { IndexMap::const_iterator indexMapItr(_indexMap.constFind(messages.at(row).identifier())); if(indexMapItr == _indexMap.constEnd()) { MessagePointer newMessage(new Message(messages.at(row))); _list.insert(position, newMessage); _indexMap.insert(messages.at(row).identifier(), newMessage); } } endInsertRows(); return true; } bool MessageList::reset() { beginResetModel(); _list.clear(); __indexMap.clear(); endResetModel(); return true; } QVariantMap MessageList::get(const QString& identifier) const { QVariantMap result; IndexMap::const_iterator indexMapItr(_indexMap.constFind(identifier)); if(indexMapItr != _indexMap.constEnd()) { result["identifier"] = QVariant(indexMapItr->data()->identifier()); result["title"] = QVariant(indexMapItr->data()->title()); result["message"] = QVariant(indexMapItr->data()->message()); } return result; } const Message& MessageList::at(int index) const { return *(_list.at(index).data()); }

    main.cpp:

    #include <QGuiApplication> #include <QQmlApplicationEngine> #include <QQmlContext> #include "Message.hpp" #include "MessageList.hpp" int main(int argc, char *argv[]) { QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling); QGuiApplication app(argc, argv); MessageList messageList; messageList.insert(QList<Message> { Message("a", "first message", "this is a sample text message of the first message"), Message("b", "second message", "another sample text message of the second message"), Message("c", "third message", "yet a third text message sample"), Message("d", "fouth message", "last sample message") }); QQmlApplicationEngine engine; engine.rootContext()->setContextProperty("MessageList", &messageList); engine.load(QUrl(QLatin1String("qrc:/main.qml"))); return app.exec(); }

    main.qml:

    import QtQuick 2.7 import QtQuick.Controls 2.0 import QtQuick.Layouts 1.0 ApplicationWindow { visible: true width: 640 height: 480 title: qsTr("Messages") Rectangle { id: menu color: Qt.rgba(0.9, 0.9, 0.9, 1) height: 32 anchors.top: parent.top anchors.left: parent.left anchors.right: parent.right Text { anchors.left: parent.left anchors.margins: 8 anchors.verticalCenter: parent.verticalCenter text: "at id 'b' there is: " + MessageList.get("b").title } } ListView { model: MessageList anchors.top: menu.bottom anchors.left: parent.left anchors.right: parent.right anchors.bottom: parent.bottom clip: true delegate: Rectangle { height: 32 Column { anchors.fill: parent anchors.margins: 8 spacing: 2 Text { text: title + " (" + identifier + ")" font.bold: true } Text { text: message } } } } }
  • 0 Votes
    3 Posts
    4k Views
    romsharkovR

    @SGaist returning a pointer in the getter and defining the Q_PROPERTY as a pointer to the list worked out fine! Thanks for that!

  • 0 Votes
    11 Posts
    4k Views
    R

    @SGaist OS X 10.10 and Win 10

  • 0 Votes
    10 Posts
    6k Views
    GrecKoG

    When no roles are passed as a parameter, all roles ares assumed to be changed.

    The most likely error of OP is to not call begin/endInsertRows (or modelReset is all the model is changed)

  • 1 Votes
    6 Posts
    6k Views
    p3c0P

    @KiNgFrUiT You're Welcome :) Thanks for sharing the complete solution. Also it would be better if you mark the post as solved so that others may know that the post has a solution.

  • 0 Votes
    2 Posts
    2k Views
    E

    From the QT documentation it seem to be possible : Exposing Attributes of C++ Types to QML

    Any data that is transferred from C++ to QML, whether as a property value, a method parameter or return value, or a signal parameter value, must be of a type that is supported by the QML engine.

    So why it is not working ? Is any of you succeed returning one or more object through method parameters ?

  • 0 Votes
    3 Posts
    2k Views
    V

    Hi

    try to use Binding to your CheckBox:

    Binding { target: checkbox property: 'checked' value: checkboxenable }

    where checkboxenable is role in your model

  • 0 Votes
    2 Posts
    2k Views
    p3c0P

    @JDGXNV
    The delegates are recycled every-time you scroll which means there are created and destroyed as and when required internally (More here: delegate). Caching them disables it. So I guess the problem should be on the delegate side i.e the delegate is trying to access some property which it is not able and hence crashes.

  • 0 Votes
    10 Posts
    27k Views
    A

    @SiliconKiwi helps, thanks.

  • 0 Votes
    5 Posts
    10k Views
    J

    @clogwog As expected