diff options
Diffstat (limited to 'kftpgrabber/src/misc/filter.cpp')
-rw-r--r-- | kftpgrabber/src/misc/filter.cpp | 421 |
1 files changed, 421 insertions, 0 deletions
diff --git a/kftpgrabber/src/misc/filter.cpp b/kftpgrabber/src/misc/filter.cpp new file mode 100644 index 0000000..605eba7 --- /dev/null +++ b/kftpgrabber/src/misc/filter.cpp @@ -0,0 +1,421 @@ +/* + * This file is part of the KFTPGrabber project + * + * Copyright (C) 2003-2006 by the KFTPGrabber developers + * Copyright (C) 2003-2006 Jernej Kos <kostko@jweb-network.net> + * + * 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 + * is provided AS IS, WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, and + * NON-INFRINGEMENT. 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 Steet, Fifth Floor, Boston, + * MA 02110-1301, USA. + * + * In addition, as a special exception, the copyright holders give + * permission to link the code of portions of this program with the + * OpenSSL library under certain conditions as described in each + * individual source file, and distribute linked combinations + * including the two. + * + * 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) with this exception, 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. If you delete this exception statement from all source + * files in the program, then also delete it here. + */ +#include "filter.h" + +#include <qregexp.h> + +#include <kapplication.h> +#include <klocale.h> +#include <kstaticdeleter.h> +#include <kconfig.h> + +namespace KFTPCore { + +namespace Filter { + +Condition::Condition(Field field, Type type, const QVariant &value) + : m_field(field), + m_type(type), + m_value(value) +{ +} + +bool Condition::matches(const KFTPEngine::DirectoryEntry &entry) const +{ + bool result = false; + QString check; + + switch (m_field) { + default: + case Filename: check = entry.filename(); break; + case EntryType: check = entry.type(); break; + case Size: check = QString::number(entry.size()); break; + } + + switch (m_type) { + case None: result = false; break; + + case Contains: result = (check.contains(m_value.toString()) > 0); break; + case ContainsNot: result = (check.contains(m_value.toString()) == 0); break; + + case Is: result = (check == m_value.toString()); break; + case IsNot: result = (check != m_value.toString()); break; + + case Matches: { + QRegExp r(m_value.toString()); + result = (r.search(check) > -1); + break; + } + case MatchesNot: { + QRegExp r(m_value.toString()); + result = (r.search(check) == -1); + break; + } + + case Greater: result = (check.toULongLong() > m_value.toULongLong()); break; + case Smaller: result = (check.toULongLong() < m_value.toULongLong()); break; + } + + return result; +} + +ConditionChain::ConditionChain() + : QPtrList<Condition>(), + m_type(All) +{ + setAutoDelete(true); +} + +ConditionChain::ConditionChain(Type type) + : QPtrList<Condition>(), + m_type(type) +{ + setAutoDelete(true); +} + +bool ConditionChain::matches(const KFTPEngine::DirectoryEntry &entry) const +{ + if (isEmpty()) + return false; + + QPtrList<Condition>::ConstIterator le = end(); + for (QPtrList<Condition>::ConstIterator i = begin(); i != le; ++i) { + bool match = (*i)->matches(entry); + + if (match && m_type == Any) + return true; + else if (!match && m_type == All) + return false; + } + + if (m_type == Any) + return false; + + return true; +} + +Action::Action() + : m_valid(false) +{ +} + +Action::Action(Type type, const QVariant &value) + : m_valid(true), + m_type(type), + m_value(value) +{ +} + +ActionChain::ActionChain() + : QPtrList<Action>() +{ + setAutoDelete(true); +} + +const Action *ActionChain::getAction(Action::Type type) const +{ + ActionChain::ConstIterator le = end(); + for (ActionChain::ConstIterator i = begin(); i != le; ++i) + if ((*i)->type() == type) + return (*i); + + return 0; +} + +Rule::Rule() + : m_name(QString::null), + m_enabled(false) +{ +} + +Rule::Rule(const Rule *rule) + : m_name(rule->name()), + m_enabled(rule->isEnabled()) +{ + // Copy conditions + const ConditionChain *conditionList = rule->conditions(); + m_conditionChain.setType(conditionList->type()); + + ConditionChain::ConstIterator cle = conditionList->end(); + for (ConditionChain::ConstIterator i = conditionList->begin(); i != cle; ++i) { + const Condition *c = (*i); + + m_conditionChain.append(new Condition(c->field(), c->type(), c->value())); + } + + // Copy actions + const ActionChain *actionList = rule->actions(); + + ActionChain::ConstIterator ale = actionList->end(); + for (ActionChain::ConstIterator i = actionList->begin(); i != ale; ++i) { + const Action *a = (*i); + + m_actionChain.append(new Action(a->type(), a->value())); + } +} + +Rule::Rule(const QString &name) + : m_name(name), + m_enabled(true) +{ + // Add a simple condition and a simple action + m_conditionChain.append(new Condition(Filename, Condition::Contains, QVariant(""))); + m_actionChain.append(new Action(Action::None, QVariant())); +} + +Filters *Filters::m_self = 0; +static KStaticDeleter<Filters> staticFiltersDeleter; + +Filters *Filters::self() +{ + if (!m_self) { + staticFiltersDeleter.setObject(m_self, new Filters()); + } + + return m_self; +} + +Filters::Filters() + : QPtrList<Rule>(), + m_enabled(true) +{ + setAutoDelete(true); + + // Generate human readable strings + m_fieldNames << i18n("Filename"); + m_fieldNames << i18n("Entry Type"); + m_fieldNames << i18n("Size"); + + m_actionNames << " "; + m_actionNames << i18n("Change priority"); + m_actionNames << i18n("Skip when queuing"); + m_actionNames << i18n("Colorize in list view"); + m_actionNames << i18n("Hide from list view"); + m_actionNames << i18n("Lowercase destination"); + + // Load the filters + load(); +} + +Filters::~Filters() +{ + if (m_self == this) + staticFiltersDeleter.setObject(m_self, 0, false); +} + +void Filters::save() +{ + int num = 0; + KConfig *config = kapp->config(); + + config->setGroup("Filters"); + config->writeEntry("count", count()); + + // Remove any existing sections + for (int i = 0; ; i++) { + QString groupName = QString("Filter #%1").arg(i); + + if (config->hasGroup(groupName)) + config->deleteGroup(groupName); + else + break; + } + + Filters::ConstIterator le = end(); + for (Filters::ConstIterator i = begin(); i != le; ++i, num++) { + const Rule *rule = (*i); + + config->setGroup(QString("Filter #%1").arg(num)); + config->writeEntry("name", rule->name()); + config->writeEntry("enabled", rule->isEnabled()); + + // Write conditions + int cnum = 0; + const ConditionChain *conditions = rule->conditions(); + config->writeEntry("conditions", conditions->count()); + config->writeEntry("conditions-type", (int) conditions->type()); + + ConditionChain::ConstIterator cle = conditions->end(); + for (ConditionChain::ConstIterator j = conditions->begin(); j != cle; ++j, cnum++) { + const Condition *c = (*j); + QString prefix = QString("condition%1-").arg(cnum); + + config->writeEntry(prefix + "field", (int) c->field()); + config->writeEntry(prefix + "type", (int) c->type()); + config->writeEntry(prefix + "value", c->value()); + config->writeEntry(prefix + "valueType", (int) c->value().type()); + } + + // Write actions + int anum = 0; + const ActionChain *actions = rule->actions(); + config->writeEntry("actions", actions->count()); + + ActionChain::ConstIterator ale = actions->end(); + for (ActionChain::ConstIterator j = actions->begin(); j != ale; ++j, anum++) { + const Action *a = (*j); + QString prefix = QString("action%1-").arg(anum); + + config->writeEntry(prefix + "type", (int) a->type()); + config->writeEntry(prefix + "value", a->value()); + config->writeEntry(prefix + "valueType", (int) a->value().type()); + } + } +} + +void Filters::load() +{ + int num = 0; + KConfig *config = kapp->config(); + + config->setGroup("Filters"); + num = config->readNumEntry("count"); + + for (int i = 0; i < num; i++) { + Rule *rule = new Rule(); + + config->setGroup(QString("Filter #%1").arg(i)); + rule->setName(config->readEntry("name", i18n("Unnamed Rule"))); + rule->setEnabled(config->readBoolEntry("enabled", true)); + + // Read conditions + ConditionChain *conditions = const_cast<ConditionChain*>(rule->conditions()); + int cnum = config->readNumEntry("conditions"); + conditions->setType((ConditionChain::Type) config->readNumEntry("conditions-type")); + + for (int j = 0; j < cnum; j++) { + QString prefix = QString("condition%1-").arg(j); + + conditions->append(new Condition((Field) config->readNumEntry(prefix + "field"), + (Condition::Type) config->readNumEntry(prefix + "type"), + config->readPropertyEntry(prefix + "value", + (QVariant::Type) config->readNumEntry(prefix + "valueType")))); + } + + // Read actions + ActionChain *actions = const_cast<ActionChain*>(rule->actions()); + int anum = config->readNumEntry("actions"); + + for (int j = 0; j < anum; j++) { + QString prefix = QString("action%1-").arg(j); + + actions->append(new Action((Action::Type) config->readNumEntry(prefix + "type"), + config->readPropertyEntry(prefix + "value", + (QVariant::Type) config->readNumEntry(prefix + "valueType")))); + } + + append(rule); + } +} + +const ActionChain *Filters::process(const KFTPEngine::DirectoryEntry &entry) const +{ + if (m_enabled) { + QPtrList<Rule>::ConstIterator le = end(); + for (QPtrList<Rule>::ConstIterator i = begin(); i != le; ++i) { + const Rule *rule = (*i); + + if (rule->isEnabled() && rule->conditions()->matches(entry)) + return rule->actions(); + } + } + + // Nothing has matched + return 0; +} + +const Action *Filters::process(const KFTPEngine::DirectoryEntry &entry, QValueList<Action::Type> types) const +{ + const ActionChain *chain = process(entry); + + if (!chain || chain->isEmpty()) + return 0; + + // Find an action that matches the filter + ActionChain::ConstIterator le = chain->end(); + for (ActionChain::ConstIterator i = chain->begin(); i != le; ++i) { + if (types.contains((*i)->type())) + return (*i); + } + + return 0; +} + +const Action *Filters::process(const KFTPEngine::DirectoryEntry &entry, Action::Type filter) const +{ + const ActionChain *chain = process(entry); + + if (!chain || chain->isEmpty()) + return 0; + + // Find an action that matches the filter + ActionChain::ConstIterator le = chain->end(); + for (ActionChain::ConstIterator i = chain->begin(); i != le; ++i) { + if ((*i)->type() == filter) + return (*i); + } + + return 0; +} + +const Action *Filters::process(const KURL &url, filesize_t size, bool directory, Action::Type filter) const +{ + KFTPEngine::DirectoryEntry entry; + entry.setFilename(url.filename()); + entry.setSize(size); + entry.setType(directory ? 'd' : 'f'); + + return process(entry, filter); +} + +const ActionChain *Filters::process(const KURL &url, filesize_t size, bool directory) const +{ + KFTPEngine::DirectoryEntry entry; + entry.setFilename(url.filename()); + entry.setSize(size); + entry.setType(directory ? 'd' : 'f'); + + return process(entry); +} + +const Action *Filters::process(const KURL &url, Action::Type filter) const +{ + return process(url, 0, false, filter); +} + +} + +} |