view DataController.cpp @ 0:a3834af36579

Working with memory backend.
author Tom Fredrik Blenning Klaussen <bfg@blenning.no>
date Mon, 20 Aug 2012 15:49:48 +0200
parents
children aae83c0a771d
line wrap: on
line source

#include "DataController.hpp"

#include "MemoryDbLink.hpp"

#include "PermissionException.hpp"
#include "DataController.hpp"

#include <QtGui/QApplication>
#include <QtCore/QDir>

#include <QtCore/QDebug>
#include <QtCore/QTimer>
#include <QtCore/QCryptographicHash>
#include <QtCore/QDateTime>

#include <QtGui/QMainWindow>
#include <QtGui/QTreeWidget>
#include <QtGui/QHeaderView>
#include <QtGui/QMenuBar>
#include <QtGui/QToolBar>
#include <QtGui/QDoubleSpinBox>
#include <QtGui/QLabel>
#include <QtGui/QHBoxLayout>
#include <QtGui/QProgressBar>

#include "EditDistance.hpp"

#include <cassert>
void findFiles(const QDir& dir, FileDbLink& dblink)
{
  /*
  QProgressDialog progressDialog(this);
  progressDialog.setCancelButtonText(tr("&Cancel"));
  progressDialog.setRange(0, files.size());
  progressDialog.setWindowTitle(tr("Find Files"));
  */

  foreach(QString filename, dir.entryList(QDir::NoDotAndDotDot | QDir::Dirs)) {
    filename = dir.absoluteFilePath(filename);
    findFiles(QDir(filename), dblink);
  }

  foreach(QString filename, dir.entryList(QDir::Files)) {
    filename = dir.absoluteFilePath(filename);
    try {
      dblink.updateIfModified(filename);
    }
    catch (const PermissionException& e) {
      qDebug()<<e.toString();
    }
    catch (Exception& e) {
      qDebug()<<e.toString();
      exit(1);
    }
  }
}

QTreeWidgetItem* DataController::createItem(const FileDbLink::DBInfo& info)
{
  QTreeWidgetItem* item = new QTreeWidgetItem();
  item->setData(0, Qt::DisplayRole, info.name());
  item->setData(0, 32, info.path());
  item->setData(0, 33, info.name());
  
  item->setData(1, Qt::DisplayRole, info.size());
  item->setData(2, Qt::DisplayRole, info.mtime());
  item->setData(3, Qt::DisplayRole, info.checksum().toHex());
  return item;
}

void DataController::delayPopulate()
{
  populateDelay->start();
}


void DataController::populate()
{
  populate(nameFilter->isChecked(), sizeFilter->isChecked(), mtimeFilter->isChecked(),
	   checksumFilter->isChecked(), (100 - editCutoffSpin->value()) * .01);
}

void DataController::populate(bool showNameDups, bool showSizeDups,
			      bool showMTimeDups, bool showCheckSumDups,
			      float editDistanceCutoff)
{
  tw->clear();

  const QList<QSharedPointer<FileDbLink::DBInfo> > elems = dblink->sortOn(FileDbLink::EDIT, true);

  QProgressBar bar;

  bar.resize(200,25);
  bar.setValue(0);
  bar.setMinimum(0);
  bar.setMaximum(elems.size());
  bar.show();

  connect(this, SIGNAL(populateProgress(int)), &bar, SLOT(setValue(int)));

  int n = 0;

  tw->setUpdatesEnabled(false);

  foreach(QSharedPointer<FileDbLink::DBInfo> line, elems) {
    QTreeWidgetItem* item = 0;
    bool anyAdded = false;

    if (showNameDups) {
      QTreeWidgetItem* topLevelItem = 0;
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, elems) {
	if(dup != line && line->name() == dup->name() ) {
	  if (!topLevelItem) {
	    topLevelItem =  new QTreeWidgetItem();
	    topLevelItem->setData(0, Qt::DisplayRole, "Name");
	    if(!item)
	      item = createItem(*line);
	    item->addChild(topLevelItem);
	    anyAdded = true;
	  }
	  topLevelItem->addChild(createItem(*dup));
	}
      }
    }

    if (showSizeDups) {
      QTreeWidgetItem* topLevelItem = 0;
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, elems) {
	if(dup != line && line->size() == dup->size() ) {
	  if (!topLevelItem) {
	    topLevelItem =  new QTreeWidgetItem();
	    topLevelItem->setData(0, Qt::DisplayRole, "Size");
	    if(!item)
	      item = createItem(*line);
	    item->addChild(topLevelItem);
	    anyAdded = true;
	  }
	  topLevelItem->addChild(createItem(*dup));
	}
      }
    }

    if (showMTimeDups) {
      QTreeWidgetItem* topLevelItem = 0;
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, elems) {
	if(dup != line && line->mtime() == dup->mtime() ) {
	  if (!topLevelItem) {
	    topLevelItem =  new QTreeWidgetItem();
	    topLevelItem->setData(0, Qt::DisplayRole, "MTime");
	    if(!item)
	      item = createItem(*line);
	    item->addChild(topLevelItem);
	    anyAdded = true;
	  }
	  topLevelItem->addChild(createItem(*dup));
	}
      }
    }

    if (showCheckSumDups) {
      QTreeWidgetItem* topLevelItem = 0;
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, elems) {
	if(dup != line && line->checksum() == dup->checksum() ) {
	  if (!topLevelItem) {
	    topLevelItem =  new QTreeWidgetItem();
	    topLevelItem->setData(0, Qt::DisplayRole, "Checksum");
	    if(!item)
	      item = createItem(*line);
	    item->addChild(topLevelItem);
	    anyAdded = true;
	  }
	  topLevelItem->addChild(createItem(*dup));
	}
      }
    }

    if (editDistanceCutoff < 1.0) {
      QTreeWidgetItem* topLevelItem = 0;
      QMultiMap<int, QSharedPointer<FileDbLink::DBInfo> > oList;

      int absoluteCutoff = line->name().length() * editDistanceCutoff;
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, elems) {
	if(dup != line) {
	  int distance = EditDistance::Compute(line->name(), dup->name());

	  if (distance <= absoluteCutoff) {
	    oList.insert(distance, dup);
	  }
	}
      }

      if (oList.size() > 0 ) {
	topLevelItem =  new QTreeWidgetItem();
	topLevelItem->setData(0, Qt::DisplayRole, "Editdistance");
	if(!item)
	  item = createItem(*line);
	item->addChild(topLevelItem);
	anyAdded = true;
      }
      
      foreach(QSharedPointer<FileDbLink::DBInfo> dup, oList.values()) {
	topLevelItem->addChild(createItem(*dup));
      }
    }



    if (item)
      tw->addTopLevelItem(item);
    emit populateProgress(++n);
    if (n % 64 == 0) {
      QCoreApplication::processEvents();
    }
  }
  tw->setUpdatesEnabled(true);

}


