crossplatform.ru

Здравствуйте, гость ( Вход | Регистрация )

4 страниц V   1 2 3 > »   
Тема закрытаНачать новую тему
> [Решено] Cоздание собственной модели для отображения таблицы., наследник QAbstractTableModel
AD
  опции профиля:
сообщение 17.3.2009, 15:33
Сообщение #1


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Имеется QTableView* tblLicences. Это представление зависит от модели QSqlTableModel* modelLicView. Но есть желание, чтобы отображение таблички было немного другим, чем в базе данных. Для этого создал след. класс:
/// Класс для представления вида одной записи таблицы
class ViewLicence
{
private:
    QString licence_name;            ///< название лицензии
    QString path;                    ///< путь, по которому лежит данная лицензия
    QDateTime date;                    ///< дата создания лицензии
    QStringList list_numbers;        ///< список серийных номеров лицензии
    QList<uint> list_id;            ///< список id-шников данных серийных номеров

public:
    ViewLicence();
    ViewLicence(const QString name, const QString pth, const QDateTime& d, const QStringList& lst,
        const QList<uint>& lId) { licence_name = name; path = pth; date = d; list_numbers = lst; list_id = lId; }
    ViewLicence(const ViewLicence& view) { licence_name = view.licence_name; path = view.path; date = view.date;
        list_numbers = view.list_numbers; list_id = view.list_id; }
    virtual ~ViewLicence();
    uint size() const { return list_numbers.size(); }
    uint elementIndex(QString num) const { return list_numbers.indexOf(num, 0); }
    uint ID(uint index) const { return (index > -1 && index < size()) ? list_id[index] : -1; }
    QString licenceName() const { return licence_name; }
    QString licencePath() const { return path; }
    QString serialNumber(uint index) const { return (index > -1 && index < size()) ? list_numbers[index] : ""; }
    QDateTime createDate() const { return date; }
    void licenceName(const QString name) { licence_name = name; }
    void licencePath(const QString pth) { path = pth; }
    void addNum(const QString number) { if(!number.isEmpty()) list_numbers.append(number); }
    void createDate(const QDateTime& d) { date = d; }
    void ID(const uint id) { list_id.append(id); }
    bool operator==(const ViewLicence& lv) { return licence_name == lv.licence_name && path == lv.path &&
        date == lv.date && list_numbers == lv.list_numbers && list_id == lv.list_id; }
    const ViewLicence& operator=(const ViewLicence& lv) { licence_name = lv.licence_name; path = lv.path;
        date = lv.date; list_numbers = lv.list_numbers; list_id = lv.list_id; return *this; }
};

Смысл такой, что таблица должна отображаться так:
Имя лицензии | Локальный путь доступа к лицензии | Дата создания | Список серийных номеров.
У меня есть список QList<ViewLicence*> listView, который я уже заполнил из модели.

А в БД это отображается следующим образом
[attachment=497:table.JPG]

Как мне отобразить список QList<ViewLicences*> listView в представлении? Поможете, а то не сообразить что-то?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:05
Сообщение #2


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(AD @ 17.3.2009, 18:33) *
У меня есть список QList<ViewLicence*> listView, который я уже заполнил из модели.
и что в этом списке? судя по имени список указателей на пачку предствалений
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:07
Сообщение #3


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:05) *
и что в этом списке? судя по имени список указателей на пачку предствалений

Грубо говоря, список строк таблицы, которую хочу отобразить!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:08
Сообщение #4


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


конечное представление должно предоставлять возможность редактировать данные?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:09
Сообщение #5


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:08) *
конечное представление должно предоставлять возможность редактировать данные?

Нет (Слава Богу). Только просмотр!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:13
Сообщение #6


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


тогда сделай запрос, положи его в модель запроса (QSqlQueryModel) ну а к ней прицепи представление

Цитата(AD @ 17.3.2009, 18:33) *
Имя лицензии |
откуда берется имя лицензии?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:15
Сообщение #7


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:13) *
тогда сделай запрос, положи его в модель запроса (QSqlQueryModel) ну а к ней прицепи представление

