Seite 1 von 1

Rollen, QVarianten und ein Model für eine Liste

Verfasst: 8. Oktober 2006 18:11
von Sym
Hallo,

ich habe mir jetzt Listen genauer angeschaut und habe leichte Verständnigsprobleme, was die Implementation eines zugehörigen Model betrifft.

Ich möchte eine Instanz einer Klasse ContentElement in ein QListWidget übergeben. Die Klasse sieht wie folgt aus:

Code: Alles auswählen

#ifndef __CONTENTELEMENT_H_
#define __CONTENTELEMENT_H_

#include <QString>
#include <QStringList>

class ContentElement : public QObject
{
  public:
    ContentElement() {}
    virtual ~ContentElement() {}

    // setters
    inline void setTitle(const QString &value)    { title = value;    }
    inline void setSubtitle(const QString &value) { subtitle = value; }
    inline void setPage(const QString &value)     { page = value;     }
    inline void setContent(const QString &value)  { content = value;  }
    inline void setBookletNumber(int value)       { booklet = value;  }
    inline void setYearNumber(int value)          { year = value;     }

    // getters
    inline QString getTitle()    { return title;    }
    inline QString getSubtitle() { return subtitle; }
    inline QString getPage()     { return page;     }
    inline QString getContent()  { return content;  }
    inline int getBooklet()      { return booklet;  }
    inline int getYear()         { return year;     }

  private:
    QString title;    // the titles string
    QString subtitle; // the subtitles string
    QString page;     // the pages string
    QString content;  // the contents string
    int booklet;      // the booklets string
    int year;         // the year

    QStringList findList; // the list of identifiers
};

//Q_DECLARE_METATYPE(ContentElement)

#endif
Das QAbstractListModel möchte ich nun überschreiben. Die Methoden data und setData benötigen QVariants. Soweit so gut.

Die Rollen geben nun, wenn ich das richtig verstanden habe, an, für wen das Objekt sein soll.

Ok und wie fülle ich nun mein QVariant? Wie bekomme ich meine selektierten Objekte dann zurück? Ich stehe da leider auf dem Schlauch und wäre für jede Hilfe dankbar.

Als Beispiel für mein Model:

Code: Alles auswählen

QVariant ListModel::data(const QModelIndex &index, int role) const
{
  QVariant v(QVariant::UserType);

  if(index.isValid() && index.row() >= 0 && index.row() < entities.size() && role == Qt::DisplayRole) {
    ContentElement e = entities.at(index.row());
    return e.getBooklet();
  }

  return v;
} 

bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
  if (index.isValid() && role == Qt::EditRole) {
    //ContentElement e = value.value<ContentElement>();
    //entities.replace(index.row(), e);
    emit dataChanged(index, index);
    return true;
  }
  return false;
} 

Verfasst: 9. Oktober 2006 12:28
von Sym
Hmm, hat keiner einen Tip? Oder kennt vielleicht jemand eine Stelle für das gut beschrieben ist?

Verfasst: 9. Oktober 2006 14:17
von upsala
Möchtest du wirklich eine Liste, oder nicht vielleicht doch eher eine Tabelle in der der Title, Subtitle, Page usw. nebeneinander stehen?

Verfasst: 9. Oktober 2006 16:05
von Sym
Hallo,

es soll schon eine Liste sein. Es soll darin eine Komposition der Datenelemente angezeigt werden, sprich 'Title + Year + Page' oder ähnliches.

Verfasst: 9. Oktober 2006 17:06
von upsala
setData() wird im normalfall von der View benutzt um Daten ans Model zurückzugeben, deswegen macht das bei dir recht wenig Sinn, ich hab jetzt trotzdem mal ein Beispiel eingebaut.

Den Sinn der Ableitung ContentElement von QObject erschließt sich mir nicht ganz.

Die aktuelle Auswahl kriegst du über QAbstractItemView::selectionModel(). Lies darüber mal die Dokumentation durch.


Code: Alles auswählen

class ListModel : public QAbstractListModel
{
Q_OBJECT
public:
	ListModel(QObject *parent=0);
	
	int rowCount(const QModelIndex &parent=QModelIndex()) const;
	QVariant data(const QModelIndex &index, int role=Qt::DisplayRole) const;
			
	void append(ContentElement *element);
	void insertAt(int row, ContentElement *element);
	bool setData(const QModelIndex &index, const QVariant &value, int role=Qt::EditRole);
	
private:
	QList<*ContentElement> m_elements;	
};



ListModel::ListModel(QObject *parent)
	: QAbstractListModel(parent)
{
}

int ListModel::rowCount(const QModelIndex &/*parent*/) const
{
	return m_elements.count();
}

QVariant ListModel::data(const QModelIndex &index, int role) const 
{	
	if (role==Qt::DisplayRole) {
		ContentElement *elem=m_elements.at(index.row());
		if (elem) {
			return QString("%1, %2, %3").arg(elem->getTitle()).arg(elem->getYear()).arg(elem->getPage());;
		}
	}
	
	return QVariant();
}

void ListModel::append(ContentElement *elem)
{
	beginInsertRows(QModelIndex(), m_elements.count(), m_elements.count()+1);
	m_elements.append(elem);
	endInsertRows();
}

void ListModel::insertAt(int row, ContentElement *element)
{
	if (row>=0 && row<m_elements.count()) {
		m_elements.replace(row, element);
		QModelIndex idx=createIndex(row, 0);
		emit dataChanged(idx, idx);
	}

	if (row>=m_elements.count()) {
		append(element);
	}
}

bool ListModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
	if (role==Qt::EditRole) {
		QStringList list=value.toString().split(",");
		ContentElement *elem=m_elements.value(index.row());
		if (list.count() && elem) {
			if (list.count()>0) {
				elem->setTitle(list[0].trimmed());
			}
			if (list.count()>1) {
				elem->setPage(list[1].trimmed());
			}
			if (list.count()>2) {
				elem->setYear(list[2].toInt());
			}
			return true;
		}
	}

	return false;
}


Verfasst: 9. Oktober 2006 17:25
von Sym
Ah wundervoll. Vielen Dank.

Ich wollte es schon so lösen. War meine anfangliche Idee. Und dann kam ich irgendwie auf den Trichter, das ganze müsste über die setData geregelt werden. Und so kam auch das Erben von QObject zustande. ;)

Ich dachte, die Liste so zu füllen wäre nicht konform. Ok, viel gelernt!

Danke nochmal.

Verfasst: 10. Oktober 2006 17:52
von Sym
Edit:

Fehler behoben. Nun klappt es. Wunderbar. Danke