Refactored feed cḧecking models.
This commit is contained in:
parent
827bd4a79f
commit
99ec71f4c4
4 changed files with 358 additions and 287 deletions
283
src/services/abstract/accountcheckmodel.cpp
Normal file
283
src/services/abstract/accountcheckmodel.cpp
Normal file
|
@ -0,0 +1,283 @@
|
||||||
|
// This file is part of RSS Guard.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2011-2016 by Martin Rotter <rotter.martinos@gmail.com>
|
||||||
|
//
|
||||||
|
// RSS Guard is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// RSS Guard is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#include "services/abstract/accountcheckmodel.h"
|
||||||
|
|
||||||
|
#include "definitions/definitions.h"
|
||||||
|
#include "miscellaneous/application.h"
|
||||||
|
#include "miscellaneous/iconfactory.h"
|
||||||
|
|
||||||
|
|
||||||
|
AccountCheckModel::AccountCheckModel(QObject *parent)
|
||||||
|
: QAbstractItemModel(parent), m_checkStates(QHash<RootItem*, Qt::CheckState>()),
|
||||||
|
m_rootItem(NULL), m_recursiveChange(false) {
|
||||||
|
}
|
||||||
|
|
||||||
|
AccountCheckModel::~AccountCheckModel() {
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem *AccountCheckModel::itemForIndex(const QModelIndex &index) const {
|
||||||
|
if (index.isValid() && index.model() == this) {
|
||||||
|
return static_cast<RootItem*>(index.internalPointer());
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return m_rootItem;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem *AccountCheckModel::rootItem() const {
|
||||||
|
return m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccountCheckModel::setRootItem(RootItem *root_item) {
|
||||||
|
if (m_rootItem != NULL) {
|
||||||
|
delete m_rootItem;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_rootItem = root_item;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccountCheckModel::checkAllItems() {
|
||||||
|
if (m_rootItem != NULL) {
|
||||||
|
foreach (RootItem *root_child, m_rootItem->childItems()) {
|
||||||
|
if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) {
|
||||||
|
setItemChecked(root_child, Qt::Checked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void AccountCheckModel::uncheckAllItems() {
|
||||||
|
if (m_rootItem != NULL) {
|
||||||
|
foreach (RootItem *root_child, m_rootItem->childItems()) {
|
||||||
|
if (root_child->kind() == RootItemKind::Feed || root_child->kind() == RootItemKind::Category) {
|
||||||
|
setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex AccountCheckModel::index(int row, int column, const QModelIndex &parent) const {
|
||||||
|
if (!hasIndex(row, column, parent)) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem *parent_item = itemForIndex(parent);
|
||||||
|
RootItem *child_item = parent_item->child(row);
|
||||||
|
|
||||||
|
if (child_item) {
|
||||||
|
return createIndex(row, column, child_item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex AccountCheckModel::indexForItem(RootItem *item) const {
|
||||||
|
if (item == NULL || item->kind() == RootItemKind::ServiceRoot || item->kind() == RootItemKind::Root) {
|
||||||
|
// Root item lies on invalid index.
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<QModelIndex> parents;
|
||||||
|
|
||||||
|
// Start with root item (which obviously has invalid index).
|
||||||
|
parents << indexForItem(m_rootItem);
|
||||||
|
|
||||||
|
while (!parents.isEmpty()) {
|
||||||
|
QModelIndex active_index = parents.takeFirst();
|
||||||
|
int row_count = rowCount(active_index);
|
||||||
|
|
||||||
|
if (row_count > 0) {
|
||||||
|
// This index has children.
|
||||||
|
// Lets take a look if our target item is among them.
|
||||||
|
RootItem *active_item = itemForIndex(active_index);
|
||||||
|
int candidate_index = active_item->childItems().indexOf(item);
|
||||||
|
|
||||||
|
if (candidate_index >= 0) {
|
||||||
|
// We found our item.
|
||||||
|
return index(candidate_index, 0, active_index);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Item is not found, add all "categories" from active_item.
|
||||||
|
for (int i = 0; i < row_count; i++) {
|
||||||
|
RootItem *possible_category = active_item->child(i);
|
||||||
|
|
||||||
|
if (possible_category->kind() == RootItemKind::Category) {
|
||||||
|
parents << index(i, 0, active_index);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
QModelIndex AccountCheckModel::parent(const QModelIndex &child) const {
|
||||||
|
if (!child.isValid()) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem *child_item = itemForIndex(child);
|
||||||
|
RootItem *parent_item = child_item->parent();
|
||||||
|
|
||||||
|
if (parent_item == m_rootItem) {
|
||||||
|
return QModelIndex();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return createIndex(parent_item->row(), 0, parent_item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AccountCheckModel::rowCount(const QModelIndex &parent) const {
|
||||||
|
if (parent.column() > 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
RootItem *item = itemForIndex(parent);
|
||||||
|
|
||||||
|
if (item != NULL) {
|
||||||
|
return item->childCount();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int AccountCheckModel::columnCount(const QModelIndex &parent) const {
|
||||||
|
Q_UNUSED(parent)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
QVariant AccountCheckModel::data(const QModelIndex &index, int role) const {
|
||||||
|
if (index.column() != 0) {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
|
||||||
|
RootItem *item = itemForIndex(index);
|
||||||
|
|
||||||
|
if (role == Qt::CheckStateRole) {
|
||||||
|
if (m_checkStates.contains(item)) {
|
||||||
|
return m_checkStates.value(item);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return static_cast<int>(Qt::Unchecked);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (role == Qt::DecorationRole) {
|
||||||
|
switch (item->kind()) {
|
||||||
|
case RootItemKind::Category:
|
||||||
|
case RootItemKind::Bin:
|
||||||
|
case RootItemKind::Feed:
|
||||||
|
return item->icon();
|
||||||
|
|
||||||
|
default:
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (role == Qt::DisplayRole) {
|
||||||
|
switch (item->kind()) {
|
||||||
|
case RootItemKind::Category:
|
||||||
|
return QVariant(item->data(index.column(), role).toString() + tr(" (category)"));
|
||||||
|
|
||||||
|
case RootItemKind::Feed:
|
||||||
|
return QVariant(item->data(index.column(), role).toString() + tr(" (feed)"));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return item->title();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return QVariant();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AccountCheckModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
||||||
|
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) {
|
||||||
|
RootItem *item = itemForIndex(index);
|
||||||
|
|
||||||
|
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());
|
||||||
|
emit dataChanged(index, index);
|
||||||
|
|
||||||
|
if (m_recursiveChange) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set new data for all descendants of this actual item.
|
||||||
|
foreach(RootItem *child, item->childItems()) {
|
||||||
|
setData(indexForItem(child), value, Qt::CheckStateRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now we need to change new data to all parents.
|
||||||
|
QModelIndex parent_index = index;
|
||||||
|
m_recursiveChange = true;
|
||||||
|
|
||||||
|
// Iterate all valid parents.
|
||||||
|
while ((parent_index = parent_index.parent()).isValid()) {
|
||||||
|
// We now have parent index. Get parent item too.
|
||||||
|
item = item->parent();
|
||||||
|
|
||||||
|
// Check children of this new parent item.
|
||||||
|
Qt::CheckState parent_state = Qt::Unchecked;
|
||||||
|
foreach (RootItem *child_of_parent, item->childItems()) {
|
||||||
|
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;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
setData(parent_index, parent_state, Qt::CheckStateRole);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_recursiveChange = false;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags AccountCheckModel::flags(const QModelIndex &index) const {
|
||||||
|
if (!index.isValid() || itemForIndex(index)->kind() == RootItemKind::Bin) {
|
||||||
|
return Qt::NoItemFlags;
|
||||||
|
}
|
||||||
|
|
||||||
|
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
||||||
|
|
||||||
|
if ( index.column() == 0 ) {
|
||||||
|
flags |= Qt::ItemIsUserCheckable;
|
||||||
|
}
|
||||||
|
|
||||||
|
return flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AccountCheckModel::isItemChecked(RootItem *item) {
|
||||||
|
return m_checkStates.contains(item) && m_checkStates.value(item, Qt::Unchecked);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AccountCheckModel::setItemChecked(RootItem *item, Qt::CheckState check) {
|
||||||
|
return setData(indexForItem(item), check, Qt::CheckStateRole);
|
||||||
|
}
|
68
src/services/abstract/accountcheckmodel.h
Normal file
68
src/services/abstract/accountcheckmodel.h
Normal file
|
@ -0,0 +1,68 @@
|
||||||
|
// This file is part of RSS Guard.
|
||||||
|
//
|
||||||
|
// Copyright (C) 2011-2016 by Martin Rotter <rotter.martinos@gmail.com>
|
||||||
|
//
|
||||||
|
// RSS Guard is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// RSS Guard is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
#ifndef ACCOUNTCHECKMODEL_H
|
||||||
|
#define ACCOUNTCHECKMODEL_H
|
||||||
|
|
||||||
|
#include <QAbstractItemModel>
|
||||||
|
|
||||||
|
#include "services/abstract/rootitem.h"
|
||||||
|
|
||||||
|
|
||||||
|
class AccountCheckModel : public QAbstractItemModel {
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Constructors and destructors.
|
||||||
|
explicit AccountCheckModel(QObject *parent = 0);
|
||||||
|
virtual ~AccountCheckModel();
|
||||||
|
|
||||||
|
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
||||||
|
QModelIndex parent(const QModelIndex &child) const;
|
||||||
|
int rowCount(const QModelIndex &parent) const;
|
||||||
|
int columnCount(const QModelIndex &parent) const;
|
||||||
|
QVariant data(const QModelIndex &index, int role) const;
|
||||||
|
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
||||||
|
Qt::ItemFlags flags(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
bool isItemChecked(RootItem *item);
|
||||||
|
bool setItemChecked(RootItem *item, Qt::CheckState check);
|
||||||
|
|
||||||
|
// Returns feed/category which lies at the specified index or
|
||||||
|
// root item if index is invalid.
|
||||||
|
RootItem *itemForIndex(const QModelIndex &index) const;
|
||||||
|
|
||||||
|
// Returns source QModelIndex on which lies given item.
|
||||||
|
QModelIndex indexForItem(RootItem *item) const;
|
||||||
|
|
||||||
|
// Root item manipulators.
|
||||||
|
RootItem *rootItem() const;
|
||||||
|
void setRootItem(RootItem *root_item);
|
||||||
|
|
||||||
|
public slots:
|
||||||
|
void checkAllItems();
|
||||||
|
void uncheckAllItems();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
RootItem *m_rootItem;
|
||||||
|
|
||||||
|
private:
|
||||||
|
QHash<RootItem*,Qt::CheckState> m_checkStates;
|
||||||
|
bool m_recursiveChange;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ACCOUNTCHECKMODEL_H
|
|
@ -32,8 +32,7 @@
|
||||||
|
|
||||||
|
|
||||||
FeedsImportExportModel::FeedsImportExportModel(QObject *parent)
|
FeedsImportExportModel::FeedsImportExportModel(QObject *parent)
|
||||||
: QAbstractItemModel(parent), m_checkStates(QHash<RootItem*, Qt::CheckState>()),
|
: AccountCheckModel(parent), m_mode(Import) {
|
||||||
m_rootItem(NULL), m_recursiveChange(false), m_mode(Import) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FeedsImportExportModel::~FeedsImportExportModel() {
|
FeedsImportExportModel::~FeedsImportExportModel() {
|
||||||
|
@ -44,27 +43,6 @@ FeedsImportExportModel::~FeedsImportExportModel() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RootItem *FeedsImportExportModel::itemForIndex(const QModelIndex &index) const {
|
|
||||||
if (index.isValid() && index.model() == this) {
|
|
||||||
return static_cast<RootItem*>(index.internalPointer());
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return m_rootItem;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
RootItem *FeedsImportExportModel::rootItem() const {
|
|
||||||
return m_rootItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedsImportExportModel::setRootItem(RootItem *root_item) {
|
|
||||||
if (m_rootItem != NULL) {
|
|
||||||
delete m_rootItem;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_rootItem = root_item;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
||||||
QDomDocument opml_document;
|
QDomDocument opml_document;
|
||||||
QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction(QSL("xml"),
|
QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction(QSL("xml"),
|
||||||
|
@ -99,7 +77,7 @@ bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) {
|
||||||
RootItem *active_item = items_to_process.pop();
|
RootItem *active_item = items_to_process.pop();
|
||||||
|
|
||||||
foreach (RootItem *child_item, active_item->childItems()) {
|
foreach (RootItem *child_item, active_item->childItems()) {
|
||||||
if (!m_checkStates.contains(child_item) || m_checkStates[child_item] != Qt::Checked) {
|
if (!isItemChecked(child_item)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -361,230 +339,3 @@ FeedsImportExportModel::Mode FeedsImportExportModel::mode() const {
|
||||||
void FeedsImportExportModel::setMode(const FeedsImportExportModel::Mode &mode) {
|
void FeedsImportExportModel::setMode(const FeedsImportExportModel::Mode &mode) {
|
||||||
m_mode = mode;
|
m_mode = mode;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FeedsImportExportModel::checkAllItems() {
|
|
||||||
if (m_rootItem != NULL) {
|
|
||||||
foreach (RootItem *root_child, m_rootItem->childItems()) {
|
|
||||||
if (root_child->kind() != RootItemKind::Bin) {
|
|
||||||
setData(indexForItem(root_child), Qt::Checked, Qt::CheckStateRole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void FeedsImportExportModel::uncheckAllItems() {
|
|
||||||
if (m_rootItem != NULL) {
|
|
||||||
foreach (RootItem *root_child, m_rootItem->childItems()) {
|
|
||||||
if (root_child->kind() != RootItemKind::Bin) {
|
|
||||||
setData(indexForItem(root_child), Qt::Unchecked, Qt::CheckStateRole);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FeedsImportExportModel::index(int row, int column, const QModelIndex &parent) const {
|
|
||||||
if (!hasIndex(row, column, parent)) {
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
RootItem *parent_item = itemForIndex(parent);
|
|
||||||
RootItem *child_item = parent_item->child(row);
|
|
||||||
|
|
||||||
if (child_item) {
|
|
||||||
return createIndex(row, column, child_item);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FeedsImportExportModel::indexForItem(RootItem *item) const {
|
|
||||||
if (item == NULL || item->kind() == RootItemKind::ServiceRoot || item->kind() == RootItemKind::Root) {
|
|
||||||
// Root item lies on invalid index.
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
QList<QModelIndex> parents;
|
|
||||||
|
|
||||||
// Start with root item (which obviously has invalid index).
|
|
||||||
parents << indexForItem(m_rootItem);
|
|
||||||
|
|
||||||
while (!parents.isEmpty()) {
|
|
||||||
QModelIndex active_index = parents.takeFirst();
|
|
||||||
int row_count = rowCount(active_index);
|
|
||||||
|
|
||||||
if (row_count > 0) {
|
|
||||||
// This index has children.
|
|
||||||
// Lets take a look if our target item is among them.
|
|
||||||
RootItem *active_item = itemForIndex(active_index);
|
|
||||||
int candidate_index = active_item->childItems().indexOf(item);
|
|
||||||
|
|
||||||
if (candidate_index >= 0) {
|
|
||||||
// We found our item.
|
|
||||||
return index(candidate_index, 0, active_index);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
// Item is not found, add all "categories" from active_item.
|
|
||||||
for (int i = 0; i < row_count; i++) {
|
|
||||||
RootItem *possible_category = active_item->child(i);
|
|
||||||
|
|
||||||
if (possible_category->kind() == RootItemKind::Category) {
|
|
||||||
parents << index(i, 0, active_index);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
QModelIndex FeedsImportExportModel::parent(const QModelIndex &child) const {
|
|
||||||
if (!child.isValid()) {
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
|
|
||||||
RootItem *child_item = itemForIndex(child);
|
|
||||||
RootItem *parent_item = child_item->parent();
|
|
||||||
|
|
||||||
if (parent_item == m_rootItem) {
|
|
||||||
return QModelIndex();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return createIndex(parent_item->row(), 0, parent_item);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FeedsImportExportModel::rowCount(const QModelIndex &parent) const {
|
|
||||||
if (parent.column() > 0) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
RootItem *item = itemForIndex(parent);
|
|
||||||
|
|
||||||
if (item != NULL) {
|
|
||||||
return item->childCount();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int FeedsImportExportModel::columnCount(const QModelIndex &parent) const {
|
|
||||||
Q_UNUSED(parent)
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
QVariant FeedsImportExportModel::data(const QModelIndex &index, int role) const {
|
|
||||||
if (index.column() != 0) {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
|
|
||||||
RootItem *item = itemForIndex(index);
|
|
||||||
|
|
||||||
if (role == Qt::CheckStateRole) {
|
|
||||||
if (m_checkStates.contains(item)) {
|
|
||||||
return m_checkStates.value(item);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return static_cast<int>(Qt::Unchecked);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (role == Qt::DecorationRole) {
|
|
||||||
switch (item->kind()) {
|
|
||||||
case RootItemKind::Category:
|
|
||||||
case RootItemKind::Bin:
|
|
||||||
case RootItemKind::Feed:
|
|
||||||
return item->icon();
|
|
||||||
|
|
||||||
default:
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (role == Qt::DisplayRole) {
|
|
||||||
switch (item->kind()) {
|
|
||||||
case RootItemKind::Category:
|
|
||||||
return QVariant(item->data(index.column(), role).toString() + tr(" (category)"));
|
|
||||||
|
|
||||||
case RootItemKind::Feed:
|
|
||||||
return QVariant(item->data(index.column(), role).toString() + tr(" (feed)"));
|
|
||||||
|
|
||||||
default:
|
|
||||||
return item->title();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return QVariant();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FeedsImportExportModel::setData(const QModelIndex &index, const QVariant &value, int role) {
|
|
||||||
if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) {
|
|
||||||
RootItem *item = itemForIndex(index);
|
|
||||||
|
|
||||||
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());
|
|
||||||
emit dataChanged(index, index);
|
|
||||||
|
|
||||||
if (m_recursiveChange) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set new data for all descendants of this actual item.
|
|
||||||
foreach(RootItem *child, item->childItems()) {
|
|
||||||
setData(indexForItem(child), value, Qt::CheckStateRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Now we need to change new data to all parents.
|
|
||||||
QModelIndex parent_index = index;
|
|
||||||
m_recursiveChange = true;
|
|
||||||
|
|
||||||
// Iterate all valid parents.
|
|
||||||
while ((parent_index = parent_index.parent()).isValid()) {
|
|
||||||
// We now have parent index. Get parent item too.
|
|
||||||
item = item->parent();
|
|
||||||
|
|
||||||
// Check children of this new parent item.
|
|
||||||
Qt::CheckState parent_state = Qt::Unchecked;
|
|
||||||
foreach (RootItem *child_of_parent, item->childItems()) {
|
|
||||||
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;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
setData(parent_index, parent_state, Qt::CheckStateRole);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_recursiveChange = false;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags FeedsImportExportModel::flags(const QModelIndex &index) const {
|
|
||||||
if (!index.isValid() || itemForIndex(index)->kind() == RootItemKind::Bin) {
|
|
||||||
return Qt::NoItemFlags;
|
|
||||||
}
|
|
||||||
|
|
||||||
Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable;
|
|
||||||
|
|
||||||
if ( index.column() == 0 ) {
|
|
||||||
flags |= Qt::ItemIsUserCheckable;
|
|
||||||
}
|
|
||||||
|
|
||||||
return flags;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool FeedsImportExportModel::isItemChecked(RootItem *item) {
|
|
||||||
return m_checkStates.contains(item) && m_checkStates.value(item, Qt::Unchecked);
|
|
||||||
}
|
|
||||||
|
|
|
@ -15,15 +15,13 @@
|
||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
// along with RSS Guard. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#ifndef FEEDIMPORTEXPORTMODEL_H
|
#ifndef STANDARDFEEDSIMPORTEXPORTMODEL_H
|
||||||
#define FEEDIMPORTEXPORTMODEL_H
|
#define STANDARDFEEDSIMPORTEXPORTMODEL_H
|
||||||
|
|
||||||
#include <QAbstractItemModel>
|
#include "services/abstract/accountcheckmodel.h"
|
||||||
|
|
||||||
#include "services/abstract/rootitem.h"
|
|
||||||
|
|
||||||
|
|
||||||
class FeedsImportExportModel : public QAbstractItemModel {
|
class FeedsImportExportModel : public AccountCheckModel {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -36,27 +34,6 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
||||||
explicit FeedsImportExportModel(QObject *parent = 0);
|
explicit FeedsImportExportModel(QObject *parent = 0);
|
||||||
virtual ~FeedsImportExportModel();
|
virtual ~FeedsImportExportModel();
|
||||||
|
|
||||||
QModelIndex index(int row, int column, const QModelIndex &parent) const;
|
|
||||||
QModelIndex parent(const QModelIndex &child) const;
|
|
||||||
int rowCount(const QModelIndex &parent) const;
|
|
||||||
int columnCount(const QModelIndex &parent) const;
|
|
||||||
QVariant data(const QModelIndex &index, int role) const;
|
|
||||||
bool setData(const QModelIndex &index, const QVariant &value, int role);
|
|
||||||
Qt::ItemFlags flags(const QModelIndex &index) const;
|
|
||||||
|
|
||||||
bool isItemChecked(RootItem *item);
|
|
||||||
|
|
||||||
// Returns feed/category which lies at the specified index or
|
|
||||||
// root item if index is invalid.
|
|
||||||
RootItem *itemForIndex(const QModelIndex &index) const;
|
|
||||||
|
|
||||||
// Returns source QModelIndex on which lies given item.
|
|
||||||
QModelIndex indexForItem(RootItem *item) const;
|
|
||||||
|
|
||||||
// Root item manipulators.
|
|
||||||
RootItem *rootItem() const;
|
|
||||||
void setRootItem(RootItem *root_item);
|
|
||||||
|
|
||||||
// Exports to OPML 2.0
|
// Exports to OPML 2.0
|
||||||
// NOTE: http://dev.opml.org/spec2.html
|
// NOTE: http://dev.opml.org/spec2.html
|
||||||
bool exportToOMPL20(QByteArray &result);
|
bool exportToOMPL20(QByteArray &result);
|
||||||
|
@ -70,10 +47,6 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
||||||
Mode mode() const;
|
Mode mode() const;
|
||||||
void setMode(const Mode &mode);
|
void setMode(const Mode &mode);
|
||||||
|
|
||||||
public slots:
|
|
||||||
void checkAllItems();
|
|
||||||
void uncheckAllItems();
|
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
// These signals are emitted when user selects some data
|
// These signals are emitted when user selects some data
|
||||||
// to be imported/parsed into the model.
|
// to be imported/parsed into the model.
|
||||||
|
@ -82,11 +55,7 @@ class FeedsImportExportModel : public QAbstractItemModel {
|
||||||
void parsingFinished(int count_failed, int count_succeeded, bool parsing_error);
|
void parsingFinished(int count_failed, int count_succeeded, bool parsing_error);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QHash<RootItem*,Qt::CheckState> m_checkStates;
|
|
||||||
RootItem *m_rootItem;
|
|
||||||
|
|
||||||
bool m_recursiveChange;
|
|
||||||
Mode m_mode;
|
Mode m_mode;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // FEEDIMPORTEXPORTMODEL_H
|
#endif // STANDARDFEEDSIMPORTEXPORTMODEL_H
|
||||||
|
|
Loading…
Add table
Reference in a new issue