Цитата(AD @ 17.3.2009, 18:33) *
Имя лицензии |
откуда берется имя лицензии?

Имя из БД. На картинке ведь видны данные БД. Там все это есть.

А с методом не очень понял. Какой запрос сделать? Можешь подсказать, пожалуйста?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:20
Сообщение #8


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(AD @ 17.3.2009, 18:33) *
Имя лицензии | Локальный путь доступа к лицензии
т.е. имя лицензии это просто имя файла без пути?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:29
Сообщение #9


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:20) *
т.е. имя лицензии это просто имя файла без пути?

именно.

Вообще, если привести пример из картинки, то получается, что есть всего две строки у таблицы представления
Имя | Путь | Дата | Серийные номера
1 database.lic | D:/Projects/Win32/Bin/Release/LicenceBuilderGui/DBNAV1\ | 16.03.2009 17:56:23 | 22001
22004
22005
22009

2 database1.lic | D:/Projects/Win32/Bin/Release/LicenceBuilderGui/DBNAV1\ | 17.03.2009 15:13:59 | 22009
M-22001
MAKET
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:37
Сообщение #10


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(AD @ 17.3.2009, 19:29) *
1 database.lic | D:/Projects/Win32/Bin/Release/LicenceBuilderGui/DBNAV1\ | 16.03.2009 17:56:23 | 22001
22004
22005
22009
дак тебе дерево надо ?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:45
Сообщение #11


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Таблица удобнее пользователю. Да и нагляднее.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:45
Сообщение #12


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


т.е. что-то такое:

 Р Р€Р С˜Р ВµР Р…ьшено Р Т‘Р С• 39%
Прикрепленное изображение
434 x 312 (4.25 килобайт)

да?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 17.3.2009, 16:51
Сообщение #13


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:45) *
т.е. что-то такое:

 Р Р€Р С˜Р ВµР Р…ьшено Р Т‘Р С• 77%
Прикрепленное изображение
434 x 312 (4.25 килобайт)

да?

Если перенести номера в отдельный столбик, то да, такое. Я именно так и показывал.

Лицензия | Путь к ней | Дата создания | Список номеров (отдельный столбик, а не в том же, что и лицензия)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 17.3.2009, 16:56
Сообщение #14


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


для случая таблицы, а не дерева можно сделать так:
  QSqlDataBase        db;
  QString            qstr;
  QSqlQueryModel    *m;
  QTableView        *view;
  
    db = QSqlDatabase::database("myDb");
    qstr = "SELECT a.licence_name, a.create_date, a.serialnumber FROM MyTable a ORDER BY a.licence_name";
    
    m = new QSqlQueryModel;
    m->setQuery(qstr, db);
    m->setHeaderData(0, Qt::Horizontal, tr("Лицензия"));
    m->setHeaderData(1, Qt::Horizontal, tr("Дата"));
    m->setHeaderData(2, Qt::Horizontal, tr("Серийный\nномер"));
    
    view = new  QTableView(this);
    view->setModel(m);
но это без имени файла лицензии.
Для создания имени у меня есть два варианта, оба я непробовал:
1) Использовать возможности БД, если таковые есть, по формированию запроса так, чтобы можно было выкинуть из строки все что до последнего слэша.
2) Использовать между представлением и моделью еще одну - промежуточную модель.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 9:03
Сообщение #15


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(Litkevich Yuriy @ 17.3.2009, 16:56) *
но это без имени файла лицензии.
Для создания имени у меня есть два варианта, оба я непробовал:
1) Использовать возможности БД, если таковые есть, по формированию запроса так, чтобы можно было выкинуть из строки все что до последнего слэша.
2) Использовать между представлением и моделью еще одну - промежуточную модель.

