not quite so much needs to be delayed to the init() function
[personal-kdebase.git] / workspace / klipper / configdialog.cpp
blob2f1960857d5121a132b5518bc45f4070f5719482
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 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 )
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 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."
109 "</qt>"));
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\" "
122 "in a menubar."));
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
163 #if 0
164 void ListView::rename( Q3ListViewItem* item, int c )
166 bool gui = false;
167 if ( item->childCount() != 0 && c == 0) {
168 // This is the regular expression
169 if ( _configWidget->useGUIRegExpEditor() ) {
170 gui = true;
174 if ( gui ) {
175 if ( ! _regExpEditor )
176 _regExpEditor = KServiceTypeTrader::createInstanceFromQuery<QDialog>( "KRegExpEditor/KRegExpEditor", QString(), this );
177 KRegExpEditorInterface *iface = qobject_cast<KRegExpEditorInterface *>(_regExpEditor);
179 Q_ASSERT( iface );
180 iface->setRegExp( item->text( 0 ) );
182 bool ok = _regExpEditor->exec();
183 if ( ok )
184 item->setText( 0, iface->regExp() );
186 else
187 K3ListView::rename( item ,c );
189 #endif
191 ActionWidget::ActionWidget( const ActionList *list, QWidget *parent )
192 : QWidget(parent),
193 advancedWidget(0)
195 Q_ASSERT(list);
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()) {
218 action = it.next();
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);
296 if ( !item )
297 return;
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 )
316 delete item;
318 delete menu;
321 void ActionWidget::slotItemChanged(QTreeWidgetItem *item, int column)
323 if (!item->parent() || column != 0)
324 return;
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();
346 delete item;
350 ActionList * ActionWidget::actionList()
352 ClipAction *action = 0;
353 ActionList *list = new ActionList;
355 QTreeWidgetItemIterator it(treeWidget);
356 while (*it) {
357 if (!(*it)->parent()) {
358 if (action) {
359 list->append(action);
360 action = 0;
362 action = new ClipAction((*it)->text(0), (*it)->text(1));
363 } else {
364 if (action)
365 action->addCommand((*it)->text(0), (*it)->text(1), true);
367 it++;
369 if (action)
370 list->append(action);
372 return list;
375 void ActionWidget::slotAdvanced()
377 KDialog dlg(this);
378 dlg.setModal(true);
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 )
393 : 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"