File indexing completed on 2024-04-28 05:35:27
0001 /* 0002 SPDX-FileCopyrightText: 2022 Jonathan Marten <jjm@keelhaul.me.uk> 0003 SPDX-License-Identifier: GPL-2.0-or-later 0004 */ 0005 0006 #include "editcommanddialog.h" 0007 0008 #include <qbuttongroup.h> 0009 #include <qdialogbuttonbox.h> 0010 #include <qformlayout.h> 0011 #include <qlabel.h> 0012 #include <qlineedit.h> 0013 #include <qpushbutton.h> 0014 #include <qradiobutton.h> 0015 #include <qwindow.h> 0016 0017 #include <kiconbutton.h> 0018 #include <klocalizedstring.h> 0019 #include <kstandardguiitem.h> 0020 #include <kwindowconfig.h> 0021 0022 #include "klipper_debug.h" 0023 0024 #include "configdialog.h" 0025 0026 static void setIconForCommand(ClipCommand *cmd) 0027 { 0028 // let's try to update icon of the item according to command 0029 QString command = cmd->command; 0030 if (command.contains(QLatin1Char(' '))) { 0031 // get first word 0032 command = command.section(QLatin1Char(' '), 0, 0); 0033 } 0034 0035 if (QIcon::hasThemeIcon(command)) { 0036 cmd->icon = command; 0037 } else { 0038 cmd->icon.clear(); 0039 } 0040 } 0041 0042 EditCommandDialog::EditCommandDialog(const ClipCommand &command, QWidget *parent) 0043 : QDialog(parent) 0044 , m_command(command) 0045 { 0046 setWindowTitle(i18n("Command Properties")); 0047 QDialogButtonBox *buttons = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this); 0048 m_okButton = buttons->button(QDialogButtonBox::Ok); 0049 m_okButton->setShortcut(Qt::CTRL | Qt::Key_Return); 0050 connect(buttons, &QDialogButtonBox::accepted, this, &EditCommandDialog::slotAccepted); 0051 connect(buttons, &QDialogButtonBox::rejected, this, &QDialog::reject); 0052 0053 QWidget *optionsWidget = new QWidget(this); 0054 QFormLayout *optionsLayout = new QFormLayout(optionsWidget); 0055 0056 // Command 0057 m_commandEdit = new QLineEdit(optionsWidget); 0058 m_commandEdit->setClearButtonEnabled(true); 0059 m_commandEdit->setPlaceholderText(i18n("Enter the command and arguments")); 0060 connect(m_commandEdit, &QLineEdit::textEdited, this, &EditCommandDialog::slotUpdateButtons); 0061 0062 optionsLayout->addRow(i18n("Command:"), m_commandEdit); 0063 0064 // See ClipCommandProcess::ClipCommandProcess() for the 0065 // substitutions made. "%0" is the complete text matched by the 0066 // regular expression, which may only match a part of the clipboard 0067 // contents, so it is mentioned here. However, "%u"/"%U" and "%f"/"%F" 0068 // are exactly equivalent to "%s", the complete clipboard contents, 0069 // so there is no point mentioning them here. 0070 QLabel *hint = ConfigDialog::createHintLabel(xi18nc("@info", 0071 "A <placeholder>%s</placeholder> in the command will be replaced by the \ 0072 complete clipboard contents. <placeholder>%0</placeholder> through \ 0073 <placeholder>%9</placeholder> will be replaced by the corresponding \ 0074 captured texts from the match pattern."), 0075 optionsWidget); 0076 optionsLayout->addRow(QString(), hint); 0077 0078 // Description 0079 m_descriptionEdit = new QLineEdit(optionsWidget); 0080 m_descriptionEdit->setClearButtonEnabled(true); 0081 m_descriptionEdit->setPlaceholderText(i18n("Enter a description for the command")); 0082 connect(m_descriptionEdit, &QLineEdit::textEdited, this, &EditCommandDialog::slotUpdateButtons); 0083 optionsLayout->addRow(i18n("Description:"), m_descriptionEdit); 0084 optionsLayout->addRow(QString(), new QLabel(this)); 0085 0086 // Radio button group: Output handling 0087 QButtonGroup *buttonGroup = new QButtonGroup(this); 0088 0089 m_ignoreRadio = new QRadioButton(i18n("Ignore"), this); 0090 buttonGroup->addButton(m_ignoreRadio); 0091 optionsLayout->addRow(i18n("Output from command:"), m_ignoreRadio); 0092 0093 m_replaceRadio = new QRadioButton(i18n("Replace current clipboard"), this); 0094 buttonGroup->addButton(m_replaceRadio); 0095 optionsLayout->addRow(QString(), m_replaceRadio); 0096 0097 m_appendRadio = new QRadioButton(i18n("Append to clipboard"), this); 0098 buttonGroup->addButton(m_appendRadio); 0099 optionsLayout->addRow(QString(), m_appendRadio); 0100 0101 optionsLayout->addRow(QString(), ConfigDialog::createHintLabel(i18n("What happens to the standard output of the command executed."), this)); 0102 0103 optionsLayout->addRow(QString(), new QLabel(this)); 0104 0105 // Icon and reset button 0106 QHBoxLayout *hb = new QHBoxLayout; 0107 hb->setContentsMargins(0, 0, 0, 0); 0108 0109 m_iconButton = new KIconButton(this); 0110 m_iconButton->setIconSize(KIconLoader::SizeSmall); 0111 hb->addWidget(m_iconButton); 0112 0113 QPushButton *resetButton = new QPushButton(this); 0114 KStandardGuiItem::assign(resetButton, KStandardGuiItem::Reset); 0115 resetButton->setToolTip(i18n("Reset the icon to the default for the command")); 0116 connect(resetButton, &QAbstractButton::clicked, this, [this]() { 0117 setIconForCommand(&m_command); 0118 m_iconButton->setIcon(m_command.icon); 0119 }); 0120 hb->addWidget(resetButton); 0121 optionsLayout->addRow(i18n("Icon:"), hb); 0122 0123 // Main dialogue layout 0124 QVBoxLayout *mainLayout = new QVBoxLayout(this); 0125 mainLayout->addWidget(optionsWidget); 0126 mainLayout->addStretch(); 0127 mainLayout->addWidget(buttons); 0128 0129 (void)winId(); 0130 windowHandle()->resize(560, 440); // default, if there is no saved size 0131 const KConfigGroup grp = KSharedConfig::openConfig()->group(QLatin1String(metaObject()->className())); 0132 KWindowConfig::restoreWindowSize(windowHandle(), grp); 0133 resize(windowHandle()->size()); 0134 0135 updateWidgets(); 0136 } 0137 0138 void EditCommandDialog::slotUpdateButtons() 0139 { 0140 m_okButton->setEnabled(!m_commandEdit->text().isEmpty() && !m_descriptionEdit->text().isEmpty()); 0141 } 0142 0143 void EditCommandDialog::updateWidgets() 0144 { 0145 m_commandEdit->setText(m_command.command); 0146 m_descriptionEdit->setText(m_command.description); 0147 0148 m_replaceRadio->setChecked(m_command.output == ClipCommand::REPLACE); 0149 m_appendRadio->setChecked(m_command.output == ClipCommand::ADD); 0150 m_ignoreRadio->setChecked(m_command.output == ClipCommand::IGNORE); 0151 0152 m_iconButton->setIcon(m_command.icon); 0153 0154 slotUpdateButtons(); 0155 } 0156 0157 void EditCommandDialog::saveCommand() 0158 { 0159 m_command.command = m_commandEdit->text(); 0160 m_command.description = m_descriptionEdit->text(); 0161 0162 if (m_replaceRadio->isChecked()) { 0163 m_command.output = ClipCommand::REPLACE; 0164 } else if (m_appendRadio->isChecked()) { 0165 m_command.output = ClipCommand::ADD; 0166 } else { 0167 m_command.output = ClipCommand::IGNORE; 0168 } 0169 0170 const QString icon = m_iconButton->icon(); 0171 if (!icon.isEmpty()) { 0172 m_command.icon = icon; 0173 } else { 0174 setIconForCommand(&m_command); 0175 } 0176 } 0177 0178 void EditCommandDialog::slotAccepted() 0179 { 0180 saveCommand(); 0181 0182 KConfigGroup grp = KSharedConfig::openConfig()->group(QLatin1String(metaObject()->className())); 0183 KWindowConfig::saveWindowSize(windowHandle(), grp); 0184 accept(); 0185 }