Спасибо, попробую.
Смысл в том, что хочу именно с путем и файлом лицензии. А как через промежуточную модель или через SQL? Но в любом случае, спасибо. Данный вариант уже кое-что! :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 9:48
Сообщение #16


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Блин, получилось не так, как я хотел. Есть желание, чтобы это выглядело так, две записи, в которых в последнем столбце перечислены серийные номера, принадлежащие данным лицензиям. А исходя из приведенного кода получилось то же, что если сделать обычную выборку без первого столбца.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 11:52
Сообщение #17


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Кое-что из ассистента почитал и сделал так:
/// Отображение таблицы статистики
/// modelView - QSqlTableModel*
/// listView - QList<ViewLicence*>
void StatisticView::viewTable()
{
    int count = listView.size();
    for(register int row=0; row<listView.size(); ++row)
    {
        ViewLicence* view = listView[row];
        QSqlRecord record;
        record.setValue(QString("licence_name"), view -> licenceName());
        record.setValue(QString("create_date"), view -> createDate());
        record.setValue(QString("serialnumber"), view -> listNumbers());
        bool flag = modelView -> insertRecord(row, record);
        int sss2 = 0;
    }
    tblLicences -> setModel(modelView);
}

Но на экране вижу только квадрати и цифру 1. В чем ошибка? Где и что я не так делаю? :(

Кто-нибудь может помочь? Очень и очень нужно. Буду благодарен за помощь!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 18.3.2009, 11:57
Сообщение #18


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Почему не сделать свою модель и не обрабатывать нужный столбец "Серийный номер"?
Все данные есть, запросил view серийные номера для нужной строки - открыл нужный файл, прочитал их в строку через ";" (закешировать можно), вернул из data().
Или в конструкторе модели сделал запрос, загнал все в список структуры (попутно читая серийные номера из файлов), а дальше в data() возвращай?
Или я чего не понял? ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 12:53
Сообщение #19


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(BRE @ 18.3.2009, 11:57) *
Все данные есть, запросил view серийные номера для нужной строки - открыл нужный файл, прочитал их в строку через ";" (закешировать можно), вернул из data().
Или в конструкторе модели сделал запрос, загнал все в список структуры (попутно читая серийные номера из файлов), а дальше в data() возвращай?
Или я чего не понял? ;)

Не понял, как это реализовать? Как понять, свою модель? На основе модели QSqlTableModel? Или что-то еще?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 18.3.2009, 13:21
Сообщение #20


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 18.3.2009, 12:53) *
Не понял, как это реализовать? Как понять, свою модель? На основе модели QSqlTableModel? Или что-то еще?

Да наследоваться от QAbstractTableModel или QSqlTableModel.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 14:08
Сообщение #21


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


еще несколько уточнений:
1) Правильно понял, что заполненный QListView<ViewLicence*> listView передать этому наследнику и заполнить значениями модель?
2) Каким образом можно заполнять, с помощью какой функции: setData?

Сообщение отредактировал AD - 18.3.2009, 14:08
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 18.3.2009, 14:21
Сообщение #22


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


LicenceModel

struct LicenceData
{
    QString licence_name;    ///< название лицензии
    QString path;        ///< путь, по которому лежит данная лицензия
    QDateTime date;        ///< дата создания лицензии
    QStringList list_numbers;    ///< список серийных номеров лицензии
    QList<uint> list_id;    ///< список id-шников данных серийных номеров
};

typedef QList<LicenceData> LicenceList;

class LicenceModel : public QAbstractTableModel
{
    Q_OBJECT
public:
    ActionModel( const LicenceList &actions, QObject *parent = 0 );

    // В зависимости от указанного индекса и роли возвращает данные о лицензии (берет все из m_licences)
    virtual    QVariant        data( const QModelIndex &index, int role ) const;

    // Возвращает флаги ячейки (return Qt::ItemIsEnabled | Qt::ItemIsSelectable;)
        virtual    Qt::ItemFlags        flags( const QModelIndex &index ) const;

    // Возвращает имена секций (берет из списка m_columnNames, который формируется в конструкторе модели)
        virtual    QVariant        headerData( int section, Qt::Orientation orientation, int role = Qt::DisplayRole ) const;

    // Возвращает число строк (return m_licences.size();)
    virtual    int            rowCount( const QModelIndex &parent = QModelIndex() ) const;
    // Возвращает число столбцов (return m_columnNames.size();)
    virtual int            columnCount( const QModelIndex &parent = QModelIndex() ) const;

private:
    QStringList    m_columnNames;            //!< Список строк с названием столбцов.
    LicenceList    m_licences;            //!< Список данных о лицензиях.
};



