Source file: src/import_window.cpp
/* Copyright (C) 2004-2012 Daniel Verite
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 "import_window.h"
#include "mbox_import_wizard.h"
#include "icons.h"
#include "date.h"
#include <QTreeWidget>
#include <QPushButton>
#include <QBoxLayout>
#include <QProgressBar>
#include <QHeaderView>
#include <QTimer>
#include <QTreeWidgetItemIterator>
#include <QMessageBox>
import_window*
import_window::m_current_instance; // singleton
void
open_import_window()
{
import_window* w = import_window::open_unique();
w->show();
w->activateWindow();
w->raise();
}
import_window*
import_window::open_unique()
{
if (!m_current_instance)
m_current_instance = new import_window();
return m_current_instance;
}
import_window::import_window()
{
setAttribute(Qt::WA_DeleteOnClose);
setWindowIcon(UI_ICON(ICON16_IMPORT_MBOX));
setWindowTitle(tr("Mail import"));
QVBoxLayout* top_layout = new QVBoxLayout(this);
top_layout->setMargin(5);
QTreeWidget* w = new QTreeWidget();
m_treewidget = w;
top_layout->addWidget(w);
QStringList labels;
labels << tr("File") << tr("Status") << tr("Completion");
w->setHeaderLabels(labels);
w->header()->resizeSection(0, 200);
w->setRootIsDecorated(false);
w->setAllColumnsShowFocus(true);
QHBoxLayout* buttons = new QHBoxLayout();
top_layout->addLayout(buttons);
m_btn_stop_restart = new QPushButton(tr("Stop"));
buttons->addWidget(m_btn_stop_restart);
connect(m_btn_stop_restart, SIGNAL(clicked()), this, SLOT(start_stop()));
m_btn_purge = new QPushButton(tr("Purge"));
buttons->addWidget(m_btn_purge);
connect(m_btn_purge, SIGNAL(clicked()), this, SLOT(purge_import()));
buttons->addStretch(5);
m_btn_refresh = new QPushButton(tr("Refresh"));
buttons->addWidget(m_btn_refresh);
connect(m_btn_refresh, SIGNAL(clicked()), this, SLOT(refresh()));
m_btn_new = new QPushButton(tr("New..."));
buttons->addWidget(m_btn_new);
connect(m_btn_new, SIGNAL(clicked()), this, SLOT(new_import()));
connect(w, SIGNAL(currentItemChanged(QTreeWidgetItem*,QTreeWidgetItem*)),
this, SLOT(item_changed(QTreeWidgetItem*,QTreeWidgetItem*)));
#if 0
w->setSortingEnabled(true);
w->sortByColumn(import_window_widget_item::index_column_date, Qt::DescendingOrder);
#endif
load();
m_timer = new QTimer(this);
m_timer->start(5000);
connect(m_timer, SIGNAL(timeout()), this, SLOT(refresh()));
resize(600,300);
}
import_window::~import_window()
{
m_current_instance=NULL;
}
void
import_window::item_changed(QTreeWidgetItem* item, QTreeWidgetItem* old)
{
Q_UNUSED(old);
if (item) {
import_mbox* m = get_import_mbox(item->data(0, import_window_widget_item::import_mbox_id_role).toInt());
update_buttons(m); // m may be NULL
}
else {
update_buttons(NULL);
}
}
void
import_window::update_buttons(import_mbox* m)
{
if (m==NULL) {
m_btn_purge->setEnabled(false);
m_btn_stop_restart->setEnabled(false);
}
else {
if (m->status()==import_mbox::status_not_started ||
m->status()==import_mbox::status_stopped) {
m_btn_stop_restart->setText(tr("Start"));
m_btn_stop_restart->setEnabled(true);
}
else if (m->status()==import_mbox::status_running) {
m_btn_stop_restart->setText(tr("Stop"));
m_btn_stop_restart->setEnabled(true);
}
else if (m->status()==import_mbox::status_finished) {
m_btn_stop_restart->setText(tr("Stop"));
m_btn_stop_restart->setEnabled(false);
}
m_btn_purge->setEnabled(true);
}
}
import_mbox*
import_window::get_import_mbox(int import_mbox_id)
{
import_mbox_list::iterator iter = m_list.begin();
for (; iter != m_list.end(); ++iter) {
if (iter->id() == import_mbox_id)
return &(*iter);
}
return NULL;
}
// retrieve the item in the treeview by the import_mbox_id
import_window_widget_item*
import_window::get_item(int import_mbox_id)
{
QTreeWidgetItemIterator it(m_treewidget);
while (*it) {
if ((*it)->data(0,import_window_widget_item::import_mbox_id_role).toInt() == import_mbox_id)
return static_cast<import_window_widget_item*>(*it);
++it;
}
return NULL;
}
import_mbox*
import_window::selected_item()
{
QTreeWidgetItem* item = m_treewidget->currentItem();
return item ? get_import_mbox(item->data(0, import_window_widget_item::import_mbox_id_role).toInt()) : NULL;
}
// Populate the list with contents from the database
void
import_window::load()
{
m_list.load();
import_mbox_list::const_iterator iter = m_list.constBegin();
for (; iter != m_list.constEnd(); ++iter) {
add_item(&(*iter));
}
}
import_window_widget_item*
import_window::add_item(const import_mbox* m)
{
import_window_widget_item* item = new import_window_widget_item();
QProgressBar* bar = new QProgressBar();
m_progress_bars[m->id()] = bar;
bar->setRange(0, 100);
m_treewidget->addTopLevelItem(item);
m_treewidget->setItemWidget(item, 2, bar);
item->setData(0, import_window_widget_item::import_mbox_id_role, m->id());
#if 0
QVariant vdate;
vdate.setValue(m->creation_date());
item->setData(import_window_widget_item::index_column_date,
import_window_widget_item::import_mbox_date_role, vdate);
#endif
display_entry(item, m);
return item;
}
void
import_window::display_entry(QTreeWidgetItem* item, const import_mbox* m)
{
if (!item)
return;
int col=0;
item->setText(col++, m->filename());
// item->setText(col++, m->creation_date().output_8());
item->setText(col++, m->status_text());
QProgressBar* bar = m_progress_bars[m->id()];
if (bar) {
bar->setValue((int)(m->m_completion*100));
QString color="#1e8bd8"; // blue
switch(m->status()) {
case import_mbox::status_running:
color="green";
break;
case import_mbox::status_stopped:
color="red";
break;
}
QString style=QString("QProgressBar:horizontal {"
"border: 1px solid gray;"
"border-radius: 3px;"
"background: white;"
"padding: 1px;"
"text-align: center;"
"font-weight: bold;"
"}"
"QProgressBar::chunk:horizontal {"
"background: qlineargradient(x1: 0, y1: 0.5, x2: 1, y2: 0.5, stop: 0 %1, stop: 1 white);"
"}").arg(color);
bar->setStyleSheet(style);
}
}
void
import_window::start_stop()
{
import_mbox* m = selected_item();
if (!m) return;
if (m->status()==import_mbox::status_not_started || m->status()==import_mbox::status_stopped ) {
m->instantiate_job();
}
else if (m->status()==import_mbox::status_running) {
m->stop();
}
update_buttons(m);
display_entry(m_treewidget->currentItem(), m);
}
// Refetch from the database the status and progress of running imports
void
import_window::refresh()
{
import_mbox_list list;
if (list.load()) {
// foreach import_mbox, check if changes have occurred
import_mbox_list::iterator iter = list.begin();
for (; iter != list.end(); ++iter) {
DBG_PRINTF(4, "import_mbox_id=%d in the list", iter->id());
import_mbox* m = get_import_mbox(iter->id());
if (!m) {
// add new entry
m_list.append(*iter); // a new import_mbox has appeared
add_item(&(*iter));
}
else if (m->status()!=iter->status() || m->m_completion!=iter->m_completion) {
// redisplay entry
import_window_widget_item* item = get_item(iter->id());
if (item)
display_entry(item, &(*iter));
*m = *iter;
}
}
/* foreach element on display, check if it's still in the fresh
list If not, remove it from the display. We don't use
QTreeWidgetItemIterator since it's not clear if it supports
deletion of items during traversal */
int i=0;
while (i<m_treewidget->topLevelItemCount()) {
QTreeWidgetItem* item = m_treewidget->topLevelItem(i);
if (item) {
int id=item->data(0,import_window_widget_item::import_mbox_id_role).toInt();
if (!list.id_exists(id))
delete item; // index doesn't move
else
i++;
}
}
}
update_buttons(selected_item());
}
void
import_window::new_import()
{
mbox_import_wizard* mw = new mbox_import_wizard();
connect(mw, SIGNAL(accepted()), this, SLOT(new_import_started()));
mw->show();
}
void
import_window::new_import_started()
{
show();
activateWindow();
raise();
refresh();
}
void
import_window::purge_import()
{
import_mbox* m = selected_item();
if (!m)
return;
int rep = QMessageBox::question(this, tr("Confirm purge"),
tr("Please confirm the purge of the import data from the database.\nMessages not yet imported will be lost."),
QMessageBox::Ok | QMessageBox::Cancel, QMessageBox::Cancel);
if (rep==QMessageBox::Cancel) {
return;
}
else {
if (m->purge()) {
QTreeWidgetItem* item = m_treewidget->currentItem();
if (item) {
int index = m_treewidget->indexOfTopLevelItem(item);
m_treewidget->takeTopLevelItem(index);
}
}
}
}
#if 0
bool
import_window_widget_item::operator<(const QTreeWidgetItem& other) const
{
int column = treeWidget()->header()->sortIndicatorSection();
if (column==index_column_date) {
QVariant v1 = data(column, import_mbox_date_role);
QVariant v2 = other.data(column, import_mbox_date_role);
return v1.value<date>() < v2.value<date>();
}
else
return QTreeWidgetItem::operator<(other);
}
#endif
bool
import_mbox_list::load()
{
db_cnx db;
try {
sql_stream s("SELECT import_id,completion,status,filename FROM import_mbox ORDER BY import_id DESC", db);
while (!s.eof()) {
import_mbox m;
s >> m.m_id >> m.m_completion >> m.m_status >> m.m_filename;
append(m);
}
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
import_mbox_list::id_exists(int id) const
{
import_mbox_list::const_iterator iter = constBegin();
for (; iter != constEnd(); ++iter) {
if (id==iter->id())
return true;
}
return false;
}
QString
import_mbox::status_text() const
{
switch(m_status) {
case 0: return QObject::tr("Not started");
case 1: return QObject::tr("Running");
case 2: return QObject::tr("Stopped");
case 3: return QObject::tr("Finished");
}
return QObject::tr("Unknown");
}
bool
import_mbox::stop()
{
db_cnx db;
try {
sql_stream s("UPDATE import_mbox SET status=2 WHERE import_id=:p1", db);
s << id();
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
import_mbox::purge()
{
db_cnx db;
try {
db.begin_transaction();
sql_stream sd1("DELETE FROM import_message WHERE import_id=:p1", db);
sd1 << id();
sql_stream sd("DELETE FROM import_mbox WHERE import_id=:p1", db);
sd << id();
db.commit_transaction();
}
catch(db_excpt& p) {
DBEXCPT(p);
return false;
}
return true;
}
bool
import_mbox::instantiate_job()
{
db_cnx db;
try {
db.begin_transaction();
sql_stream s1("UPDATE import_mbox SET status=:s WHERE import_id=:id", db);
s1 << status_running << m_id;
sql_stream s("INSERT INTO jobs_queue(job_type, job_args) VALUES(:t,:a)", db);
s << "import_mailbox" << QString("%1").arg(m_id);
sql_stream sn("NOTIFY job_request", db);
db.commit_transaction();
}
catch(db_excpt& p) {
db.rollback_transaction();
DBEXCPT(p);
return false;
}
return true;
}
HTML source code generated by GNU Source-Highlight plus some custom post-processing
List of all available source files