Pith - whittle
whittle/src/ui/SchemeDialogs.cpp [5.6 kb]
Modified: 20:17:02 158 026 (24 Aug 026)
5 Days Ago
#include "core/ConfigStore.h"
#include "ui/SchemeDialogs.h"
#include <QAbstractButton>
#include <QDialogButtonBox>
#include <QFrame>
#include <QHBoxLayout>
#include <QIcon>
#include <QLabel>
#include <QLineEdit>
#include <QListWidget>
#include <QMessageBox>
#include <QPushButton>
#include <QVBoxLayout>

namespace whittle {
namespace {

constexpr char kHeadStyle[] = "color: #999999; font-size: 8pt;";
constexpr char kRuleStyle[] = "color: #cccccc; background-color: #cccccc;";

constexpr char kSheet[] =
    "QDialog { background: #F4F4F4; }"
    "QPushButton { border: 1px solid #c1c1c1; border-radius: 4px;"
    " padding: 0 12px; min-height: 24px; max-height: 24px;"
    " background: #F9F9F9; color: #000000; }"
    "QPushButton:hover { background: #F1F1F1; }"
    "QPushButton:pressed { background: #F4F4F4; }"
    "QLineEdit { border: 1px solid #c1c1c1; border-radius: 4px;"
    " padding: 6px; background: #FAFAFA; color: #222222; }"
    "QListWidget { border: 1px solid #c1c1c1; border-radius: 4px;"
    " background: #FAFAFA; color: #222222; outline: none; }"
    "QListWidget::item { padding: 3px 6px; border: none; }"
    "QListWidget::item:selected { padding: 3px 6px; border: none;"
    " background: #E5E5E5; color: #222222; }";

constexpr int kHeadGap   = 4;
constexpr int kBlockGap  = 8;
constexpr int kActionGap = 6;

QWidget* sectionHeader(const QString& title) {
    auto* w = new QWidget;
    auto* h = new QHBoxLayout(w);
    h->setContentsMargins(0, 0, 0, 0);
    h->setSpacing(8);

    auto* label = new QLabel(title);
    label->setStyleSheet(QLatin1String(kHeadStyle));
    label->setSizePolicy(QSizePolicy::Maximum, QSizePolicy::Fixed);
    h->addWidget(label);

    auto* hr = new QFrame;
    hr->setFrameShape(QFrame::HLine);
    hr->setFrameShadow(QFrame::Plain);
    hr->setStyleSheet(QLatin1String(kRuleStyle));
    hr->setFixedHeight(1);
    hr->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
    h->addWidget(hr, 1);
    return w;
}

QMessageBox::StandardButton askYesNo(QWidget* parent, const QString& title,
                                     const QString& text) {
    QMessageBox box(QMessageBox::Question, title, text,
                    QMessageBox::Yes | QMessageBox::No, parent);
    box.setDefaultButton(QMessageBox::No);
    for (QAbstractButton* b : box.buttons()) b->setIcon(QIcon());
    box.exec();
    return box.standardButton(box.clickedButton());
}

}

SaveSchemeDialog::SaveSchemeDialog(const QStringList& existing, bool allowSave,
                                   QWidget* parent)
    : QDialog(parent), m_existing(existing), m_allowSave(allowSave) {
    setWindowTitle(tr("Schemes"));
    setModal(true);
    resize(333, 280);
    setStyleSheet(QLatin1String(kSheet));

    auto* v = new QVBoxLayout(this);
    v->setContentsMargins(16, 14, 16, 14);
    v->setSpacing(0);

    m_edit = new QLineEdit;
    m_edit->setEnabled(allowSave);
    m_edit->setPlaceholderText(allowSave ? tr("Moniker")
                                         : tr("Nothing to save!"));
    v->addWidget(m_edit);
    v->addSpacing(kBlockGap);

    m_list = new QListWidget;
    m_list->addItems(existing);
    v->addWidget(m_list, 1);
    v->addSpacing(kActionGap);

    m_del = new QPushButton(tr("Delete"));
    m_del->setEnabled(false);

    auto* buttons = new QDialogButtonBox(
        QDialogButtonBox::Save | QDialogButtonBox::Cancel);
    for (QAbstractButton* b : buttons->buttons()) b->setIcon(QIcon());
    m_ok = buttons->button(QDialogButtonBox::Save);
    m_ok->setEnabled(false);

    int btnW = 0;
    for (QAbstractButton* b : buttons->buttons()) {
        btnW = qMax(btnW, b->sizeHint().width());
        if (auto* p = qobject_cast<QPushButton*>(b)) p->setAutoDefault(false);
    }
    m_del->setMinimumWidth(btnW);

    auto* buttonRow = new QHBoxLayout;
    buttonRow->setContentsMargins(0, 0, 0, 0);
    buttonRow->addWidget(m_del);
    buttonRow->addStretch();
    buttonRow->addWidget(buttons);
    v->addLayout(buttonRow);

    connect(m_edit, &QLineEdit::textChanged, this, &SaveSchemeDialog::validate);
    connect(m_list, &QListWidget::itemClicked, this, [this](QListWidgetItem* i) {
        if (m_allowSave && i) m_edit->setText(i->text());
    });
    connect(m_list, &QListWidget::currentRowChanged,
            this, [this](int row) { m_del->setEnabled(row >= 0); });
    connect(m_del, &QPushButton::clicked, this, &SaveSchemeDialog::onDelete);
    connect(buttons, &QDialogButtonBox::accepted, this, &SaveSchemeDialog::tryAccept);
    connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
}

void SaveSchemeDialog::validate() {
    m_ok->setEnabled(m_allowSave && !m_edit->text().trimmed().isEmpty());
}

void SaveSchemeDialog::onDelete() {
    auto* item = m_list->currentItem();
    if (!item) return;
    const QString name = item->text();

    const auto btn = askYesNo(this, tr("Delete"), tr("Delete \"%1\"?").arg(name));
    if (btn != QMessageBox::Yes) return;

    if (!ConfigStore::deleteScheme(name)) {
        QMessageBox::warning(this, tr("Delete"),
            tr("Could not delete \"%1\".").arg(name));
        return;
    }

    delete m_list->takeItem(m_list->row(item));
    m_existing.removeAll(name);
    m_listChanged = true;
    m_del->setEnabled(m_list->currentRow() >= 0);
}

void SaveSchemeDialog::tryAccept() {
    const QString name = schemeName();
    if (name.isEmpty()) return;
    if (m_existing.contains(name)) {
        const auto btn = askYesNo(this, tr("Over-Write?"),
            tr("\"%1\" already exists.").arg(name));
        if (btn != QMessageBox::Yes) return;
    }
    accept();
}

QString SaveSchemeDialog::schemeName() const {
    return m_edit->text().trimmed();
}

}
Updates
Stave - Android 158.026
Kerf - Android 157.026
Kiln - Android 157.026
Wedge - Android 156.026
Whittle - Linux 155.026

Menu
Calendar
Project Tin (024/029)
Miter
RSS Feed
User Avatar
@vgmlr
=SUM(parts)
0.00185
260,501 (+915)