В данном примере ты должен заполнить список лицензий извне, модель будет использовать его для вывода.
Можно переделать и формировать этот список в конструкторе.
Можно в самой моделе читать данные из БД.
Все можно. ;)

Сообщение отредактировал BRE - 18.3.2009, 14:24
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 14:50
Сообщение #23


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Спасибо. Попробую! :)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 18.3.2009, 16:40
Сообщение #24


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Цитата(AD @ 18.3.2009, 14:50) *
Спасибо. Попробую! :)

ActionModel( const LicenceList &actions, QObject *parent = 0 ); - имелся в виду конструктор? :))))

А какой должно быть значение переменной role, если разрешен только просмотр записей?

Сообщение отредактировал AD - 18.3.2009, 16:58
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 18.3.2009, 17:18
Сообщение #25


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 18.3.2009, 16:40) *
ActionModel( const LicenceList &actions, QObject *parent = 0 ); - имелся в виду конструктор? :))))

Да, забыл исправить. :)

Цитата(AD @ 18.3.2009, 16:40) *
А какой должно быть значение переменной role, если разрешен только просмотр записей?

Когда view начинает себя рисовать, она у модели спрашивает:
* какой текст нарисовать в ячейке (Qt::DisplayRole)
* как этот текст расположить (Qt::TextAlignmentRole)
* каким фонтом нарисовать (Qt::FontRole)
и т.д.

В data перехватываешь и обрабатываешь те роли которые нужны.

Сообщение отредактировал BRE - 18.3.2009, 17:19
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 18.3.2009, 17:46
Сообщение #26


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


Цитата(BRE @ 18.3.2009, 20:18) *
В data перехватываешь и обрабатываешь те роли которые нужны.
пример
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 19.3.2009, 11:44
Сообщение #27


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Не могу понять, по какой причине на вот этом break вылетает из цикла:
if(fullNameLic.isEmpty() || serialNumber.isEmpty() || !date.isValid())
            break;

Это в функции createList!
Вот реализация кода:
Source
/// Класс модели для отображения статистики созданных лицензий
class StatisticModel: public QSqlTableModel
{
    Q_OBJECT

private:
    QList<LicenceData*> listView;        ///< список указателей на данные о лицензии
    QStringList listClmNames;            ///< список названий столбцов

private:
    void addDataTable(LicenceData* view, const QString& lic_name, const QString& path, const QDateTime& date,
                const QString& serialNumber, const uint& id);
    void createList();

public:
    StatisticModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
    ~StatisticModel();
    virtual Qt::ItemFlags flags(const QModelIndex &index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; }
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { return listView.size(); }
    virtual int columnCount(const QModelIndex& parent = QModelIndex()) { return listClmNames.size(); }
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};


StatisticModel::StatisticModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db)
{
    setTable(QString("LogLicence"));
    createList();
}

StatisticModel::~StatisticModel()
{}

/// Добавление в элемент строки таблицы представления view данных
void StatisticModel::addDataTable(LicenceData* view, const QString& lic_name, const QString& path,
            const QDateTime& date, const QString& serialNumber, const uint& id)
{
    view -> licenceName(lic_name);
    view -> licencePath(path);
    view -> createDate(date);
    view -> addID(id);
    view -> addNum(serialNumber);
}

/// Создание списка данных о лицензиях
void StatisticModel::createList()
{
    select();
    for(register int row=0; row<QSqlTableModel::rowCount(); ++row)
    {
        QDateTime date(record(row).value(QString("create_date")).toDateTime());
        QString fullNameLic(record(row).value(QString("licence_name")).toString());
        QString serialNumber(record(row).value(QString("serialnumber")).toString());
        if(fullNameLic.isEmpty() || serialNumber.isEmpty() || !date.isValid())
            break;
        if(row > 0)
        {
            if(date.toTime_t() == record(row - 1).value(QString("create_date")).toDateTime().toTime_t() &&
                fullNameLic == record(row - 1).value("licence_name").toString() &&
                serialNumber != record(row - 1).value("serialnumber").toString())
            {
                listView.last() -> addNum(serialNumber);
                listView.last() -> addID(record(row).value(0).toUInt());
            }
            else
            {
                QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
                LicenceData* view(new LicenceData());
                addDataTable(view, lic_name, path, date, serialNumber, record(row).value(0).toUInt());
                listView.append(view);
            }
        }
        else
        {
            QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
            LicenceData* view(new LicenceData());
            addDataTable(view, lic_name, path, date, serialNumber, record(row).value(0).toUInt());
            listView.append(view);
        }
    }
}

