mirror of https://github.com/Qortal/Brooklyn
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
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()); |
|
}
|
|
|