Форум программистов, компьютерный форум, киберфорум
C++ Qt
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск  
 
 
Рейтинг 4.82/22: Рейтинг темы: голосов - 22, средняя оценка - 4.82
5 / 5 / 1
Регистрация: 10.07.2013
Сообщений: 99

Сохранение состояния QStandardItemModel при обновлении

07.08.2013, 11:30. Показов 4691. Ответов 26
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Как можно сохранить состояние элементов модели при ее обновлении? Не смог придумать ничего лучше, чем использовать индексы элементов.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void MainWindow::treeRenew()
{
    QList<int> modelState;
    saveModelState(model->invisibleRootItem()->index(), &modelState);
    treeView->setModel(0);
    model->clear();
    getClass();
    model->sort(0);
    treeView->setModel(model);
    loadModelState(&modelState);
}
 
void MainWindow::saveModelState(const QModelIndex parentIndex, QList<int> *modelState)
{
   for (int i = 0; i < model->rowCount(parentIndex); i++)
       if (model->index(i, 0, parentIndex).isValid())
       {
           if (treeView->isExpanded(model->index(i, 0, parentIndex)))
           {
               modelState->append(i);
               saveModelState(model->index(i, 0, parentIndex), modelState);
           }
       }
}
 
void MainWindow::loadModelState(QList<int> *modelState)
{
   for (int i = 0; i < modelState->count(); i++)
   {
       treeView->setExpanded(model->index(modelState->at(i),0, model->invisibleRootItem()->index()), true);
   }
}
(После вызова treeRenew() модель изменяется незначительно, максимум отличаются нескольколькими элементами. Заполнение модели происходит в getClass().)
Это работает, но в последствии мне нужно будет отказаться от индексов, что полностью подорвет работоспособность кода.
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
07.08.2013, 11:30
Ответы с готовыми решениями:

Сохранение состояния элемента измененного JavaScript при обновлении страницы?
Как сохранить состояние элемента измененного JavaScript при обновлении страницы?

Сохранение бд при обновлении версии
как сделать чтобы setup заменял все файлы кроме бд. бд хранится прямо в папке с exe

Сохранение перемнной при обновлении страницы
Есть комбобокс, при выборе значения оно заносится как новый элемент массива(а страница обновляется), но при выводе всего массива выводит...

26
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
21.08.2013, 11:05
Студворк — интернет-сервис помощи студентам
Цитата Сообщение от dBuSh83 Посмотреть сообщение
Если точно известно, что использоваться будет только 1 колонка можно ли вернуть просто "return 1;" ?
Да, чаще всего именно так и делают. Функции columnCount и rowCount по сути просто ограничивают диапазоны, по которым view строят QModelIndex для обращения к методу data (и другим).
То есть, если Вы возвращаете константу "1" из метода columnCount в модели, то view никогда не пришлет в метод data индекс, для которого выражение "index.column() >= 1" будет истинно.
1
5 / 5 / 1
Регистрация: 10.07.2013
Сообщений: 99
21.08.2013, 13:41  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
То есть, если Вы возвращаете константу "1" из метода columnCount в модели, то view никогда не пришлет в метод data индекс, для которого выражение "index.column() >= 1" будет истинно.
"index.column() >= 1" или "index.column() >= 0" ? Я думал с нуля нумеруются столбцы.

rootItem модели должен быть invalid, как пишет компилятор7. Каким образом тогда добавлять новые элементы в модель?

Добавлено через 23 минуты
Добавление работает, но treeView вылетает на "setModel".

Добавлено через 5 минут
Нет, добаление элемента тоже вылетает для rootItema. Т.к. "rootItem = 0" то и я не могу добавить к нему дочение элементы.