/// Возвращает данные о лицензии в зависимости от индекса и роли
QVariant StatisticModel::data(const QModelIndex& index, int role) const
{
    if(!index.isValid() || role != Qt::DisplayRole)
        return QVariant();
    if(index.row() >= listView.size())
        return QVariant();

    LicenceData* d = listView.at(index.row());
    return listView.at(index.row());
}

/// Возвращает данные о заголовках таблицы
QVariant StatisticModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
         return QVariant();

    QString result("");
    if(orientation == Qt::Horizontal && !listClmNames.isEmpty())
    {
        result = listClmNames.at(section);
        return QVariant(result);
    }
    else
        return QSqlTableModel::headerData(section, orientation, role);
}

По какой причине select() не срабатывает, почему нет выборки из указанной таблицы?

Сообщение отредактировал AD - 19.3.2009, 11:47
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.3.2009, 12:11
Сообщение #28


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Раскрывающийся текст

/// Класс модели для отображения статистики созданных лицензий
/// [BRE] Для чего ты наследуешься от QSqlTableModel. Эта модель тебе нужна в одной функции createList для формирования списка?
/// IMHO наследоваться лучше от QAbstractTableModel.
class StatisticModel: public QSqlTableModel
{
    Q_OBJECT

private:
    // [BRE] Для чего указатели? И если указатели, где удаляются объекты LicenceData при разрушении StatisticModel
    QList<LicenceData*> listView;        ///< список указателей на данные о лицензии
    QStringList listClmNames;            ///< список названий столбцов

private:
    void addDataTable(LicenceData* view, const QString& lic_name, const QString& path, const QDateTime& date,
                const QString& serialNumber, const uint& id);
    void createList();

public:
    StatisticModel(QObject *parent = 0, QSqlDatabase db = QSqlDatabase());
    ~StatisticModel();
    virtual Qt::ItemFlags flags(const QModelIndex &index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; }
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { return listView.size(); }
    virtual int columnCount(const QModelIndex& parent = QModelIndex()) { return listClmNames.size(); }
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};


StatisticModel::StatisticModel(QObject *parent, QSqlDatabase db): QSqlTableModel(parent, db)
{
    // [BRE]
    // setTable(QString("LogLicence"));
    createList();
}

StatisticModel::~StatisticModel()
{}

/// Добавление в элемент строки таблицы представления view данных
void StatisticModel::addDataTable(LicenceData* view, const QString& lic_name, const QString& path,
            const QDateTime& date, const QString& serialNumber, const uint& id)
{
    view -> licenceName(lic_name);
    view -> licencePath(path);
    view -> createDate(date);
    view -> addID(id);
    view -> addNum(serialNumber);
}

