Russian Qt Forum
Апрель 27, 2024, 16:46 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перерисовка модели в TreeView с сохранением состояния  (Прочитано 3402 раз)
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« : Ноябрь 10, 2023, 18:11 »

Всем привет.
Есть treeView в котормо рисуется bookmark дерево. Есть оглавления и под оглавления, и само собою можно арскрывать их.
Со стороны логики прилетает изменение номера текущей страницы и я в этмо случаи должен отметить в модели цветом нужный пункт, но этого не происходит.
Вопрос: как обновить модель без beginResetModel() и endResetModel()? Или как сохранить состояние открытых пунктов?

Благодарю.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #1 : Ноябрь 10, 2023, 20:26 »

можно попробовать поменять свойство айтема напрямую через itemAtCell() / itemAtIndex(), но подход с обновлением модели мне кажется более правильным. Как сохранить состояние пунктов — ну ручками и сохранить Улыбающийся и в модели возвращать сохраненное состояние для соответствующей роли.
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #2 : Ноябрь 11, 2023, 17:28 »


Вот на первой картинке тут на 1 страние 3 раздела, под намерами 1, 1.1 и 1.2.
Само собою границами отмечается у меня все пункты что на 1 странице, то есть на текушей.


На второй такой же случай, на 1 странице несколько пунктов, они отмечены.


Проблема возникает если я выбираю пункт уже из открытой ветки, то есть модель не перерисовывается.

Это я для уточнения привел пример.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #3 : Ноябрь 11, 2023, 23:21 »

картинок нет, да суть проблемы и так ясна: у тебя меняются данные модели, что должно привести к изменению отображения, но ничего не меняется, потому что, судя по всему, ты не отправляешь сигнал dataChanged
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #4 : Ноябрь 11, 2023, 23:38 »

 Плачущий
картинок нет, да суть проблемы и так ясна: у тебя меняются данные модели, что должно привести к изменению отображения, но ничего не меняется, потому что, судя по всему, ты не отправляешь сигнал dataChanged

Странно  картинками, отправляю еще раз
https://ibb.co/9N414WJ

https://ibb.co/S5JGTt7


https://ibb.co/zJcFVqp

На третей нажат пункт 2.5.4 и так как на даннйо странице присутствует только данный пункт то границы должны были быть у него, но ничего ни меняется. Только темным цветом окрашивается та часть куда я нажимаю.
Записан
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #5 : Ноябрь 11, 2023, 23:47 »

картинок нет, да суть проблемы и так ясна: у тебя меняются данные модели, что должно привести к изменению отображения, но ничего не меняется, потому что, судя по всему, ты не отправляешь сигнал dataChanged

Не могли бы обьяснить как я должен этот сигнал использовать? А точнее в каком месте? Я смотрел там у него аргументы индексы и роль.
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #6 : Ноябрь 12, 2023, 10:10 »

насколько я понимаю, логика должна быть такая:
1. тыкаем в раздел
2. в модели меняется текущая страница
3. модель сообщает, что какие-то ее данные изменились
4. это приводит к автоматическому обновлению / перерисовке тривью

вот сигнал dataChanged как раз для п.3 и служит. ты должен определить какой элемент (индекс) изменился, также опционально можно указать какая именно роль изменилась. beginResetModel можно использовать как альтернативу, если меняется много индексов сразу:
Цитировать
When a model radically changes its data it can sometimes be easier to just call this function rather than emit dataChanged() to inform other components when the underlying data source, or its structure, has changed.

код начнешь показывать или так и будем сидеть рассуждать? Улыбающийся
« Последнее редактирование: Ноябрь 12, 2023, 10:27 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #7 : Ноябрь 12, 2023, 15:14 »


код начнешь показывать или так и будем сидеть рассуждать? Улыбающийся

