Source file: src/edit_rules.cpp
/* Copyright (C) 2004-2009 Daniel Vérité
This file is part of Manitou-Mail (see http://www.manitou-mail.org)
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
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., 59 Temple Place - Suite 330,
Boston, MA 02111-1307, USA.
*/
#include "main.h"
#include "filter_rules.h"
#include "edit_rules.h"
#include "tags.h"
#include "icons.h"
#include "helper.h"
#include "ui_controls.h"
#include "headers_groupview.h"
#include "tagsdialog.h"
#include <QMessageBox>
#include <QFrame>
#include <QHeaderView>
#include <QPushButton>
#include <QLayout>
#include <QLineEdit>
#include <QButtonGroup>
#include <QLabel>
#include <QCheckBox>
#include <QSpinBox>
#include <QStringList>
#include <QEvent>
#include <QFont>
#include <QPainter>
#include <QHBoxLayout>
#include <QKeyEvent>
#include <QGridLayout>
#include <QFocusEvent>
int expr_lvitem::m_max_id=0;
//
// expr_lvitem
//
expr_lvitem::expr_lvitem(QTreeWidget* parent, QString name) :
QTreeWidgetItem(parent, QStringList(name))
{
m_id = ++m_max_id;
m_dirty=false;
}
expr_lvitem::~expr_lvitem()
{
}
//
// action_line
//
action_line::action_line(QWidget* parent, const QString& label,
const QString& type) : QWidget(parent)
{
m_rb = new action_radio_button(label, this);
m_type = type;
setContentsMargins(0,0,0,0);
}
action_line::~action_line()
{
}
void
action_line::set_checked(bool b)
{
m_rb->blockSignals(true);
m_rb->setChecked(b);
m_rb->m_checked=b;
m_rb->blockSignals(false);
}
//
// action_tag
//
action_tag::action_tag(QWidget* parent) :
action_line(parent, tr("Assign tag"), "tag")
{
QHBoxLayout* layout = new QHBoxLayout(this);
m_qc_tag = new tag_selector(this);
layout->addWidget(m_qc_tag);
layout->setStretchFactor(m_qc_tag, 10);
m_qc_tag->init(false);
connect(m_qc_tag, SIGNAL(activated(int)), this, SLOT(newval(int)));
layout->setSpacing(3);
m_edit_btn = new QPushButton(tr("Edit"));
layout->addWidget(m_edit_btn);
layout->setStretchFactor(m_edit_btn, 1);
connect(m_edit_btn, SIGNAL(clicked()), SLOT(edit_tags()));
}
/*
Launch the tag editor in modal mode, and when it gets closed,
refresh the tag list to reflect the modifications
*/
void
action_tag::edit_tags()
{
tags_dialog w(0);
int r = w.exec();
if (r==QDialog::Accepted) {
m_qc_tag->init(false);
}
}
void
action_tag::newval(int index)
{
if (index>=0) {
emit new_value(m_type, m_qc_tag->itemText(index));
}
}
QString
action_tag::get_param()
{
return m_qc_tag->currentText();
}
void
action_tag::set_param(const QString& tag)
{
// No better way to find an entry in a combobox?
int c=m_qc_tag->count();
int i;
for (i=0; i<c; i++) {
if (m_qc_tag->itemText(i) == tag) {
m_qc_tag->setCurrentIndex(i);
break;
}
}
if (i==c) { // if not found, then add the item
m_qc_tag->addItem(tag);
m_qc_tag->setCurrentIndex(c);
}
}
void
action_tag::enable(bool b)
{
m_qc_tag->setEnabled(b);
m_edit_btn->setEnabled(b);
}
void
action_tag::reset()
{
m_qc_tag->setCurrentIndex(-1);
}
//
// action_status
//
const char* action_status::status_text[nb_status] = {
QT_TR_NOOP("Mark read"),
QT_TR_NOOP("Archive"),
QT_TR_NOOP("Trash"),
QT_TR_NOOP("Delete")
};
const char action_status::status_letter[nb_status] = {
'R', 'A', 'T', 'D'
};
action_status::action_status(QWidget* parent):
action_line(parent, tr("Set status"), "status")
{
// setSpacing(3);
QHBoxLayout* layout = new QHBoxLayout(this);
for (int i=0; i<nb_status; i++) {
m_check[i] = new QCheckBox(tr(status_text[i]), this);
CHECK_PTR(m_check[i]);
layout->addWidget(m_check[i]);
connect(m_check[i], SIGNAL(clicked()), this, SLOT(btn_clicked()));
}
}
void
action_status::enable(bool b)
{
for (int i=0; i<nb_status; i++) {
m_check[i]->setEnabled(b);
//m_check[i]->setChecked(b);
}
}
void
action_status::btn_clicked()
{
emit new_value(m_type, get_param());
}
QString
action_status::get_param()
{
QString res;
for (int i=0; i<nb_status; i++) {
if (m_check[i]->isChecked()) {
if (!res.isEmpty())
res.append('+');
res.append(status_letter[i]);
}
}
return res;
}
/*
Set the status checkboxes according to 'param', which should be
of the form R+A+... (read+archived+...)
*/
void
action_status::set_param(const QString& param)
{
reset();
QStringList l=param.split('+', QString::KeepEmptyParts);
for (QStringList::Iterator it=l.begin(); it!=l.end(); ++it) {
QChar s=(*it).at(0);
for (int i=0; i<nb_status; i++) {
if (s==status_letter[i])
m_check[i]->setChecked(true);
}
}
}
void
action_status::reset()
{
for (int i=0; i<nb_status; i++) {
m_check[i]->setChecked(false);
}
}
//
// action_prio
//
action_prio::action_prio(QWidget* parent):
action_line(parent, tr("Priority"), "priority")
{
// setSpacing(3);
QHBoxLayout* layout = new QHBoxLayout(this);
m_check_set=new QRadioButton(tr("Set priority"), this);
connect(m_check_set, SIGNAL(toggled(bool)), this, SLOT(toggle_set(bool)));
connect(m_check_set, SIGNAL(clicked()), this, SLOT(btn_clicked()));
layout->addWidget(m_check_set);
m_prio_set = new QSpinBox(this);
connect(m_prio_set, SIGNAL(valueChanged(int)), this, SLOT(value_changed(int)));
m_prio_set->setMinimum(-1000);
m_prio_set->setMaximum(1000);
layout->addWidget(m_prio_set);
m_check_add = new QRadioButton(tr("Add priority"), this);
connect(m_check_add, SIGNAL(toggled(bool)), this, SLOT(toggle_add(bool)));
connect(m_check_add, SIGNAL(clicked()), this, SLOT(btn_clicked()));
layout->addWidget(m_check_add);
m_prio_add = new QSpinBox(this);
connect(m_prio_add, SIGNAL(valueChanged(int)), this, SLOT(value_changed(int)));
m_prio_add->setMinimum(-1000);
m_prio_add->setMaximum(1000);
layout->addWidget(m_prio_add);
}
void
action_prio::value_changed(int v)
{
DBG_PRINTF(6, "action_prio::value_changed(%d)\n", v);
emit new_value(m_type, get_param());
}
void
action_prio::btn_clicked()
{
DBG_PRINTF(6, "action_prio::btn_clicked()\n");
emit new_value(m_type, get_param());
}
void
action_prio::toggle_set(bool b)
{
DBG_PRINTF(6, "action_prio::toggle_set(%d)\n", (int)b);
if (b) {
m_prio_add->setEnabled(false);
m_check_add->setChecked(false);
m_prio_set->setEnabled(true);
}
}
void
action_prio::toggle_add(bool b)
{
DBG_PRINTF(6, "action_prio::toggle_add(%d)\n", (int)b);
if (b) {
m_prio_set->setEnabled(false);
m_check_set->setChecked(false);
m_prio_add->setEnabled(true);
}
}
void
action_prio::enable(bool b)
{
DBG_PRINTF(6, "action_prio::enable(%d)\n", b);
QWidget* w[]={m_check_set, m_prio_set, m_check_add, m_prio_add};
for (unsigned int i=0; i<sizeof(w)/sizeof(w[0]); i++)
w[i]->setEnabled(b);
m_prio_add->setEnabled(b & m_check_add->isChecked());
m_prio_set->setEnabled(b & m_check_set->isChecked());
}
void
action_prio::reset()
{
DBG_PRINTF(6, "action_prio::reset\n");
blockSignals(true);
m_check_set->setChecked(false);
m_check_add->setChecked(false);
m_prio_add->setValue(0);
m_prio_set->setValue(0);
m_prio_add->setEnabled(false);
m_prio_set->setEnabled(false);
blockSignals(false);
}
QString
action_prio::get_param()
{
QString res;
if (m_check_set->isChecked())
res = "=" + m_prio_set->text();
if (m_check_add->isChecked())
res = "+=" + m_prio_add->text();
// DBG_PRINTF(6, "action_prio::get_param returns '%s'\n", res.latin1());
return res;
}
/*
'param' should be "=value" or "+=value", value being an integer
*/
void
action_prio::set_param(const QString& param)
{
// DBG_PRINTF(6, "action_prio::set_param('%s')\n", param.latin1());
blockSignals(true); // avoid signals for change of value
if (param.at(0)=='=') {
m_prio_set->setValue(param.mid(1).toInt());
m_check_set->setChecked(true);
m_check_add->setChecked(false);
}
else if (param.mid(0,2)=="+=") {
m_prio_add->setValue(param.mid(2).toInt());
m_check_add->setChecked(true);
m_check_set->setChecked(false);
}
// else error
blockSignals(false);
}
//
// filter_edit
//
filter_edit::filter_edit(QWidget* parent): QWidget(parent)
{
m_hd=NULL;
setWindowTitle(tr("Filter rules"));
QVBoxLayout* top_layout = new QVBoxLayout(this);
top_layout->setMargin(5);
QLabel* lexpr = new QLabel(tr("Conditions:"));
QFont fnt1 = lexpr->font();
QFont u_fnt = fnt1;
fnt1.setBold(true);
u_fnt.setUnderline(true);
lexpr->setFont(fnt1);
top_layout->addWidget(lexpr);
QVBoxLayout* box_expr = new QVBoxLayout();
top_layout->addLayout(box_expr);
// expr_sv->setMaximumHeight(150);
// box_expr->setFrameStyle(QFrame::Panel|QFrame::Raised);
box_expr->setMargin(2);
lv_expr = new QTreeWidget();
box_expr->addWidget(lv_expr);
// lv_expr->setMultiSelection(false);
QStringList labels;
labels << tr("Name") << tr("Expression");
lv_expr->setHeaderLabels(labels);
lv_expr->header()->resizeSection(0, 100); // width for "Name" column
lv_expr->header()->resizeSection(1, 400); // width for "Expression" column
lv_expr->setRootIsDecorated(false);
lv_expr->setAllColumnsShowFocus(true);
connect(lv_expr, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(expr_selection_changed(QTreeWidgetItem*,QTreeWidgetItem*)));
QHBoxLayout* expr_btn_box = new QHBoxLayout();
box_expr->addLayout(expr_btn_box);
QPushButton* expr_new = new QPushButton(tr("New"));
expr_btn_box->addWidget(expr_new);
expr_btn_box->setStretchFactor(expr_new, 1);
connect(expr_new, SIGNAL(clicked()), this, SLOT(new_expr()));
expr_btn_delete = new QPushButton(tr("Delete"));
expr_btn_box->addWidget(expr_btn_delete);
expr_btn_box->setStretchFactor(expr_btn_delete, 1);
connect(expr_btn_delete, SIGNAL(clicked()), this, SLOT(delete_expr()));
expr_btn_delete->setEnabled(false);
m_suggest_btn = new QPushButton(tr("Suggest"));
expr_btn_box->addWidget(m_suggest_btn);
m_suggest_btn->setEnabled(false);
expr_btn_box->setStretchFactor(m_suggest_btn, 1);
connect(m_suggest_btn, SIGNAL(clicked()), this, SLOT(suggest_filter()));
expr_btn_box->addStretch(8);
QFrame* expr_cont = new QFrame();
expr_cont->setFrameStyle(QFrame::Box);
box_expr->addWidget(expr_cont);
QGridLayout* expr_grid = new QGridLayout(expr_cont);
// expr_grid->setSpacing(1);
int row=0;
int col=0;
lexpr_name = new QLabel(tr("Condition's name:"), expr_cont);
// lexpr_name->setFont(u_fnt); // underline
expr_grid->addWidget(lexpr_name, row, col++);
ql_expr_label = new QLabel(tr("Expression:"), expr_cont);
expr_grid->addWidget(ql_expr_label, row, col++);
row++; col=0;
ql_expr_name = new focus_line_edit(expr_cont, "expr_name", this);
expr_grid->addWidget(ql_expr_name, row, col++);
ql_expr_full = new focus_line_edit(expr_cont, "expr_text", this);
expr_grid->addWidget(ql_expr_full, row, col++);
expr_grid->setColumnStretch(0, 1); // 1/5 for name
expr_grid->setColumnStretch(1, 4); // 4/5 for expression
row++; col=0;
expr_grid->addWidget(new QLabel(tr("Filter's direction:")), row, col++);
QHBoxLayout* dirlayout = new QHBoxLayout;
m_dir = new button_group(QBoxLayout::LeftToRight);
m_dir->setLineWidth(0); //ContentsMargins(1,1,1,1);
m_dir->addButton(new QRadioButton(tr("Incoming mail")), 0);
m_dir->addButton(new QRadioButton(tr("Outgoing mail")), 1);
m_dir->addButton(new QRadioButton(tr("Both")), 2);
dirlayout->addWidget(m_dir, 0);
dirlayout->addStretch(10);
expr_grid->addLayout(dirlayout, row, col++);
connect(m_dir->group(), SIGNAL(buttonClicked(int)), this, SLOT(direction_changed(int)));
// -- Actions --
m_lrules = new QLabel(tr("Actions:"));
m_lrules->setFont(fnt1);
top_layout->addWidget(m_lrules);
QHBoxLayout* box_rules = new QHBoxLayout();
top_layout->addLayout(box_rules);
// box_rules->setFrameStyle(QFrame::Panel|QFrame::Raised);
box_rules->setMargin(5);
lv_actions = new action_listview();
box_rules->addWidget(lv_actions);
QFrame* rules_cont = new QFrame();
rules_cont->setFrameStyle(QFrame::Panel|QFrame::Raised);
box_rules->addWidget(rules_cont);
QGridLayout* rules_grid = new QGridLayout(rules_cont);
row=0;
/* Instantiate one box for each kind of action, and place them
into the grid, radiobutton in row 0 and the rest in row 1 */
for (int idx=0; idx<action_tag::idx_max; idx++) {
if (idx==action_tag::idx_tag)
w_actions[idx] = new action_tag();
else if (idx==action_tag::idx_status)
w_actions[idx] = new action_status();
else if (idx==action_tag::idx_prio)
w_actions[idx] = new action_prio();
else if (idx==action_tag::idx_stop)
w_actions[idx] = new action_stop();
else if (idx==action_tag::idx_redirect)
w_actions[idx] = new action_redirect();
connect(w_actions[idx]->m_rb, SIGNAL(toggled(bool)),
this, SLOT(action_radio_toggled(bool)));
connect(w_actions[idx], SIGNAL(new_value(QString,QString)),
this, SLOT(action_new_val(QString,QString)));
rules_grid->addWidget(w_actions[idx]->m_rb, row, 0);
rules_grid->addWidget(w_actions[idx], row, 1);
rules_grid->setColumnStretch(1, 10);
row++;
}
lv_actions->setHeaderLabels(QStringList(tr("Actions list")));
lv_actions->setSortingEnabled(false); // should be kept sorted by the order of actions
connect(lv_actions, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(action_sel_changed(QTreeWidgetItem*,QTreeWidgetItem*)));
connect(lv_actions, SIGNAL(key_del()), this, SLOT(delete_action()));
// Help OK Cancel
QHBoxLayout* hbox_valid = new QHBoxLayout();
hbox_valid->setMargin(5);
hbox_valid->setSpacing(5);
top_layout->addLayout(hbox_valid);
hbox_valid->addStretch(1); // space at left
QPushButton* whelp = new QPushButton(tr("Help"));
hbox_valid->addWidget(whelp, 0);
QPushButton* wok = new QPushButton(tr("OK"));
hbox_valid->addWidget(wok, 0);
wok->setDefault(true);
QPushButton* wcancel = new QPushButton(tr("Cancel"));
hbox_valid->addWidget(wcancel);
connect(wok, SIGNAL(clicked()), this, SLOT(ok()));
connect(wcancel, SIGNAL(clicked()), this, SLOT(cancel()));
connect(whelp, SIGNAL(clicked()), this, SLOT(help()));
clear_expr();
disable_all_expr();
untie_actions();
load();
}
filter_edit::~filter_edit()
{
if (m_hd)
delete m_hd;
}
void
filter_edit::direction_changed(int id)
{
Q_UNUSED(id);
DBG_PRINTF(4, "direction_changed\n");
if (m_current_expr) {
m_current_expr->m_dirty=true;
dlg_fields_to_filter_expr(m_current_expr);
}
}
void
filter_edit::set_sel_list(const std::list<unsigned int>& l)
{
m_sel_list = l;
m_suggest_btn->setEnabled(true);
}
void
filter_edit::action_new_val(QString type, QString val)
{
if (val.isNull())
val=QString("");
// DBG_PRINTF(6, "action_new_val type=%s, val=%s\n", type.latin1(), val.latin1());
// QListViewItem* item=lv_actions->selectedItem();
action_lvitem* p = m_current_action;
if (!p) {
DBG_PRINTF(2, "ERR: no current_action\n");
return;
}
if (!p->m_act_ptr) {
filter_action a;
a.m_str_atype=val;
m_current_expr->m_actions.push_back(a);
p->m_act_ptr=&(m_current_expr->m_actions.back());
// create another null action for future use
create_null_action();
m_current_action=p;
}
p->m_act_ptr->m_action_string = val;
p->m_act_ptr->m_str_atype = type;
p->setText(0, type + ": " + val);
m_current_expr->m_dirty=true;
}
/*
Emulate the behavior of a button group containing radiobuttons,
except that the currently selected button can be deselected.
(we don't use a QButtonGroup because its layout (a QVBox) doesn't
fit into our grid)
*/
void
filter_edit::action_radio_toggled(bool b)
{
const QObject* o = sender();
DBG_PRINTF(6, "action_radio_toggled(b=%d,sender=%p)\n", b, o);
for (int idx=0; idx<action_tag::idx_max; idx++) {
if (o==w_actions[idx]->m_rb) {
w_actions[idx]->enable(b);
if (b) {
action_new_val(w_actions[idx]->m_type, w_actions[idx]->get_param());
}
}
else {
w_actions[idx]->enable(false);
w_actions[idx]->set_checked(false);
}
}
}
void
filter_edit::action_sel_changed(QTreeWidgetItem* item, QTreeWidgetItem* previous)
{
Q_UNUSED(previous);
DBG_PRINTF(6, "action_sel_changed(item=%p)\n", item);
if (!item) return;
action_lvitem* a = static_cast<action_lvitem*>(item);
m_current_action=a;
for (int i=0; i<action_line::idx_max; i++) {
if (a->m_act_ptr && w_actions[i]->m_type == a->m_act_ptr->m_str_atype) {
w_actions[i]->set_param(a->m_act_ptr->m_action_string);
w_actions[i]->enable(true);
w_actions[i]->set_checked(true);
// break; // action types are unique, no need to continue
}
else {
w_actions[i]->reset();
w_actions[i]->set_checked(false);
}
}
}
/*
Disable entirely the actions panel.
To be called when no expression is selected.
*/
void
filter_edit::untie_actions()
{
m_lrules->setEnabled(false);
m_lrules->setText(tr("Actions:"));
// uncheck all and disable each action widget
reset_actions();
// disable the actions list
lv_actions->setEnabled(false);
// also disable the radio buttons
for (int i=0; i<action_line::idx_max; i++) {
w_actions[i]->m_rb->setEnabled(false);
}
}
void
filter_edit::ok()
{
ql_expr_full->validate();
ql_expr_name->validate();
// accept();
if (m_expr_list.update_db())
close();
}
void
filter_edit::cancel()
{
// accept();
close();
}
bool
filter_edit::load()
{
expr_list* l = &m_expr_list;
if (!l->fetch()) return false;
std::list<filter_expr>::iterator it = l->begin();
for (; it != l->end(); ++it) {
expr_lvitem* item = new expr_lvitem(lv_expr, (*it).m_expr_name);
item->setText(1, (*it).m_expr_text);
item->m_expr = &(*it);
item->m_db=true;
}
return true;
}
void
filter_edit::clear_expr()
{
ql_expr_name->setText(QString::null);
ql_expr_full->setText(QString::null);
m_current_expr=NULL;
lv_expr->clearSelection();
untie_actions();
}
void
filter_edit::suggest_filter()
{
if (!m_hd) {
m_hd = new headers_groupview();
m_hd->set_threshold(100);
m_hd->init(m_sel_list);
connect(m_hd->m_trview, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(expr_from_header(QTreeWidgetItem*)));
connect(m_hd, SIGNAL(close()), this, SLOT(close_headers_groupview()));
}
m_hd->show();
}
void
filter_edit::expr_from_header(QTreeWidgetItem* item)
{
if (!item) return;
DBG_PRINTF(3, "expr_from_header (item=%p)\n", item);
const QString h = item->text(1);
int sep_pos = h.indexOf(":");
if (sep_pos>0) {
QString header_name = h.left(sep_pos);
QString header_value = h.mid(sep_pos+1);
header_value = header_value.trimmed();
new_expr();
QString expr = "header(\""+ header_name + "\") eq \"" + header_value + "\"";
ql_expr_full->setText(expr);
}
}
void
filter_edit::close_headers_groupview()
{
}
void
filter_edit::delete_expr()
{
if (!m_current_expr) {
DBG_PRINTF(6, "no current expr\n");
return;
}
int r=QMessageBox::warning(this, tr("Please confirm"), tr("Delete condition?"), tr("OK"), tr("Cancel"), QString::null);
if (r==0) {
expr_lvitem* item=static_cast<expr_lvitem*>(lv_expr->currentItem());
if (!item) {
DBG_PRINTF(1, "Couldn't find selected item\n");
return;
}
item->m_expr->m_delete=true;
delete item;
clear_expr();
}
}
void
filter_edit::expr_selection_changed(QTreeWidgetItem* i, QTreeWidgetItem* prev)
{
Q_UNUSED(prev);
if (!i) {
DBG_PRINTF(6,"expr deselected\n");
clear_expr();
return;
}
expr_lvitem* item = static_cast<expr_lvitem*>(i);
filter_expr* e = item->m_expr;
m_current_expr = e;
ql_expr_name->setText(e->m_expr_name);
ql_expr_full->setText(e->m_expr_text);
expr_btn_delete->setEnabled(item->m_id!=0);
DBG_PRINTF(6, "expr sel=%d\n", item->m_id);
enable_expr_edit(true);
//grp_edit_method->setEnabled(false);
switch(e->m_direction) {
case 'I':
m_dir->setButton(0);
break;
case 'O':
m_dir->setButton(1);
break;
case 'B':
m_dir->setButton(2);
break;
}
reset_actions();
display_actions();
}
/*
update the 'Actions' panel with the actions connected to the
currently selected expression
*/
void
filter_edit::display_actions()
{
m_lrules->setEnabled(true);
lv_actions->clear();
lv_actions->setEnabled(true);
m_current_action=NULL;
filter_expr* e = m_current_expr;
if (!e) {
DBG_PRINTF(1, "ERR: no current expression\n");
return;
}
if (e->m_expr_name.isEmpty())
m_lrules->setText(tr("Actions connected to current condition"));
else
m_lrules->setText(tr("Actions connected to condition '%1':").arg(e->m_expr_name));
std::list<filter_action>::iterator iter;
action_lvitem* after=NULL;
for (iter=e->m_actions.begin(); iter!=e->m_actions.end(); ++iter) {
after = new action_lvitem(lv_actions, after);
CHECK_PTR(after);
// DBG_PRINTF(6, "add action %s:%s\n", iter->m_str_atype.latin1(),
// iter->m_action_string.latin1());
after->m_act_ptr = &(*iter);
after->setText(0, iter->m_str_atype + ": " + iter->m_action_string);
}
create_null_action();
if (lv_actions->topLevelItem(0)) {
// pre-select the first element
DBG_PRINTF(6, "setSelected(0x%p)\n", lv_actions->topLevelItem(0));
lv_actions->setCurrentItem(lv_actions->topLevelItem(0));
m_current_action=static_cast<action_lvitem*>(lv_actions->topLevelItem(0));
}
for (int i=0; i<action_line::idx_max; i++) {
w_actions[i]->m_rb->setEnabled(true);
}
}
// Add the (New action) entry
void
filter_edit::create_null_action()
{
int count=lv_actions->topLevelItemCount();
action_lvitem* last=NULL;
if (count>0)
last = static_cast<action_lvitem*>(lv_actions->topLevelItem(count-1));
action_lvitem* item = new action_lvitem(lv_actions, last);
CHECK_PTR(item);
item->setText(0, tr("(New action)"));
item->m_act_ptr = NULL; // no real associated action
}
/*
Reset the 'Actions' panel
*/
void
filter_edit::reset_actions()
{
for (int i=0; i<action_line::idx_max; i++) {
w_actions[i]->enable(false);
w_actions[i]->set_checked(false);
}
lv_actions->clear();
}
void
filter_edit::enable_expr_edit(bool enable)
{
ql_expr_full->setEnabled(enable);
ql_expr_label->setEnabled(enable);
ql_expr_name->setEnabled(enable);
lexpr_name->setEnabled(enable);
}
void
filter_edit::new_expr()
{
clear_expr();
enable_expr_edit(true);
ql_expr_name->setFocus();
}
bool
filter_edit::expr_fields_filled() const
{
return !ql_expr_full->text().isEmpty();
}
QString
filter_edit::compute_expr_text()
{
return ql_expr_full->text();
}
void
filter_edit::dlg_fields_to_filter_expr(filter_expr *e)
{
e->m_element.truncate(0);
e->m_value.truncate(0);
e->m_match_type=0;
e->m_expr_text = ql_expr_full->text();
static char dir[]={'I','O','B'};
e->m_direction = dir[m_dir->selected_id()];
}
void
filter_edit::expr_update()
{
bool select_item=false;
// change the text in the expressions listview
QList<QTreeWidgetItem*> list_selected = lv_expr->selectedItems();
expr_lvitem* item = list_selected.count()==1 ?
static_cast<expr_lvitem*>(list_selected.first()) : NULL;
if (!item) {
item = new expr_lvitem(lv_expr, ql_expr_name->text());
CHECK_PTR(item);
select_item=true;
filter_expr new_expr;
m_expr_list.push_back(new_expr);
item->m_expr = &(m_expr_list.back());
DBG_PRINTF(6, "creating new expr\n");
item->m_expr->m_new=true;
item->m_expr->m_expr_id=0;
m_current_expr = item->m_expr;
}
QString expr_text = compute_expr_text();
item->setText(0, ql_expr_name->text());
item->setText(1, expr_text);
ql_expr_full->setText(expr_text);
filter_expr* e = item->m_expr; // should be m_current_expr
e->m_expr_name = ql_expr_name->text();
e->m_expr_text = expr_text;
dlg_fields_to_filter_expr(e);
e->m_dirty=true;
item->m_dirty=true;
DBG_PRINTF(6, "expr_id %d is marked dirty\n", e->m_expr_id);
if (select_item)
lv_expr->setCurrentItem(item);
}
void
filter_edit::disable_all_expr()
{
enable_expr_edit(false);
// grp_edit_method->setEnabled(false);
ql_expr_name->setEnabled(false);
lexpr_name->setEnabled(false);
expr_btn_delete->setEnabled(false);
}
/*
Delete the current action
*/
void
filter_edit::delete_action()
{
if (!m_current_action ||
m_current_action!=lv_actions->currentItem() ||
!m_current_action->m_act_ptr)
{
return;
}
filter_expr* e=m_current_expr;
std::list<filter_action>::iterator iter;
for (iter=e->m_actions.begin(); iter!=e->m_actions.end(); ++iter) {
if (m_current_action->m_act_ptr==&(*iter)) {
DBG_PRINTF(6, "found\n");
e->m_actions.erase(iter);
e->m_dirty=true;
break;
}
}
delete m_current_action;
m_current_action=NULL;
#if 0 // huh?
if (!lv_actions->currentItem()) {
if (lv_actions->currentItem()) { // mutually exclusive with the IF above
lv_actions->setSelected(lv_actions->currentItem(), true);
}
}
#endif
}
void
filter_edit::help()
{
#if 0
filter_expr* e=m_current_expr;
std::list<filter_action>::iterator iter;
DBG_PRINTF(6, "current actions (m_current_action=0x%p\n", m_current_action);
for (iter=e->m_actions.begin(); iter!=e->m_actions.end(); ++iter) {
DBG_PRINTF(6,"\tm_str_atype=%s, m_action_string=%s\n",
iter->m_str_atype.latin1(), iter->m_action_string.latin1());
}
#endif
helper::show_help("filters");
}
//
// focus_line_edit
//
focus_line_edit::focus_line_edit(QWidget* parent, const QString& name,
filter_edit* form) :
QLineEdit(parent)
{
m_form=form;
m_name=name;
connect(this, SIGNAL(returnPressed()), this, SLOT(validate()));
}
void
focus_line_edit::validate()
{
if (text()!=m_last_value && m_form->expr_fields_filled()) {
m_form->expr_update();
m_last_value=text();
}
}
void
focus_line_edit::setText(const QString& t)
{
m_last_value=t;
QLineEdit::setText(t);
}
void
focus_line_edit::focusOutEvent(QFocusEvent * e)
{
DBG_PRINTF(6, "focusOutEvent()\n");
validate();
QLineEdit::focusOutEvent(e);
}
void
action_listview::keyPressEvent(QKeyEvent* e)
{
if (e->modifiers()!=0 || e->key()!=Qt::Key_Delete) {
QTreeWidget::keyPressEvent(e);
}
else
emit key_del();
}
//
// action_radio_button
//
#if QT_VERSION<0x040000
void
action_radio_button::drawButtonLabel(QPainter* p)
{
if (isChecked()) {
QFont f=p->font();
f.setBold(true);
p->setFont(f);
}
QRadioButton::drawButtonLabel(p);
}
#endif
void
action_radio_button::setChecked(bool b)
{
QRadioButton::setChecked(b);
repaint();
}
action_stop::action_stop(QWidget* parent) :
action_line(parent, tr("Stop filters"), "stop")
{
}
void
action_stop::enable(bool b)
{
Q_UNUSED(b);
}
QString
action_line::get_param()
{
return QString();
}
void
action_line::reset()
{
}
void
action_line::set_param(const QString& param)
{
Q_UNUSED(param); // base action has no parameter
}
/* action_redirect */
action_redirect::action_redirect(QWidget* parent) :
action_line(parent, tr("Redirect to"), "redirect")
{
m_redirect = new QLineEdit();
QHBoxLayout* layout = new QHBoxLayout(this);
layout->addWidget(m_redirect);
// m_redirect->setMinimumWidth(300);
connect(m_redirect, SIGNAL(textEdited(const QString&)), this, SLOT(report_change(const QString&)));
}
void
action_redirect::report_change(const QString& newval)
{
emit new_value(m_type, newval);
}
HTML source code generated by GNU Source-Highlight plus some custom post-processing
List of all available source files