You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
552 lines
16 KiB
C++
552 lines
16 KiB
C++
#include "common.h"
|
|
|
|
#include "cmainwindow.h"
|
|
#include "ui_cmainwindow.h"
|
|
|
|
#include <QSettings>
|
|
#include <QDir>
|
|
#include <QFileDialog>
|
|
|
|
#include <QElapsedTimer>
|
|
#include <QDebug>
|
|
|
|
|
|
//#define TREEVIEW
|
|
|
|
bool g_bMatchDir = true;
|
|
bool g_bMatchFile = true;
|
|
bool g_bMatchDateTime = true;
|
|
bool g_bMatchSize = true;
|
|
|
|
|
|
bool fileSort(cFile* file1, cFile* file2)
|
|
{
|
|
if(file1->dir().compare(file2->dir(), Qt::CaseInsensitive) < 0)
|
|
return(true);
|
|
if(file1->file().compare(file2->file(), Qt::CaseInsensitive) < 0)
|
|
return(true);
|
|
if(file1->dateTime() < file2->dateTime())
|
|
return(true);
|
|
if(file1->size() < file2->size())
|
|
return(true);
|
|
|
|
return(false);
|
|
}
|
|
|
|
cMainWindow::cMainWindow(QWidget *parent) :
|
|
QMainWindow(parent),
|
|
ui(new Ui::cMainWindow),
|
|
m_lpLeftListModel(nullptr),
|
|
m_lpRightListModel(nullptr),
|
|
m_lpLeftListProxyModel(nullptr),
|
|
m_lpRightListProxyModel(nullptr),
|
|
m_lpProgressBar(nullptr),
|
|
m_initializing(true),
|
|
m_loading(false)
|
|
{
|
|
initUI();
|
|
createActions();
|
|
|
|
m_initializing = false;
|
|
}
|
|
|
|
cMainWindow::~cMainWindow()
|
|
{
|
|
delete ui;
|
|
}
|
|
|
|
void cMainWindow::closeEvent(QCloseEvent *event)
|
|
{
|
|
QSettings settings;
|
|
settings.setValue("main/width", QVariant::fromValue(size().width()));
|
|
settings.setValue("main/height", QVariant::fromValue(size().height()));
|
|
settings.setValue("main/x", QVariant::fromValue(x()));
|
|
settings.setValue("main/y", QVariant::fromValue(y()));
|
|
if(this->isMaximized())
|
|
settings.setValue("main/maximized", QVariant::fromValue(true));
|
|
else
|
|
settings.setValue("main/maximized", QVariant::fromValue(false));
|
|
|
|
QList<qint32> sizes = ui->m_lpSplitter->sizes();
|
|
|
|
for(int x = 0;x < sizes.count();x++)
|
|
settings.setValue(QString("main/splitter%1").arg(x+1), QVariant::fromValue(sizes[x]));
|
|
|
|
event->accept();
|
|
}
|
|
|
|
void cMainWindow::initUI()
|
|
{
|
|
ui->setupUi(this);
|
|
|
|
m_lpProgressBar = new QProgressBar(this);
|
|
m_lpProgressBar->setVisible(false);
|
|
ui->m_lpStatusBar->addPermanentWidget(m_lpProgressBar);
|
|
|
|
m_lpLeftListModel = new QStandardItemModel(0, 1);
|
|
m_lpLeftListProxyModel = new cSortFilterProxyModel(this);
|
|
ui->m_lpLeftList->setModel(m_lpLeftListProxyModel);
|
|
m_lpLeftListProxyModel->setSourceModel(m_lpLeftListModel);
|
|
|
|
m_lpRightListModel = new QStandardItemModel(0, 1);
|
|
m_lpRightListProxyModel = new cSortFilterProxyModel(this);
|
|
ui->m_lpRightList->setModel(m_lpRightListProxyModel);
|
|
m_lpRightListProxyModel->setSourceModel(m_lpRightListModel);
|
|
|
|
QSettings settings;
|
|
|
|
if(!settings.value("main/maximized").toBool())
|
|
{
|
|
qint32 iX = settings.value("main/x", QVariant::fromValue(-1)).toInt();
|
|
qint32 iY = settings.value("main/y", QVariant::fromValue(-1)).toInt();
|
|
qint32 iWidth = settings.value("main/width", QVariant::fromValue(-1)).toInt();
|
|
qint32 iHeight = settings.value("main/height", QVariant::fromValue(-1)).toInt();
|
|
|
|
if(iWidth != -1 && iHeight != -1)
|
|
resize(iWidth, iHeight);
|
|
if(iX != -1 && iY != -1)
|
|
move(iX, iY);
|
|
}
|
|
|
|
qint32 iWidth1 = settings.value("main/splitter1", QVariant::fromValue(-1)).toInt();
|
|
qint32 iWidth2 = settings.value("main/splitter2", QVariant::fromValue(-1)).toInt();
|
|
|
|
ui->m_lpSplitter->setSizes(QList<int>() << iWidth1 << iWidth2);
|
|
|
|
g_bMatchDir = settings.value("filter/dir", QVariant::fromValue(true)).toBool();
|
|
g_bMatchFile = settings.value("filter/file", QVariant::fromValue(true)).toBool();
|
|
g_bMatchDateTime = settings.value("filter/datetime", QVariant::fromValue(true)).toBool();
|
|
g_bMatchSize = settings.value("filter/size", QVariant::fromValue(true)).toBool();
|
|
|
|
ui->m_lpMatchDir->setChecked(g_bMatchDir);
|
|
ui->m_lpMatchFile->setChecked(g_bMatchFile);
|
|
ui->m_lpMatchDateTime->setChecked(g_bMatchDateTime);
|
|
ui->m_lpMatchSize->setChecked(g_bMatchSize);
|
|
}
|
|
|
|
void cMainWindow::createActions()
|
|
{
|
|
setToolButtonStyle(Qt::ToolButtonFollowStyle);
|
|
|
|
createFileActions();
|
|
createContextActions();
|
|
|
|
connect(ui->m_lpLoadListFromFileLeft, &QToolButton::clicked, this, &cMainWindow::onLoadListFromFileLeft);
|
|
connect(ui->m_lpLoadListFromFileRight, &QToolButton::clicked, this, &cMainWindow::onLoadListFromFileRight);
|
|
|
|
connect(ui->m_lpLoadListFromDirLeft, &QToolButton::clicked, this, &cMainWindow::onLoadListFromDirLeft);
|
|
connect(ui->m_lpLoadListFromDirRight, &QToolButton::clicked, this, &cMainWindow::onLoadListFromDirRight);
|
|
|
|
connect(ui->m_lpLeftList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &cMainWindow::onLeftListSelected);
|
|
connect(ui->m_lpRightList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &cMainWindow::onRightListSelected);
|
|
|
|
connect(ui->m_lpMatchDir, &QCheckBox::clicked, this, &cMainWindow::onMatchDirChecked);
|
|
connect(ui->m_lpMatchFile, &QCheckBox::clicked, this, &cMainWindow::onMatchFileChecked);
|
|
connect(ui->m_lpMatchDateTime, &QCheckBox::clicked, this, &cMainWindow::onMatchDateTimeChecked);
|
|
connect(ui->m_lpMatchSize, &QCheckBox::clicked, this, &cMainWindow::onMatchSizeChecked);
|
|
|
|
connect(ui->m_lpMarkDifference, &QToolButton::clicked, this, &cMainWindow::onMarkDifference);
|
|
|
|
connect(ui->m_lpClearSelectionLeft, &QToolButton::clicked, this, &cMainWindow::onClearSelectionLeft);
|
|
connect(ui->m_lpClearSelectionRight, &QToolButton::clicked, this, &cMainWindow::onClearSelectionRight);
|
|
}
|
|
|
|
void cMainWindow::createFileActions()
|
|
{
|
|
}
|
|
|
|
void cMainWindow::createContextActions()
|
|
{
|
|
}
|
|
|
|
void cMainWindow::onLoadListFromFileLeft()
|
|
{
|
|
QSettings settings;
|
|
QString szPath = settings.value("main/leftFile", QDir::homePath()).toString();
|
|
QString szFile = QFileDialog::getOpenFileName(this, tr("Open Text File"), szPath, tr("Text Files (*.txt)"));
|
|
|
|
if(szFile.isEmpty())
|
|
return;
|
|
|
|
settings.setValue("main/leftFile", QVariant::fromValue(szFile.left(szFile.lastIndexOf("/"))));
|
|
|
|
m_loading = true;
|
|
m_lpProgressBar->setVisible(true);
|
|
ui->m_lpStatusBar->showMessage("loading list...");
|
|
qApp->processEvents();
|
|
m_listLeft.load(szFile, m_lpProgressBar);
|
|
ui->m_lpStatusBar->showMessage("populating list...");
|
|
qApp->processEvents();
|
|
displayList(ui->m_lpLeftList, m_lpLeftListModel, m_listLeft);
|
|
ui->m_lpStatusBar->showMessage("done.", 5000);
|
|
m_lpProgressBar->setVisible(false);
|
|
m_loading = false;
|
|
}
|
|
|
|
void cMainWindow::onLoadListFromFileRight()
|
|
{
|
|
QSettings settings;
|
|
QString szPath = settings.value("main/rightFile", QDir::homePath()).toString();
|
|
QString szFile = QFileDialog::getOpenFileName(this, tr("Open Text File"), szPath, tr("Text Files (*.txt)"));
|
|
|
|
if(szFile.isEmpty())
|
|
return;
|
|
|
|
settings.setValue("main/rightFile", QVariant::fromValue(szFile.left(szFile.lastIndexOf("/"))));
|
|
|
|
m_loading = true;
|
|
m_lpProgressBar->setVisible(true);
|
|
ui->m_lpStatusBar->showMessage("loading list...");
|
|
qApp->processEvents();
|
|
m_listRight.load(szFile, m_lpProgressBar);
|
|
ui->m_lpStatusBar->showMessage("populating list...");
|
|
qApp->processEvents();
|
|
displayList(ui->m_lpRightList, m_lpRightListModel, m_listRight);
|
|
ui->m_lpStatusBar->showMessage("done.", 5000);
|
|
m_lpProgressBar->setVisible(false);
|
|
m_loading = false;
|
|
}
|
|
|
|
void cMainWindow::onLoadListFromDirLeft()
|
|
{
|
|
QSettings settings;
|
|
QString szPath = settings.value("main/leftDir", QDir::homePath()).toString();
|
|
QString szDir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), szPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
if(szDir.isEmpty())
|
|
return;
|
|
|
|
settings.setValue("main/leftDir", QVariant::fromValue(szDir));
|
|
|
|
m_loading = true;
|
|
ui->m_lpStatusBar->showMessage("loading list...");
|
|
qApp->processEvents();
|
|
m_listLeft.load(szDir, ui->m_lpStatusBar);
|
|
ui->m_lpStatusBar->showMessage("populating list...");
|
|
qApp->processEvents();
|
|
displayList(ui->m_lpLeftList, m_lpLeftListModel, m_listLeft);
|
|
ui->m_lpStatusBar->showMessage("done.", 5000);
|
|
m_loading = false;
|
|
}
|
|
|
|
void cMainWindow::onLoadListFromDirRight()
|
|
{
|
|
QSettings settings;
|
|
QString szPath = settings.value("main/rightDir", QDir::homePath()).toString();
|
|
QString szDir = QFileDialog::getExistingDirectory(this, tr("Open Directory"), szPath, QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
|
|
|
|
if(szDir.isEmpty())
|
|
return;
|
|
|
|
settings.setValue("main/rightDir", QVariant::fromValue(szDir));
|
|
|
|
m_loading = true;
|
|
ui->m_lpStatusBar->showMessage("loading list...");
|
|
qApp->processEvents();
|
|
m_listRight.load(szDir, ui->m_lpStatusBar);
|
|
ui->m_lpStatusBar->showMessage("populating list...");
|
|
qApp->processEvents();
|
|
displayList(ui->m_lpRightList, m_lpRightListModel, m_listRight);
|
|
ui->m_lpStatusBar->showMessage("done.", 5000);
|
|
m_loading = false;
|
|
}
|
|
|
|
void cMainWindow::onMarkDifference()
|
|
{
|
|
qint64 div = m_lpLeftListModel->rowCount() / 1000;
|
|
|
|
ui->m_lpStatusBar->showMessage("processing left list...");
|
|
|
|
m_lpProgressBar->setVisible(true);
|
|
m_lpProgressBar->setRange(0, m_lpLeftListModel->rowCount());
|
|
|
|
QVariant white = QVariant::fromValue(QBrush(QColor(Qt::white)));
|
|
QVariant green = QVariant::fromValue(QBrush(QColor(Qt::green)));
|
|
|
|
for(int i = 0;i < m_lpLeftListModel->rowCount();i++)
|
|
{
|
|
QStandardItem* lpItem = m_lpLeftListModel->item(i, 0);
|
|
cFile* lpFile = lpItem->data(Qt::UserRole+1).value<cFile*>();
|
|
QVariant var;
|
|
|
|
if(m_listRight.contains(*lpFile))
|
|
{
|
|
lpItem->setData(green, Qt::BackgroundRole);
|
|
m_lpLeftListModel->setData(m_lpLeftListModel->index(i, 1), green, Qt::BackgroundRole);
|
|
m_lpLeftListModel->setData(m_lpLeftListModel->index(i, 2), green, Qt::BackgroundRole);
|
|
#ifndef TREEVIEW
|
|
m_lpLeftListModel->setData(m_lpLeftListModel->index(i, 3), green, Qt::BackgroundRole);
|
|
#endif
|
|
}
|
|
|
|
if(!(i % div))
|
|
{
|
|
m_lpProgressBar->setValue(i);
|
|
qApp->processEvents();
|
|
}
|
|
}
|
|
|
|
div = m_lpRightListModel->rowCount() / 1000;
|
|
|
|
ui->m_lpStatusBar->showMessage("processing right list...");
|
|
|
|
m_lpProgressBar->setRange(0, m_lpRightListModel->rowCount());
|
|
|
|
for(int i = 0;i < m_lpRightListModel->rowCount();i++)
|
|
{
|
|
QStandardItem* lpItem = m_lpRightListModel->item(i, 0);
|
|
cFile* lpFile = lpItem->data(Qt::UserRole+1).value<cFile*>();
|
|
QBrush brush(Qt::white);
|
|
|
|
if(m_listLeft.contains(*lpFile))
|
|
{
|
|
lpItem->setData(green, Qt::BackgroundRole);
|
|
m_lpRightListModel->setData(m_lpRightListModel->index(i, 1), green, Qt::BackgroundRole);
|
|
m_lpRightListModel->setData(m_lpRightListModel->index(i, 2), green, Qt::BackgroundRole);
|
|
#ifndef TREEVIEW
|
|
m_lpRightListModel->setData(m_lpRightListModel->index(i, 3), green, Qt::BackgroundRole);
|
|
#endif
|
|
}
|
|
|
|
if(!(i % div))
|
|
{
|
|
m_lpProgressBar->setValue(i);
|
|
qApp->processEvents();
|
|
}
|
|
}
|
|
|
|
m_lpProgressBar->setVisible(false);
|
|
|
|
ui->m_lpStatusBar->showMessage("done.", 5000);
|
|
}
|
|
|
|
void cMainWindow::onClearSelectionLeft()
|
|
{
|
|
ui->m_lpLeftList->clearSelection();
|
|
m_lpRightListProxyModel->setFilterFile(nullptr);
|
|
}
|
|
|
|
void cMainWindow::onClearSelectionRight()
|
|
{
|
|
ui->m_lpRightList->clearSelection();
|
|
m_lpLeftListProxyModel->setFilterFile(nullptr);
|
|
}
|
|
|
|
#ifdef TREEVIEW
|
|
QStandardItem* insertPath(QTreeView* lpView, QStandardItem* lpRootItem, QString szPath)
|
|
{
|
|
if(!lpRootItem)
|
|
return(nullptr);
|
|
|
|
QStringList szPathList = szPath.split("/");
|
|
QStandardItem* lpCurRoot = lpRootItem;
|
|
int path;
|
|
bool bFound;
|
|
QString szPath1 = "";
|
|
|
|
for(path = 0;path < szPathList.count();path++)
|
|
{
|
|
bFound = false;
|
|
for(int x = 0;x < lpCurRoot->rowCount();x++)
|
|
{
|
|
QStandardItem* lpCurItem = lpCurRoot->child(x, 0);
|
|
|
|
if(!lpCurItem->text().compare(szPathList[path], Qt::CaseInsensitive))
|
|
{
|
|
lpCurRoot = lpCurItem;
|
|
bFound = true;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(!bFound)
|
|
break;
|
|
|
|
szPath1.append(szPathList[path]+"/");
|
|
}
|
|
|
|
for(;path < szPathList.count();path++)
|
|
{
|
|
szPath1.append(szPathList[path]);
|
|
|
|
QStandardItem* lpNewItem = new QStandardItem(szPathList[path]);
|
|
|
|
lpCurRoot->appendRow(lpNewItem);
|
|
lpView->setFirstColumnSpanned(lpRootItem->rowCount()-1, lpRootItem->index(), true);
|
|
|
|
lpNewItem->setData(QVariant::fromValue(szPath1), Qt::UserRole+1);
|
|
szPath1.append("/");
|
|
|
|
lpCurRoot = lpNewItem;
|
|
}
|
|
|
|
return(lpCurRoot);
|
|
}
|
|
#endif
|
|
|
|
void cMainWindow::displayList(QTreeView* lpView, QStandardItemModel* lpModel, cFileList& fileList)
|
|
{
|
|
lpView->setUpdatesEnabled(false);
|
|
|
|
lpModel->clear();
|
|
|
|
QStringList header;
|
|
#ifdef TREEVIEW
|
|
header << "file" << "date/time" << "size";
|
|
QStandardItem* lpDir = nullptr;
|
|
#else
|
|
header << "path" << "file" << "date/time" << "size";
|
|
#endif
|
|
|
|
lpModel->setHorizontalHeaderLabels(header);
|
|
QStandardItem* lpRoot = lpModel->invisibleRootItem();
|
|
|
|
m_lpProgressBar->setRange(0, fileList.count());
|
|
|
|
for(cFileList::iterator i = fileList.begin();i != fileList.end();i++)
|
|
{
|
|
QList<QStandardItem*> items;
|
|
cFile* lpFile = &(*i);
|
|
|
|
#ifdef TREEVIEW
|
|
lpDir = insertPath(lpView, lpRoot, lpFile->dir());
|
|
#else
|
|
items.append(new QStandardItem(lpFile->dir()));
|
|
#endif
|
|
|
|
items.append(new QStandardItem(lpFile->file()));
|
|
items.append(new QStandardItem(lpFile->dateTime().toString()));
|
|
items.append(new QStandardItem(QString::number(lpFile->size())));
|
|
items[0]->setData(QVariant::fromValue(lpFile), Qt::UserRole+1);
|
|
items[1]->setData(QVariant::fromValue(lpFile), Qt::UserRole+1);
|
|
items[2]->setData(QVariant::fromValue(lpFile), Qt::UserRole+1);
|
|
#ifdef TREEVIEW
|
|
items[2]->setTextAlignment(Qt::AlignRight);
|
|
#else
|
|
items[3]->setData(QVariant::fromValue(lpFile), Qt::UserRole+1);
|
|
items[3]->setTextAlignment(Qt::AlignRight);
|
|
#endif
|
|
|
|
#ifdef TREEVIEW
|
|
lpDir->appendRow(items);
|
|
#else
|
|
lpRoot->appendRow(items);
|
|
#endif
|
|
}
|
|
|
|
#ifdef TREEVIEW
|
|
lpView->expandAll();
|
|
#endif
|
|
lpView->resizeColumnToContents(0);
|
|
lpView->resizeColumnToContents(1);
|
|
lpView->resizeColumnToContents(2);
|
|
#ifndef TREEVIEW
|
|
lpView->resizeColumnToContents(3);
|
|
#endif
|
|
lpView->setUpdatesEnabled(true);
|
|
lpView->update();
|
|
}
|
|
|
|
void cMainWindow::onLeftListSelected(const QItemSelection& selection, const QItemSelection& /*previous*/)
|
|
{
|
|
if(m_loading)
|
|
return;
|
|
|
|
if(!selection.indexes().count())
|
|
return;
|
|
|
|
QModelIndex index = selection.indexes()[0];
|
|
if(!index.isValid())
|
|
return;
|
|
|
|
cFile* lpFile = index.data(Qt::UserRole+1).value<cFile*>();
|
|
if(!lpFile)
|
|
return;
|
|
|
|
m_lpLeftListProxyModel->setFilterFile(nullptr);
|
|
m_lpRightListProxyModel->setFilterFile(lpFile);
|
|
}
|
|
|
|
void cMainWindow::onRightListSelected(const QItemSelection& selection, const QItemSelection& /*previous*/)
|
|
{
|
|
if(m_loading)
|
|
return;
|
|
|
|
if(!selection.indexes().count())
|
|
return;
|
|
|
|
QModelIndex index = selection.indexes()[0];
|
|
if(!index.isValid())
|
|
return;
|
|
|
|
cFile* lpFile = index.data(Qt::UserRole+1).value<cFile*>();
|
|
if(!lpFile)
|
|
return;
|
|
|
|
m_lpRightListProxyModel->setFilterFile(nullptr);
|
|
m_lpLeftListProxyModel->setFilterFile(lpFile);
|
|
}
|
|
|
|
void cMainWindow::onMatchDirChecked(bool checked)
|
|
{
|
|
if(m_initializing)
|
|
return;
|
|
|
|
g_bMatchDir = checked;
|
|
|
|
QSettings settings;
|
|
settings.setValue("filter/dir", QVariant::fromValue(checked));
|
|
|
|
if(m_lpLeftListProxyModel->filterFile())
|
|
m_lpLeftListProxyModel->invalidate();
|
|
if(m_lpRightListProxyModel->filterFile())
|
|
m_lpRightListProxyModel->invalidate();
|
|
}
|
|
|
|
void cMainWindow::onMatchFileChecked(bool checked)
|
|
{
|
|
if(m_initializing)
|
|
return;
|
|
|
|
g_bMatchFile = checked;
|
|
|
|
QSettings settings;
|
|
settings.setValue("filter/file", QVariant::fromValue(checked));
|
|
|
|
if(m_lpLeftListProxyModel->filterFile())
|
|
m_lpLeftListProxyModel->invalidate();
|
|
if(m_lpRightListProxyModel->filterFile())
|
|
m_lpRightListProxyModel->invalidate();
|
|
}
|
|
|
|
void cMainWindow::onMatchDateTimeChecked(bool checked)
|
|
{
|
|
if(m_initializing)
|
|
return;
|
|
|
|
g_bMatchDateTime = checked;
|
|
|
|
QSettings settings;
|
|
settings.setValue("filter/datetime", QVariant::fromValue(checked));
|
|
|
|
if(m_lpLeftListProxyModel->filterFile())
|
|
m_lpLeftListProxyModel->invalidate();
|
|
if(m_lpRightListProxyModel->filterFile())
|
|
m_lpRightListProxyModel->invalidate();
|
|
}
|
|
|
|
void cMainWindow::onMatchSizeChecked(bool checked)
|
|
{
|
|
if(m_initializing)
|
|
return;
|
|
|
|
g_bMatchSize = checked;
|
|
|
|
QSettings settings;
|
|
settings.setValue("filter/size", QVariant::fromValue(checked));
|
|
|
|
if(m_lpLeftListProxyModel->filterFile())
|
|
m_lpLeftListProxyModel->invalidate();
|
|
if(m_lpRightListProxyModel->filterFile())
|
|
m_lpRightListProxyModel->invalidate();
|
|
}
|