Manitou-Mail logo title

Source file: src/headers_groupview.cpp

/* Copyright (C) 2004-2007 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 <math.h>
#include <QWidget>
#include <QLayout>
#include <QTreeWidget>
#include <QStringList>
#include <QPushButton>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QCloseEvent>

#include "db.h"
#include "main.h"
#include "sqlstream.h"
#include "headers_groupview.h"

void analyze_headers(const std::list<unsigned int>& l)
{
  headers_groupview* w = new headers_groupview(NULL);
  w->init(l);
  w->show();
}

headers_groupview::headers_groupview(QWidget* parent) : QWidget(parent)
{
  m_threshold=0;
  QVBoxLayout* top_layout = new QVBoxLayout(this);

  m_trview = new hd_treeview(this);
  CHECK_PTR(m_trview);
  m_trview->setRootIsDecorated(true);
  m_trview->setAllColumnsShowFocus(true);
  top_layout->addWidget(m_trview);

  QHBoxLayout* hl = new QHBoxLayout();
  top_layout->addLayout(hl);
  QPushButton* ok = new QPushButton(tr("Close"), this);
  connect(ok, SIGNAL(clicked()), this, SLOT(close()));
  hl->addStretch(1);
  hl->addWidget(ok);
  hl->addStretch(1);
}

headers_groupview::~headers_groupview()
{
}

void
headers_groupview::set_threshold(int v)
{
  m_threshold=v;
}

void
headers_groupview::closeEvent(QCloseEvent* e)
{
  emit close();
  e->accept();
}

void
headers_groupview::init(const std::list<unsigned int>& id_list)
{
  int headers_count=0;
  db_cnx db;
  sql_stream s("SELECT lines FROM header WHERE mail_id=:p1", db);
  std::list<unsigned int>::const_iterator iter=id_list.begin();
  QString h;
  m_mv_t::iterator v_it;
  for (; iter!=id_list.end(); ++iter) {
    s << *iter;
    if (!s.eos()) {
      s >> h;
    }
    headers_count++;
    mail_id_t mail_id=*iter;
    QStringList sl = h.split('\n', QString::SkipEmptyParts);
    QString s;

    std::set<QString> hset;
    m_mid_t::iterator mit;
    m_map_id[mail_id] = hset;
    mit = m_map_id.find(mail_id);

    for (QStringList::iterator isl = sl.begin(); isl!=sl.end(); ++isl) {
      s = (*isl).trimmed();
      //DBG_PRINTF(3, "%s\n", s.latin1());
      v_it = m_map_val.find(s);
      if (v_it==m_map_val.end()) {
	std::set<mail_id_t> mset;
	mset.insert(*iter);
	m_map_val[s] = mset;
      }
      else {
	v_it->second.insert(*iter); // update m_map_val
      }
      mit->second.insert(s);	// update m_map_id
    }
  }
  
  header_item* qitem;
  for (v_it=m_map_val.begin(); v_it!=m_map_val.end(); ++v_it) {
    int count=v_it->second.size();
    if (count>1 && ceil((100.0*count)/headers_count) >= m_threshold) {
      qitem = new header_item(m_trview, count, v_it->first, headers_count);
      //      qitem->setExpandable(true);
      qitem->m_id_set = v_it->second;
      qitem->m_pmap_id = &m_map_id;
    }
  }
  
}

hd_treeview::hd_treeview(QWidget* parent) : QTreeWidget(parent)
{
  sortByColumn(0, Qt::DescendingOrder);
  QStringList headers;
  headers << tr("Count") << tr("Header: value");
  setHeaderLabels(headers);
}

hd_treeview::~hd_treeview()
{
}

header_item::header_item(hd_treeview* parent, int count, 
			 const QString& hval, int total):
  QTreeWidgetItem(parent), m_cnt(count)
{
  char buf[10]="";
  if (total!=0)
    sprintf(buf, "%2.2f%%", (100.0*count)/total);
  setText(col_for_count, QString("%1 (%2)").arg(count).arg(buf));
  setText(col_for_value, hval);
}

header_item::header_item(header_item* parent, int count, 
			 const QString& hval, int total):
  QTreeWidgetItem(parent), m_cnt(count)
{
  char buf[10]="";
  if (total!=0)
    sprintf(buf, "%2.2f%%", (100.0*count)/total);
  setText(col_for_count, QString("%1 (%2)").arg(count).arg(buf));
  setText(col_for_value, hval);
}

#if 0
// maybe reactivate that code when we'll support tree-based navigation
// through headers. It's still Qt3 code because of setOpen() and setExpandable()
void
header_item::setOpen(bool b)
{
  if (b && childCount()==0) {
    QString hs=text(col_for_value);
    std::map<QString,int> lmap; // header value => count
    std::map<QString,int>::iterator lmap_it;
    if (!m_id_set.empty()) {
      std::set<mail_id_t>::iterator ml_it = m_id_set.begin();
      // for each mail that contains the current header line
      for (; ml_it!=m_id_set.end(); ++ml_it) {
	mail_id_t mail_id = *ml_it;
	// for each header line contained by the message numbered 'id'
	m_mid_t::iterator mit = m_pmap_id->find(mail_id);
	if (mit == m_pmap_id->end())
	  continue;
	std::set<QString>& s = mit->second;
	std::set<QString>::iterator sit;
	// store in lmap the number of occurrences of the header line
	for (sit = s.begin(); sit!=s.end(); ++sit) {
	  lmap_it = lmap.find(*sit);
	  if (lmap_it==lmap.end())
	    lmap[*sit]=1;
	  else
	    lmap_it->second++;
	}
      }
      // Here we have lmap filled with each different header line associated
      // with its number of occurrences
      // Now create the child entries
      header_item* qitem;
      for (lmap_it=lmap.begin(); lmap_it!=lmap.end(); ++lmap_it) {
	if (lmap_it->second >= 2 && lmap_it->first!=hs) {
	  qitem = new header_item(this, lmap_it->second, lmap_it->first,
				  m_id_set.size());
	  qitem->setExpandable(true);
	  qitem->m_pmap_id = m_pmap_id;
	}
      }
    }
  }
  QTreeWidgetItem::setOpen(b);
}
#endif


HTML source code generated by GNU Source-Highlight plus some custom post-processing

List of all available source files