Добавлено через 1 час 22 минуты
С вылетом модели я разобрался. Вылетало при проверке модели на childAt(int) и childCount() при работе с rootItem модели. Решил проблему проверкой:
C++ (Qt)
1
return (this) ? (указатель на child/число child'ов): 0;
Корректно ли это решение?
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
21.08.2013, 14:46
dBuSh83, приведите лучше полный код модели, будем пошагово разбираться.
0
 Аватар для Genco
16 / 16 / 3
Регистрация: 05.08.2012
Сообщений: 89
22.08.2013, 01:46
Цитата Сообщение от fasked Посмотреть сообщение
Куда передать и от кого?
В любом случае неправильно, когда содержимое модели управляется, находящимся кодом в GUI слое приложения.
Подумалось, что человек не может разобраться, какая часть данных обновилась, это можно передать в сигнале, не парсить модель. Про содержимое согласен, если не имеется в виду что-то вроде вызова в интерфейсе
coolModel->remove(42); ( управляется через интерфейс этой самой модели )

Цитата Сообщение от fasked Посмотреть сообщение
Есть мнение, что использование функции sender() является нарушением инкапсуляции и интерфейсов.
Возможно, но в C#, Java и Delphi есть аналоги. А это вполне ООП языки. Так что вопрос.
0
5 / 5 / 1
Регистрация: 10.07.2013
Сообщений: 99
22.08.2013, 11:47  [ТС]
Header:
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
#ifndef TREEMODEL_H
#define TREEMODEL_H
 
#include <QAbstractItemModel>
 
#include "treeitem.h"
 
class TreeModel : public QAbstractItemModel
{
    Q_OBJECT
public:
    explicit TreeModel(QObject *parent = 0);
    ~TreeModel();
 
    void appendItem(TreeItem *parent, TreeItem *child);
    TreeItem *invisibleRootItem() const;
    TreeItem *itemFromIndex(const QModelIndex &index) const;
    QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const;
    QModelIndex index(int row, int column, const QModelIndex &parent = QModelIndex()) const;
    QModelIndex parent(const QModelIndex &index) const;
    int rowCount(const QModelIndex &parent = QModelIndex()) const;
    int columnCount(const QModelIndex &parent = QModelIndex()) const;
    Qt::ItemFlags flags(const QModelIndex &index) const;
    bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::DisplayRole);
    void clear();
 
private:
    TreeItem *getItem(const QModelIndex &index) const;
    TreeItem *rootItem;
};
 
#endif // TREEMODEL_H

Код:
Кликните здесь для просмотра всего текста
C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
#include "treemodel.h"
 
TreeModel::TreeModel(QObject *parent) : QAbstractItemModel(parent), rootItem(0){}
 
TreeModel::~TreeModel() { delete rootItem; }
QVariant TreeModel::data(const QModelIndex &index, int role) const
{
    if (!index.isValid())
        return QVariant();
    if (TreeItem *item = itemFromIndex(index))
    {
        if (role == Qt::DisplayRole && role == Qt::EditRole)
            return item->name();
        else if (role == Qt::DecorationRole)
            return item->icon();
        else if (role == Qt::UserRole)
            return item->isDevice();
        else if (role == Qt::UserRole + 1)
            return item->guid();
        else if (role == Qt::UserRole + 2)
            return item->index();
    }
    return QVariant();
}
 
TreeItem *TreeModel::itemFromIndex(const QModelIndex &index) const
{
    return getItem(index);
}
 
Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
{
    if (!index.isValid())
        return 0;
 
    return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
 
TreeItem *TreeModel::getItem(const QModelIndex &index) const
{
    if (index.isValid()) {
        TreeItem *item = static_cast<TreeItem*>(index.internalPointer());
        if (item) return item;
    }
    return rootItem;
}
 
QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
{
    if (parent.isValid() && parent.column() != 0)
        return QModelIndex();
 
    TreeItem *parentItem = getItem(parent);
 
    TreeItem *childItem = parentItem->childAt(row);
    if (childItem)
        return createIndex(row, column, childItem);
    else
        return QModelIndex();
}
 
QModelIndex TreeModel::parent(const QModelIndex &index) const
{
    if (!index.isValid())
        return QModelIndex();
 
    TreeItem *childItem = getItem(index);
    TreeItem *parentItem = childItem->parent();
 
    if (parentItem == rootItem)
        return QModelIndex();
 
    return createIndex(parentItem->childNumber(), 0, parentItem);
}
 
int TreeModel::rowCount(const QModelIndex &parent) const
{
    TreeItem *parentItem = getItem(parent);
 
    return parentItem->childCount();
}
 
bool TreeModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
    if (!index.isValid())
        return false;
    if (TreeItem *item = itemFromIndex(index)) {
        if (role == Qt::EditRole && role == Qt::DisplayRole)
                item->setName(value.toString());
        /*else if (role == Qt::DecorationRole)
            item->setIcon(value);*/
        else if (role == Qt::UserRole)
            item->setDevice(value.toBool());
        else if (role == Qt::UserRole + 1)
            item->setGuid(value.toInt());
        else if (role == Qt::UserRole + 2)
            item->setIndex(value.toInt());
        else
            return false;
        emit dataChanged(index, index);
        return true;
    }
    return false;
}
 
