Make a branch to make krunner Good Enough For Aaron™.
[kdebase/uwolfer.git] / workspace / klipper / configdialog.cpp
blobdbf5036c400cee25e3b72738300bb3aa5c986213
1 // -*- Mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 8; -*-
2 /* This file is part of the KDE project
3 Copyright (C) 2000 by Carsten Pfeiffer <pfeiffer@kde.org>
5 This program is free software; you can redistribute it and/or
6 modify it under the terms of the GNU General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; see the file COPYING. If not, write to
17 the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
18 Boston, MA 02110-1301, USA.
20 #include <QLabel>
21 #include <QLayout>
22 #include <QPushButton>
23 #include <QHeaderView>
25 #include <klocale.h>
26 #include <kmenu.h>
27 #include <kshortcutsdialog.h>
28 #include <KServiceTypeTrader>
30 #include "configdialog.h"
32 ConfigDialog::ConfigDialog(QWidget *parent, KConfigSkeleton *skeleton, const ActionList *list, KActionCollection *collection,
33 bool isApplet)
34 : KConfigDialog(parent, "preferences", skeleton)
36 if ( isApplet )
37 setHelp( QString(), "klipper" );
39 QWidget *w = 0; // the parent for the widgets
41 w = new QWidget(this);
42 generalWidget = new GeneralWidget(w);
43 addPage(generalWidget, i18nc("General Config", "General"), "klipper", i18n("General Config"));
45 w = new QWidget(this);
46 actionWidget = new ActionWidget(list, w);
47 addPage(actionWidget, i18nc("Actions Config", "Actions"), "system-run", i18n("Actions Config"));
49 w = new QWidget(this);
50 shortcutsWidget = new KShortcutsEditor( collection, w, KShortcutsEditor::GlobalAction );
51 addPage(shortcutsWidget, i18nc("Shortcuts Config", "Shortcuts"), "configure-shortcuts", i18n("Shortcuts Config"));
55 ConfigDialog::~ConfigDialog()
59 void ConfigDialog::commitShortcuts()
61 //keysWidget->commitChanges();
64 GeneralWidget::GeneralWidget( QWidget *parent )
65 : QWidget( parent )
67 QVBoxLayout *mainLayout = new QVBoxLayout(this);
69 cbMousePos = new QCheckBox(i18n("&Popup menu at mouse-cursor position"), this);
70 mainLayout->addWidget(cbMousePos);
72 cbSaveContents = new QCheckBox(i18n("Save clipboard contents on e&xit"), this);
73 mainLayout->addWidget(cbSaveContents);
75 cbStripWhitespace = new QCheckBox(i18n("Remove whitespace when executing actions"), this);
76 cbStripWhitespace->setWhatsThis(i18n("Sometimes, the selected text has some whitespace at the end, which, "
77 "if loaded as URL in a browser would cause an error. Enabling this option "
78 "removes any whitespace at the beginning or end of the selected string (the original "
79 "clipboard contents will not be modified)."));
80 mainLayout->addWidget(cbStripWhitespace);
82 cbReplayAIH = new QCheckBox(i18n("&Replay actions on an item selected from history"), this);
83 mainLayout->addWidget(cbReplayAIH);
85 cbNoNull = new QCheckBox(i18n("Pre&vent empty clipboard"), this);
86 cbNoNull->setWhatsThis(i18n("Selecting this option has the effect, that the "
87 "clipboard can never be emptied. E.g. when an application "
88 "exits, the clipboard would usually be emptied."));
89 mainLayout->addWidget(cbNoNull);
91 cbIgnoreSelection = new QCheckBox(i18n("&Ignore selection"), this);
92 cbIgnoreSelection->setWhatsThis(i18n("This option prevents the selection being recorded "
93 "in the clipboard history. Only explicit clipboard "
94 "changes are recorded."));
95 mainLayout->addWidget(cbIgnoreSelection);
97 QGroupBox *group = new QGroupBox(i18n("Clipboard/Selection Behavior"), this);
98 group->setWhatsThis(i18n("<qt>There are two different clipboard buffers available:<br /><br />"
99 "<b>Clipboard</b> is filled by selecting something "
100 "and pressing Ctrl+C, or by clicking \"Copy\" in a toolbar or "
101 "menubar.<br /><br />"
102 "<b>Selection</b> is available immediately after "
103 "selecting some text. The only way to access the selection "
104 "is to press the middle mouse button.<br /><br />"
105 "You can configure the relationship between Clipboard and Selection."
106 "</qt>"));
107 mainLayout->addWidget(group);
109 QVBoxLayout *groupLayout = new QVBoxLayout(group);
111 cbSynchronize = new QRadioButton(i18n("Sy&nchronize contents of the clipboard and the selection"), group);
112 cbSynchronize->setWhatsThis(i18n("Selecting this option synchronizes these two buffers."));
113 connect(cbSynchronize, SIGNAL(clicked()), SLOT(slotClipConfigChanged()));
114 groupLayout->addWidget(cbSynchronize);
116 cbSeparate = new QRadioButton(i18n("Separate clipboard and selection"), group);
117 cbSeparate->setWhatsThis(i18n("Using this option will only set the selection when highlighting "
118 "something and the clipboard when choosing e.g. \"Copy\" "
119 "in a menubar."));
120 connect(cbSeparate, SIGNAL(clicked()), SLOT(slotClipConfigChanged()));
121 groupLayout->addWidget(cbSeparate);
123 cbSeparate->setChecked(!cbSynchronize->isChecked());
125 popupTimeout = new KIntNumInput(this);
126 popupTimeout->setLabel(i18n("Tim&eout for action popups:"));
127 popupTimeout->setRange(0, 200);
128 popupTimeout->setSuffix(i18n(" sec"));
129 popupTimeout->setToolTip(i18n("A value of 0 disables the timeout"));
130 mainLayout->addWidget(popupTimeout);
132 maxItems = new KIntNumInput(this);
133 maxItems->setLabel(i18n("C&lipboard history size:"));
134 maxItems->setRange(2, 2048);
135 connect(maxItems, SIGNAL(valueChanged(int)), SLOT(historySizeChanged(int)));
136 mainLayout->addWidget(maxItems);
138 slotClipConfigChanged();
141 GeneralWidget::~GeneralWidget()
145 void GeneralWidget::historySizeChanged( int value )
147 // Note there is no %n in this string, because value is not supposed
148 // to be put into the suffix of the spinbox.
149 maxItems->setSuffix( i18np( " entry", " entries", value ) );
152 void GeneralWidget::slotClipConfigChanged()
154 cbIgnoreSelection->setEnabled( !cbSynchronize->isChecked() );
157 // it does not make sense to port / enable this since KRegExpEditor is in a very bad shape. just keep this
158 // code here because it will probably help at a later point to port it when KRegExpEditor is again usable.
159 // 2007-10-20, uwolfer
160 #if 0
161 void ListView::rename( Q3ListViewItem* item, int c )
163 bool gui = false;
164 if ( item->childCount() != 0 && c == 0) {
165 // This is the regular expression
166 if ( _configWidget->useGUIRegExpEditor() ) {
167 gui = true;
171 if ( gui ) {
172 if ( ! _regExpEditor )
173 _regExpEditor = KServiceTypeTrader::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString(), this );
174 KRegExpEditorInterface *iface = qobject_cast<KRegExpEditorInterface *>(_regExpEditor);
176 Q_ASSERT( iface );
177 iface->setRegExp( item->text( 0 ) );
179 bool ok = _regExpEditor->exec();
180 if ( ok )
181 item->setText( 0, iface->regExp() );
183 else
184 K3ListView::rename( item ,c );
186 #endif
188 ActionWidget::ActionWidget( const ActionList *list, QWidget *parent )
189 : QWidget(parent),
190 advancedWidget(0)
192 Q_ASSERT(list);
194 QVBoxLayout *mainLayout = new QVBoxLayout(this);
196 QLabel *lblAction = new QLabel(i18n("Action &list (right click to add/remove commands):"), this);
197 mainLayout->addWidget(lblAction);
199 treeWidget = new QTreeWidget(this);
200 lblAction->setBuddy(treeWidget);
202 treeWidget->setHeaderLabels(QStringList() << i18n("Regular Expression") << i18n("Description"));
203 treeWidget->header()->resizeSection(0, 250);
204 treeWidget->setSelectionBehavior(QTreeWidget::SelectRows);
205 treeWidget->setSelectionMode(QTreeWidget::SingleSelection);
207 mainLayout->addWidget(treeWidget);
209 ClipAction *action = 0L;
210 ClipCommand *command = 0L;
212 ActionListIterator it( *list );
214 while (it.hasNext()) {
215 action = it.next();
217 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget,
218 QStringList() << action->regExp() << action->description());
219 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
221 QListIterator<ClipCommand*> it2( action->commands() );
222 while (it2.hasNext()) {
223 command = it2.next();
225 QTreeWidgetItem *child = new QTreeWidgetItem(item, QStringList()
226 << command->command << command->description);
227 child->setIcon(0, KIcon(command->pixmap.isEmpty() ? "system-run" : command->pixmap));
228 child->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
232 connect(treeWidget, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
234 treeWidget->setContextMenuPolicy(Qt::CustomContextMenu);
235 connect(treeWidget, SIGNAL(customContextMenuRequested(const QPoint &)), SLOT(slotContextMenu(const QPoint &)));
237 connect(treeWidget, SIGNAL(itemChanged(QTreeWidgetItem*, int)), SLOT(slotItemChanged(QTreeWidgetItem*, int)));
239 treeWidget->setSortingEnabled(false);
241 cbUseGUIRegExpEditor = new QCheckBox(i18n("&Use graphical editor for editing regular expressions" ), this);
242 if ( /*KServiceTypeTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty()*/ true) // see notice above about KRegExpEditor
244 cbUseGUIRegExpEditor->hide();
245 cbUseGUIRegExpEditor->setChecked( false );
247 mainLayout->addWidget(cbUseGUIRegExpEditor);
249 QHBoxLayout *buttonLayout = new QHBoxLayout;
250 mainLayout->addLayout(buttonLayout);
252 QPushButton *button = new QPushButton(KIcon("list-add"), i18n("&Add Action"), this);
253 connect(button, SIGNAL(clicked()), SLOT(slotAddAction()));
254 buttonLayout->addWidget(button);
256 delActionButton = new QPushButton(KIcon("list-remove"), i18n("&Delete Action"), this);
257 connect(delActionButton, SIGNAL(clicked()), SLOT(slotDeleteAction()));
258 buttonLayout->addWidget(delActionButton);
260 buttonLayout->addStretch();
262 QPushButton *advanced = new QPushButton(KIcon("configure"), i18n("Advanced..."), this);
263 connect(advanced, SIGNAL(clicked()), SLOT(slotAdvanced()));
264 buttonLayout->addWidget(advanced);
266 QLabel *label = new QLabel(i18n("Click on a highlighted item's column to change it. \"%s\" in a "
267 "command will be replaced with the clipboard contents."), this);
268 label->setWordWrap(true);
269 mainLayout->addWidget(label);
271 QLabel *labelRegexp = new QLabel(i18n("For more information about regular expressions, you could have a look at the "
272 "<a href=\"http://en.wikipedia.org/wiki/Regular_expression\">Wikipedia entry "
273 "about this topic</a>."), this);
274 labelRegexp->setOpenExternalLinks(true);
275 labelRegexp->setWordWrap(true);
276 mainLayout->addWidget(labelRegexp);
278 delActionButton->setEnabled(treeWidget->currentItem());
281 ActionWidget::~ActionWidget()
285 void ActionWidget::selectionChanged()
287 delActionButton->setEnabled(!treeWidget->selectedItems().isEmpty());
290 void ActionWidget::slotContextMenu(const QPoint& pos)
292 QTreeWidgetItem *item = treeWidget->itemAt(pos);
293 if ( !item )
294 return;
296 KMenu *menu = new KMenu;
297 QAction *addCmd = menu->addAction(KIcon("list-add"), i18n("Add Command"));
298 QAction *rmCmd = menu->addAction(KIcon("list-remove"), i18n("Remove Command"));
299 if ( !item->parent() ) {// no "command" item
300 rmCmd->setEnabled( false );
301 item->setExpanded ( true );
304 QAction *executed = menu->exec(mapToGlobal(pos));
305 if ( executed == addCmd ) {
306 QTreeWidgetItem *child = new QTreeWidgetItem(item->parent() ? item->parent() : item, QStringList()
307 << i18n("Double-click here to set the command to be executed")
308 << i18n("<new command>"));
309 child->setIcon(0, KIcon("system-run"));
310 child->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
312 else if ( executed == rmCmd )
313 delete item;
315 delete menu;
318 void ActionWidget::slotItemChanged(QTreeWidgetItem *item, int column)
320 if (!item->parent() || column != 0)
321 return;
322 ClipCommand command( item->text(0), item->text(1) );
324 treeWidget->blockSignals(true); // don't lead in infinite recursion...
325 item->setIcon(0, KIcon(command.pixmap.isEmpty() ? "system-run" : command.pixmap));
326 treeWidget->blockSignals(false);
329 void ActionWidget::slotAddAction()
331 QTreeWidgetItem *item = new QTreeWidgetItem(treeWidget,
332 QStringList() << i18n("Double-click here to set the regexp")
333 << i18n("<new action>"));
334 item->setFlags(Qt::ItemIsSelectable | Qt::ItemIsEditable | Qt::ItemIsEnabled);
338 void ActionWidget::slotDeleteAction()
340 QTreeWidgetItem *item = treeWidget->currentItem();
341 if ( item && item->parent() )
342 item = item->parent();
343 delete item;
347 ActionList * ActionWidget::actionList()
349 ClipAction *action = 0;
350 ActionList *list = new ActionList;
352 QTreeWidgetItemIterator it(treeWidget);
353 while (*it) {
354 if (!(*it)->parent()) {
355 if (action) {
356 list->append(action);
357 action = 0;
359 action = new ClipAction((*it)->text(0), (*it)->text(1));
360 } else {
361 if (action)
362 action->addCommand((*it)->text(0), (*it)->text(1), true);
364 it++;
366 if (action)
367 list->append(action);
369 return list;
372 void ActionWidget::slotAdvanced()
374 KDialog dlg(this);
375 dlg.setModal(true);
376 dlg.setCaption( i18n("Advanced Settings") );
377 dlg.setButtons( KDialog::Ok | KDialog::Cancel );
379 AdvancedWidget *widget = new AdvancedWidget(&dlg);
380 widget->setWMClasses( m_wmClasses );
382 dlg.setMainWidget(widget);
384 if ( dlg.exec() == KDialog::Accepted ) {
385 m_wmClasses = widget->wmClasses();
389 AdvancedWidget::AdvancedWidget( QWidget *parent )
390 : QWidget(parent)
392 QVBoxLayout *mainLayout = new QVBoxLayout(this);
394 editListBox = new KEditListBox(i18n("D&isable Actions for Windows of Type WM_CLASS"), this);
396 editListBox->setButtons(KEditListBox::Add | KEditListBox::Remove);
397 editListBox->setCheckAtEntering(true);
399 editListBox->setWhatsThis(i18n("<qt>This lets you specify windows in which Klipper should "
400 "not invoke \"actions\". Use<br /><br />"
401 "<center><b>xprop | grep WM_CLASS</b></center><br />"
402 "in a terminal to find out the WM_CLASS of a window. "
403 "Next, click on the window you want to examine. The "
404 "first string it outputs after the equal sign is the one "
405 "you need to enter here.</qt>"));
406 mainLayout->addWidget(editListBox);
408 editListBox->setFocus();
411 AdvancedWidget::~AdvancedWidget()
415 void AdvancedWidget::setWMClasses( const QStringList& items )
417 editListBox->setItems(items);
420 #include "configdialog.moc"