diff options
-rw-r--r-- | CMakeLists.txt | 2 | ||||
-rw-r--r-- | mingui/CMakeLists.txt | 25 | ||||
-rw-r--r-- | mingui/main.cpp | 161 | ||||
-rw-r--r-- | qdeduper/CMakeLists.txt | 18 | ||||
-rw-r--r-- | qdeduper/README.md (renamed from mingui/README.md) | 0 | ||||
-rw-r--r-- | qdeduper/imageitem.cpp (renamed from mingui/imageitem.cpp) | 0 | ||||
-rw-r--r-- | qdeduper/imageitem.hpp (renamed from mingui/imageitem.hpp) | 0 | ||||
-rw-r--r-- | qdeduper/main.cpp | 29 | ||||
-rw-r--r-- | qdeduper/mingui.cpp (renamed from mingui/mingui.cpp) | 69 | ||||
-rw-r--r-- | qdeduper/mingui.hpp (renamed from mingui/mingui.hpp) | 6 |
10 files changed, 104 insertions, 206 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index f535cf3..9c85b78 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,5 +20,5 @@ option(BUILD_SHARED_LIBS ON) add_compile_definitions(PATH_VALSIZE=${PATH_VALSIZE}) add_subdirectory(xsig) - +add_subdirectory(qdeduper) add_subdirectory(tests) diff --git a/mingui/CMakeLists.txt b/mingui/CMakeLists.txt deleted file mode 100644 index 3503f98..0000000 --- a/mingui/CMakeLists.txt +++ /dev/null @@ -1,25 +0,0 @@ -cmake_minimum_required(VERSION 3.10.0) - -project(mingui VERSION 0.0.1 LANGUAGES CXX) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) - -set(CMAKE_CXX_STANDARD 17) -set(CMAKE_CXX_STANDARD_REQUIRED ON) -set(CMAKE_CXX_EXTENSIONS OFF) - -find_package(Qt5 REQUIRED COMPONENTS Widgets) - -set(CMAKE_AUTOMOC ON) -set(CMAKE_AUTORCC ON) -set(CMAKE_AUTOUIC ON) - -add_executable(mingui - main.cpp - mingui.cpp - imageitem.cpp -) - -target_link_libraries(mingui - Qt5::Widgets -) diff --git a/mingui/main.cpp b/mingui/main.cpp deleted file mode 100644 index 8199cb9..0000000 --- a/mingui/main.cpp +++ /dev/null @@ -1,161 +0,0 @@ -#include <cstdio> -#include <algorithm> -#include <filesystem> -#include <map> -#include <string> -#include <vector> -#include <unordered_map> -#include <utility> - -#include <QWidget> -#include <QApplication> -#include "mingui.hpp" - -using std::size_t; -namespace fs = std::filesystem; - -std::unordered_map<fs::path, size_t> fnmap; -std::vector<fs::path> fns; -std::map<std::pair<size_t, size_t>, double> dist; -std::vector<size_t> par; -std::vector<std::vector<size_t>> lists; - -MinGuiWidget *w = nullptr; -size_t curlist; - -size_t get_root(size_t x) -{ - if (x != par[x]) - return par[x] = get_root(par[x]); - return x; -} - -void combine(size_t x, size_t y) -{ - x = get_root(x); - y = get_root(y); - par[x] = y; -} - -void load_result(const char* rp) -{ - FILE *f = fopen(rp, "rb"); - while (1) - { - int l; - double d; - fs::path::string_type s1, s2; - if (feof(f)) break; - fread(&l, sizeof(int), 1, f); - s1.resize(l); - fread(s1.data(), sizeof(fs::path::value_type), l, f); - fnmap.try_emplace(s1, fnmap.size() + 1); - fread(&l, sizeof(int), 1, f); - s2.resize(l); - fread(s2.data(), sizeof(fs::path::value_type), l, f); - fnmap.try_emplace(s2, fnmap.size() + 1); - fread(&d, sizeof(double), 1, f); - dist[std::make_pair(fnmap[s1], fnmap[s2])] = d; - } - fclose(f); -} - -std::vector<fs::path> build_list(const std::vector<size_t> &l) -{ - std::vector<fs::path> ret; - for (auto &x : l) - ret.push_back(fns[x]); - return ret; -} - -std::map<std::pair<size_t, size_t>, double> build_dists(const std::vector<size_t> &l) -{ - std::map<std::pair<size_t, size_t>, double> ret; - for (size_t i = 0; i < l.size(); ++i) - { - for (size_t j = i + 1; j < l.size(); ++j) - { - size_t x = l[i], y = l[j]; - if (dist.find(std::make_pair(x, y)) != dist.end()) - ret[std::make_pair(i, j)] = dist[std::make_pair(x, y)]; - else if (dist.find(std::make_pair(y, x)) != dist.end()) - ret[std::make_pair(i, j)] = dist[std::make_pair(y, x)]; - } - } - return ret; -} - -int main(int argc, char **argv) -{ - if (argc < 2) return 1; - - load_result(argv[1]); - printf("%lu known files\n", fnmap.size()); - - par.resize(fnmap.size() + 1); - fns.resize(fnmap.size() + 1); - lists.resize(fnmap.size() + 1); - for (auto &kp : fnmap) - fns[kp.second] = kp.first; - - for (size_t i = 1; i < par.size(); ++i) - par[i] = i; - for (auto &kp : dist) - { - auto p = kp.first; - combine(p.first, p.second); - } - for (size_t i = 1; i < par.size(); ++i) - lists[get_root(i)].push_back(i); - - auto listend = std::remove_if(lists.begin(), lists.end(), [](auto &a){return a.size() < 2;}); - lists.erase(listend, lists.end()); - if (lists.empty()) return 0; - for (auto &l : lists) - { - if (l.size()) - { - for (auto &x : l) - printf("%s,", fns[x].c_str()); - puts(""); - } - } - fflush(stdout); - - QApplication a(argc, argv); - - curlist = 0; - w = new MinGuiWidget(); - w->show_images(build_list(lists[curlist])); - w->update_distances(build_dists(lists[curlist])); - w->update_viewstatus(curlist, lists.size()); - w->show(); - QObject::connect(w, &MinGuiWidget::next, - []{ - if (curlist < lists.size() - 1) ++curlist; - w->show_images(build_list(lists[curlist])); - w->update_distances(build_dists(lists[curlist])); - w->update_viewstatus(curlist, lists.size()); - }); - QObject::connect(w, &MinGuiWidget::prev, - []{ - if (curlist > 0) --curlist; - w->show_images(build_list(lists[curlist])); - w->update_distances(build_dists(lists[curlist])); - w->update_viewstatus(curlist, lists.size()); - }); - QObject::connect(w, &MinGuiWidget::switch_group, - [](size_t g){ - if (g < lists.size()) - { - curlist = g; - w->show_images(build_list(lists[curlist])); - w->update_distances(build_dists(lists[curlist])); - w->update_viewstatus(curlist, lists.size()); - } - }); - - a.exec(); - - return 0; -} diff --git a/qdeduper/CMakeLists.txt b/qdeduper/CMakeLists.txt new file mode 100644 index 0000000..f862c16 --- /dev/null +++ b/qdeduper/CMakeLists.txt @@ -0,0 +1,18 @@ +set(CMAKE_INCLUDE_CURRENT_DIR ON) + +find_package(Qt5 REQUIRED COMPONENTS Widgets) + +set(CMAKE_AUTOMOC ON) +set(CMAKE_AUTORCC ON) +set(CMAKE_AUTOUIC ON) + +add_executable(qdeduper + main.cpp + mingui.cpp + imageitem.cpp +) + +target_link_libraries(qdeduper + xsig + Qt5::Widgets +) diff --git a/mingui/README.md b/qdeduper/README.md index dff674f..dff674f 100644 --- a/mingui/README.md +++ b/qdeduper/README.md diff --git a/mingui/imageitem.cpp b/qdeduper/imageitem.cpp index 6fee930..6fee930 100644 --- a/mingui/imageitem.cpp +++ b/qdeduper/imageitem.cpp diff --git a/mingui/imageitem.hpp b/qdeduper/imageitem.hpp index 43fb0c8..43fb0c8 100644 --- a/mingui/imageitem.hpp +++ b/qdeduper/imageitem.hpp diff --git a/qdeduper/main.cpp b/qdeduper/main.cpp new file mode 100644 index 0000000..9b40ea4 --- /dev/null +++ b/qdeduper/main.cpp @@ -0,0 +1,29 @@ +#include <cstdio> +#include <algorithm> +#include <filesystem> +#include <map> +#include <string> +#include <vector> +#include <unordered_map> +#include <utility> + +#include <QWidget> +#include <QApplication> +#include "mingui.hpp" + +using std::size_t; +namespace fs = std::filesystem; + +DeduperMainWindow *w = nullptr; + +int main(int argc, char **argv) +{ + QApplication a(argc, argv); + + w = new DeduperMainWindow(); + w->show(); + + a.exec(); + + return 0; +} diff --git a/mingui/mingui.cpp b/qdeduper/mingui.cpp index 494745a..317076c 100644 --- a/mingui/mingui.cpp +++ b/qdeduper/mingui.cpp @@ -9,6 +9,8 @@ #include <QCloseEvent> #include <QMouseEvent> #include <QScrollBar> +#include <QMenuBar> +#include <QMenu> #include <QAction> #include <QSplitter> #include <QString> @@ -41,18 +43,18 @@ const std::vector<int> keys = { QString fsstr_to_qstring(const fs::path::string_type &s) { -#ifdef _WIN32 //the degenerate platform +#if PATH_VALSIZE == 2 //the degenerate platform return QString::fromStdWString(s); #else return QString::fromStdString(s); #endif } -MinGuiWidget::MinGuiWidget() +DeduperMainWindow::DeduperMainWindow() { this->setFont(QFontDatabase::systemFont(QFontDatabase::SystemFont::FixedFont)); - this->setWindowTitle("deduper minigui"); - this->setLayout(new QVBoxLayout(this)); + this->setWindowTitle("deduper"); + this->setup_menu(); sb = this->statusBar(); sb->addPermanentWidget(permamsg = new QLabel()); QLabel *opm = new QLabel(); @@ -164,7 +166,40 @@ MinGuiWidget::MinGuiWidget() nohotkeywarn = false; } -void MinGuiWidget::show_images(const std::vector<fs::path> &fns) +void DeduperMainWindow::setup_menu() +{ + QMenu *file = this->menuBar()->addMenu("File"); + QMenu *view = this->menuBar()->addMenu("View"); + QMenu *mark = this->menuBar()->addMenu("Marks"); + QMenu *help = this->menuBar()->addMenu("Help"); + + file->addAction("Create Database..."); + file->addAction("Load Database..."); + file->addAction("Save Database..."); + file->addSeparator(); + file->addAction("Search for Image..."); + file->addSeparator(); + file->addAction("Preferences..."); + file->addAction("Exit"); + + view->addAction("Next Group"); + view->addAction("Previous Group"); + view->addSeparator(); + QMenu *sort = view->addMenu("Sort by"); + sort->addAction("File size"); + sort->addAction("Image dimension"); + sort->addAction("File path"); + + mark->addAction("Mark All"); + mark->addAction("Mark None"); + mark->addAction("Mark All within..."); + mark->addAction("Review Marked Imagess"); + + help->addAction("View Documentation"); + help->addAction("About"); +} + +void DeduperMainWindow::show_images(const std::vector<fs::path> &fns) { current_set = fns; marks.clear(); @@ -191,7 +226,7 @@ void MinGuiWidget::show_images(const std::vector<fs::path> &fns) mark_view_update(false); } -void MinGuiWidget::update_distances(const std::map<std::pair<size_t, size_t>, double> &d) +void DeduperMainWindow::update_distances(const std::map<std::pair<size_t, size_t>, double> &d) { QString r; for (auto &p : d) @@ -207,14 +242,14 @@ void MinGuiWidget::update_distances(const std::map<std::pair<size_t, size_t>, do infopanel->setText(r); } -void MinGuiWidget::update_viewstatus(std::size_t cur, std::size_t size) +void DeduperMainWindow::update_viewstatus(std::size_t cur, std::size_t size) { permamsg->setText(QString("Viewing group %1 of %2").arg(cur + 1).arg(size)); ngroups = size; curgroup = cur; } -void MinGuiWidget::save_list() +void DeduperMainWindow::save_list() { QString fn = QFileDialog::getSaveFileName(this, "Save list", QString(), "*.txt"); FILE *f = fopen(fn.toStdString().c_str(), "w"); @@ -228,7 +263,7 @@ void MinGuiWidget::save_list() fclose(f); } -void MinGuiWidget::load_list() +void DeduperMainWindow::load_list() { QString fn = QFileDialog::getOpenFileName(this, "Load list", QString(), "*.txt"); FILE *f = fopen(fn.toStdString().c_str(), "r"); @@ -256,7 +291,7 @@ void MinGuiWidget::load_list() mark_view_update(); } -void MinGuiWidget::mark_toggle(size_t x) +void DeduperMainWindow::mark_toggle(size_t x) { if (x < marks.size()) { @@ -270,7 +305,7 @@ void MinGuiWidget::mark_toggle(size_t x) mark_view_update(); } -void MinGuiWidget::mark_all_but(size_t x) +void DeduperMainWindow::mark_all_but(size_t x) { if (x < marks.size()) { @@ -287,7 +322,7 @@ void MinGuiWidget::mark_all_but(size_t x) mark_view_update(); } -void MinGuiWidget::mark_all() +void DeduperMainWindow::mark_all() { for (size_t i = 0; i < marks.size(); ++i) { @@ -297,7 +332,7 @@ void MinGuiWidget::mark_all() mark_view_update(); } -void MinGuiWidget::mark_none() +void DeduperMainWindow::mark_none() { for (size_t i = 0; i < marks.size(); ++i) { @@ -308,7 +343,7 @@ void MinGuiWidget::mark_none() mark_view_update(); } -void MinGuiWidget::mark_view_update(bool update_msg) +void DeduperMainWindow::mark_view_update(bool update_msg) { size_t m = 0; for (size_t i = 0; i < current_set.size(); ++i) @@ -327,7 +362,7 @@ void MinGuiWidget::mark_view_update(bool update_msg) sb->showMessage(QString("%1 of %2 marked for deletion").arg(m).arg(current_set.size()), 1000); } -fs::path::string_type MinGuiWidget::common_prefix(const std::vector<fs::path> &fns) +fs::path::string_type DeduperMainWindow::common_prefix(const std::vector<fs::path> &fns) { using fsstr = fs::path::string_type; fsstr ret; @@ -349,7 +384,7 @@ fs::path::string_type MinGuiWidget::common_prefix(const std::vector<fs::path> &f return ret; } -void MinGuiWidget::resizeEvent(QResizeEvent *e) +void DeduperMainWindow::resizeEvent(QResizeEvent *e) { QWidget::resizeEvent(e); if (!id || !im) return; @@ -357,7 +392,7 @@ void MinGuiWidget::resizeEvent(QResizeEvent *e) id->resize(im->indexFromItem(im->item(i))); } -void MinGuiWidget::closeEvent(QCloseEvent *e) +void DeduperMainWindow::closeEvent(QCloseEvent *e) { if (QMessageBox::StandardButton::Yes == QMessageBox::question(this, "Confirmation", "Really quit?", diff --git a/mingui/mingui.hpp b/qdeduper/mingui.hpp index f80561b..b8d13ef 100644 --- a/mingui/mingui.hpp +++ b/qdeduper/mingui.hpp @@ -21,7 +21,7 @@ class ImageItemDelegate; namespace fs = std::filesystem; -class MinGuiWidget : public QMainWindow +class DeduperMainWindow : public QMainWindow { Q_OBJECT private: @@ -48,7 +48,9 @@ protected: void resizeEvent(QResizeEvent *e) override; void closeEvent(QCloseEvent *e) override; public: - MinGuiWidget(); + DeduperMainWindow(); + + void setup_menu(); void show_images(const std::vector<std::filesystem::path> &fns); void update_distances(const std::map<std::pair<std::size_t, std::size_t>, double> &d); void update_viewstatus(std::size_t cur, std::size_t size); |