#include "ui/SettingsDialog.h"
#include <QAbstractButton>
#include <QColor>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QFormLayout>
#include <QFrame>
#include <QIcon>
#include <QLabel>
#include <QPalette>
#include <QVBoxLayout>
#include <QWidget>
#include <QFontMetrics>
#include <QStringList>
namespace {
constexpr char kVersion[] = "130.026.1";
constexpr char kSourceText[] = "vgmlr.com/mlwrk";
constexpr char kSourceUrl[] = "https://vgmlr.com/mlwrk";
constexpr char kLinkStyle[] = "text-decoration:none; color:#000000;";
constexpr int kMetricSize = 1 << 0;
constexpr int kMetricTime = 1 << 1;
constexpr int kRowSpacing = 6;
constexpr int kMetaSpacing = 10;
constexpr int kButtonSpacing = 6;
constexpr int kLabelGap = 14;
constexpr int kRulePad = 6;
constexpr int kDialogWidth = 300;
const QColor kRule {0xE3, 0xE3, 0xE8};
QLabel* rowLabel(const QString& text, int w) {
auto* l = new QLabel(text);
l->setMinimumWidth(w);
return l;
}
QWidget* hline() {
auto* f = new QFrame;
f->setFrameShape(QFrame::HLine);
f->setFrameShadow(QFrame::Plain);
f->setLineWidth(1);
f->setFixedHeight(1);
QPalette p = f->palette();
p.setColor(QPalette::WindowText, kRule);
f->setPalette(p);
auto* w = new QWidget;
auto* v = new QVBoxLayout(w);
v->setContentsMargins(0, kRulePad, 0, kRulePad);
v->setSpacing(0);
v->addWidget(f);
w->setFixedHeight(1 + kRulePad * 2);
return w;
}
}
namespace whittle {
SettingsDialog::SettingsDialog(const FilterSettings& initial, QWidget* parent)
: QDialog(parent) {
setWindowTitle(tr("Settings"));
setModal(true);
setFixedWidth(kDialogWidth);
m_metric = new QComboBox;
m_metric->addItem(tr("File Size"), kMetricSize);
m_metric->addItem(tr("Last Modified"), kMetricTime);
m_metric->addItem(tr("Size + mTime"), kMetricSize | kMetricTime);
const int mi = m_metric->findData((initial.compareSize ? kMetricSize : 0) |
(initial.compareTime ? kMetricTime : 0));
m_metric->setCurrentIndex(mi >= 0 ? mi : m_metric->count() - 1);
m_tol = new QComboBox;
m_tol->addItem(tr("1ns (ext4)"), qint64(FilterSettings::Tol_ext4));
m_tol->addItem(tr("100ns (NTFS)"), qint64(FilterSettings::Tol_ntfs));
m_tol->addItem(tr("1s (ext2/3)"), qint64(FilterSettings::Tol_ext23));
m_tol->addItem(tr("2s (VFAT)"), qint64(FilterSettings::Tol_vfat));
const int ti = m_tol->findData(qint64(initial.toleranceNs));
m_tol->setCurrentIndex(ti >= 0 ? ti : 0);
m_display = new QComboBox;
m_display->addItem(tr("Only Diff"), int(FilterSettings::Display::OnlyDiff));
m_display->addItem(tr("Show All"), int(FilterSettings::Display::All));
m_display->setCurrentIndex(
initial.display == FilterSettings::Display::All ? 1 : 0);
m_recursive = new QComboBox;
m_recursive->addItem(tr("Recursive"), true);
m_recursive->addItem(tr("Non-Recursive"), false);
m_recursive->setCurrentIndex(initial.recursive ? 0 : 1);
m_loadLast = new QComboBox;
m_loadLast->addItem(tr("Load Last"), true);
m_loadLast->addItem(tr("Reset"), false);
m_loadLast->setCurrentIndex(initial.loadLastScheme ? 0 : 1);
QComboBox* const fields[] = {m_metric, m_tol, m_display,
m_recursive, m_loadLast};
int rowH = 0;
for (QComboBox* c : fields) {
c->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
rowH = qMax(rowH, c->sizeHint().height());
}
for (QComboBox* c : fields) c->setMinimumHeight(rowH);
auto* version = new QLabel(QLatin1String(kVersion));
version->setTextInteractionFlags(Qt::TextSelectableByMouse);
auto* source = new QLabel(
QStringLiteral("<a href=\"%1\" style=\"%2\">%3</a>")
.arg(QLatin1String(kSourceUrl), QLatin1String(kLinkStyle),
QLatin1String(kSourceText)));
source->setTextFormat(Qt::RichText);
source->setOpenExternalLinks(true);
source->setTextInteractionFlags(Qt::TextBrowserInteraction);
const QStringList labelText{tr("Metric"), tr("Tolerance"), tr("Display"),
tr("Directories"), tr("Scheme"),
tr("Build"), tr("Source")};
const QFontMetrics fm(font());
int labelW = 0;
for (const QString& t : labelText) labelW = qMax(labelW, fm.horizontalAdvance(t));
auto* form = new QFormLayout;
form->setVerticalSpacing(kRowSpacing);
form->setHorizontalSpacing(kLabelGap);
form->setContentsMargins(0, 0, 0, 0);
form->setLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
form->setRowWrapPolicy(QFormLayout::DontWrapRows);
form->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
form->addRow(rowLabel(tr("Metric"), labelW), m_metric);
form->addRow(rowLabel(tr("Tolerance"), labelW), m_tol);
form->addRow(rowLabel(tr("Display"), labelW), m_display);
form->addRow(hline());
form->addRow(rowLabel(tr("Directories"), labelW), m_recursive);
form->addRow(rowLabel(tr("Scheme"), labelW), m_loadLast);
form->addRow(hline());
auto* meta = new QFormLayout;
meta->setVerticalSpacing(kMetaSpacing);
meta->setHorizontalSpacing(kLabelGap);
meta->setContentsMargins(0, 0, 0, 0);
meta->setLabelAlignment(Qt::AlignLeft | Qt::AlignVCenter);
meta->setRowWrapPolicy(QFormLayout::DontWrapRows);
meta->setFieldGrowthPolicy(QFormLayout::ExpandingFieldsGrow);
meta->addRow(rowLabel(tr("Build"), labelW), version);
meta->addRow(rowLabel(tr("Source"), labelW), source);
auto* buttons = new QDialogButtonBox(
QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
for (QAbstractButton* b : buttons->buttons()) b->setIcon(QIcon());
connect(buttons, &QDialogButtonBox::accepted, this, &QDialog::accept);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
auto* v = new QVBoxLayout(this);
v->setContentsMargins(20, 14, 20, 14);
v->setSpacing(kButtonSpacing);
v->addLayout(form);
v->addLayout(meta);
v->addSpacing(6);
v->addWidget(buttons);
}
FilterSettings SettingsDialog::settings() const {
FilterSettings f;
const int metric = m_metric->currentData().toInt();
f.compareSize = (metric & kMetricSize) != 0;
f.compareTime = (metric & kMetricTime) != 0;
f.toleranceNs = m_tol->currentData().toLongLong();
f.display = (m_display->currentData().toInt() == int(FilterSettings::Display::All))
? FilterSettings::Display::All
: FilterSettings::Display::OnlyDiff;
f.recursive = m_recursive->currentData().toBool();
f.loadLastScheme = m_loadLast->currentData().toBool();
return f;
}
}