Да, надо было сразу кинуть.
Так, тут qml часть и делегат дял которого и роль нужная мне и нажатие(хотя оно думал не нужно в решении данной проблемы)
Код:
delegate: Item
{
    id: treeDelegate

    implicitWidth: padding + text.x + text.implicitWidth + padding
    implicitHeight: text.height

    property var delegateIndex : treeDelegate.treeView.index(row, column)

    readonly property real indent: 20
    readonly property real padding: 5

    required property TreeView treeView
    required property bool isTreeNode
    required property bool expanded
    required property bool selected
    required property int hasChildren
    required property int depth

    Item
    {
        id: rectIndicator

        height: parent.height
        width: height
        anchors.verticalCenter: parent.verticalCenter

        x: padding + (treeDelegate.depth * treeDelegate.indent)
        visible: treeViewBookmark.model.isHasChild(treeDelegate.delegateIndex)

        Image
        {
            id: indicator

            anchors.fill: parent
            height: 5
            verticalAlignment: Image.AlignVCenter
            horizontalAlignment: Image.AlignHCenter
            source: model.eIndicator
            rotation: treeDelegate.expanded ? 90 : 0
        }
    }

    Rectangle
    {
        id: labelRect

        color: treeViewBookmark.idx === treeDelegate.delegateIndex ? model.eColorBackgroundWithoutChild : style.hovered ? model.eColorBackgroundWithChild : "transparent"
        border.width: 1
        border.color: model.eBorderColor // вот эта ролько обработка которой и нужна
        width: text.width
        height: text.height

        x: padding + (treeDelegate.isTreeNode ? (treeDelegate.depth + 1) * treeDelegate.indent : 0)

        HoverHandler
        {
            id: style
        }

        Text
        {
            id: text

            clip: true
            text: model.display
            color: model.eValueTextColor

            font.pixelSize: 10 // constant from XD
            antialiasing: true
            horizontalAlignment: Text.AlignHCenter
            verticalAlignment: Text.AlignVCenter
        }

        TapHandler
        {
            acceptedButtons: Qt.LeftButton
            onTapped:
            {
                treeViewBookmark.toggleExpanded(row)

                var numberPage = treeViewBookmark.model.page(delegateIndex)
                root.pelData.signalUpdateCurrentPage(numberPage)
            }
        }
    }

Тут С++ часть с использованием роли и той переменнйо что отвечает за текузий номер страницы что прилетает из логики
Код:
void CC2gdocv_CustomPdfBookmarkModel::setCurrentPage(int currentPage)
{

    m_SelectedCurrentPage.setValue(currentPage);
}

QBindable<int> CC2gdocv_CustomPdfBookmarkModel::getCurrentPage()
{
    return &m_SelectedCurrentPage;
}

QVariant CC2gdocv_CustomPdfBookmarkModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
    {
        return QVariant{};
    }

    if (role == Qt::DisplayRole)
    {
        role = Qt::UserRole + index.column();
    }

    switch (role)
    {
        case static_cast<int>(RoleAttributes::eNameRole):
        {
            return QPdfBookmarkModel::data(index, role).toString();
        }
        case static_cast<int>(RoleAttributes::ePageRole):
        {
            auto localRole = static_cast<int>(QPdfBookmarkModel::Role::Page);
            auto localRoleTitle = static_cast<int>(QPdfBookmarkModel::Role::Title);
//                auto localIndex = QPdfBookmarkModel::index(index.row(), 0, index);

            qDebug() << "DATA role page: " << QPdfBookmarkModel::data( index, localRole).toInt() + 1 << QPdfBookmarkModel::data( index, localRoleTitle).toString();

            return QPdfBookmarkModel::data( index, role).toInt() + 1;
        }
        case static_cast<int>(RoleAttributes::eBorderColor):
        {
            auto localRole = static_cast<int>(QPdfBookmarkModel::Role::Page);

            const int intNumberPage =  QPdfBookmarkModel::data( index, localRole).toInt();

            qDebug() << intNumberPage << ": " << m_SelectedCurrentPage.value();

            if(intNumberPage == m_SelectedCurrentPage.value())
            {
                return QVariant::fromValue(getColorBorder() );
            }
            else
            {
                return QVariant::fromValue(QColor(Qt::transparent ));
            }

//                qDebug() << "DATA role page: " << QPdfBookmarkModel::data( index, localRole).toInt() + 1;


        }
        default:
            break;
    }

    return QVariant{};
}
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #8 : Ноябрь 12, 2023, 18:52 »

