diff --git a/src/rss/feeddownloader.cpp b/src/rss/feeddownloader.cpp new file mode 100644 index 000000000..d0ce0b77a --- /dev/null +++ b/src/rss/feeddownloader.cpp @@ -0,0 +1,294 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2006 Christophe Dumez + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact : chris@qbittorrent.org + */ + +#include "feeddownloader.h" + +FeedDownloaderDlg::FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, Bittorrent* BTSession): + QDialog(parent), feed_url(feed_url), feed_name(feed_name), BTSession(BTSession), selected_filter(QString::null) +{ + setupUi(this); + setAttribute(Qt::WA_DeleteOnClose); + Q_ASSERT(!feed_name.isEmpty()); + rssfeed_lbl->setText(feed_name); + filters = RssFilters::getFeedFilters(feed_url); + // Connect Signals/Slots + connect(filtersList, SIGNAL(currentItemChanged(QListWidgetItem* , QListWidgetItem *)), this, SLOT(showFilterSettings(QListWidgetItem *))); + connect(filtersList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFiltersListMenu(const QPoint&))); + connect(actionAdd_filter, SIGNAL(triggered()), this, SLOT(addFilter())); + connect(actionRemove_filter, SIGNAL(triggered()), this, SLOT(deleteFilter())); + connect(actionRename_filter, SIGNAL(triggered()), this, SLOT(renameFilter())); + connect(del_button, SIGNAL(clicked(bool)), this, SLOT(deleteFilter())); + connect(add_button, SIGNAL(clicked(bool)), this, SLOT(addFilter())); + connect(enableDl_cb, SIGNAL(stateChanged(int)), this, SLOT(enableFilterBox(int))); + // Restore saved info + enableDl_cb->setChecked(filters.isDownloadingEnabled()); + fillFiltersList(); + if(filters.size() > 0) { + // Select first filter + filtersList->setCurrentItem(filtersList->item(0)); + //showFilterSettings(filtersList->item(0)); + } + // Show + show(); +} + +FeedDownloaderDlg::~FeedDownloaderDlg() { + if(enableDl_cb->isChecked()) + emit filteringEnabled(); + // Make sure we save everything + saveCurrentFilterSettings(); + filters.save(); +} + +void FeedDownloaderDlg::saveCurrentFilterSettings() { + if(!selected_filter.isEmpty()) { + RssFilter filter = filters.getFilter(selected_filter); + filter.setMatchingTokens(match_line->text()); + filter.setNotMatchingTokens(notmatch_line->text()); + QString save_path = savepath_line->text().trimmed(); + if(save_path.isEmpty()) + save_path = BTSession->getDefaultSavePath(); + filter.setSavePath(save_path); + // Save updated filter + filters.setFilter(selected_filter, filter); + } +} + +void FeedDownloaderDlg::on_browse_button_clicked() { + QString default_path = savepath_line->text(); + if(default_path.isEmpty() || !QDir(default_path).exists()) { + default_path = QDir::homePath(); + } + QString dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath()); + if(!dir.isNull() && QDir(dir).exists()) { + savepath_line->setText(dir); + } +} + +void FeedDownloaderDlg::fillFiltersList() { + // Fill filter list + foreach(QString filter_name, filters.names()) { + new QListWidgetItem(filter_name, filtersList); + } +} + +void FeedDownloaderDlg::displayFiltersListMenu(const QPoint&) { + QMenu myFiltersListMenu(this); + if(filtersList->selectedItems().size() > 0) { + myFiltersListMenu.addAction(actionRename_filter); + myFiltersListMenu.addAction(actionRemove_filter); + } else { + myFiltersListMenu.addAction(actionAdd_filter); + } + // Call menu + myFiltersListMenu.exec(QCursor::pos()); +} + +void FeedDownloaderDlg::showFilterSettings(QListWidgetItem *item) { + // First, save current filter settings + saveCurrentFilterSettings(); + // Clear all fields + clearFields(); + if(!item) { + qDebug("No new selected item"); + return; + } + // Actually show filter settings + QString filter_name = item->text(); + RssFilter filter = filters.getFilter(filter_name); + filterSettingsBox->setEnabled(true); + match_line->setText(filter.getMatchingTokens_str()); + if(match_line->text().trimmed().isEmpty()) { + match_line->setText(filter_name); + } + notmatch_line->setText(filter.getNotMatchingTokens_str()); + QString save_path = filter.getSavePath(); + if(save_path.isEmpty()) + save_path = BTSession->getDefaultSavePath(); + savepath_line->setText(save_path); + // Update selected filter + selected_filter = filter_name; +} + +void FeedDownloaderDlg::deleteFilter() { + QList items = filtersList->selectedItems(); + if(items.size() == 1) { + QListWidgetItem * item = items.first(); + filters.remove(item->text()); + selected_filter = QString::null; + delete item; + // Reset Filter settings view + if(filters.size() == 0) { + clearFields(); + filterSettingsBox->setEnabled(false); + } + } +} + +void FeedDownloaderDlg::renameFilter() { + QList items = filtersList->selectedItems(); + if(items.size() == 1) { + QListWidgetItem *item = items.first(); + QString current_name = item->text(); + QString new_name; + bool validated = false; + do { + new_name = askFilterName(current_name); + if(new_name.isNull() || new_name == current_name) return; + if(!filters.hasFilter(new_name)) { + validated = true; + } else { + QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); + } + }while(!validated); + // Save the current filter + saveCurrentFilterSettings(); + // Rename the filter + filters.rename(current_name, new_name); + if(selected_filter == current_name) + selected_filter = new_name; + item->setText(new_name); + } +} + +void FeedDownloaderDlg::enableFilterBox(int state) { + if(state == Qt::Checked) { + filtersBox->setEnabled(true); + filters.setDownloadingEnabled(true); + } else { + filtersBox->setEnabled(false); + filters.setDownloadingEnabled(false); + } +} + +QString FeedDownloaderDlg::askFilterName(QString name) { + QString name_prop; + if(name.isEmpty()) + name_prop = tr("New filter"); + else + name_prop = name; + QString new_name; + bool validated = false; + do { + bool ok; + new_name = QInputDialog::getText(this, tr("Please choose a name for this filter"), tr("Filter name:"), QLineEdit::Normal, name_prop, &ok); + if(!ok) { + return QString::null; + } + // Validate filter name + new_name = new_name.trimmed(); + if(new_name.isEmpty()) { + // Cannot be left empty + QMessageBox::warning(0, tr("Invalid filter name"), tr("The filter name cannot be left empty.")); + } else { + validated = true; + } + } while(!validated); + return new_name; +} + +void FeedDownloaderDlg::addFilter() { + QString filter_name = QString::null; + bool validated = false; + do { + filter_name = askFilterName(); + if(filter_name.isNull()) return; + if(filters.hasFilter(filter_name)) { + // Filter alread exists + QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); + } else { + validated = true; + } + }while(!validated); + QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList); + filtersList->setCurrentItem(it); + //showFilterSettings(it); +} + +void FeedDownloaderDlg::clearFields() { + match_line->clear(); + notmatch_line->clear(); + savepath_line->clear(); + test_res_lbl->setText(""); + test_line->clear(); +} + +void FeedDownloaderDlg::on_testButton_clicked(bool) { + test_res_lbl->clear(); + if(selected_filter.isEmpty()) { + qDebug("No filter is selected!!!"); + return; + } + QString s = test_line->text().trimmed(); + if(s.isEmpty()) { + QMessageBox::warning(0, tr("Filter testing error"), tr("Please specify a test torrent name.")); + return; + } + // Get current filter + saveCurrentFilterSettings(); + RssFilter f = filters.getFilter(selected_filter); + if(f.matches(s)) + test_res_lbl->setText(""+tr("matches")+""); + else + test_res_lbl->setText(""+tr("does not match")+""); +} + +void FeedDownloaderDlg::on_importButton_clicked(bool) { + QString source = QFileDialog::getOpenFileName(0, tr("Select file to import"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)")); + if(source.isEmpty()) return; + if(filters.unserialize(source)) { + // Clean up first + clearFields(); + filtersList->clear(); + selected_filter = QString::null; + fillFiltersList(); + if(filters.size() > 0) + filtersList->setCurrentItem(filtersList->item(0)); + QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful.")); + } else { + QMessageBox::warning(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error.")); + } +} + +void FeedDownloaderDlg::on_exportButton_clicked(bool) { + QString destination = QFileDialog::getSaveFileName(this, tr("Select destination file"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)")); + if(destination.isEmpty()) return; + // Append file extension + if(!destination.endsWith(".filters")) + destination += ".filters"; + /*if(QFile::exists(destination)) { + int ret = QMessageBox::question(0, tr("Overwriting confirmation"), tr("Are you sure you want to overwrite existing file?"), QMessageBox::Yes|QMessageBox::No); + if(ret != QMessageBox::Yes) return; + }*/ + if(filters.serialize(destination)) + QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful.")); + else + QMessageBox::warning(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error.")); +} diff --git a/src/rss/feeddownloader.h b/src/rss/feeddownloader.h index e52665182..d97c47320 100644 --- a/src/rss/feeddownloader.h +++ b/src/rss/feeddownloader.h @@ -46,460 +46,41 @@ #include "qbtsession.h" #include "ui_feeddownloader.h" #include "qinisettings.h" - - -class FeedFilter: public QHash { -private: - bool valid; -public: - FeedFilter():valid(true) {} - FeedFilter(bool valid): valid(valid) {} - FeedFilter(QHash filter): QHash(filter), valid(true) {} - - bool matches(QString s) { - QStringList match_tokens = getMatchingTokens(); - foreach(const QString& token, match_tokens) { - if(token.isEmpty() || token == "") - continue; - QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard); - //reg.setMinimal(false); - if(reg.indexIn(s) < 0) return false; - } - qDebug("Checking not matching tokens"); - // Checking not matching - QStringList notmatch_tokens = getNotMatchingTokens(); - foreach(const QString& token, notmatch_tokens) { - if(token.isEmpty()) continue; - QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard); - if(reg.indexIn(s) > -1) return false; - } - return true; - } - - bool isValid() const { - return valid; - } - - QStringList getMatchingTokens() const { - QString matches = this->value("matches", "").toString(); - return matches.split(" "); - } - - QString getMatchingTokens_str() const { - return this->value("matches", "").toString(); - } - - void setMatchingTokens(QString tokens) { - tokens = tokens.trimmed(); - if(tokens.isEmpty()) - (*this)["matches"] = ""; - else - (*this)["matches"] = tokens; - } - - QStringList getNotMatchingTokens() const { - QString notmatching = this->value("not", "").toString(); - return notmatching.split(QRegExp("[\\s|]")); - } - - QString getNotMatchingTokens_str() const { - return this->value("not", "").toString(); - } - - void setNotMatchingTokens(QString tokens) { - (*this)["not"] = tokens.trimmed(); - } - - QString getSavePath() const { - return this->value("save_path", "").toString(); - } - - void setSavePath(QString save_path) { - (*this)["save_path"] = save_path; - } - -}; - -class FeedFilters : public QHash { - -private: - QString feed_url; - -public: - FeedFilters() {} - FeedFilters(QString feed_url, QHash filters): QHash(filters), feed_url(feed_url) {} - - bool hasFilter(QString name) const { - return this->contains(name); - } - - FeedFilter* matches(QString s) { - if(!isDownloadingEnabled()) return 0; - if(this->size() == 0) return new FeedFilter(false); - foreach(QVariant var_hash_filter, this->values()) { - QHash hash_filter = var_hash_filter.toHash(); - FeedFilter *filter = new FeedFilter(hash_filter); - if(filter->matches(s)) - return filter; - else - delete filter; - } - return 0; - } - - QStringList names() const { - return this->keys(); - } - - FeedFilter getFilter(QString name) const { - if(this->contains(name)) - return FeedFilter(this->value(name).toHash()); - return FeedFilter(); - } - - void setFilter(QString name, FeedFilter f) { - (*this)[name] = f; - } - - bool isDownloadingEnabled() const { - QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); - QHash feeds_w_downloader = qBTRSS.value("downloader_on", QHash()).toHash(); - return feeds_w_downloader.value(feed_url, false).toBool(); - } - - void setDownloadingEnabled(bool enabled) { - QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); - QHash feeds_w_downloader = qBTRSS.value("downloader_on", QHash()).toHash(); - feeds_w_downloader[feed_url] = enabled; - qBTRSS.setValue("downloader_on", feeds_w_downloader); - } - - static FeedFilters getFeedFilters(QString url) { - QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); - QHash all_feeds_filters = qBTRSS.value("feed_filters", QHash()).toHash(); - return FeedFilters(url, all_feeds_filters.value(url, QHash()).toHash()); - } - - void rename(QString old_name, QString new_name) { - Q_ASSERT(this->contains(old_name)); - (*this)[new_name] = this->take(old_name); - } - - bool serialize(QString path) { - QFile f(path); - if(f.open(QIODevice::WriteOnly)) { - QDataStream out(&f); - out.setVersion(QDataStream::Qt_4_3); - out << (QHash)(*this); - f.close(); - return true; - } else { - return false; - } - } - - bool unserialize(QString path) { - QFile f(path); - if(f.open(QIODevice::ReadOnly)) { - QDataStream in(&f); - in.setVersion(QDataStream::Qt_4_3); - QHash tmp; - in >> tmp; - qDebug("Unserialized %d filters", tmp.size()); - foreach(const QString& key, tmp.keys()) { - (*this)[key] = tmp[key]; - } - return true; - } else { - return false; - } - } - - void save() { - QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); - QHash all_feeds_filters = qBTRSS.value("feed_filters", QHash()).toHash(); - qDebug("Saving filters for feed: %s (%d filters)", qPrintable(feed_url), (*this).size()); - all_feeds_filters[feed_url] = *this; - qBTRSS.setValue("feed_filters", all_feeds_filters); - } -}; +#include "rssfilters.h" class FeedDownloaderDlg : public QDialog, private Ui_FeedDownloader{ Q_OBJECT -private: - QString feed_url; - QString feed_name; - FeedFilters filters; - Bittorrent *BTSession; - QString selected_filter; // name - public: - FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, Bittorrent* BTSession): QDialog(parent), feed_url(feed_url), feed_name(feed_name), BTSession(BTSession), selected_filter(QString::null){ - setupUi(this); - setAttribute(Qt::WA_DeleteOnClose); - Q_ASSERT(!feed_name.isEmpty()); - rssfeed_lbl->setText(feed_name); - filters = FeedFilters::getFeedFilters(feed_url); - // Connect Signals/Slots - connect(filtersList, SIGNAL(currentItemChanged(QListWidgetItem* , QListWidgetItem *)), this, SLOT(showFilterSettings(QListWidgetItem *))); - connect(filtersList, SIGNAL(customContextMenuRequested(const QPoint&)), this, SLOT(displayFiltersListMenu(const QPoint&))); - connect(actionAdd_filter, SIGNAL(triggered()), this, SLOT(addFilter())); - connect(actionRemove_filter, SIGNAL(triggered()), this, SLOT(deleteFilter())); - connect(actionRename_filter, SIGNAL(triggered()), this, SLOT(renameFilter())); - connect(del_button, SIGNAL(clicked(bool)), this, SLOT(deleteFilter())); - connect(add_button, SIGNAL(clicked(bool)), this, SLOT(addFilter())); - connect(enableDl_cb, SIGNAL(stateChanged(int)), this, SLOT(enableFilterBox(int))); - // Restore saved info - enableDl_cb->setChecked(filters.isDownloadingEnabled()); - fillFiltersList(); - if(filters.size() > 0) { - // Select first filter - filtersList->setCurrentItem(filtersList->item(0)); - //showFilterSettings(filtersList->item(0)); - } - // Show - show(); - } - - ~FeedDownloaderDlg() { - if(enableDl_cb->isChecked()) - emit filteringEnabled(); - // Make sure we save everything - saveCurrentFilterSettings(); - filters.save(); - } + FeedDownloaderDlg(QWidget *parent, QString feed_url, QString feed_name, Bittorrent* BTSession); + ~FeedDownloaderDlg(); protected slots: - void saveCurrentFilterSettings() { - if(!selected_filter.isEmpty()) { - FeedFilter filter = filters.getFilter(selected_filter); - filter.setMatchingTokens(match_line->text()); - filter.setNotMatchingTokens(notmatch_line->text()); - QString save_path = savepath_line->text().trimmed(); - if(save_path.isEmpty()) - save_path = BTSession->getDefaultSavePath(); - filter.setSavePath(save_path); - // Save updated filter - filters.setFilter(selected_filter, filter); - } - } - - void on_browse_button_clicked() { - QString default_path = savepath_line->text(); - if(default_path.isEmpty() || !QDir(default_path).exists()) { - default_path = QDir::homePath(); - } - QString dir = QFileDialog::getExistingDirectory(this, tr("Choose save path"), QDir::homePath()); - if(!dir.isNull() && QDir(dir).exists()) { - savepath_line->setText(dir); - } - } - - void fillFiltersList() { - // Fill filter list - foreach(QString filter_name, filters.names()) { - new QListWidgetItem(filter_name, filtersList); - } - } - - void displayFiltersListMenu(const QPoint&) { - QMenu myFiltersListMenu(this); - if(filtersList->selectedItems().size() > 0) { - myFiltersListMenu.addAction(actionRename_filter); - myFiltersListMenu.addAction(actionRemove_filter); - } else { - myFiltersListMenu.addAction(actionAdd_filter); - } - // Call menu - myFiltersListMenu.exec(QCursor::pos()); - } - - void showFilterSettings(QListWidgetItem *item) { - // First, save current filter settings - saveCurrentFilterSettings(); - // Clear all fields - clearFields(); - if(!item) { - qDebug("No new selected item"); - return; - } - // Actually show filter settings - QString filter_name = item->text(); - FeedFilter filter = filters.getFilter(filter_name); - filterSettingsBox->setEnabled(true); - match_line->setText(filter.getMatchingTokens_str()); - if(match_line->text().trimmed().isEmpty()) { - match_line->setText(filter_name); - } - notmatch_line->setText(filter.getNotMatchingTokens_str()); - QString save_path = filter.getSavePath(); - if(save_path.isEmpty()) - save_path = BTSession->getDefaultSavePath(); - savepath_line->setText(save_path); - // Update selected filter - selected_filter = filter_name; - } - - void deleteFilter() { - QList items = filtersList->selectedItems(); - if(items.size() == 1) { - QListWidgetItem * item = items.first(); - filters.remove(item->text()); - selected_filter = QString::null; - delete item; - // Reset Filter settings view - if(filters.size() == 0) { - clearFields(); - filterSettingsBox->setEnabled(false); - } - } - } - - void renameFilter() { - QList items = filtersList->selectedItems(); - if(items.size() == 1) { - QListWidgetItem *item = items.first(); - QString current_name = item->text(); - QString new_name; - bool validated = false; - do { - new_name = askFilterName(current_name); - if(new_name.isNull() || new_name == current_name) return; - if(!filters.hasFilter(new_name)) { - validated = true; - } else { - QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); - } - }while(!validated); - // Save the current filter - saveCurrentFilterSettings(); - // Rename the filter - filters.rename(current_name, new_name); - if(selected_filter == current_name) - selected_filter = new_name; - item->setText(new_name); - } - } - - void enableFilterBox(int state) { - if(state == Qt::Checked) { - filtersBox->setEnabled(true); - filters.setDownloadingEnabled(true); - } else { - filtersBox->setEnabled(false); - filters.setDownloadingEnabled(false); - } - } - - QString askFilterName(QString name=QString::null) { - QString name_prop; - if(name.isEmpty()) - name_prop = tr("New filter"); - else - name_prop = name; - QString new_name; - bool validated = false; - do { - bool ok; - new_name = QInputDialog::getText(this, tr("Please choose a name for this filter"), tr("Filter name:"), QLineEdit::Normal, name_prop, &ok); - if(!ok) { - return QString::null; - } - // Validate filter name - new_name = new_name.trimmed(); - if(new_name.isEmpty()) { - // Cannot be left empty - QMessageBox::warning(0, tr("Invalid filter name"), tr("The filter name cannot be left empty.")); - } else { - validated = true; - } - } while(!validated); - return new_name; - } - - void addFilter() { - QString filter_name = QString::null; - bool validated = false; - do { - filter_name = askFilterName(); - if(filter_name.isNull()) return; - if(filters.hasFilter(filter_name)) { - // Filter alread exists - QMessageBox::warning(0, tr("Invalid filter name"), tr("This filter name is already in use.")); - } else { - validated = true; - } - }while(!validated); - QListWidgetItem *it = new QListWidgetItem(filter_name, filtersList); - filtersList->setCurrentItem(it); - //showFilterSettings(it); - } - - void clearFields() { - match_line->clear(); - notmatch_line->clear(); - savepath_line->clear(); - test_res_lbl->setText(""); - test_line->clear(); - } - - void on_testButton_clicked(bool) { - test_res_lbl->clear(); - if(selected_filter.isEmpty()) { - qDebug("No filter is selected!!!"); - return; - } - QString s = test_line->text().trimmed(); - if(s.isEmpty()) { - QMessageBox::warning(0, tr("Filter testing error"), tr("Please specify a test torrent name.")); - return; - } - // Get current filter - saveCurrentFilterSettings(); - FeedFilter f = filters.getFilter(selected_filter); - if(f.matches(s)) - test_res_lbl->setText(""+tr("matches")+""); - else - test_res_lbl->setText(""+tr("does not match")+""); - } - - void on_importButton_clicked(bool) { - QString source = QFileDialog::getOpenFileName(0, tr("Select file to import"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)")); - if(source.isEmpty()) return; - if(filters.unserialize(source)) { - // Clean up first - clearFields(); - filtersList->clear(); - selected_filter = QString::null; - fillFiltersList(); - if(filters.size() > 0) - filtersList->setCurrentItem(filtersList->item(0)); - QMessageBox::information(0, tr("Import successful"), tr("Filters import was successful.")); - } else { - QMessageBox::warning(0, tr("Import failure"), tr("Filters could not be imported due to an I/O error.")); - } - } - - void on_exportButton_clicked(bool) { - QString destination = QFileDialog::getSaveFileName(this, tr("Select destination file"), QDir::homePath(), tr("Filters Files")+QString::fromUtf8(" (*.filters)")); - if(destination.isEmpty()) return; - // Append file extension - if(!destination.endsWith(".filters")) - destination += ".filters"; - /*if(QFile::exists(destination)) { - int ret = QMessageBox::question(0, tr("Overwriting confirmation"), tr("Are you sure you want to overwrite existing file?"), QMessageBox::Yes|QMessageBox::No); - if(ret != QMessageBox::Yes) return; - }*/ - if(filters.serialize(destination)) - QMessageBox::information(0, tr("Export successful"), tr("Filters export was successful.")); - else - QMessageBox::warning(0, tr("Export failure"), tr("Filters could not be exported due to an I/O error.")); - } + void saveCurrentFilterSettings(); + void on_browse_button_clicked(); + void fillFiltersList(); + void displayFiltersListMenu(const QPoint&); + void showFilterSettings(QListWidgetItem *item); + void deleteFilter(); + void renameFilter(); + void enableFilterBox(int state); + QString askFilterName(QString name=QString::null); + void addFilter(); + void clearFields(); + void on_testButton_clicked(bool); + void on_importButton_clicked(bool); + void on_exportButton_clicked(bool); signals: void filteringEnabled(); +private: + QString feed_url; + QString feed_name; + RssFilters filters; + Bittorrent *BTSession; + QString selected_filter; // name + }; #endif // FEEDDOWNLOADER_H diff --git a/src/rss/rss.pri b/src/rss/rss.pri index b0c6d8721..1ae393c9a 100644 --- a/src/rss/rss.pri +++ b/src/rss/rss.pri @@ -10,7 +10,8 @@ INCLUDEPATH += $$PWD $$PWD/rssfeed.h \ $$PWD/rssfolder.h \ $$PWD/rssfile.h \ - $$PWD/rssarticle.h + $$PWD/rssarticle.h \ + $$PWD/rssfilters.h SOURCES += $$PWD/rss_imp.cpp \ $$PWD/rsssettings.cpp \ @@ -18,7 +19,9 @@ INCLUDEPATH += $$PWD $$PWD/rssmanager.cpp \ $$PWD/rssfeed.cpp \ $$PWD/rssfolder.cpp \ - $$PWD/rssarticle.cpp + $$PWD/rssarticle.cpp \ + $$PWD/feeddownloader.cpp \ + $$PWD/rssfilters.cpp FORMS += $$PWD/ui/rss.ui \ $$PWD/ui/feeddownloader.ui \ diff --git a/src/rss/rssfeed.cpp b/src/rss/rssfeed.cpp index aa6203461..05e05cd5e 100644 --- a/src/rss/rssfeed.cpp +++ b/src/rss/rssfeed.cpp @@ -297,7 +297,7 @@ short RssFeed::readDoc(QIODevice* device) { else torrent_url = item->getLink(); // Check if the item should be automatically downloaded - FeedFilter * matching_filter = FeedFilters::getFeedFilters(url).matches(item->getTitle()); + RssFilter * matching_filter = RssFilters::getFeedFilters(url).matches(item->getTitle()); if(matching_filter != 0) { // Download the torrent BTSession->addConsoleMessage(tr("Automatically downloading %1 torrent from %2 RSS feed...").arg(item->getTitle()).arg(getName())); diff --git a/src/rss/rssfilters.cpp b/src/rss/rssfilters.cpp new file mode 100644 index 000000000..fa1ef53fb --- /dev/null +++ b/src/rss/rssfilters.cpp @@ -0,0 +1,216 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact: chris@qbittorrent.org, arnaud@qbittorrent.org + */ + +#include + +#include "preferences.h" +#include "rssfilters.h" + +// RssFilter + +RssFilter::RssFilter(): valid(true) { + +} + +RssFilter::RssFilter(bool valid): valid(valid) { + +} + +RssFilter::RssFilter(QHash filter): + QHash(filter), valid(true) { + +} + +bool RssFilter::matches(QString s) { + QStringList match_tokens = getMatchingTokens(); + foreach(const QString& token, match_tokens) { + if(token.isEmpty() || token == "") + continue; + QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard); + //reg.setMinimal(false); + if(reg.indexIn(s) < 0) return false; + } + qDebug("Checking not matching tokens"); + // Checking not matching + QStringList notmatch_tokens = getNotMatchingTokens(); + foreach(const QString& token, notmatch_tokens) { + if(token.isEmpty()) continue; + QRegExp reg(token, Qt::CaseInsensitive, QRegExp::Wildcard); + if(reg.indexIn(s) > -1) return false; + } + return true; +} + +bool RssFilter::isValid() const { + return valid; +} + +QStringList RssFilter::getMatchingTokens() const { + QString matches = this->value("matches", "").toString(); + return matches.split(" "); +} + +QString RssFilter::getMatchingTokens_str() const { + return this->value("matches", "").toString(); +} + +void RssFilter::setMatchingTokens(QString tokens) { + tokens = tokens.trimmed(); + if(tokens.isEmpty()) + (*this)["matches"] = ""; + else + (*this)["matches"] = tokens; +} + +QStringList RssFilter::getNotMatchingTokens() const { + QString notmatching = this->value("not", "").toString(); + return notmatching.split(QRegExp("[\\s|]")); +} + +QString RssFilter::getNotMatchingTokens_str() const { + return this->value("not", "").toString(); +} + +void RssFilter::setNotMatchingTokens(QString tokens) { + (*this)["not"] = tokens.trimmed(); +} + +QString RssFilter::getSavePath() const { + return this->value("save_path", "").toString(); +} + +void RssFilter::setSavePath(QString save_path) { + (*this)["save_path"] = save_path; +} + +// RssFilters + +RssFilters::RssFilters() { + +} + +RssFilters::RssFilters(QString feed_url, QHash filters): + QHash(filters), feed_url(feed_url) { + +} + +bool RssFilters::hasFilter(QString name) const { + return this->contains(name); +} + +RssFilter* RssFilters::matches(QString s) { + if(!isDownloadingEnabled()) return 0; + if(this->size() == 0) return new RssFilter(false); + foreach(QVariant var_hash_filter, this->values()) { + QHash hash_filter = var_hash_filter.toHash(); + RssFilter *filter = new RssFilter(hash_filter); + if(filter->matches(s)) + return filter; + else + delete filter; + } + return 0; +} + +QStringList RssFilters::names() const { + return this->keys(); +} + +RssFilter RssFilters::getFilter(QString name) const { + if(this->contains(name)) + return RssFilter(this->value(name).toHash()); + return RssFilter(); +} + +void RssFilters::setFilter(QString name, RssFilter f) { + (*this)[name] = f; +} + +bool RssFilters::isDownloadingEnabled() const { + QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); + QHash feeds_w_downloader = qBTRSS.value("downloader_on", QHash()).toHash(); + return feeds_w_downloader.value(feed_url, false).toBool(); +} + +void RssFilters::setDownloadingEnabled(bool enabled) { + QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); + QHash feeds_w_downloader = qBTRSS.value("downloader_on", QHash()).toHash(); + feeds_w_downloader[feed_url] = enabled; + qBTRSS.setValue("downloader_on", feeds_w_downloader); +} + +RssFilters RssFilters::getFeedFilters(QString url) { + QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); + QHash all_feeds_filters = qBTRSS.value("feed_filters", QHash()).toHash(); + return RssFilters(url, all_feeds_filters.value(url, QHash()).toHash()); +} + +void RssFilters::rename(QString old_name, QString new_name) { + Q_ASSERT(this->contains(old_name)); + (*this)[new_name] = this->take(old_name); +} + +bool RssFilters::serialize(QString path) { + QFile f(path); + if(f.open(QIODevice::WriteOnly)) { + QDataStream out(&f); + out.setVersion(QDataStream::Qt_4_3); + out << (QHash)(*this); + f.close(); + return true; + } else { + return false; + } +} + +bool RssFilters::unserialize(QString path) { + QFile f(path); + if(f.open(QIODevice::ReadOnly)) { + QDataStream in(&f); + in.setVersion(QDataStream::Qt_4_3); + QHash tmp; + in >> tmp; + qDebug("Unserialized %d filters", tmp.size()); + foreach(const QString& key, tmp.keys()) { + (*this)[key] = tmp[key]; + } + return true; + } else { + return false; + } +} + +void RssFilters::save() { + QIniSettings qBTRSS("qBittorrent", "qBittorrent-rss"); + QHash all_feeds_filters = qBTRSS.value("feed_filters", QHash()).toHash(); + qDebug("Saving filters for feed: %s (%d filters)", qPrintable(feed_url), (*this).size()); + all_feeds_filters[feed_url] = *this; + qBTRSS.setValue("feed_filters", all_feeds_filters); +} diff --git a/src/rss/rssfilters.h b/src/rss/rssfilters.h new file mode 100644 index 000000000..cc9a8299b --- /dev/null +++ b/src/rss/rssfilters.h @@ -0,0 +1,80 @@ +/* + * Bittorrent Client using Qt4 and libtorrent. + * Copyright (C) 2010 Christophe Dumez, Arnaud Demaiziere + * + * This program 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 2 + * of the License, or (at your option) any later version. + * + * This program 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 this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give permission to + * link this program with the OpenSSL project's "OpenSSL" library (or with + * modified versions of it that use the same license as the "OpenSSL" library), + * and distribute the linked executables. You must obey the GNU General Public + * License in all respects for all of the code used other than "OpenSSL". If you + * modify file(s), you may extend this exception to your version of the file(s), + * but you are not obligated to do so. If you do not wish to do so, delete this + * exception statement from your version. + * + * Contact: chris@qbittorrent.org, arnaud@qbittorrent.org + */ + +#ifndef RSSDOWNLOADERFILTERS_H +#define RSSDOWNLOADERFILTERS_H + +#include +#include +#include + +class RssFilter: public QHash { +private: + bool valid; +public: + RssFilter(); + RssFilter(bool valid); + RssFilter(QHash filter); + bool matches(QString s); + bool isValid() const; + QStringList getMatchingTokens() const; + QString getMatchingTokens_str() const; + void setMatchingTokens(QString tokens); + QStringList getNotMatchingTokens() const; + QString getNotMatchingTokens_str() const; + void setNotMatchingTokens(QString tokens); + QString getSavePath() const; + void setSavePath(QString save_path); +}; + +class RssFilters : public QHash { + +public: + RssFilters(); + RssFilters(QString feed_url, QHash filters); + bool hasFilter(QString name) const; + RssFilter* matches(QString s); + QStringList names() const; + RssFilter getFilter(QString name) const; + void setFilter(QString name, RssFilter f); + bool isDownloadingEnabled() const; + void setDownloadingEnabled(bool enabled); + static RssFilters getFeedFilters(QString url); + void rename(QString old_name, QString new_name); + bool serialize(QString path); + bool unserialize(QString path); + void save(); + +private: + QString feed_url; + +}; + +#endif // RSSDOWNLOADERFILTERS_H