void TreeModel::appendItem(TreeItem *parent, TreeItem *child)
{
    if (!child)
        return;
    parent->appendChild(child);
}
 
int TreeModel::columnCount(const QModelIndex &parent) const
{
    return (parent.isValid()) ? 0: 1;
}
 
void TreeModel::clear()
{
    delete rootItem;
    rootItem = 0;
    reset();
}
 
TreeItem *TreeModel::invisibleRootItem() const { return rootItem; }


Добавлено через 28 минут
Случилась "магия" и модель заработала!
C++ (Qt)
1
TreeModel::TreeModel(QObject *parent) : QAbstractItemModel(parent) {rootItem new TreeItem();}
Вчера отказывалась работать при этом! Теперь другая проблема! Он определяет структуру построенного дерева, но выводит только rootItem'ы. ТК они не имеют имени выводится пустота.

Добавлено через 1 час 36 минут
Проблему с отображением решил, ошибка была в невнимательности (заменил на ||):
C++ (Qt)
1
if (role == Qt::DisplayRole [COLOR="Red"]&&[/COLOR] role == Qt::EditRole)
0
Эксперт С++
 Аватар для fasked
5045 / 2624 / 241
Регистрация: 07.10.2009
Сообщений: 4,310
Записей в блоге: 5
22.08.2013, 19:35
dBuSh83, ну если все работает, то у меня только пара замечаний по стилю, с Вашего позволения:
  • C++ (Qt)
    1
    2
    3
    4
    5
    6
    
            else if (role == Qt::UserRole)
                return item->isDevice();
            else if (role == Qt::UserRole + 1)
                return item->guid();
            else if (role == Qt::UserRole + 2)
                return item->index();
    Вместо Qt::UserRole лучше завести отдельные константы вроде:
    C++ (Qt)
    1
    2
    3
    4
    5
    6
    
    enum DeviceRole
    {
        IsDeviceRole = Qt::UserRole,
        GuidRole,
        IndexRole
    };
    Ну и чисто субъективно switch здесь более подходяще выглядит чем серия if-else-if.
  • C++ (Qt)
    1
    2
    3
    4
    
    TreeItem *TreeModel::itemFromIndex(const QModelIndex &index) const
    {
        return getItem(index);
    }
    Зачем нужны две функции выполняющие одинаковое действие, можно оставить только одну.
  • C++ (Qt)
    1
    2
    3
    4
    5
    6
    7
    
    Qt::ItemFlags TreeModel::flags(const QModelIndex &index) const
    {
        if (!index.isValid())
            return 0;
     
        return Qt::ItemIsEnabled | Qt::ItemIsSelectable;
    }
    Такие же флаги устанавливает и QAbstractItemModel по-умолчанию, поэтому данную функцию можно удалить целиком.
    The base class implementation returns a combination of flags that enables the item (ItemIsEnabled) and allows it to be selected (ItemIsSelectable).
  • C++ (Qt)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    
    QModelIndex TreeModel::index(int row, int column, const QModelIndex &parent) const
    {
        if (parent.isValid() && parent.column() != 0)
            return QModelIndex();
     
        TreeItem *parentItem = getItem(parent);
     
        TreeItem *childItem = parentItem->childAt(row);
        if (childItem)
            return createIndex(row, column, childItem);
        else
            return QModelIndex();
    }
    Переменную parentItem лучше все таки проверить на NULL. Мало ли что. Тоже самое в функции "parent".
  • C++ (Qt)
    1
    2
    3
    4
    5
    6
    
    void TreeModel::clear()
    {
        delete rootItem;
        rootItem = 0;
        reset();
    }
    Вот вместо подобных вызовов delete и последующих обнулений указателя я бы посоветовал посмотреть в сторону использования QScopedPointer.
    Еще в данном месте надо вызвать два метода: beginResetModel и endResetModel. Почитайте про них в документации. И вызов reset уже будет не нужен.
0
5 / 5 / 1
Регистрация: 10.07.2013
Сообщений: 99
27.08.2013, 09:43  [ТС]
Цитата Сообщение от fasked Посмотреть сообщение
dBuSh83, ну если все работает, то у меня только пара замечаний по стилю, с Вашего позволения:
Это даже хорошо! Стиль программирования у меня и вправду не устоявшийся еще и неопрятный немного!
Цитата Сообщение от fasked Посмотреть сообщение
Зачем нужны две функции выполняющие одинаковое действие, можно оставить только одну.
Проблема в том, что у меня несколько сигналов использовать должны, по идее, 1 слот, но в одном передается пораметр index, а в другом не. И если не использовать слот без параметра, там где параметр передается, то он не подключается к этому сигналу, и наоборот.
Цитата Сообщение от fasked Посмотреть сообщение
Вот вместо подобных вызовов delete и последующих обнулений указателя я бы посоветовал посмотреть в сторону использования QScopedPointer.
Я подумал, что он тяжеловат, поэтому не стал его использовать, но раз вы советуете, то рассмотрю это поподробнее.

