aboutsummaryrefslogtreecommitdiff
path: root/mingui
diff options
context:
space:
mode:
authorGravatar Chris Xiong <chirs241097@gmail.com> 2022-09-18 11:08:01 -0400
committerGravatar Chris Xiong <chirs241097@gmail.com> 2022-09-18 11:08:01 -0400
commit4b8d314f575d9e893d8dda7431194f8b470fc888 (patch)
tree4d42ebc06d2522c9141c42ff91be214e521e5fcb /mingui
parent0570b0f172631ba8f3c6180d2c850635c3cd6037 (diff)
downloaddeduper-4b8d314f575d9e893d8dda7431194f8b470fc888.tar.xz
First step to adopt mingui as part of the project -- break it!
Diffstat (limited to 'mingui')
-rw-r--r--mingui/CMakeLists.txt25
-rw-r--r--mingui/README.md7
-rw-r--r--mingui/imageitem.cpp136
-rw-r--r--mingui/imageitem.hpp42
-rw-r--r--mingui/main.cpp161
-rw-r--r--mingui/mingui.cpp369
-rw-r--r--mingui/mingui.hpp63
7 files changed, 0 insertions, 803 deletions
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/README.md b/mingui/README.md
deleted file mode 100644
index dff674f..0000000
--- a/mingui/README.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# Minimal GUI for Deduper
-
-Very minimalistic, but working, prototype GUI for deduper.
-
-For testing purposes only. Not part of the main deduper project (yet).
-
-Beware extremely ugly code.
diff --git a/mingui/imageitem.cpp b/mingui/imageitem.cpp
deleted file mode 100644
index 6fee930..0000000
--- a/mingui/imageitem.cpp
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "imageitem.hpp"
-
-#include <algorithm>
-
-#include <QDebug>
-#include <QFileInfo>
-#include <QPixmap>
-#include <QListView>
-#include <QFontMetrics>
-#include <QPainter>
-#include <QLocale>
-
-ImageItem::ImageItem(QString fn, QString dispn, QKeySequence hotkey, double pxratio)
-{
- this->setText(dispn);
- this->setData(fn, ImageItemRoles::path_role);
- this->setData(QFileInfo(fn).size(), ImageItemRoles::file_size_role);
- this->setCheckable(true);
- QPixmap pm(fn);
- pm.setDevicePixelRatio(pxratio);
- this->setData(pm.size(), ImageItemRoles::dimension_role);
- this->setData(hotkey, ImageItemRoles::hotkey_role);
- this->setData(pm, Qt::ItemDataRole::DecorationRole);
-}
-
-void ImageItemDelegate::paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- QRect imr = option.rect;
- imr.adjust(MARGIN + BORDER, MARGIN + BORDER, -MARGIN - BORDER, -MARGIN - BORDER);
- QFont bfnt(option.font);
- bfnt.setBold(true);
- QFontMetrics bfm(bfnt);
- imr.adjust(0, 0, 0, -2 * HKPADD - bfm.height() - LINESP);
-
- QRect selr = option.rect.adjusted(MARGIN, MARGIN, -MARGIN, -MARGIN);
- QStyleOptionViewItem so(option);
- so.rect = selr;
- if (index.data(Qt::ItemDataRole::CheckStateRole).value<Qt::CheckState>() == Qt::CheckState::Checked)
- so.state |= QStyle::StateFlag::State_Selected;
- so.state |= QStyle::StateFlag::State_Active;
- option.widget->style()->drawPrimitive(QStyle::PrimitiveElement::PE_PanelItemViewItem, &so, painter, option.widget);
-
-
- QPixmap pm = index.data(Qt::ItemDataRole::DecorationRole).value<QPixmap>();
- QSize imd = pm.size().scaled(imr.size(), Qt::AspectRatioMode::KeepAspectRatio);
- painter->setRenderHint(QPainter::RenderHint::SmoothPixmapTransform);
- painter->drawPixmap(QRect(imr.topLeft(), imd), pm);
- QPoint dtopright = QRect(imr.topLeft(),imd).bottomLeft();
-
- QPoint hko = dtopright + QPoint(HKPADD, HKPADD + LINESP);
- QKeySequence ks = index.data(ImageItem::ImageItemRoles::hotkey_role).value<QKeySequence>();
- QString kss = ks.toString();
- QRect r = bfm.boundingRect(kss);
- r.moveTopLeft(hko);
- QRect hkbg = r.adjusted(-HKPADD, -HKPADD, HKPADD, HKPADD);
- if (hkbg.width() < hkbg.height())
- {
- int shift = (hkbg.height() - hkbg.width()) / 2;
- r.adjust(shift, 0, shift, 0);
- hkbg.setWidth(hkbg.height());
- }
- painter->setPen(QPen(QBrush(), 0));
- painter->setBrush(option.widget->palette().color(QPalette::ColorGroup::Normal, QPalette::ColorRole::Light));
- painter->drawRoundedRect(hkbg.adjusted(HKSHDS, HKSHDS, HKSHDS, HKSHDS), 4, 4);
- painter->setBrush(option.widget->palette().color(QPalette::ColorGroup::Normal, QPalette::ColorRole::WindowText));
- painter->drawRoundedRect(hkbg, 4, 4);
- painter->setPen(option.widget->palette().color(QPalette::ColorGroup::Normal, QPalette::ColorRole::Window));
- painter->setBrush(QBrush());
- painter->setFont(bfnt);
- painter->drawText(r, kss);
-
- QPoint ftopright = hkbg.topRight() + QPoint(LINESP + HKSHDS, 0);
- QSize dim = index.data(ImageItem::ImageItemRoles::dimension_role).value<QSize>();
- qint64 fsz = index.data(ImageItem::ImageItemRoles::file_size_role).value<qint64>();
- QString infos = QString("%1 x %2, %3")
- .arg(dim.width()).arg(dim.height())
- .arg(QLocale::system().formattedDataSize(fsz, 3));
- QString fns = index.data(Qt::ItemDataRole::DisplayRole).toString();
- QTextOption topt;
- topt.setWrapMode(QTextOption::WrapMode::NoWrap);
- r = option.fontMetrics.boundingRect(infos);
- r.moveTopLeft(ftopright + QPoint(0, (hkbg.height() - r.height()) / 2));
- painter->setFont(option.font);
- painter->setPen(option.widget->palette().color(QPalette::ColorGroup::Normal, QPalette::ColorRole::Text));
- painter->drawText(r, infos, topt);
- topt.setAlignment(Qt::AlignmentFlag::AlignRight);
- r.setLeft(r.right());
- r.setRight(imr.right());
- QString efns = option.fontMetrics.elidedText(fns, Qt::TextElideMode::ElideMiddle, r.width());
- painter->drawText(r, efns, topt);
-}
-
-QSize ImageItemDelegate::sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const
-{
- const QListView *lw = qobject_cast<const QListView*>(option.widget);
- QSize vpsz = lw->maximumViewportSize();
- vpsz.setWidth(vpsz.width() - vw);
- vpsz.setHeight(vpsz.height() - hh);
- QPixmap pm = index.data(Qt::ItemDataRole::DecorationRole).value<QPixmap>();
- QSize onscsz = pm.size() / pm.devicePixelRatioF();
- int imh = onscsz.height();
- if (onscsz.width() > vpsz.width() - 2 * MARGIN - 2 * BORDER)
- imh = (vpsz.width() - 2 * MARGIN - 2 * BORDER) / (double)onscsz.width() * onscsz.height();
-
- QFont fnt(option.font);
- fnt.setBold(true);
- QFontMetrics fm(fnt);
- int extra_height = 2 * MARGIN + 2 * BORDER + LINESP + fm.height() + 2 * HKPADD + HKSHDS;
- int min_height = 64;
- int max_height = imh;
-
- QSize dim = index.data(ImageItem::ImageItemRoles::dimension_role).value<QSize>();
- qint64 fsz = index.data(ImageItem::ImageItemRoles::file_size_role).value<qint64>();
- QString infos = QString("%1 x %2, %3")
- .arg(dim.width()).arg(dim.height())
- .arg(QLocale::system().formattedDataSize(fsz, 3));
- int textw = option.fontMetrics.boundingRect(infos).width() + fm.height() + 2 * HKPADD + 48;
-
- QSize ret(vpsz);
- if (textw > vpsz.width()) ret.setWidth(textw);
- ret.setHeight(vpsz.height() / index.model()->rowCount() - lw->spacing());
- ret.setHeight(std::max(min_height + extra_height, ret.height()));
- ret.setHeight(std::min(max_height + extra_height, ret.height()));
- return ret;
-}
-
-void ImageItemDelegate::resize(const QModelIndex &index)
-{
- Q_EMIT sizeHintChanged(index);
-}
-
-void ImageItemDelegate::setScrollbarMargins(int vw, int hh)
-{
- this->vw = vw;
- this->hh = hh;
-}
diff --git a/mingui/imageitem.hpp b/mingui/imageitem.hpp
deleted file mode 100644
index 43fb0c8..0000000
--- a/mingui/imageitem.hpp
+++ /dev/null
@@ -1,42 +0,0 @@
-#ifndef IMAGEITEM_HPP
-#define IMAGEITEM_HPP
-
-#include <QStandardItem>
-#include <QAbstractItemDelegate>
-#include <QStyleOptionViewItem>
-#include <QModelIndex>
-
-class ImageItem : public QStandardItem
-{
-public:
- enum ImageItemRoles
- {
- path_role = Qt::ItemDataRole::UserRole + 0x1000,
- dimension_role,
- file_size_role,
- hotkey_role
- };
- ImageItem(QString fn, QString dispn, QKeySequence hotkey, double pxratio = 1.0);
-};
-
-class ImageItemDelegate : public QAbstractItemDelegate
-{
- Q_OBJECT
-private:
- const static int MARGIN = 3;
- const static int BORDER = 3;
- const static int HKPADD = 4;
- const static int LINESP = 4;
- const static int HKSHDS = 2;
- int vw = -1;
- int hh = -1;
-public:
- void paint(QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index) const;
- QSize sizeHint(const QStyleOptionViewItem &option, const QModelIndex &index) const;
- void resize(const QModelIndex &index);
- void setScrollbarMargins(int vw, int hh);
-Q_SIGNALS:
- void sizeHintChanged(const QModelIndex &index);
-};
-
-#endif
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/mingui/mingui.cpp b/mingui/mingui.cpp
deleted file mode 100644
index 494745a..0000000
--- a/mingui/mingui.cpp
+++ /dev/null
@@ -1,369 +0,0 @@
-#include "mingui.hpp"
-#include "imageitem.hpp"
-
-#include <cstdio>
-#include <cwchar>
-#include <type_traits>
-
-#include <QDebug>
-#include <QCloseEvent>
-#include <QMouseEvent>
-#include <QScrollBar>
-#include <QAction>
-#include <QSplitter>
-#include <QString>
-#include <QScrollArea>
-#include <QListView>
-#include <QStandardItemModel>
-#include <QLabel>
-#include <QHBoxLayout>
-#include <QVBoxLayout>
-#include <QStatusBar>
-#include <QPixmap>
-#include <QFile>
-#include <QScreen>
-#include <QFont>
-#include <QFontDatabase>
-#include <QFileDialog>
-#include <QKeySequence>
-#include <QTextEdit>
-#include <QMessageBox>
-#include <QInputDialog>
-#include <QDesktopServices>
-
-using std::size_t;
-const std::vector<int> keys = {
- Qt::Key::Key_A, Qt::Key::Key_S, Qt::Key::Key_D, Qt::Key::Key_F,
- Qt::Key::Key_G, Qt::Key::Key_H, Qt::Key::Key_J, Qt::Key::Key_K,
- Qt::Key::Key_L, Qt::Key::Key_Semicolon, Qt::Key::Key_T, Qt::Key::Key_Y,
- Qt::Key::Key_U, Qt::Key::Key_I, Qt::Key::Key_O, Qt::Key::Key_P
-};
-
-QString fsstr_to_qstring(const fs::path::string_type &s)
-{
-#ifdef _WIN32 //the degenerate platform
- return QString::fromStdWString(s);
-#else
- return QString::fromStdString(s);
-#endif
-}
-
-MinGuiWidget::MinGuiWidget()
-{
- this->setFont(QFontDatabase::systemFont(QFontDatabase::SystemFont::FixedFont));
- this->setWindowTitle("deduper minigui");
- this->setLayout(new QVBoxLayout(this));
- sb = this->statusBar();
- sb->addPermanentWidget(permamsg = new QLabel());
- QLabel *opm = new QLabel();
- opm->setText("placeholder status bar text");
- sb->addWidget(opm);
- l = new QSplitter(Qt::Orientation::Horizontal, this);
- l->setContentsMargins(6, 6, 6, 6);
- l->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
- this->setCentralWidget(l);
- infopanel = new QTextEdit(this);
- infopanel->setReadOnly(true);
- infopanel->setMinimumWidth(80);
- lw = new QListView(this);
- im = new QStandardItemModel(this);
- lw->setModel(im);
- lw->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
- lw->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAlwaysOn);
- id = new ImageItemDelegate();
- id->setScrollbarMargins(lw->verticalScrollBar()->width(),
- lw->horizontalScrollBar()->height());
- lw->setItemDelegate(id);
- lw->setSelectionMode(QAbstractItemView::SelectionMode::NoSelection);
- lw->setResizeMode(QListView::ResizeMode::Adjust);
- lw->setVerticalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
- lw->setHorizontalScrollBarPolicy(Qt::ScrollBarPolicy::ScrollBarAsNeeded);
- lw->setHorizontalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
- lw->setVerticalScrollMode(QAbstractItemView::ScrollMode::ScrollPerPixel);
- lw->setMinimumWidth(240);
-
- for (size_t i = 0; i < keys.size(); ++i)
- {
- auto &k = keys[i];
- QAction *a = new QAction();
- a->setShortcut(QKeySequence(k));
- QObject::connect(a, &QAction::triggered, [this, i](){this->mark_toggle(i);});
- selhk.push_back(a);
- QAction *sa = new QAction();
- sa->setShortcut(QKeySequence(Qt::Modifier::SHIFT | k));
- QObject::connect(sa, &QAction::triggered, [this, i](){this->mark_all_but(i);});
- selhk.push_back(a);
- }
- this->addActions(selhk);
- QAction *mall = new QAction();
- mall->setShortcut(QKeySequence(Qt::Key::Key_X));
- QObject::connect(mall, &QAction::triggered, [this]{this->mark_all();});
- this->addAction(mall);
- QAction *mnone = new QAction();
- mnone->setShortcut(QKeySequence(Qt::Key::Key_C));
- QObject::connect(mnone, &QAction::triggered, [this]{this->mark_none();});
- this->addAction(mnone);
- QAction *nxt = new QAction();
- nxt->setShortcut(QKeySequence(Qt::Key::Key_M));
- QObject::connect(nxt, &QAction::triggered, [this]{Q_EMIT this->next();});
- this->addAction(nxt);
- QAction *prv = new QAction();
- prv->setShortcut(QKeySequence(Qt::Key::Key_Z));
- QObject::connect(prv, &QAction::triggered, [this]{Q_EMIT this->prev();});
- this->addAction(prv);
- QAction *load = new QAction();
- load->setShortcut(QKeySequence(Qt::Key::Key_N));
- QObject::connect(load, &QAction::triggered, [this]{Q_EMIT this->load_list();});
- this->addAction(load);
- QAction *skip = new QAction();
- skip->setShortcut(QKeySequence(Qt::Key::Key_B));
- QObject::connect(skip, &QAction::triggered, [this]{
- bool ok = false;
- int g = QInputDialog::getInt(this, "Skip to group",
- QString("Group # (1-%1)").arg(ngroups),
- curgroup + 1,
- 1, ngroups, 1, &ok);
- if (ok) Q_EMIT switch_group((size_t) g - 1);
- });
- this->addAction(skip);
- QAction *save = new QAction();
- save->setShortcut(QKeySequence(Qt::Modifier::SHIFT | Qt::Key::Key_Return));
- QObject::connect(save, &QAction::triggered, [this]{Q_EMIT this->save_list();});
- this->addAction(save);
-
- QObject::connect(lw, &QListView::clicked, [this](const QModelIndex &i) {
- auto cs = i.data(Qt::ItemDataRole::CheckStateRole).value<Qt::CheckState>();
- if (cs == Qt::CheckState::Checked)
- cs = Qt::CheckState::Unchecked;
- else cs = Qt::CheckState::Checked;
- this->im->setData(i, cs, Qt::ItemDataRole::CheckStateRole);
- });
- QObject::connect(lw, &QListView::doubleClicked, [this](const QModelIndex &i) {
- auto cs = i.data(Qt::ItemDataRole::CheckStateRole).value<Qt::CheckState>();
- if (cs == Qt::CheckState::Checked)
- cs = Qt::CheckState::Unchecked;
- else cs = Qt::CheckState::Checked;
- this->im->setData(i, cs, Qt::ItemDataRole::CheckStateRole);
- QDesktopServices::openUrl(QUrl::fromLocalFile(i.data(ImageItem::ImageItemRoles::path_role).toString()));
- });
- QObject::connect(im, &QStandardItemModel::itemChanged, [this](QStandardItem *i) {
- ImageItem *itm = static_cast<ImageItem*>(i);
- QModelIndex idx = itm->index();
- bool checked = itm->data(Qt::ItemDataRole::CheckStateRole) == Qt::CheckState::Checked;
- if (checked != marks[idx.row()])
- this->mark_toggle(idx.row());
- });
- l->addWidget(lw);
- l->addWidget(infopanel);
- l->setStretchFactor(0, 3);
- l->setStretchFactor(1, 1);
- l->setCollapsible(0, false);
- marked.clear();
- infopanel->setText("bleh");
- infopanel->setSizePolicy(QSizePolicy::Policy::Minimum, QSizePolicy::Policy::Minimum);
- nohotkeywarn = false;
-}
-
-void MinGuiWidget::show_images(const std::vector<fs::path> &fns)
-{
- current_set = fns;
- marks.clear();
- im->clear();
- int max_height = (this->screen()->size().height() / fns.size() * 0.8 - 24) * this->screen()->devicePixelRatio();
- int max_width = this->screen()->size().width() * 0.8 * this->screen()->devicePixelRatio();
- if (max_height < 64) max_height = 64;
- if (max_width < 64) max_width = 64;
- fs::path::string_type common_pfx = common_prefix(fns);
- size_t idx = 0;
- if (fns.size() > keys.size() && !nohotkeywarn)
- nohotkeywarn = QMessageBox::StandardButton::Ignore ==
- QMessageBox::warning(this,
- "Too many duplicates",
- "Too many duplicates found. Some couldn't be assigned a hotkey. Ignore = do not show again.",
- QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Ignore,
- QMessageBox::StandardButton::Ok);
- for (auto &f : fns)
- {
- marks.push_back(marked.find(f) != marked.end());
- im->appendRow(new ImageItem(fsstr_to_qstring(f.native()), fsstr_to_qstring(f.native().substr(common_pfx.length())), keys[idx], lw->devicePixelRatioF()));
- ++idx;
- }
- mark_view_update(false);
-}
-
-void MinGuiWidget::update_distances(const std::map<std::pair<size_t, size_t>, double> &d)
-{
- QString r;
- for (auto &p : d)
- {
- QString ka = "(No hotkey)";
- QString kb = "(No hotkey)";
- if (p.first.first < keys.size())
- ka = QKeySequence(keys[p.first.first]).toString();
- if (p.first.second < keys.size())
- kb = QKeySequence(keys[p.first.second]).toString();
- r += QString("%1 <-> %2: %3\n").arg(ka).arg(kb).arg(QString::number(p.second));
- }
- infopanel->setText(r);
-}
-
-void MinGuiWidget::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()
-{
- QString fn = QFileDialog::getSaveFileName(this, "Save list", QString(), "*.txt");
- FILE *f = fopen(fn.toStdString().c_str(), "w");
- if (!f) return;
- for (auto &x : this->marked)
-#ifdef _WIN32
- fwprintf(f, L"%ls\n", x.c_str());
-#else
- fprintf(f, "%s\n", x.c_str());
-#endif
- fclose(f);
-}
-
-void MinGuiWidget::load_list()
-{
- QString fn = QFileDialog::getOpenFileName(this, "Load list", QString(), "*.txt");
- FILE *f = fopen(fn.toStdString().c_str(), "r");
- if (!f) return;
- this->marked.clear();
- while(!feof(f))
- {
-#ifdef _WIN32
- wchar_t buf[32768];
- fgetws(buf, 32768, f);
- std::wstring ws(buf);
- if (ws.back() == L'\n') ws.pop_back();
- if (!ws.empty()) this->marked.insert(ws);
-#else
- char buf[32768];
- fgets(buf, 32768, f);
- std::string s(buf);
- if (s.back() == '\n') s.pop_back();
- if (!s.empty()) this->marked.insert(s);
-#endif
- }
- fclose(f);
- for (size_t i = 0; i < marks.size(); ++i)
- marks[i] = marked.find(current_set[i]) != marked.end();
- mark_view_update();
-}
-
-void MinGuiWidget::mark_toggle(size_t x)
-{
- if (x < marks.size())
- {
- marks[x] = !marks[x];
- if (marks[x])
- marked.insert(current_set[x]);
- else
- if (marked.find(current_set[x]) != marked.end())
- marked.erase(marked.find(current_set[x]));
- }
- mark_view_update();
-}
-
-void MinGuiWidget::mark_all_but(size_t x)
-{
- if (x < marks.size())
- {
- for (size_t i = 0; i < marks.size(); ++i)
- {
- marks[i] = (i != x);
- if (marks[i])
- marked.insert(current_set[i]);
- else
- if (marked.find(current_set[i]) != marked.end())
- marked.erase(marked.find(current_set[i]));
- }
- }
- mark_view_update();
-}
-
-void MinGuiWidget::mark_all()
-{
- for (size_t i = 0; i < marks.size(); ++i)
- {
- marks[i] = true;
- marked.insert(current_set[i]);
- }
- mark_view_update();
-}
-
-void MinGuiWidget::mark_none()
-{
- for (size_t i = 0; i < marks.size(); ++i)
- {
- marks[i] = false;
- if (marked.find(current_set[i]) != marked.end())
- marked.erase(marked.find(current_set[i]));
- }
- mark_view_update();
-}
-
-void MinGuiWidget::mark_view_update(bool update_msg)
-{
- size_t m = 0;
- for (size_t i = 0; i < current_set.size(); ++i)
- {
- if (marks[i])
- {
- im->item(i)->setCheckState(Qt::CheckState::Checked);
- ++m;
- }
- else
- {
- im->item(i)->setCheckState(Qt::CheckState::Unchecked);
- }
- }
- if (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)
-{
- using fsstr = fs::path::string_type;
- fsstr ret;
- fsstr shortest = *std::min_element(fns.begin(), fns.end(), [](auto &a, auto &b){return a.native().length() < b.native().length();});
- for (size_t i = 0; i < shortest.length(); ++i)
- {
- fs::path::value_type c = shortest[i];
- bool t = true;
- for (auto &s : fns) if (s.c_str()[i] != c) {t = false; break;}
- if (!t) break;
- ret.push_back(c);
- }
- if (!ret.empty())
- {
- auto p = ret.rfind(std::filesystem::path::preferred_separator);
- if (p != fsstr::npos)
- return fs::path(ret.substr(0, p + 1));
- }
- return ret;
-}
-
-void MinGuiWidget::resizeEvent(QResizeEvent *e)
-{
- QWidget::resizeEvent(e);
- if (!id || !im) return;
- for (int i = 0; i < im->rowCount(); ++i)
- id->resize(im->indexFromItem(im->item(i)));
-}
-
-void MinGuiWidget::closeEvent(QCloseEvent *e)
-{
- if (QMessageBox::StandardButton::Yes ==
- QMessageBox::question(this, "Confirmation", "Really quit?",
- QMessageBox::StandardButton::Yes | QMessageBox::StandardButton::No,
- QMessageBox::StandardButton::No))
- e->accept();
- else
- e->ignore();
-}
diff --git a/mingui/mingui.hpp b/mingui/mingui.hpp
deleted file mode 100644
index f80561b..0000000
--- a/mingui/mingui.hpp
+++ /dev/null
@@ -1,63 +0,0 @@
-#ifndef MINGUI_HPP
-#define MINGUI_HPP
-
-#include <filesystem>
-#include <vector>
-#include <string>
-#include <unordered_set>
-
-#include <QMainWindow>
-#include <QList>
-
-class QHBoxLayout;
-class QLabel;
-class QStatusBar;
-class QScrollArea;
-class QTextEdit;
-class QListView;
-class QSplitter;
-class QStandardItemModel;
-class ImageItemDelegate;
-
-namespace fs = std::filesystem;
-
-class MinGuiWidget : public QMainWindow
-{
- Q_OBJECT
-private:
- QSplitter *l;
- QTextEdit *infopanel;
- QLabel *permamsg;
- QStatusBar *sb;
- QListView *lw;
- QList<QAction*> selhk;
- QStandardItemModel *im = nullptr;
- ImageItemDelegate *id = nullptr;
- std::size_t ngroups, curgroup;
- bool nohotkeywarn;
- void mark_toggle(std::size_t x);
- void mark_all_but(std::size_t x);
- void mark_all();
- void mark_none();
- void mark_view_update(bool update_msg = true);
- fs::path::string_type common_prefix(const std::vector<fs::path> &fns);
- std::vector<bool> marks;
- std::unordered_set<fs::path> marked;
- std::vector<fs::path> current_set;
-protected:
- void resizeEvent(QResizeEvent *e) override;
- void closeEvent(QCloseEvent *e) override;
-public:
- MinGuiWidget();
- 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);
- void save_list();
- void load_list();
-Q_SIGNALS:
- void next();
- void prev();
- void switch_group(std::size_t group);
-};
-
-#endif