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.
22 #include <QPushButton>
23 #include <QHeaderView>
27 #include <kshortcutsdialog.h>
28 #include <KServiceTypeTrader>
30 #include "configdialog.h"
32 ConfigDialog::ConfigDialog(QWidget
*parent
, KConfigSkeleton
*skeleton
, const ActionList
*list
, KActionCollection
*collection
,
34 : KConfigDialog(parent
, "preferences", skeleton
)
37 setHelp( QString(), "klipper" );
39 QWidget
*w
= 0; // the parent for the widgets
41 w
= new QWidget(this);
42 m_generalWidget
= new GeneralWidget(w
);
43 addPage(m_generalWidget
, i18nc("General Config", "General"), "klipper", i18n("General Config"));
45 w
= new QWidget(this);
46 m_actionWidget
= new ActionWidget(list
, w
);
47 addPage(m_actionWidget
, i18nc("Actions Config", "Actions"), "system-run", i18n("Actions Config"));
49 w
= new QWidget(this);
50 m_shortcutsWidget
= new KShortcutsEditor( collection
, w
, KShortcutsEditor::GlobalAction
);
51 addPage(m_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
)
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 cbIgnoreImages
= new QCheckBox(i18n("Ignore images"), this);
98 mainLayout
->addWidget(cbIgnoreImages
);
100 QGroupBox
*group
= new QGroupBox(i18n("Clipboard/Selection Behavior"), this);
101 group
->setWhatsThis(i18n("<qt>There are two different clipboard buffers available:<br /><br />"
102 "<b>Clipboard</b> is filled by selecting something "
103 "and pressing Ctrl+C, or by clicking \"Copy\" in a toolbar or "
104 "menubar.<br /><br />"
105 "<b>Selection</b> is available immediately after "
106 "selecting some text. The only way to access the selection "
107 "is to press the middle mouse button.<br /><br />"
108 "You can configure the relationship between Clipboard and Selection."
110 mainLayout
->addWidget(group
);
112 QVBoxLayout
*groupLayout
= new QVBoxLayout(group
);
114 cbSynchronize
= new QRadioButton(i18n("Sy&nchronize contents of the clipboard and the selection"), group
);
115 cbSynchronize
->setWhatsThis(i18n("Selecting this option synchronizes these two buffers."));
116 connect(cbSynchronize
, SIGNAL(clicked()), SLOT(slotClipConfigChanged()));
117 groupLayout
->addWidget(cbSynchronize
);
119 cbSeparate
= new QRadioButton(i18n("Separate clipboard and selection"), group
);
120 cbSeparate
->setWhatsThis(i18n("Using this option will only set the selection when highlighting "
121 "something and the clipboard when choosing e.g. \"Copy\" "
123 connect(cbSeparate
, SIGNAL(clicked()), SLOT(slotClipConfigChanged()));
124 groupLayout
->addWidget(cbSeparate
);
126 cbSeparate
->setChecked(!cbSynchronize
->isChecked());
128 popupTimeout
= new KIntNumInput(this);
129 popupTimeout
->setLabel(i18n("Tim&eout for action popups:"));
130 popupTimeout
->setRange(0, 200);
131 popupTimeout
->setSuffix(i18n(" sec"));
132 popupTimeout
->setToolTip(i18n("A value of 0 disables the timeout"));
133 mainLayout
->addWidget(popupTimeout
);
135 maxItems
= new KIntNumInput(this);
136 maxItems
->setLabel(i18n("C&lipboard history size:"));
137 maxItems
->setRange(2, 2048);
138 connect(maxItems
, SIGNAL(valueChanged(int)), SLOT(historySizeChanged(int)));
139 mainLayout
->addWidget(maxItems
);
141 slotClipConfigChanged();
144 GeneralWidget::~GeneralWidget()
148 void GeneralWidget::historySizeChanged( int value
)
150 // Note there is no %n in this string, because value is not supposed
151 // to be put into the suffix of the spinbox.
152 maxItems
->setSuffix( i18np( " entry", " entries", value
) );
155 void GeneralWidget::slotClipConfigChanged()
157 cbIgnoreSelection
->setEnabled( !cbSynchronize
->isChecked() );
160 // it does not make sense to port / enable this since KRegExpEditor is in a very bad shape. just keep this
161 // code here because it will probably help at a later point to port it when KRegExpEditor is again usable.
162 // 2007-10-20, uwolfer
164 void ListView::rename( Q3ListViewItem
* item
, int c
)
167 if ( item
->childCount() != 0 && c
== 0) {
168 // This is the regular expression
169 if ( _configWidget
->useGUIRegExpEditor() ) {
175 if ( ! _regExpEditor
)
176 _regExpEditor
= KServiceTypeTrader::createInstanceFromQuery
<QDialog
>( "KRegExpEditor/KRegExpEditor", QString(), this );
177 KRegExpEditorInterface
*iface
= qobject_cast
<KRegExpEditorInterface
*>(_regExpEditor
);
180 iface
->setRegExp( item
->text( 0 ) );
182 bool ok
= _regExpEditor
->exec();
184 item
->setText( 0, iface
->regExp() );
187 K3ListView::rename( item
,c
);
191 ActionWidget::ActionWidget( const ActionList
*list
, QWidget
*parent
)
197 QVBoxLayout
*mainLayout
= new QVBoxLayout(this);
199 QLabel
*lblAction
= new QLabel(i18n("Action &list (right click to add/remove commands):"), this);
200 mainLayout
->addWidget(lblAction
);
202 treeWidget
= new QTreeWidget(this);
203 lblAction
->setBuddy(treeWidget
);
205 treeWidget
->setHeaderLabels(QStringList() << i18n("Regular Expression") << i18n("Description"));
206 treeWidget
->header()->resizeSection(0, 250);
207 treeWidget
->setSelectionBehavior(QTreeWidget::SelectRows
);
208 treeWidget
->setSelectionMode(QTreeWidget::SingleSelection
);
210 mainLayout
->addWidget(treeWidget
);
212 ClipAction
*action
= 0L;
213 ClipCommand
*command
= 0L;
215 ActionListIterator
it( *list
);
217 while (it
.hasNext()) {
220 QTreeWidgetItem
*item
= new QTreeWidgetItem(treeWidget
,
221 QStringList() << action
->regExp() << action
->description());
222 item
->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsEnabled
);
224 QListIterator
<ClipCommand
*> it2( action
->commands() );
225 while (it2
.hasNext()) {
226 command
= it2
.next();
228 QTreeWidgetItem
*child
= new QTreeWidgetItem(item
, QStringList()
229 << command
->command
<< command
->description
);
230 child
->setIcon(0, KIcon(command
->pixmap
.isEmpty() ? "system-run" : command
->pixmap
));
231 child
->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsEnabled
);
235 connect(treeWidget
, SIGNAL(itemSelectionChanged()), SLOT(selectionChanged()));
237 treeWidget
->setContextMenuPolicy(Qt::CustomContextMenu
);
238 connect(treeWidget
, SIGNAL(customContextMenuRequested(const QPoint
&)), SLOT(slotContextMenu(const QPoint
&)));
240 connect(treeWidget
, SIGNAL(itemChanged(QTreeWidgetItem
*, int)), SLOT(slotItemChanged(QTreeWidgetItem
*, int)));
242 treeWidget
->setSortingEnabled(false);
244 cbUseGUIRegExpEditor
= new QCheckBox(i18n("&Use graphical editor for editing regular expressions" ), this);
245 if ( /*KServiceTypeTrader::self()->query("KRegExpEditor/KRegExpEditor").isEmpty()*/ true) // see notice above about KRegExpEditor
247 cbUseGUIRegExpEditor
->hide();
248 cbUseGUIRegExpEditor
->setChecked( false );
250 mainLayout
->addWidget(cbUseGUIRegExpEditor
);
252 QHBoxLayout
*buttonLayout
= new QHBoxLayout
;
253 mainLayout
->addLayout(buttonLayout
);
255 QPushButton
*button
= new QPushButton(KIcon("list-add"), i18n("&Add Action"), this);
256 connect(button
, SIGNAL(clicked()), SLOT(slotAddAction()));
257 buttonLayout
->addWidget(button
);
259 delActionButton
= new QPushButton(KIcon("list-remove"), i18n("&Delete Action"), this);
260 connect(delActionButton
, SIGNAL(clicked()), SLOT(slotDeleteAction()));
261 buttonLayout
->addWidget(delActionButton
);
263 buttonLayout
->addStretch();
265 QPushButton
*advanced
= new QPushButton(KIcon("configure"), i18n("Advanced"), this);
266 connect(advanced
, SIGNAL(clicked()), SLOT(slotAdvanced()));
267 buttonLayout
->addWidget(advanced
);
269 QLabel
*label
= new QLabel(i18n("Click on a highlighted item's column to change it. \"%s\" in a "
270 "command will be replaced with the clipboard contents."), this);
271 label
->setWordWrap(true);
272 mainLayout
->addWidget(label
);
274 QLabel
*labelRegexp
= new QLabel(i18n("For more information about regular expressions, you could have a look at the "
275 "<a href=\"http://en.wikipedia.org/wiki/Regular_expression\">Wikipedia entry "
276 "about this topic</a>."), this);
277 labelRegexp
->setOpenExternalLinks(true);
278 labelRegexp
->setWordWrap(true);
279 mainLayout
->addWidget(labelRegexp
);
281 delActionButton
->setEnabled(treeWidget
->currentItem());
284 ActionWidget::~ActionWidget()
288 void ActionWidget::selectionChanged()
290 delActionButton
->setEnabled(!treeWidget
->selectedItems().isEmpty());
293 void ActionWidget::slotContextMenu(const QPoint
& pos
)
295 QTreeWidgetItem
*item
= treeWidget
->itemAt(pos
);
299 KMenu
*menu
= new KMenu
;
300 QAction
*addCmd
= menu
->addAction(KIcon("list-add"), i18n("Add Command"));
301 QAction
*rmCmd
= menu
->addAction(KIcon("list-remove"), i18n("Remove Command"));
302 if ( !item
->parent() ) {// no "command" item
303 rmCmd
->setEnabled( false );
304 item
->setExpanded ( true );
307 QAction
*executed
= menu
->exec(mapToGlobal(pos
));
308 if ( executed
== addCmd
) {
309 QTreeWidgetItem
*child
= new QTreeWidgetItem(item
->parent() ? item
->parent() : item
, QStringList()
310 << i18n("Double-click here to set the command to be executed")
311 << i18n("<new command>"));
312 child
->setIcon(0, KIcon("system-run"));
313 child
->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsEnabled
);
315 else if ( executed
== rmCmd
)
321 void ActionWidget::slotItemChanged(QTreeWidgetItem
*item
, int column
)
323 if (!item
->parent() || column
!= 0)
325 ClipCommand
command( 0, item
->text(0), item
->text(1) );
327 treeWidget
->blockSignals(true); // don't lead in infinite recursion...
328 item
->setIcon(0, KIcon(command
.pixmap
.isEmpty() ? "system-run" : command
.pixmap
));
329 treeWidget
->blockSignals(false);
332 void ActionWidget::slotAddAction()
334 QTreeWidgetItem
*item
= new QTreeWidgetItem(treeWidget
,
335 QStringList() << i18n("Double-click here to set the regular expression")
336 << i18n("<new action>"));
337 item
->setFlags(Qt::ItemIsSelectable
| Qt::ItemIsEditable
| Qt::ItemIsEnabled
);
341 void ActionWidget::slotDeleteAction()
343 QTreeWidgetItem
*item
= treeWidget
->currentItem();
344 if ( item
&& item
->parent() )
345 item
= item
->parent();
350 ActionList
* ActionWidget::actionList()
352 ClipAction
*action
= 0;
353 ActionList
*list
= new ActionList
;
355 QTreeWidgetItemIterator
it(treeWidget
);
357 if (!(*it
)->parent()) {
359 list
->append(action
);
362 action
= new ClipAction((*it
)->text(0), (*it
)->text(1));
365 action
->addCommand((*it
)->text(0), (*it
)->text(1), true);
370 list
->append(action
);
375 void ActionWidget::slotAdvanced()
379 dlg
.setCaption( i18n("Advanced Settings") );
380 dlg
.setButtons( KDialog::Ok
| KDialog::Cancel
);
382 AdvancedWidget
*widget
= new AdvancedWidget(&dlg
);
383 widget
->setWMClasses( m_wmClasses
);
385 dlg
.setMainWidget(widget
);
387 if ( dlg
.exec() == KDialog::Accepted
) {
388 m_wmClasses
= widget
->wmClasses();
392 AdvancedWidget::AdvancedWidget( QWidget
*parent
)
395 QVBoxLayout
*mainLayout
= new QVBoxLayout(this);
397 editListBox
= new KEditListBox(i18n("D&isable Actions for Windows of Type WM_CLASS"), this);
399 editListBox
->setButtons(KEditListBox::Add
| KEditListBox::Remove
);
400 editListBox
->setCheckAtEntering(true);
402 editListBox
->setWhatsThis(i18n("<qt>This lets you specify windows in which Klipper should "
403 "not invoke \"actions\". Use<br /><br />"
404 "<center><b>xprop | grep WM_CLASS</b></center><br />"
405 "in a terminal to find out the WM_CLASS of a window. "
406 "Next, click on the window you want to examine. The "
407 "first string it outputs after the equal sign is the one "
408 "you need to enter here.</qt>"));
409 mainLayout
->addWidget(editListBox
);
411 editListBox
->setFocus();
414 AdvancedWidget::~AdvancedWidget()
418 void AdvancedWidget::setWMClasses( const QStringList
& items
)
420 editListBox
->setItems(items
);
423 #include "configdialog.moc"