/// Создание списка данных о лицензиях
void StatisticModel::createList()
{
    // [BRE] Модель для доступа к таблице нужна только в этой функции.
    QSqlTableModel model;
    model.setTable( "LogLicence" )
    model.select();

    for(register int row=0; row < model.rowCount(); ++row)
    {
    // [BRE] Я бы сделал как-то так. :)
    QSqlRecord rec = model.record( row );
    if( rec.isEmpty() )
        continue;    // или break;

        QDateTime date( rec.value( "create_date" ).toDateTime() );
        QString fullNameLic( rec.value( "licence_name" ).toString() );
        QString serialNumber( rec.value( "serialnumber" ).toString() );
        if(fullNameLic.isEmpty() || serialNumber.isEmpty() || !date.isValid())
            break;

    [BRE] Не углублялся.... :)
        if(row > 0)
        {
            if(date.toTime_t() == model.record(row - 1).value(QString("create_date")).toDateTime().toTime_t() &&
                fullNameLic == model.record(row - 1).value("licence_name").toString() &&
                serialNumber != model.record(row - 1).value("serialnumber").toString())
            {
                listView.last() -> addNum(serialNumber);
                listView.last() -> addID(model.record(row).value(0).toUInt());
            }
            else
            {
                QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
                LicenceData* view(new LicenceData());
                addDataTable(view, lic_name, path, date, serialNumber, model.record(row).value(0).toUInt());
                listView.append(view);
            }
        }
        else
        {
            QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
            LicenceData* view(new LicenceData());
            addDataTable(view, lic_name, path, date, serialNumber, record(row).value(0).toUInt());
            listView.append(view);
        }
    }
}

/// Возвращает данные о лицензии в зависимости от индекса и роли
QVariant StatisticModel::data(const QModelIndex& index, int role) const
{
    if(!index.isValid() || role != Qt::DisplayRole)
        return QVariant();

    // [BRE] IMHO, не нужная проверка, ведь ты возвращаешь количество строк == listView.size()
    if(index.row() >= listView.size())
        return QVariant();

    // [BRE] Код не ясен. Ты получаешь указатель на LicenceData и в зависимости от index.column() должен вернуть значение из нужного поля
    // этой структуры
    LicenceData* d = listView.at(index.row());
    return listView.at(index.row());
}

/// Возвращает данные о заголовках таблицы
QVariant StatisticModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
         return QVariant();

    QString result("");
    if(orientation == Qt::Horizontal && !listClmNames.isEmpty())
    {
        result = listClmNames.at(section);
        return QVariant(result);
    }
    else
        return QSqlTableModel::headerData(section, orientation, role);
}

Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 19.3.2009, 14:07
Сообщение #29


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Сделал наследником от QAbstractTableModel. Но теперь совсем не заходит в виртуальную функцию data().
/// Возвращает данные о лицензии в зависимости от индекса и роли
QVariant StatisticModel::data(const QModelIndex& index, int role) const
{
    if(!index.isValid() || role != Qt::DisplayRole)
        return QVariant();

    QVariant result;
    LicenceData* view(listView.at(index.row()));
    int cl = index.column();
    switch(index.column())
    {
    case 0:
        result.setValue(view -> licenceName());
    break;
    case 1:
        result.setValue(view -> licencePath());
    break;
    case 2:
        result.setValue(view -> createDate());
    break;
    case 3:
    {
        QString numbers("");
        foreach(QString nums, view -> listNumbers())
        {
            numbers += nums;
            numbers += "\n";
        }
        result.setValue(numbers);
    break;
    }
    }
    return result;
}

Почему?

Да и у этой модели нет select(). При присвоении QTableView этой модели, нужная таблица должна сама определиться? Или надо писать свой select()?
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.3.2009, 14:27
Сообщение #30


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 19.3.2009, 14:07) *
Сделал наследником от QAbstractTableModel. Но теперь совсем не заходит в виртуальную функцию data().
Почему?

Да и у этой модели нет select(). При присвоении QTableView этой модели, нужная таблица должна сама определиться? Или надо писать свой select()?

В конструкторе StatisticModel вызывается метод createList, в котором исполняется select() для внутренней модели QSqlTableModel, которая используется для получения данных из БД. После отработки метода createList все данные лежат в списке listView, для отображения в представлении база данных больше не нужна.

