Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
ShSamariddin committed Mar 2, 2019
0 parents commit 8b12862
Show file tree
Hide file tree
Showing 13 changed files with 1,006 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Auto detect text files and perform LF normalization
* text=auto
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
# sleuth

Recursively indexes all files in folder and reindexes when files
changing with the ability to search for string in these files
46 changes: 46 additions & 0 deletions StringSearch.pro
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
#-------------------------------------------------
#
# Project created by QtCreator 2018-12-21T01:38:39
#
#-------------------------------------------------

QT += core gui\
concurrent

greaterThan(QT_MAJOR_VERSION, 4): QT += widgets

TARGET = sleuth
TEMPLATE = app

# The following define makes your compiler emit warnings if you use
# any feature of Qt which has been marked as deprecated (the exact warnings
# depend on your compiler). Please consult the documentation of the
# deprecated API in order to know how to port your code away from it.
DEFINES += QT_DEPRECATED_WARNINGS

# You can also make your code fail to compile if you use deprecated APIs.
# In order to do so, uncomment the following line.
# You can also select to disable deprecated APIs only up to a certain version of Qt.
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0

CONFIG += c++11

SOURCES += \
main.cpp \
mainwindow.cpp \
search_index.cpp \
find_string.cpp

HEADERS += \
mainwindow.h \
search_index.h \
find_string.h \
trigram.h

FORMS += \
mainwindow.ui

# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
322 changes: 322 additions & 0 deletions StringSearch.pro.user

Large diffs are not rendered by default.

49 changes: 49 additions & 0 deletions find_string.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
#include "find_string.h"
#include <vector>
#include <QFile>
#include <QTextStream>
#include <QMutexLocker>
#include <QDebug>

match_string::match_string(QMutex &mtx, QMap<QString, std::set<tgram>> const &paths_to_tgram, QString match_s) : mtx(mtx), paths_to_tgram(paths_to_tgram), match_s(match_s){}

void match_string::start_search() {
qDebug() << "search search";
emit set_max_progress(paths_to_tgram.size());
emit set_progress(0);
std::set<tgram> match_tgram;
auto buffer(match_s.toUtf8());
for (int i = 2; i < buffer.size(); ++i) { //size int
match_tgram.insert(tgram(buffer[i - 2], buffer[i - 1], buffer[i])); //operator[] from int and uint :(
}
QMutexLocker locker(&mtx);
int k = 0;
for(auto it = paths_to_tgram.keyValueBegin(); it != paths_to_tgram.keyValueEnd() && !QThread::currentThread()->isInterruptionRequested(); ++it) {
if(std::includes((*it).second.begin(), (*it).second.end(),
match_tgram.begin(), match_tgram.end())) {
QFile file((*it).first);
QVector<QString> ans;
if (file.open(QIODevice::ReadOnly)) {
QString line;
QTextStream in(&file);
while (!in.atEnd()) {
if (QThread::currentThread()->isInterruptionRequested()){
break;
}
line = in.readLine();
if (line.contains(match_s, Qt::CaseInsensitive)) {
ans.push_back(line);
}
}
}
if(ans.size()){
emit matched(std::make_pair((*it).first, ans));
}
}
emit set_progress(++k);
}
emit set_max_progress(1);
emit set_progress(1);
emit finished();
qDebug() << "search end";
}
34 changes: 34 additions & 0 deletions find_string.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
#ifndef MATCH_STRING_H
#define MATCH_STRING_H

#include <QObject>
#include <QMap>
#include <QSet>
#include <QByteArray>
#include <QThread>
#include <QMutex>
#include <set>
#include "trigram.h"

class match_string: public QObject {
Q_OBJECT
public:
match_string(QMutex &mtx, QMap<QString, std::set<tgram>> const &paths_to_tgram, QString match_s);

signals:
void set_progress(int value);
void search_finished();
void finished();
void matched(std::pair<QString, QVector<QString>> v);
void set_max_progress(int value);

public slots:
void start_search();

private:
QMutex& mtx;
QMap<QString, std::set<tgram>> const &paths_to_tgram;
QString match_s;
};

#endif // MATCH_STRING_H
11 changes: 11 additions & 0 deletions main.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include "mainwindow.h"
#include <QApplication>

int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();

return a.exec();
}
142 changes: 142 additions & 0 deletions mainwindow.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
#include "mainwindow.h"
#include "ui_mainwindow.h"


#include <QSizePolicy>
#include <QDebug>
#include <QFileDialog>
#include <QDesktopServices>

MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), index_now(false), ui(new Ui::MainWindow), index_thread(new QThread()), search_thread(new QThread) {
ui->setupUi(this);

qRegisterMetaType<std::pair<QString, QVector<QString>>>();
connect(ui->treeWidget, SIGNAL(itemDoubleClicked(QTreeWidgetItem*, int)), this, SLOT(open_file(QTreeWidgetItem*)));

connect(ui->SelectDirectory, &QPushButton::clicked, this, &MainWindow::select_directory);
connect(ui->IndexStop, &QPushButton::clicked, this, &MainWindow::stop_index);
connect(ui->StartStopSearch, &QPushButton::clicked, this, &MainWindow::start_search);
ui->treeWidget->setColumnWidth(0, 460);
ui->treeWidget->setStyleSheet("background-color: rgb(0,0,0);");

ui->progressBar->setMaximum(1);
ui->progressBar->setValue(0);
}

MainWindow::~MainWindow() {
stop_index();
stop_search();
}

