Rollen, QVarianten und ein Model für eine Liste

Alles rund um die Programmierung mit Qt
Antworten
Sym
Beiträge: 139
Registriert: 15. Mai 2006 15:38
Wohnort: Bremen

Rollen, QVarianten und ein Model für eine Liste

Beitrag 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;
} 
Sym
Beiträge: 139
Registriert: 15. Mai 2006 15:38
Wohnort: Bremen

Beitrag von Sym »

Hmm, hat keiner einen Tip? Oder kennt vielleicht jemand eine Stelle für das gut beschrieben ist?
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag von upsala »

Möchtest du wirklich eine Liste, oder nicht vielleicht doch eher eine Tabelle in der der Title, Subtitle, Page usw. nebeneinander stehen?
Sym
Beiträge: 139
Registriert: 15. Mai 2006 15:38
Wohnort: Bremen

Beitrag von Sym »

Hallo,

es soll schon eine Liste sein. Es soll darin eine Komposition der Datenelemente angezeigt werden, sprich 'Title + Year + Page' oder ähnliches.
upsala
Beiträge: 3946
Registriert: 5. Februar 2006 20:52
Wohnort: Landshut
Kontaktdaten:

Beitrag 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;
}

Sym
Beiträge: 139
Registriert: 15. Mai 2006 15:38
Wohnort: Bremen

Beitrag 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.
Sym
Beiträge: 139
Registriert: 15. Mai 2006 15:38
Wohnort: Bremen

Beitrag von Sym »

Edit:

Fehler behoben. Nun klappt es. Wunderbar. Danke
Dateianhänge
problem.png
problem.png (367 Bytes) 4081 mal betrachtet
Antworten