From 94100ff90a6b862e4567c4607f1b5357935b95d2 Mon Sep 17 00:00:00 2001 From: Martin Rotter Date: Sat, 30 Aug 2014 18:24:16 +0200 Subject: [PATCH] New export/import dialog. Rewritten export functionality. --- CMakeLists.txt | 5 + src/core/feedsimportexportmodel.cpp | 315 ++++++++++++++++++++++++++++ src/core/feedsimportexportmodel.h | 61 ++++++ src/core/feedsmodel.cpp | 109 ---------- src/core/feedsmodel.h | 11 - src/gui/formimportexport.cpp | 183 ++++++++++++++++ src/gui/formimportexport.h | 68 ++++++ src/gui/formimportexport.ui | 148 +++++++++++++ src/gui/formmain.cpp | 16 +- src/gui/formsettings.ui | 6 +- 10 files changed, 796 insertions(+), 126 deletions(-) create mode 100644 src/core/feedsimportexportmodel.cpp create mode 100644 src/core/feedsimportexportmodel.h create mode 100644 src/gui/formimportexport.cpp create mode 100644 src/gui/formimportexport.h create mode 100644 src/gui/formimportexport.ui diff --git a/CMakeLists.txt b/CMakeLists.txt index e7f368560..97635846d 100755 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -349,6 +349,7 @@ set(APP_SOURCES src/gui/feedstoolbar.cpp src/gui/toolbareditor.cpp src/gui/messagessearchlineedit.cpp + src/gui/formimportexport.cpp # DYNAMIC-SHORTCUTS sources. src/dynamic-shortcuts/shortcutcatcher.cpp @@ -378,6 +379,7 @@ set(APP_SOURCES src/core/feedsmodelfeed.cpp src/core/parsingfactory.cpp src/core/feeddownloader.cpp + src/core/feedsimportexportmodel.cpp # NETWORK-WEB sources. src/network-web/basenetworkaccessmanager.cpp @@ -431,6 +433,7 @@ set(APP_HEADERS src/gui/feedstoolbar.h src/gui/toolbareditor.h src/gui/messagessearchlineedit.h + src/gui/formimportexport.h # DYNAMIC-SHORTCUTS headers. src/dynamic-shortcuts/dynamicshortcutswidget.h @@ -452,6 +455,7 @@ set(APP_HEADERS src/core/feedsmodel.h src/core/feedsproxymodel.h src/core/feeddownloader.h + src/core/feedsimportexportmodel.h # NETWORK-WEB headers. src/network-web/webpage.h @@ -473,6 +477,7 @@ set(APP_FORMS src/gui/formcategorydetails.ui src/gui/formfeeddetails.ui src/gui/toolbareditor.ui + src/gui/formimportexport.ui ) # APP translations. diff --git a/src/core/feedsimportexportmodel.cpp b/src/core/feedsimportexportmodel.cpp new file mode 100644 index 000000000..e8e3a0fce --- /dev/null +++ b/src/core/feedsimportexportmodel.cpp @@ -0,0 +1,315 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2014 by Martin Rotter +// +// 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 . + +#include "core/feedsimportexportmodel.h" + +#include "core/feedsmodelfeed.h" +#include "core/feedsmodelcategory.h" +#include "definitions/definitions.h" + +#include +#include +#include +#include +#include + + +FeedsImportExportModel::FeedsImportExportModel(QObject *parent) + : QAbstractItemModel(parent), m_checkStates(QHash()), m_recursiveChange(false) { +} + +FeedsImportExportModel::~FeedsImportExportModel() { +} + +FeedsModelRootItem *FeedsImportExportModel::itemForIndex(const QModelIndex &index) const { + if (index.isValid() && index.model() == this) { + return static_cast(index.internalPointer()); + } + else { + return m_rootItem; + } +} + +FeedsModelRootItem *FeedsImportExportModel::rootItem() const { + return m_rootItem; +} + +void FeedsImportExportModel::setRootItem(FeedsModelRootItem *rootItem) { + m_rootItem = rootItem; +} + +bool FeedsImportExportModel::exportToOMPL20(QByteArray &result) { + QDomDocument opml_document; + QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction("xml", + "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\""); + opml_document.appendChild(xml_declaration); + + // Adde OPML 2.0 metadata. + opml_document.appendChild(opml_document.createElement("opml")); + opml_document.documentElement().setAttribute("version", "2.0"); + + QDomElement elem_opml_head = opml_document.createElement("head"); + + QDomElement elem_opml_title = opml_document.createElement("title"); + QDomText text_opml_title = opml_document.createTextNode(QString(APP_NAME)); + elem_opml_title.appendChild(text_opml_title); + elem_opml_head.appendChild(elem_opml_title); + + QDomElement elem_opml_created = opml_document.createElement("dateCreated"); + QDomText text_opml_created = opml_document.createTextNode(QLocale::c().toString(QDateTime::currentDateTimeUtc(), + "ddd, dd MMM yyyy hh:mm:ss") + " GMT"); + elem_opml_created.appendChild(text_opml_created); + elem_opml_head.appendChild(elem_opml_created); + opml_document.documentElement().appendChild(elem_opml_head); + + QDomElement elem_opml_body = opml_document.createElement("body"); + + QStack items_to_process; items_to_process.push(m_rootItem); + QStack elements_to_use; elements_to_use.push(elem_opml_body); + + // Process all unprocessed nodes. + while (!items_to_process.isEmpty()) { + QDomElement active_element = elements_to_use.pop(); + FeedsModelRootItem *active_item = items_to_process.pop(); + + foreach (FeedsModelRootItem *child_item, active_item->childItems()) { + if (!m_checkStates.contains(child_item) || m_checkStates[child_item] != Qt::Checked) { + continue; + } + + switch (child_item->kind()) { + case FeedsModelRootItem::Category: { + QDomElement outline_category = opml_document.createElement("outline"); + outline_category.setAttribute("text", child_item->title()); + active_element.appendChild(outline_category); + items_to_process.push(child_item); + elements_to_use.push(outline_category); + break; + } + + case FeedsModelRootItem::Feed: { + FeedsModelFeed *child_feed = static_cast(child_item); + QDomElement outline_feed = opml_document.createElement("outline"); + outline_feed.setAttribute("text", child_feed->title()); + outline_feed.setAttribute("xmlUrl", child_feed->url()); + outline_feed.setAttribute("description", child_feed->description()); + outline_feed.setAttribute("encoding", child_feed->encoding()); + + switch (child_feed->type()) { + case FeedsModelFeed::Rss0X: + case FeedsModelFeed::Rss2X: + outline_feed.setAttribute("version", "RSS"); + break; + + case FeedsModelFeed::Rdf: + outline_feed.setAttribute("version", "RSS"); + break; + + case FeedsModelFeed::Atom10: + outline_feed.setAttribute("version", "ATOM"); + break; + + default: + break; + } + + if (child_feed->passwordProtected()) { + outline_feed.setAttribute("username", child_feed->username()); + outline_feed.setAttribute("password", child_feed->password()); + } + + active_element.appendChild(outline_feed); + break; + } + + default: + break; + } + } + } + + opml_document.documentElement().appendChild(elem_opml_body); + + result = opml_document.toByteArray(2); + return true; +} + +QModelIndex FeedsImportExportModel::index(int row, int column, const QModelIndex &parent) const { + if (!hasIndex(row, column, parent)) { + return QModelIndex(); + } + + FeedsModelRootItem *parent_item = itemForIndex(parent); + FeedsModelRootItem *child_item = parent_item->child(row); + + if (child_item) { + return createIndex(row, column, child_item); + } + else { + return QModelIndex(); + } +} + +QModelIndex FeedsImportExportModel::indexForItem(FeedsModelRootItem *item) const { + if (item == NULL || item->kind() == FeedsModelRootItem::RootItem) { + // Root item lies on invalid index. + return QModelIndex(); + } + + QList 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. + FeedsModelRootItem *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++) { + FeedsModelRootItem *possible_category = active_item->child(i); + + if (possible_category->kind() == FeedsModelRootItem::Category) { + parents << index(i, 0, active_index); + } + } + } + } + } + + return QModelIndex(); +} + +QModelIndex FeedsImportExportModel::parent(const QModelIndex &child) const { + if (!child.isValid()) { + return QModelIndex(); + } + + FeedsModelRootItem *child_item = itemForIndex(child); + FeedsModelRootItem *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 { + return itemForIndex(parent)->childCount(); + } +} + +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(); + } + + FeedsModelRootItem *item = itemForIndex(index); + + if (role == Qt::CheckStateRole) { + if (m_checkStates.contains(item)) { + return m_checkStates.value(item); + } + else { + return static_cast(Qt::Unchecked); + } + } + else { + return item->data(index.column(), role); + } +} + +bool FeedsImportExportModel::setData(const QModelIndex &index, const QVariant &value, int role) { + if (index.isValid() && index.column() == 0 && role == Qt::CheckStateRole) { + FeedsModelRootItem *item = itemForIndex(index); + + if (item != m_rootItem) { + m_checkStates[item] = static_cast(value.toInt()); + emit dataChanged(index, index); + + if (m_recursiveChange) { + return true; + } + + foreach(FeedsModelRootItem *child, item->childItems()) { + setData(indexForItem(child), value, Qt::CheckStateRole); + } + + QModelIndex parent_index = index; + m_recursiveChange = true; + + while ((parent_index = parent_index.parent()).isValid()) { + // We now have parent index. + item = item->parent(); + + // Check children of this new parent item. + Qt::CheckState parent_state = Qt::Unchecked; + foreach (FeedsModelRootItem *child_of_parent, item->childItems()) { + if (m_checkStates.contains(child_of_parent) && m_checkStates[child_of_parent] == Qt::Checked) { + 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()) { + return 0; + } + + Qt::ItemFlags flags = Qt::ItemIsEnabled | Qt::ItemIsSelectable; + + if ( index.column() == 0 ) { + flags |= Qt::ItemIsUserCheckable; + } + + return flags; +} diff --git a/src/core/feedsimportexportmodel.h b/src/core/feedsimportexportmodel.h new file mode 100644 index 000000000..baf41be30 --- /dev/null +++ b/src/core/feedsimportexportmodel.h @@ -0,0 +1,61 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2014 by Martin Rotter +// +// 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 . + +#ifndef FEEDIMPORTEXPORTMODEL_H +#define FEEDIMPORTEXPORTMODEL_H + +#include + +#include "core/feedsmodelrootitem.h" + + +class FeedsImportExportModel : public QAbstractItemModel { + Q_OBJECT + + public: + explicit FeedsImportExportModel(QObject *parent = 0); + 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; + + // Returns feed/category which lies at the specified index or + // root item if index is invalid. + FeedsModelRootItem *itemForIndex(const QModelIndex &index) const; + + // Returns source QModelIndex on which lies given item. + QModelIndex indexForItem(FeedsModelRootItem *item) const; + + FeedsModelRootItem *rootItem() const; + void setRootItem(FeedsModelRootItem *rootItem); + + // Exports to OPML 2.0 + // NOTE: http://dev.opml.org/spec2.html + bool exportToOMPL20(QByteArray &result); + + private: + QHash m_checkStates; + FeedsModelRootItem *m_rootItem; + bool m_recursiveChange; +}; + +#endif // FEEDIMPORTEXPORTMODEL_H diff --git a/src/core/feedsmodel.cpp b/src/core/feedsmodel.cpp index 5a1d73504..a2c4370b4 100755 --- a/src/core/feedsmodel.cpp +++ b/src/core/feedsmodel.cpp @@ -28,11 +28,6 @@ #include #include #include -#include -#include -#include -#include -#include #include @@ -144,109 +139,6 @@ int FeedsModel::rowCount(const QModelIndex &parent) const { } } -bool FeedsModel::exportToFile(FeedsModel::ExternalFeedsFileType type, QByteArray &result) { - switch (type) { - case OPML20: - return exportToOMPL20(result); - - default: - return false; - } -} - -bool FeedsModel::exportToOMPL20(QByteArray &result) { - QDomDocument opml_document; - QDomProcessingInstruction xml_declaration = opml_document.createProcessingInstruction("xml", - "version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\""); - opml_document.appendChild(xml_declaration); - - // Adde OPML 2.0 metadata. - opml_document.appendChild(opml_document.createElement("opml")); - opml_document.documentElement().setAttribute("version", "2.0"); - - QDomElement elem_opml_head = opml_document.createElement("head"); - - QDomElement elem_opml_title = opml_document.createElement("title"); - QDomText text_opml_title = opml_document.createTextNode(QString(APP_NAME)); - elem_opml_title.appendChild(text_opml_title); - elem_opml_head.appendChild(elem_opml_title); - - QDomElement elem_opml_created = opml_document.createElement("dateCreated"); - QDomText text_opml_created = opml_document.createTextNode(QLocale::c().toString(QDateTime::currentDateTimeUtc(), - "ddd, dd MMM yyyy hh:mm:ss") + " GMT"); - elem_opml_created.appendChild(text_opml_created); - elem_opml_head.appendChild(elem_opml_created); - opml_document.documentElement().appendChild(elem_opml_head); - - QDomElement elem_opml_body = opml_document.createElement("body"); - - QStack items_to_process; items_to_process.push(m_rootItem); - QStack elements_to_use; elements_to_use.push(elem_opml_body); - - // Process all unprocessed nodes. - while (!items_to_process.isEmpty()) { - QDomElement active_element = elements_to_use.pop(); - FeedsModelRootItem *active_item = items_to_process.pop(); - - foreach (FeedsModelRootItem *child_item, active_item->childItems()) { - switch (child_item->kind()) { - case FeedsModelRootItem::Category: { - QDomElement outline_category = opml_document.createElement("outline"); - outline_category.setAttribute("text", child_item->title()); - active_element.appendChild(outline_category); - items_to_process.push(child_item); - elements_to_use.push(outline_category); - break; - } - - case FeedsModelRootItem::Feed: { - FeedsModelFeed *child_feed = static_cast(child_item); - QDomElement outline_feed = opml_document.createElement("outline"); - outline_feed.setAttribute("text", child_feed->title()); - outline_feed.setAttribute("xmlUrl", child_feed->url()); - outline_feed.setAttribute("description", child_feed->description()); - outline_feed.setAttribute("encoding", child_feed->encoding()); - - switch (child_feed->type()) { - case FeedsModelFeed::Rss0X: - case FeedsModelFeed::Rss2X: - outline_feed.setAttribute("version", "RSS"); - break; - - case FeedsModelFeed::Rdf: - outline_feed.setAttribute("version", "RSS"); - break; - - case FeedsModelFeed::Atom10: - outline_feed.setAttribute("version", "ATOM"); - break; - - default: - break; - } - - if (child_feed->passwordProtected()) { - outline_feed.setAttribute("username", child_feed->username()); - outline_feed.setAttribute("password", child_feed->password()); - } - - active_element.appendChild(outline_feed); - break; - } - - default: - break; - } - } - } - - opml_document.documentElement().appendChild(elem_opml_body); - - - result = opml_document.toByteArray(2); - return true; -} - bool FeedsModel::removeItem(const QModelIndex &index) { if (index.isValid()) { QModelIndex parent_index = index.parent(); @@ -597,7 +489,6 @@ FeedsModelCategory *FeedsModel::categoryForIndex(const QModelIndex &index) const } } - QModelIndex FeedsModel::indexForItem(FeedsModelRootItem *item) const { if (item == NULL || item->kind() == FeedsModelRootItem::RootItem) { // Root item lies on invalid index. diff --git a/src/core/feedsmodel.h b/src/core/feedsmodel.h index 88dd1c1ef..65d54545b 100644 --- a/src/core/feedsmodel.h +++ b/src/core/feedsmodel.h @@ -39,10 +39,6 @@ class FeedsModel : public QAbstractItemModel { Q_OBJECT public: - enum ExternalFeedsFileType { - OPML20 = 0 - }; - // Constructors and destructors. explicit FeedsModel(QObject *parent = 0); virtual ~FeedsModel(); @@ -72,13 +68,6 @@ class FeedsModel : public QAbstractItemModel { return m_rootItem->countOfUnreadMessages(); } - // Import/export. - bool exportToFile(ExternalFeedsFileType type, QByteArray &result); - - // Exports to OPML 2.0 - // NOTE: http://dev.opml.org/spec2.html - bool exportToOMPL20(QByteArray &result); - // Removes item with given index. bool removeItem(const QModelIndex &index); diff --git a/src/gui/formimportexport.cpp b/src/gui/formimportexport.cpp new file mode 100644 index 000000000..e96248b5a --- /dev/null +++ b/src/gui/formimportexport.cpp @@ -0,0 +1,183 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2014 by Martin Rotter +// +// 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 . + +#include "gui/formimportexport.h" + +#include "core/feedsimportexportmodel.h" +#include "core/feedsmodel.h" +#include "miscellaneous/application.h" +#include "gui/feedmessageviewer.h" +#include "gui/formmain.h" +#include "gui/feedsview.h" + +#include +#include + + +FormImportExport::FormImportExport(QWidget *parent) : QDialog(parent), m_ui(new Ui::FormImportExport), m_mode(Import) { + m_ui->setupUi(this); + m_model = new FeedsImportExportModel(m_ui->m_treeFeeds); + m_ui->m_treeFeeds->setModel(m_model); + + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Error, tr("No file is selected."), tr("No file is selected.")); + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->disconnect(); + m_ui->m_lblResult->setStatus(WidgetWithStatus::Warning, tr("No operation executed yet."), tr("No operation executed yet.")); + + connect(m_ui->m_buttonBox->button(QDialogButtonBox::Ok), SIGNAL(clicked()), this, SLOT(performAction())); + connect(m_ui->m_btnSelectFile, SIGNAL(clicked()), this, SLOT(selectFile())); +} + +FormImportExport::~FormImportExport() { + delete m_ui; +} + +FormImportExport::Mode FormImportExport::mode() const { + return m_mode; +} + +void FormImportExport::setMode(const Mode &mode) { + m_mode = mode; + + switch (m_mode) { + case Export: { + m_model->setRootItem(qApp->mainForm()->tabWidget()->feedMessageViewer()->feedsView()->sourceModel()->rootItem()); + m_ui->m_treeFeeds->expandAll(); + setWindowTitle(tr("Export feeds")); + setWindowIcon(qApp->icons()->fromTheme("document-export")); + m_ui->m_groupFile->setTitle(tr("Destination file")); + m_ui->m_groupFeeds->setTitle(tr("Source feeds && categories")); + break; + } + + case Import: { + m_ui->m_groupFile->setTitle(tr("Source file")); + m_ui->m_groupFeeds->setTitle(tr("Target feeds && categories")); + m_ui->m_treeFeeds->setDisabled(true); + setWindowTitle(tr("Import feeds")); + setWindowIcon(qApp->icons()->fromTheme("document-import")); + break; + } + + default: + break; + } +} + +void FormImportExport::selectFile() { + switch (m_mode) { + case Import: + selectImportFile(); + break; + + case Export: { + selectExportFile(); + break; + } + + default: + break; + } +} + +void FormImportExport::selectExportFile() { + QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); + + QString filter; + QString selected_filter; + + // Add more filters here. + filter += filter_opml20; + + QString selected_file = QFileDialog::getSaveFileName(this, tr("Select file for feeds export"), + QDir::homePath(), filter, &selected_filter); + + + + if (!selected_file.isEmpty()) { + if (selected_filter == filter_opml20) { + m_conversionType = OPML20; + } + // NOTE: Add other types here. + + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Ok, QDir::toNativeSeparators(selected_file), tr("File is selected.")); + } + else { + m_ui->m_lblSelectFile->setStatus(WidgetWithStatus::Error, tr("No file is selected."), tr("No file is selected.")); + } + + m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setDisabled(selected_file.isEmpty()); +} + +void FormImportExport::selectImportFile() { + // TODO: vyber soubor a kdyz je vybranej, tak rozparsovat a vytvorit dle nej strukturu + // itemů a narvat do modelu. +} + +void FormImportExport::performAction() { + switch (m_mode) { + case Import: + importFeeds(); + break; + + case Export: + exportFeeds(); + break; + + default: + break; + } +} + +void FormImportExport::exportFeeds() { + switch (m_conversionType) { + case OPML20: { + QByteArray result_data; + bool result_export = m_model->exportToOMPL20(result_data); + + if (result_export) { + // Save exported data. + QFile output_file(m_ui->m_lblSelectFile->label()->text()); + + if (output_file.open(QIODevice::Unbuffered | QIODevice::Truncate | QIODevice::WriteOnly)) { + QTextStream stream(&output_file); + + stream.setCodec("UTF-8"); + stream << QString::fromUtf8(result_data); + output_file.flush(); + output_file.close(); + + m_ui->m_lblResult->setStatus(WidgetWithStatus::Ok, tr("Feeds were exported successfully."), + tr("Feeds were exported successfully.")); + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Cannot write into destination file."), + tr("Cannot write into destination file.")); + } + } + else { + m_ui->m_lblResult->setStatus(WidgetWithStatus::Error, tr("Critical error occurred."), tr("Critical error occurred.")); + } + } + + default: + break; + } +} + +void FormImportExport::importFeeds() { + +} diff --git a/src/gui/formimportexport.h b/src/gui/formimportexport.h new file mode 100644 index 000000000..8334036d8 --- /dev/null +++ b/src/gui/formimportexport.h @@ -0,0 +1,68 @@ +// This file is part of RSS Guard. +// +// Copyright (C) 2011-2014 by Martin Rotter +// +// 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 . + +#ifndef FORMEXPORT_H +#define FORMEXPORT_H + +#include + +#include "ui_formimportexport.h" + + +namespace Ui { + class FormExport; +} + +class FeedsImportExportModel; + +class FormImportExport : public QDialog { + Q_OBJECT + + public: + enum ConversionType { + OPML20 = 0 + }; + + enum Mode { + Import, + Export + }; + + explicit FormImportExport(QWidget *parent = 0); + virtual ~FormImportExport(); + + Mode mode() const; + void setMode(const Mode &mode); + + private slots: + void performAction(); + void selectFile(); + + private: + void selectExportFile(); + void selectImportFile(); + + void exportFeeds(); + void importFeeds(); + + Ui::FormImportExport *m_ui; + Mode m_mode; + ConversionType m_conversionType; + FeedsImportExportModel *m_model; +}; + +#endif // FORMEXPORT_H diff --git a/src/gui/formimportexport.ui b/src/gui/formimportexport.ui new file mode 100644 index 000000000..cc5267abf --- /dev/null +++ b/src/gui/formimportexport.ui @@ -0,0 +1,148 @@ + + + FormImportExport + + + + 0 + 0 + 478 + 434 + + + + Dialog + + + + + + + + + + + + &Select file + + + + + + + Qt::RightToLeft + + + + + + + + + + + + + + + + + 0 + 1 + + + + 10 + + + false + + + true + + + true + + + false + + + false + + + + + + + + + + Operation results + + + + + + Qt::RightToLeft + + + + + + + + + + Qt::Horizontal + + + QDialogButtonBox::Cancel|QDialogButtonBox::Ok + + + + + + + + LabelWithStatus + QWidget +
labelwithstatus.h
+ 1 +
+
+ + + + m_buttonBox + accepted() + FormImportExport + accept() + + + 248 + 254 + + + 157 + 274 + + + + + m_buttonBox + rejected() + FormImportExport + reject() + + + 316 + 260 + + + 286 + 274 + + + + +
diff --git a/src/gui/formmain.cpp b/src/gui/formmain.cpp index de3cd1a6d..bf99dface 100755 --- a/src/gui/formmain.cpp +++ b/src/gui/formmain.cpp @@ -34,6 +34,7 @@ #include "gui/statusbar.h" #include "gui/feedmessageviewer.h" #include "gui/formupdate.h" +#include "gui/formimportexport.h" #include #include @@ -436,7 +437,13 @@ void FormMain::loadWebBrowserMenu(int index) { m_ui->m_actionCloseCurrentTab->setEnabled(m_ui->m_tabWidget->tabBar()->tabType(index) == TabBar::Closable); } -void FormMain::exportFeeds() { +void FormMain::exportFeeds() { + QPointer form = new FormImportExport(this); + form.data()->setMode(FormImportExport::Export); + form.data()->exec(); + delete form.data(); + +/* QString filter_opml20 = tr("OPML 2.0 files (*.opml)"); QString filter; @@ -476,11 +483,14 @@ void FormMain::exportFeeds() { output_file.close(); } } - } + }*/ } void FormMain::importFeeds() { - + QPointer form = new FormImportExport(this); + form.data()->setMode(FormImportExport::Import); + form.data()->exec(); + delete form.data(); } void FormMain::changeEvent(QEvent *event) { diff --git a/src/gui/formsettings.ui b/src/gui/formsettings.ui index e29de459e..099ad5438 100644 --- a/src/gui/formsettings.ui +++ b/src/gui/formsettings.ui @@ -17,7 +17,7 @@ - 3 + 0 @@ -241,8 +241,8 @@ Authors of this application are NOT responsible for lost data. 0 0 - 100 - 30 + 588 + 390