void MainWindow::select_directory() {
cur_dir = QFileDialog::getExistingDirectory(this, "Select Directory for Scanning", QString(), QFileDialog::ShowDirsOnly | QFileDialog::DontResolveSymlinks);
ui->label_2->setText("status:indexing...");
start_index();
ui->label->setText("current directory:" + cur_dir);
}

void MainWindow::start_index() {
stop_index();
index_now = true;
paths_to_tgram.clear();
index_search* worker = new index_search(mtx, paths_to_tgram, cur_dir);
worker->moveToThread(index_thread.get());

connect(worker, SIGNAL(file_change()), this, SLOT(file_change()));
connect(worker, SIGNAL(set_max_progress(int)), ui->progressBar, SLOT(setMaximum(int)));
connect(worker, SIGNAL(set_progress(int)), ui->progressBar, SLOT(setValue(int)));

connect(index_thread.get(), SIGNAL (started()), worker, SLOT (start_index()));
connect(worker, SIGNAL (finished()), this, SLOT (index_end()));
connect(worker, SIGNAL (index_end()), this, SLOT (index_end()));

index_thread->start();
}

void MainWindow::start_search() {
if(index_now) {
ui->treeWidget->clear();
ui->label_3->setText("status:Directory now indexing");
return;
}
stop_search();

ui->treeWidget->clear();
ui->lcdNumber->display(0);

search_time.start();
match_string* worker = new match_string(mtx, paths_to_tgram, ui->MatchString->text());
worker->moveToThread(search_thread.get());

connect(worker, SIGNAL(set_max_progress(int)), ui->progressBar, SLOT(setMaximum(int)));
connect(worker, SIGNAL(set_progress(int)), ui->progressBar, SLOT(setValue(int)));
connect(worker, SIGNAL(matched(std::pair<QString, QVector<QString>>)), this, SLOT(add_path(std::pair<QString, QVector<QString>>)));

connect(search_thread.get(), SIGNAL(started()), worker, SLOT(start_search()));
connect(worker, SIGNAL (finished()), search_thread.get(), SLOT (quit()));
connect(worker, SIGNAL (finished()), worker, SLOT (deleteLater()));
connect(worker, SIGNAL (finished()), this, SLOT (search_end()));

search_thread->start();
ui->label_3->setText("status:searching...");
}

void MainWindow::stop_index() {
if(index_thread != nullptr && index_thread->isRunning()){
index_thread->requestInterruption();
index_thread->quit();
index_thread->wait();
index_thread.reset(new QThread);
ui->label_2->setText("status:index canceled");
}
}

void MainWindow::stop_search() {
if(search_thread != nullptr && search_thread->isRunning()){
search_thread->requestInterruption();
search_thread->quit();
search_thread->wait();
ui->label_3->setText("status:search canceled");
}
}

void MainWindow::add_path(std::pair<QString, QVector<QString>> v){
QTreeWidgetItem *ti = new QTreeWidgetItem();
cnt++;int color1 = rand() % 200 + 55;
int color2 = rand() % 200 + 55;
int color3 = rand() % 200 + 55;
ti->setTextColor(0, QColor::fromRgb(color1, color2, color3));
ti->setTextColor(1, QColor::fromRgb(color1, color2, color3));
ti->setTextColor(2, QColor::fromRgb(color1, color2, color3));
ti->setTextColor(3, QColor::fromRgb(color1, color2, color3));
ti->setText(0, "Group" + QString::number(cnt));
ti->setText(1, QString::number(v.second.size()));
ti->setText(2, QString::number(v.second.first().size()));
int tsize = 0;
for (auto const & k: v.second) {
tsize += k.size();
QTreeWidgetItem *child = new QTreeWidgetItem();
child->setText(0, k);
child->setTextColor(0, QColor::fromRgb(color1, color2, color3));
ti->addChild(child);
}
ti->setText(3, QString::number(tsize));
ui->treeWidget->addTopLevelItem(ti);

ui->lcdNumber->display(ui->treeWidget->topLevelItemCount());
}

void MainWindow::file_change(){
ui->label_3->setText("status:some file or directory has been changed. please searching again ");
}

void MainWindow::index_end() {
index_now = false;
ui->label_2->setText("status:indexing is complete you can write a string");
}

void MainWindow::search_end() {
ui->label_3->setText("status:searching is complete");
}


60 changes: 60 additions & 0 deletions mainwindow.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include "search_index.h"
#include "find_string.h"
#include "trigram.h"

#include <QMainWindow>
#include <QMetaType>
#include <QThread>
#include <QTime>
#include <QMutex>
#include <QTreeWidgetItem>
#include <QVector>
#include <QFileSystemWatcher>

#include <memory>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
Q_OBJECT

public:
explicit MainWindow(QWidget *parent = nullptr);
~MainWindow();
signals:

public slots:
void add_path(std::pair<QString, QVector<QString>>);
void file_change();
void index_end();
void search_end();
void select_directory();

private:
QString cur_dir;
int cnt = 0;
bool index_now;
std::unique_ptr<QThread> index_thread;
std::unique_ptr<QThread> search_thread;
std::unique_ptr<Ui::MainWindow> ui;

QTime search_time;
QTime index_time;

QMap<QString, std::set<tgram>> paths_to_tgram;
QMutex mtx;

void start_search();
void start_index();

void stop_search();
void stop_index();
};

#endif // MAINWINDOW_H
Loading

0 comments on commit 8b12862

Please sign in to comment.