Проверь после вызова метода createList, сколько записей реально лежат в этом списке (это количнство строк).
Проверь сколько записей лежат в списке listClmNames (это количество столбцов).
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 19.3.2009, 14:51
Сообщение #31


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Виноват. Когда заполнил названия столбцов, все отобразилось!!!
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 19.3.2009, 16:36
Сообщение #32


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Вот окончательный вариант решения! :)
Model
/// Класс модели для отображения статистики созданных лицензий
class StatisticModel: public QAbstractTableModel
{
    Q_OBJECT

private:
    QList<LicenceData*> listView;        ///< список указателей на данные о лицензии
    QStringList listClmNames;            ///< список названий столбцов

private:
    void addDataTable(LicenceData* view, const QString& lic_name, const QString& path, const QDateTime& date,
                const QString& serialNumber, const uint& id);
    void createHeaderList();
    void createList();

public:
    StatisticModel(QObject *parent = 0);
    ~StatisticModel();
    virtual Qt::ItemFlags flags(const QModelIndex &index) const { return Qt::ItemIsEnabled | Qt::ItemIsSelectable; }
    virtual int rowCount(const QModelIndex& parent = QModelIndex()) const { return listView.size(); }
    virtual int columnCount(const QModelIndex& parent = QModelIndex()) const { return listClmNames.size(); }
    virtual QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const;
    virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
};

StatisticModel::StatisticModel(QObject *parent): QAbstractTableModel(parent)
{
    createHeaderList();
    createList();
}

StatisticModel::~StatisticModel()
{}

/// Добавление в элемент строки таблицы представления view данных
void StatisticModel::addDataTable(LicenceData* view, const QString& lic_name, const QString& path,
            const QDateTime& date, const QString& serialNumber, const uint& id)
{
    view -> licenceName(lic_name);
    view -> licencePath(path);
    view -> createDate(date);
    view -> addID(id);
    view -> addNum(serialNumber);
}

/// Создание списка данных о лицензиях
void StatisticModel::createList()
{
    QSqlTableModel model(this, db);
    model.setTable("LogLicence");
    model.select();

    for(register int row=0; row<model.rowCount(); ++row)
    {
        QSqlRecord record(model.record(row));
        if(record.isEmpty())
            break;
        QDateTime date(record.value(QString("create_date")).toDateTime());
        QString fullNameLic(record.value(QString("licence_name")).toString());
        QString serialNumber(record.value(QString("serialnumber")).toString());
        if(fullNameLic.isEmpty() || serialNumber.isEmpty() || !date.isValid())
            break;
        if(row > 0)
        {
            QSqlRecord prev_rec(model.record(row - 1));
            if(date.toTime_t() == prev_rec.value(QString("create_date")).toDateTime().toTime_t() &&
                fullNameLic == prev_rec.value("licence_name").toString() &&
                serialNumber != prev_rec.value("serialnumber").toString())
            {
                listView.last() -> addNum(serialNumber);
                listView.last() -> addID(record.value(0).toUInt());
            }
            else
            {
                QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
                LicenceData* view(new LicenceData());
                addDataTable(view, lic_name, path, date, serialNumber, record.value(0).toUInt());
                listView.append(view);
            }
        }
        else
        {
            QString lic_name(QFileInfo(fullNameLic).fileName()), path(QFileInfo(fullNameLic).path()
                            + QDir::separator());
            LicenceData* view(new LicenceData());
            addDataTable(view, lic_name, path, date, serialNumber, record.value(0).toUInt());
            listView.append(view);
        }
    }
}

/// Возвращает данные о лицензии в зависимости от индекса и роли
QVariant StatisticModel::data(const QModelIndex& index, int role) const
{
    if(!index.isValid() || role != Qt::DisplayRole)
        return QVariant();

    QVariant result;
    LicenceData* view(listView.at(index.row()));
    switch(index.column())
    {
    case 0:
        result.setValue(view -> licenceName());
    break;
    case 1:
        result.setValue(view -> licencePath());
    break;
    case 2:
        result.setValue(view -> createDate());
    break;
    case 3:
    {
        QString numbers("");
        foreach(QString nums, view -> listNumbers())
        {
            numbers += nums;
            numbers += "\n";
        }
        result.setValue(numbers);
    break;
    }
    }
    return result;
}

/// Создание заголовочного списка
void StatisticModel::createHeaderList()
{
    listClmNames.append(QString("Название\nлицензии"));
    listClmNames.append(QString("Локальный путь\nк лицензии"));
    listClmNames.append(QString("Дата создания"));
    listClmNames.append(QString("Серийные\nномера"));
}