DataController::DataController() : showFullPath(false)
{
  populateDelay = new QTimer(this);
  populateDelay->setSingleShot(true);
  populateDelay->setInterval(500);
  connect(populateDelay, SIGNAL(timeout()), this, SLOT(populate()));

  dblink = new MemoryDbLink();

  findFiles(QDir("."), *dblink);

  mw = new QMainWindow();
  QMenuBar* mb = new QMenuBar();

  QMenu* menu = mb->addMenu("&View");
  QAction* action = menu->addAction("Show full path");
  action->setCheckable(true);
  connect(action, SIGNAL(toggled(bool)), this, SLOT(setShowFullPath(bool)));

  mw->setMenuBar(mb);

  QToolBar* filterBar = new QToolBar("Filters");

  nameFilter = filterBar->addAction("Name");
  nameFilter->setCheckable(true);
  connect(nameFilter, SIGNAL(toggled(bool)), this, SLOT(delayPopulate()));

  sizeFilter = filterBar->addAction("Size");
  sizeFilter->setCheckable(true);
  connect(sizeFilter, SIGNAL(toggled(bool)), this, SLOT(delayPopulate()));

  mtimeFilter = filterBar->addAction("MTime");
  mtimeFilter->setCheckable(true);
  connect(mtimeFilter, SIGNAL(toggled(bool)), this, SLOT(delayPopulate()));

  checksumFilter = filterBar->addAction("Checksum");
  checksumFilter->setCheckable(true);
  connect(checksumFilter, SIGNAL(toggled(bool)), this, SLOT(delayPopulate()));

  QWidget* widget = new QWidget();
  QLayout* layout = new QHBoxLayout();
  layout->setContentsMargins(0,0,0,0);
  widget->setLayout(layout);
  layout->addWidget(new QLabel("Edit distance", widget));
  editCutoffSpin = new QSpinBox(widget);
  layout->addWidget(editCutoffSpin);
  editCutoffSpin->setMinimum(0);
  editCutoffSpin->setMaximum(100);
  editCutoffSpin->setValue(70);
  editCutoffSpin->setSingleStep(10);
  editCutoffSpin->setSuffix("%");
  connect(editCutoffSpin, SIGNAL(valueChanged(int)), this, SLOT(delayPopulate()));
  filterBar->addWidget(widget);

  mw->addToolBar(filterBar);

  tw = new QTreeWidget(mw);
  mw->setCentralWidget(tw);
  tw->setEditTriggers(QAbstractItemView::NoEditTriggers);

  tw->setHeaderLabels(QString("Path;Size;Date;Checksum").split(";"));	

  populate();

  tw->setSortingEnabled(true);
  tw->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
  tw->setSelectionBehavior(QAbstractItemView::SelectRows);
  //tw->resizeColumnsToContents();
  mw->resize(800,800);
  mw->show();


}

DataController::~DataController()
{
}


void DataController::cellDoubleClicked(int row, int column)
{
  if(column == 0) {
    toggleShowFullPath();
  }
}


void DataController::setShowFullPath(bool showFullPath)
{
  this->showFullPath = showFullPath;

  tw->setSortingEnabled(false);

  int role = (showFullPath)?32:33;
  for (int row = 0; row < tw->topLevelItemCount(); ++row) {
    QTreeWidgetItem* pathItem = tw->topLevelItem(row);
    pathItem->setData(0, Qt::DisplayRole, pathItem->data(0,role));
  }
  tw->setSortingEnabled(true);
}

bool DataController::toggleShowFullPath()
{
  bool showFullPath = ! this->showFullPath;
  setShowFullPath(showFullPath);
  return showFullPath;
}