страница у тебя влияет на роль eBorderColor, значит при изменении страницы надо послать dataChanged для старых и новых выделенных индексов с указанием этой роли (видимо внутри setCurrentPage())
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #9 : Ноябрь 12, 2023, 21:07 »

страница у тебя влияет на роль eBorderColor, значит при изменении страницы надо послать dataChanged для старых и новых выделенных индексов с указанием этой роли (видимо внутри setCurrentPage())

Я не совсем понимаю что значит "для старых и новых индексов". То что 3 аргумент это роль я понял(хотя сигнал принимает QList ролей а не одну роль), но вот два первых аргумента индексы я тут немного в замешательстве.
Метод setCurrentPage() получает аргументом новую текущую страницу из другого класса. Это я решил обьяснить если этот класс важен.
Или могли бы вы этот кусов кода написать для демонстрации?
« Последнее редактирование: Ноябрь 12, 2023, 21:10 от SektorCT » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #10 : Ноябрь 12, 2023, 22:56 »

метод CC2gdocv_CustomPdfBookmarkModel::data() принимает индекс, для которого рассчитывается значение переданной роли, у тебя там для eBorderColor есть логика определения каким цветом выделять заданный индекс. А теперь тебе надо по сути сделать обратную операцию: по заданному номеру страницы определить каким индексам модели она соответствует, таким образом ты сможешь получить как старые индексы (те, что выделены сейчас), так и новые (для новой страницы в setCurrentPage). По коду кажется, что можно просто пробежаться по всем доступным индексам и выполнить код, который сейчас у тебя для eBorderColor, но может можно и как-то быстрее (зависит от твоей внутренней логики и доступных данных).
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
SektorCT
Частый гость
***
Offline Offline

Сообщений: 216


Просмотр профиля
« Ответ #11 : Ноябрь 12, 2023, 23:51 »

... А теперь тебе надо по сути сделать обратную операцию: по заданному номеру страницы определить каким индексам модели она соответствует,

То есть мне надо найти все индыксы где есть соответствие со страницей текущей? А как это сделать?)
В голову приходит только идеть еще контейнер с ключ(страница) и значение(индекс).

В общем я заполнил вот такой контейнер QMap<int, QList<QPersistentModelIndex>* >* m_pBookmarkMap;
И получается что в нужном мне кейсе под нужнйо ролью мне надо пройти данный контейнер, по ключу страницы найти индексы и заменить?
А что с ролями та делать? Там же лист ролей
« Последнее редактирование: Ноябрь 13, 2023, 00:37 от SektorCT » Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4727



Просмотр профиля WWW
« Ответ #12 : Ноябрь 13, 2023, 12:10 »

как сделать — это ж ты должен знать, твой код и твоя логика Улыбающийся Вот для eBorderColor у тебя есть код получения страницы для данного индекса, можно этот код переиспользовать, только сделать цикл по всем доступным индексам (или какому-то их подмножеству, если логика позволяет упрощение) и найти где полученная страница совпадает с текущей.

Если вычисления там тяжелые, то лучше закэшировать, да. Только непонятно зачем ты хранишь указатель на список и указатель на словарь, а не по значению. Дальше просто в setCurrentPage() получаешь список индексов для старой страницы и для новой, и вот эти индексы подаешь в dataChanged.

лист ролей — ну создай лист из одного элемента, в чем проблема Улыбающийся если подашь пустой список, то будут пересчитаны все роли, что в данном случае не нужно.
Код
C++ (Qt)
QList{{static_cast<int>(RoleAttributes::eBorderColor)}}
// or
QList<int>{} << static_cast<int>(RoleAttributes::eBorderColor)
« Последнее редактирование: Ноябрь 13, 2023, 12:14 от kambala » Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.072 секунд. Запросов: 22.