Добавлено через 23 часа 26 минут
Цитата Сообщение от dBuSh83 Посмотреть сообщение
Проблема в том, что у меня несколько сигналов использовать должны, по идее, 1 слот, но в одном передается пораметр index, а в другом не. И если не использовать слот без параметра, там где параметр передается, то он не подключается к этому сигналу, и наоборот.
Понедельник - день тяжелый... Бред написал я! Разница между itemFromIndex и getItem была в том, что getItev - приватный, а тот публичный. Сделал getItem публичным и убрал itemFromIndex.
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
27.08.2013, 09:43

Сохранение состояния при ротации
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container,Bundle savedInstanceState) { View view =...

CheckBox - сохранение состояния при выходе из программы
Подскажите пожалуйста как сделать так чтоб CheckBox Сохранял галочку при выходе из программы вот записывать...

Сохранение выбранного значения в поле select при обновлении страницы
Всем привет!!! Возникла такая проблема - когда юзер заполняет поля формы обратной связи, то из списка select выбирает определенный пункт....

Сохранение состояния героя при переходе на следующий уровень
Подскажите, пожалуйста, есть ли такой скрипт (желательно на javascript, но от c# тоже не откажусь), который сохраняет текущие жизни (хп)...

Сохранение состояния приложения с целью экономии времени при последующих запусках
Всем привет. Появился небольшой вопрос. Допустим я запустил какое-то приложение, оно загрузилось и я его настроил. Весь процесс запуска и...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
27
Ответ Создать тему
Новые блоги и статьи
Беседа с ИИ о программистах, недопускающих к созданию и правке кода генеративные ИИ и причины этого
zorxor 21.09.2026
Раньше я радовался или получал некоторые эмоции, пусть небольшие, но всё же, от самого процесса написания кода, рекомпиляции и запуска, видя постепенное развитие программы и прочее. А теперь лень. . .
Мобильное приложение ColorStep
pavlinmavlin 17.09.2026
Реализовал приложение Красный, Зеленый, Синий в Unity3d + c#. Название изменил на ColorStep. Приложение прошло модерацию и теперь доступно для скачивания. Делал его сам, шаг за шагом — и вот,. . .
Запрет дублирования строк в табличной части
Maks 13.09.2026
Реализация из решения ниже выполнена на нетиповом справочнике "Нормы ТО" с табличной часть "Виды ТО", разработанного в КА2, со следующими реквизитами: - ВидТО (СправочникСсылка. ВидыТО); - ВидГСМ. . .
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр.
Jin X 06.09.2026
Скрипты Tampermonkey для CyberForum, ChatGPT, Claude и пр. Работая с форумом и нейросетями в браузере часто хочется что-то подкорректировать или добавить какого-то функционала. Ниже прикреплён. . .
Программа опроса у.з. расходомера SLS-720F
Argus19 02.09.2026
Программа опроса у. з. расходомера SLS-720F Программа опрашивает один раз в минуту три ультразвуковых расходомера SLS-720F через интерфейс RS-485 по протоколу Modbus RTU. Опрашиваются регистры. . .
Hyper-V: Компьютер должен поддерживать доверенный платформенный модуль 2.0.
Maks 31.08.2026
При установке Windows 11 на виртуальную машину Hyper-V 2-го поколения вылезла такая ошибка: Решение: в параметрах виртуальной машины, в разделе "Безопасность" (Security) активировать флаг. . .
Архитектура биовида Стива в Майнкрафте: Зачем бонобо кубический каннибализм
anaschu 30.08.2026
Кубический Вагинокапитализм в Minecraft: Математический инвариант ОДУ и рок Стивов-бонобо Главная задача разработанной «Модели Всего» — наглядно продемонстрировать наличие системной «судьбы». . .
Оттачиваю умение писать js программы.
russiannick 30.08.2026
Проектом выходного дня стало написание Книги шифров Виженера. Итогом стала версия 200, синий туман. Синий туман назван так, потому что замораживает текст под собой. Нажатие синих кнопок управляют. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru