QortalOS Brooklyn for Raspberry Pi 4
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

368 lines
12 KiB

/*
SPDX-FileCopyrightText: 2009 Dmitry Suzdalev <[email protected]>
SPDX-License-Identifier: GPL-2.0-or-later
*/
#include "editactiondialog.h"
#include "klipper_debug.h"
#include <QComboBox>
#include <QDialogButtonBox>
#include <QIcon>
#include <QItemDelegate>
#include <KWindowConfig>
#include <kwindowconfig.h>
#include "ui_editactiondialog.h"
#include "urlgrabber.h"
namespace
{
static QString output2text(ClipCommand::Output output)
{
switch (output) {
case ClipCommand::IGNORE:
return QString(i18n("Ignore"));
case ClipCommand::REPLACE:
return QString(i18n("Replace Clipboard"));
case ClipCommand::ADD:
return QString(i18n("Add to Clipboard"));
}
return QString();
}
}
/**
* Show dropdown of editing Output part of commands
*/
class ActionOutputDelegate : public QItemDelegate
{
public:
ActionOutputDelegate(QObject *parent = nullptr)
: QItemDelegate(parent)
{
}
QWidget *createEditor(QWidget *parent, const QStyleOptionViewItem & /*option*/, const QModelIndex & /*index*/) const override
{
QComboBox *editor = new QComboBox(parent);
editor->setInsertPolicy(QComboBox::NoInsert);
editor->addItem(output2text(ClipCommand::IGNORE), QVariant::fromValue<ClipCommand::Output>(ClipCommand::IGNORE));
editor->addItem(output2text(ClipCommand::REPLACE), QVariant::fromValue<ClipCommand::Output>(ClipCommand::REPLACE));
editor->addItem(output2text(ClipCommand::ADD), QVariant::fromValue<ClipCommand::Output>(ClipCommand::ADD));
return editor;
}
void setEditorData(QWidget *editor, const QModelIndex &index) const override
{
QComboBox *ed = static_cast<QComboBox *>(editor);
QVariant data(index.model()->data(index, Qt::EditRole));
ed->setCurrentIndex(static_cast<int>(data.value<ClipCommand::Output>()));
}
void setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const override
{
QComboBox *ed = static_cast<QComboBox *>(editor);
model->setData(index, ed->itemData(ed->currentIndex()));
}
void updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex & /*index*/) const override
{
editor->setGeometry(option.rect);
}
};
class ActionDetailModel : public QAbstractTableModel
{
public:
ActionDetailModel(ClipAction *action, QObject *parent = nullptr);
QVariant data(const QModelIndex &index, int role = Qt::DisplayRole) const override;
bool setData(const QModelIndex &index, const QVariant &value, int role = Qt::EditRole) override;
Qt::ItemFlags flags(const QModelIndex &index) const override;
int rowCount(const QModelIndex &parent = QModelIndex()) const override;
int columnCount(const QModelIndex &parent) const override;
QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const override;
const QList<ClipCommand> &commands() const
{
return m_commands;
}
void addCommand(const ClipCommand &command);
void removeCommand(const QModelIndex &index);
private:
enum column_t { COMMAND_COL = 0, OUTPUT_COL = 1, DESCRIPTION_COL = 2 };
QList<ClipCommand> m_commands;
QVariant displayData(ClipCommand *command, column_t column) const;
QVariant editData(ClipCommand *command, column_t column) const;
QVariant decorationData(ClipCommand *command, column_t column) const;
void setIconForCommand(ClipCommand &cmd);
};
ActionDetailModel::ActionDetailModel(ClipAction *action, QObject *parent)
: QAbstractTableModel(parent)
, m_commands(action->commands())
{
}
Qt::ItemFlags ActionDetailModel::flags(const QModelIndex & /*index*/) const
{
return Qt::ItemIsEditable | Qt::ItemIsEnabled | Qt::ItemIsSelectable;
}
void ActionDetailModel::setIconForCommand(ClipCommand &cmd)
{
// let's try to update icon of the item according to command
QString command = cmd.command;
if (command.contains(QLatin1Char(' '))) {
// get first word
command = command.section(QLatin1Char(' '), 0, 0);
}
if (QIcon::hasThemeIcon(command)) {
cmd.icon = command;
} else {
cmd.icon.clear();
}
}
bool ActionDetailModel::setData(const QModelIndex &index, const QVariant &value, int role)
{
if (role == Qt::EditRole) {
ClipCommand cmd = m_commands.at(index.row());
switch (static_cast<column_t>(index.column())) {
case COMMAND_COL:
cmd.command = value.toString();
setIconForCommand(cmd);
break;
case OUTPUT_COL:
cmd.output = value.value<ClipCommand::Output>();
break;
case DESCRIPTION_COL:
cmd.description = value.toString();
break;
}
m_commands.replace(index.row(), cmd);
Q_EMIT dataChanged(index, index);
return true;
}
return false;
}
int ActionDetailModel::columnCount(const QModelIndex & /*parent*/) const
{
return 3;
}
int ActionDetailModel::rowCount(const QModelIndex &) const
{
return m_commands.count();
}
QVariant ActionDetailModel::displayData(ClipCommand *command, ActionDetailModel::column_t column) const
{
switch (column) {
case COMMAND_COL:
return command->command;
case OUTPUT_COL:
return output2text(command->output);
case DESCRIPTION_COL:
return command->description;
}
return QVariant();
}
QVariant ActionDetailModel::decorationData(ClipCommand *command, ActionDetailModel::column_t column) const
{
switch (column) {
case COMMAND_COL:
return command->icon.isEmpty() ? QIcon::fromTheme(QStringLiteral("system-run")) : QIcon::fromTheme(command->icon);
case OUTPUT_COL:
case DESCRIPTION_COL:
break;
}
return QVariant();
}
QVariant ActionDetailModel::editData(ClipCommand *command, ActionDetailModel::column_t column) const
{
switch (column) {
case COMMAND_COL:
return command->command;
case OUTPUT_COL:
return QVariant::fromValue<ClipCommand::Output>(command->output);
case DESCRIPTION_COL:
return command->description;
}
return QVariant();
}
QVariant ActionDetailModel::headerData(int section, Qt::Orientation orientation, int role) const
{
if (orientation == Qt::Horizontal && role == Qt::DisplayRole) {
switch (static_cast<column_t>(section)) {
case COMMAND_COL:
return i18n("Command");
case OUTPUT_COL:
return i18n("Output Handling");
case DESCRIPTION_COL:
return i18n("Description");
}
}
return QAbstractTableModel::headerData(section, orientation, role);
}
QVariant ActionDetailModel::data(const QModelIndex &index, int role) const
{
const int column = index.column();
const int row = index.row();
ClipCommand cmd = m_commands.at(row);
switch (role) {
case Qt::DisplayRole:
return displayData(&cmd, static_cast<column_t>(column));
case Qt::DecorationRole:
return decorationData(&cmd, static_cast<column_t>(column));
case Qt::EditRole:
return editData(&cmd, static_cast<column_t>(column));
}
return QVariant();
}
void ActionDetailModel::addCommand(const ClipCommand &command)
{
beginInsertRows(QModelIndex(), rowCount(), rowCount());
m_commands << command;
endInsertRows();
}
void ActionDetailModel::removeCommand(const QModelIndex &index)
{
int row = index.row();
beginRemoveRows(QModelIndex(), row, row);
m_commands.removeAt(row);
endRemoveRows();
}
EditActionDialog::EditActionDialog(QWidget *parent)
: QDialog(parent)
{
setWindowTitle(i18n("Action Properties"));
QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
buttons->button(QDialogButtonBox::Ok)->setShortcut(Qt::CTRL | Qt::Key_Return);
connect(buttons, &QDialogButtonBox::accepted, this, &EditActionDialog::slotAccepted);
connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject);
QWidget *dlgWidget = new QWidget(this);
m_ui = new Ui::EditActionDialog;
m_ui->setupUi(dlgWidget);
m_ui->leRegExp->setClearButtonEnabled(true);
m_ui->leDescription->setClearButtonEnabled(true);
m_ui->pbAddCommand->setIcon(QIcon::fromTheme(QStringLiteral("list-add")));
m_ui->pbRemoveCommand->setIcon(QIcon::fromTheme(QStringLiteral("list-remove")));
// For some reason, the default row height is 30 pixel. Set it to the minimum sectionSize instead,
// which is the font height+struts.
m_ui->twCommandList->verticalHeader()->setDefaultSectionSize(m_ui->twCommandList->verticalHeader()->minimumSectionSize());
m_ui->twCommandList->horizontalHeader()->setDefaultAlignment(Qt::AlignLeft);
QVBoxLayout *layout = new QVBoxLayout(this);
layout->addWidget(dlgWidget);
layout->addWidget(buttons);
connect(m_ui->pbAddCommand, &QPushButton::clicked, this, &EditActionDialog::onAddCommand);
connect(m_ui->pbRemoveCommand, &QPushButton::clicked, this, &EditActionDialog::onRemoveCommand);
const KConfigGroup grp = KSharedConfig::openConfig()->group("EditActionDialog");
KWindowConfig::restoreWindowSize(windowHandle(), grp);
QByteArray hdrState = grp.readEntry("ColumnState", QByteArray());
if (!hdrState.isEmpty()) {
qCDebug(KLIPPER_LOG) << "Restoring column state";
m_ui->twCommandList->horizontalHeader()->restoreState(QByteArray::fromBase64(hdrState));
}
// do this after restoreState()
m_ui->twCommandList->horizontalHeader()->setHighlightSections(false);
}
EditActionDialog::~EditActionDialog()
{
delete m_ui;
}
void EditActionDialog::setAction(ClipAction *act, int commandIdxToSelect)
{
m_action = act;
m_model = new ActionDetailModel(act, this);
m_ui->twCommandList->setModel(m_model);
m_ui->twCommandList->setItemDelegateForColumn(1, new ActionOutputDelegate);
connect(m_ui->twCommandList->selectionModel(), &QItemSelectionModel::selectionChanged, this, &EditActionDialog::onSelectionChanged);
updateWidgets(commandIdxToSelect);
}
void EditActionDialog::updateWidgets(int commandIdxToSelect)
{
if (!m_action) {
qCDebug(KLIPPER_LOG) << "no action to edit was set";
return;
}
m_ui->leRegExp->setText(m_action->actionRegexPattern());
m_ui->automatic->setChecked(m_action->automatic());
m_ui->leDescription->setText(m_action->description());
if (commandIdxToSelect != -1) {
m_ui->twCommandList->setCurrentIndex(m_model->index(commandIdxToSelect, 0));
}
// update Remove button
onSelectionChanged();
}
void EditActionDialog::saveAction()
{
if (!m_action) {
qCDebug(KLIPPER_LOG) << "no action to edit was set";
return;
}
m_action->setActionRegexPattern(m_ui->leRegExp->text());
m_action->setDescription(m_ui->leDescription->text());
m_action->setAutomatic(m_ui->automatic->isChecked());
m_action->clearCommands();
foreach (const ClipCommand &cmd, m_model->commands()) {
m_action->addCommand(cmd);
}
}
void EditActionDialog::slotAccepted()
{
saveAction();
qCDebug(KLIPPER_LOG) << "Saving dialogue state";
KConfigGroup grp = KSharedConfig::openConfig()->group("EditActionDialog");
KWindowConfig::saveWindowSize(windowHandle(), grp);
grp.writeEntry("ColumnState", m_ui->twCommandList->horizontalHeader()->saveState().toBase64());
accept();
}
void EditActionDialog::onAddCommand()
{
m_model->addCommand(ClipCommand(i18n("new command"), i18n("Command Description"), true, QLatin1String("")));
m_ui->twCommandList->edit(m_model->index(m_model->rowCount() - 1, 0));
}
void EditActionDialog::onRemoveCommand()
{
m_model->removeCommand(m_ui->twCommandList->selectionModel()->currentIndex());
}
void EditActionDialog::onSelectionChanged()
{
m_ui->pbRemoveCommand->setEnabled(m_ui->twCommandList->selectionModel() && m_ui->twCommandList->selectionModel()->hasSelection());
}