/// Возвращает данные о заголовках таблицы
QVariant StatisticModel::headerData(int section, Qt::Orientation orientation, int role) const
{
    if(role != Qt::DisplayRole)
         return QVariant();

    QString result("");
    if(orientation == Qt::Horizontal && !listClmNames.isEmpty())
    {
        result = listClmNames.at(section);
        return QVariant(result);
    }
    else
        return QAbstractTableModel::headerData(section, orientation, role);
}
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.3.2009, 16:58
Сообщение #33


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 19.3.2009, 16:36) *
class StatisticModel: public QAbstractTableModel
{
    Q_OBJECT

private:
    QList<LicenceData*> listView;        ///< список указателей на данные о лицензии

...

}

Вот объясни мне, для чего используются указатели на LicenceData, а не сами объекты? ;)
Где они удаляются, после разрушения объекта StatisticModel.
Сейчас у тебя память будет утекать.

А описал бы список так QList<LicenceData> listView и проблем бы не было.
В чем тайный смысл? ;)
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
AD
  опции профиля:
сообщение 19.3.2009, 17:40
Сообщение #34


Профессионал
*****

Группа: Участник
Сообщений: 2003
Регистрация: 4.2.2008
Из: S-Petersburg
Пользователь №: 84

Спасибо сказали: 70 раз(а)




Репутация:   17  


Уговорил :) Напишу деструктор! :)

А вообще вот почему указатель, а не объект:
1) Данные могут со временем измениться, чтобы если что создать потомка.
2) Описан класс в другом файле - меньшее количество компиляции.

StatisticModel::~StatisticModel()
{
    foreach(LicenceData* view, listView)
    {
        delete view;
        view = 0;
    }
    listView.clear();
}

Вот так.
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
BRE
  опции профиля:
сообщение 19.3.2009, 17:43
Сообщение #35


Профессионал
*****

Группа: Участник
Сообщений: 1112
Регистрация: 6.3.2009
Из: Ростов-на-Дону
Пользователь №: 591

Спасибо сказали: 264 раз(а)




Репутация:   44  


Цитата(AD @ 19.3.2009, 17:37) *
А вообще вот почему указатель, а не объект:
1) Данные могут со временем измениться, чтобы если что создать потомка.
2) Описан класс в другом файле - меньшее количество компиляции.

Аргумент 2 - можно обойти.
Аргумент 1 - если есть такая необходимость, то конечно. (Я к этой структуре относился как к вспомогательно/внутренней).

Ухожу, ухожу.... :D ;)

Ан нет, еще про одну штучку напомню: ;)
Цитата из assistant

Цитата
void qDeleteAll ( ForwardIterator begin, ForwardIterator end )
Deletes all the items in the range [begin, end) using the C++ delete operator. The item type must be a pointer type (for example, QWidget *).
Example:
QList<Employee *> list;
list.append(new Employee("Blackpool", "Stephen"));
list.append(new Employee("Twist", "Oliver"));

qDeleteAll(list.begin(), list.end());
list.clear();
Notice that qDeleteAll() doesn't remove the items from the container; it merely calls delete on them. In the example above, we call clear() on the container to remove the items.
See also forward iterators.
void qDeleteAll ( const Container & c )
This is an overloaded member function, provided for convenience.
This is the same as qDeleteAll(c.begin(), c.end()).



Сообщение отредактировал BRE - 19.3.2009, 17:47
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение
Litkevich Yuriy
  опции профиля:
сообщение 13.4.2009, 13:51
Сообщение #36


разработчик РЭА
*******

Группа: Сомодератор
Сообщений: 9669
Регистрация: 9.1.2008
Из: Тюмень
Пользователь №: 64

Спасибо сказали: 807 раз(а)




Репутация:   94  


так тему почистил, отделил тему kuler'а, теперь она здесь: QSqlQueryModel + QTableView, Данные не отображаются
Перейти в начало страницы
 
Быстрая цитата+Цитировать сообщение

4 страниц V   1 2 3 > » 
Тема закрытаНачать новую тему
Теги
Нет тегов для показа


1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0


RSS Рейтинг@Mail.ru Текстовая версия Сейчас: 22.6.2025, 12:33