Work on import/export.
This commit is contained in:
parent
4be7bfdd6a
commit
1d65d99f71
@ -29,7 +29,8 @@
|
|||||||
|
|
||||||
|
|
||||||
FeedsImportExportModel::FeedsImportExportModel(QObject *parent)
|
FeedsImportExportModel::FeedsImportExportModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent), m_checkStates(QHash<FeedsModelRootItem*, Qt::CheckState>()), m_recursiveChange(false) {
|
: QAbstractItemModel(parent), m_checkStates(QHash<FeedsModelRootItem*, Qt::CheckState>()),
|
||||||
|
m_rootItem(NULL), m_recursiveChange(false) {
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedsImportExportModel::~FeedsImportExportModel() {
|
FeedsImportExportModel::~FeedsImportExportModel() {
|
||||||
@ -77,7 +78,6 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
|||||||
opml_document.documentElement().appendChild(elem_opml_head);
|
opml_document.documentElement().appendChild(elem_opml_head);
|
||||||
|
|
||||||
QDomElement elem_opml_body = opml_document.createElement("body");
|
QDomElement elem_opml_body = opml_document.createElement("body");
|
||||||
|
|
||||||
QStack<FeedsModelRootItem*> items_to_process; items_to_process.push(m_rootItem);
|
QStack<FeedsModelRootItem*> items_to_process; items_to_process.push(m_rootItem);
|
||||||
QStack<QDomElement> elements_to_use; elements_to_use.push(elem_opml_body);
|
QStack<QDomElement> elements_to_use; elements_to_use.push(elem_opml_body);
|
||||||
|
|
||||||
@ -129,11 +129,6 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (child_feed->passwordProtected()) {
|
|
||||||
outline_feed.setAttribute("username", child_feed->username());
|
|
||||||
outline_feed.setAttribute("password", child_feed->password());
|
|
||||||
}
|
|
||||||
|
|
||||||
active_element.appendChild(outline_feed);
|
active_element.appendChild(outline_feed);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -145,7 +140,6 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
opml_document.documentElement().appendChild(elem_opml_body);
|
opml_document.documentElement().appendChild(elem_opml_body);
|
||||||
|
|
||||||
result = opml_document.toByteArray(2);
|
result = opml_document.toByteArray(2);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -159,11 +153,11 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
|
|||||||
|
|
||||||
if (opml_document.documentElement().isNull() || opml_document.documentElement().tagName() != "opml" ||
|
if (opml_document.documentElement().isNull() || opml_document.documentElement().tagName() != "opml" ||
|
||||||
opml_document.documentElement().elementsByTagName("body").size() != 1) {
|
opml_document.documentElement().elementsByTagName("body").size() != 1) {
|
||||||
|
// This really is not an OPML file.
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedsModelRootItem *root_item = new FeedsModelRootItem();
|
FeedsModelRootItem *root_item = new FeedsModelRootItem();
|
||||||
|
|
||||||
QStack<FeedsModelRootItem*> model_items; model_items.push(root_item);
|
QStack<FeedsModelRootItem*> model_items; model_items.push(root_item);
|
||||||
QStack<QDomElement> elements_to_process; elements_to_process.push(opml_document.documentElement().elementsByTagName("body").at(0).toElement());
|
QStack<QDomElement> elements_to_process; elements_to_process.push(opml_document.documentElement().elementsByTagName("body").at(0).toElement());
|
||||||
|
|
||||||
@ -178,7 +172,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
|
|||||||
QDomElement child_element = child.toElement();
|
QDomElement child_element = child.toElement();
|
||||||
|
|
||||||
// Now analyze if this element is category or feed.
|
// Now analyze if this element is category or feed.
|
||||||
// NOTE: All feeds must include xmlUrl attribute.
|
// NOTE: All feeds must include xmlUrl attribute and text attribute.
|
||||||
if (child_element.attributes().contains("xmlUrl") && child.attributes().contains("text")) {
|
if (child_element.attributes().contains("xmlUrl") && child.attributes().contains("text")) {
|
||||||
// This is FEED.
|
// This is FEED.
|
||||||
// Add feed and end this iteration.
|
// Add feed and end this iteration.
|
||||||
@ -186,8 +180,6 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
|
|||||||
QString feed_url = child_element.attribute("xmlUrl");
|
QString feed_url = child_element.attribute("xmlUrl");
|
||||||
QString feed_encoding = child_element.attribute("encoding", DEFAULT_FEED_ENCODING);
|
QString feed_encoding = child_element.attribute("encoding", DEFAULT_FEED_ENCODING);
|
||||||
QString feed_type = child_element.attribute("version", DEFAULT_FEED_TYPE);
|
QString feed_type = child_element.attribute("version", DEFAULT_FEED_TYPE);
|
||||||
QString feed_username = child_element.attribute("username");
|
|
||||||
QString feed_password = child_element.attribute("password");
|
|
||||||
QString feed_description = child_element.attribute("description");
|
QString feed_description = child_element.attribute("description");
|
||||||
|
|
||||||
FeedsModelFeed *new_feed = new FeedsModelFeed(active_model_item);
|
FeedsModelFeed *new_feed = new FeedsModelFeed(active_model_item);
|
||||||
@ -195,12 +187,7 @@ bool FeedsImportExportModel::importAsOPML20(const QByteArray &data) {
|
|||||||
new_feed->setDescription(feed_description);
|
new_feed->setDescription(feed_description);
|
||||||
new_feed->setEncoding(feed_encoding);
|
new_feed->setEncoding(feed_encoding);
|
||||||
new_feed->setUrl(feed_url);
|
new_feed->setUrl(feed_url);
|
||||||
|
new_feed->setAutoUpdateType(FeedsModelFeed::DefaultAutoUpdate);
|
||||||
if (!feed_username.isEmpty() && !feed_password.isEmpty()) {
|
|
||||||
new_feed->setPasswordProtected(true);
|
|
||||||
new_feed->setUsername(feed_username);
|
|
||||||
new_feed->setPassword(feed_password);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (feed_type == "RSS1") {
|
if (feed_type == "RSS1") {
|
||||||
new_feed->setType(FeedsModelFeed::Rdf);
|
new_feed->setType(FeedsModelFeed::Rdf);
|
||||||
@ -345,8 +332,20 @@ QVariant FeedsImportExportModel::data(const QModelIndex &index, int role) const
|
|||||||
return static_cast<int>(Qt::Unchecked);
|
return static_cast<int>(Qt::Unchecked);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else if (role == Qt::DisplayRole) {
|
||||||
|
switch (item->kind()) {
|
||||||
|
case FeedsModelRootItem::Category:
|
||||||
|
return QVariant(item->data(index.column(), role).toString() + tr(" (category)"));
|
||||||
|
|
||||||
|
case FeedsModelRootItem::Feed:
|
||||||
|
return QVariant(item->data(index.column(), role).toString() + tr(" (feed)"));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
return item->data(index.column(), role);
|
return QVariant();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -354,7 +353,12 @@ bool FeedsImportExportModel::setData(const QModelIndex &index, const QVariant &v
|
|||||||
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) {
|
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) {
|
||||||
FeedsModelRootItem *item = itemForIndex(index);
|
FeedsModelRootItem *item = itemForIndex(index);
|
||||||
|
|
||||||
if (item != m_rootItem) {
|
if (item == m_rootItem) {
|
||||||
|
// Cannot set data on root item.
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Change data for the actual item.
|
||||||
m_checkStates[item] = static_cast<Qt::CheckState>(value.toInt());
|
m_checkStates[item] = static_cast<Qt::CheckState>(value.toInt());
|
||||||
emit dataChanged(index, index);
|
emit dataChanged(index, index);
|
||||||
|
|
||||||
@ -362,21 +366,26 @@ bool FeedsImportExportModel::setData(const QModelIndex &index, const QVariant &v
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Set new data for all descendants of this actual item.
|
||||||
foreach(FeedsModelRootItem *child, item->childItems()) {
|
foreach(FeedsModelRootItem *child, item->childItems()) {
|
||||||
setData(indexForItem(child), value, Qt::CheckStateRole);
|
setData(indexForItem(child), value, Qt::CheckStateRole);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now we need to change new data to all parents.
|
||||||
QModelIndex parent_index = index;
|
QModelIndex parent_index = index;
|
||||||
m_recursiveChange = true;
|
m_recursiveChange = true;
|
||||||
|
|
||||||
|
// Iterate all valid parents.
|
||||||
while ((parent_index = parent_index.parent()).isValid()) {
|
while ((parent_index = parent_index.parent()).isValid()) {
|
||||||
// We now have parent index.
|
// We now have parent index. Get parent item too.
|
||||||
item = item->parent();
|
item = item->parent();
|
||||||
|
|
||||||
// Check children of this new parent item.
|
// Check children of this new parent item.
|
||||||
Qt::CheckState parent_state = Qt::Unchecked;
|
Qt::CheckState parent_state = Qt::Unchecked;
|
||||||
foreach (FeedsModelRootItem *child_of_parent, item->childItems()) {
|
foreach (FeedsModelRootItem *child_of_parent, item->childItems()) {
|
||||||
if (m_checkStates.contains(child_of_parent) && m_checkStates[child_of_parent] == Qt::Checked) {
|
if (m_checkStates.contains(child_of_parent) && m_checkStates[child_of_parent] == Qt::Checked) {
|
||||||
|
// We found out, that some child of this item is checked,
|
||||||
|
// therefore this item must be checked too.
|
||||||
parent_state = Qt::Checked;
|
parent_state = Qt::Checked;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -386,17 +395,15 @@ bool FeedsImportExportModel::setData(const QModelIndex &index, const QVariant &v
|
|||||||
}
|
}
|
||||||
|
|
||||||
m_recursiveChange = false;
|
m_recursiveChange = false;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags FeedsImportExportModel::flags(const QModelIndex &index) const {
|
Qt::ItemFlags FeedsImportExportModel::flags(const QModelIndex &index) const {
|
||||||
if (!index.isValid()) {
|
if (!index.isValid()) {
|
||||||
return 0;
|
return Qt::NoItemFlags;
|
||||||
}
|
}
|
||||||
|
|
||||||
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
@ -27,6 +27,7 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
|||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
// Constructors and destructors.
|
||||||
explicit FeedsImportExportModel(QObject *parent = 0);
|
explicit FeedsImportExportModel(QObject *parent = 0);
|
||||||
virtual ~FeedsImportExportModel();
|
virtual ~FeedsImportExportModel();
|
||||||
|
|
||||||
@ -45,6 +46,7 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
|||||||
// Returns source QModelIndex on which lies given item.
|
// Returns source QModelIndex on which lies given item.
|
||||||
QModelIndex indexForItem(FeedsModelRootItem *item) const;
|
QModelIndex indexForItem(FeedsModelRootItem *item) const;
|
||||||
|
|
||||||
|
// Root item manipulators.
|
||||||
FeedsModelRootItem *rootItem() const;
|
FeedsModelRootItem *rootItem() const;
|
||||||
void setRootItem(FeedsModelRootItem *rootItem);
|
void setRootItem(FeedsModelRootItem *rootItem);
|
||||||
|
|
||||||
@ -56,6 +58,8 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
|||||||
private:
|
private:
|
||||||
QHash<FeedsModelRootItem*, Qt::CheckState> m_checkStates;
|
QHash<FeedsModelRootItem*, Qt::CheckState> m_checkStates;
|
||||||
FeedsModelRootItem *m_rootItem;
|
FeedsModelRootItem *m_rootItem;
|
||||||
|
|
||||||
|
// When it's true, then
|
||||||
bool m_recursiveChange;
|
bool m_recursiveChange;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -538,12 +538,6 @@ void FeedsModel::reloadChangedLayout(QModelIndexList list) {
|
|||||||
// Underlying data are changed.
|
// Underlying data are changed.
|
||||||
emit dataChanged(index(indx.row(), 0, indx_parent),
|
emit dataChanged(index(indx.row(), 0, indx_parent),
|
||||||
index(indx.row(), FDS_MODEL_COUNTS_INDEX, indx_parent));
|
index(indx.row(), FDS_MODEL_COUNTS_INDEX, indx_parent));
|
||||||
|
|
||||||
// NOTE: The code below seems not to be necessary.
|
|
||||||
/*if (indx_parent.isValid()) {
|
|
||||||
// Make sure that data of parent are changed too.
|
|
||||||
list.prepend(indx_parent);
|
|
||||||
}*/
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ class FeedsModelFeed : public FeedsModelRootItem {
|
|||||||
enum Type {
|
enum Type {
|
||||||
Rss0X = 0,
|
Rss0X = 0,
|
||||||
Rss2X = 1,
|
Rss2X = 1,
|
||||||
Rdf = 2,
|
Rdf = 2, // Sometimes denoted as RSS 1.0.
|
||||||
Atom10 = 3
|
Atom10 = 3
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -176,9 +176,10 @@ void FormImportExport::parseImportFile(const QString &file_name) {
|
|||||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were imported."), tr("Feeds were imported."));
|
m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were imported."), tr("Feeds were imported."));
|
||||||
m_ui->m_treeFeeds->setEnabled(true);
|
m_ui->m_treeFeeds->setEnabled(true);
|
||||||
m_ui->m_treeFeeds->setModel(m_model);
|
m_ui->m_treeFeeds->setModel(m_model);
|
||||||
|
m_ui->m_treeFeeds->expandAll();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Error occurred. File is not well-formed. Select another file."),
|
m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Error, file is not well-formed. Select another file."),
|
||||||
tr("Error occurred. File is not well-formed. Select another file."));
|
tr("Error occurred. File is not well-formed. Select another file."));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user