SVN_SILENT made messages (.desktop file)
[kdeartwork.git] / kscreensaver / kxsconfig / kxsconfig.cpp
blob736c1cd421750436e4957d2729185ef0cb30c4be
1 //-----------------------------------------------------------------------------
2 //
3 // KDE xscreensaver configuration dialog
4 //
5 // Copyright (c) Martin R. Jones <mjones@kde.org> 1999
6 //
7 // This program is free software; you can redistribute it and/or
8 // modify it under the terms of the GNU General Public
9 // License as published by the Free Software Foundation;
10 // version 2 of the License.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 // General Public License for more details.
17 // You should have received a copy of the GNU General Public License
18 // along with this program; see the file COPYING. If not, write to
19 // the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20 // Boston, MA 02110-1301, USA.
22 // This file contains code copied from xscreensaver. The xscreensaver
23 // copyright notice follows.
26 * xscreensaver, Copyright (c) 1993-2002 Jamie Zawinski <jwz@jwz.org>
28 * Permission to use, copy, modify, distribute, and sell this software and its
29 * documentation for any purpose is hereby granted without fee, provided that
30 * the above copyright notice appear in all copies and that both that
31 * copyright notice and this permission notice appear in supporting
32 * documentation. No representations are made about the suitability of this
33 * software for any purpose. It is provided "as is" without express or
34 * implied warranty.
36 #include <config-kxsconfig.h>
38 #include <stdlib.h>
39 #include <qlayout.h>
40 #include <qtimer.h>
41 #include <kvbox.h>
42 #include <qlabel.h>
43 #include <qfileinfo.h>
44 #include <QVBoxLayout>
45 #include <QHBoxLayout>
46 #include <QBoxLayout>
48 #include <kdebug.h>
49 #include <kapplication.h>
50 #include <kconfig.h>
51 #include <kstandarddirs.h>
52 #include <klocale.h>
53 #include <kcmdlineargs.h>
54 #include <kshell.h>
55 #include <kmessagebox.h>
57 #include "kxsconfig.h"
58 #include "kxscontrol.h"
59 #include "kxsxml.h"
61 #include <X11/Xlib.h>
62 #include <X11/Xatom.h>
63 #include <X11/IntrinsicP.h>
64 #include <X11/ShellP.h>
66 int ignoreXError(Display *, XErrorEvent *);
68 //===========================================================================
70 const uint widgetEventMask = // X event mask
71 (uint)(
72 ExposureMask |
73 PropertyChangeMask |
74 StructureNotifyMask
77 KXSConfigDialog::KXSConfigDialog(const QString &filename, const QString &name)
78 : KDialog(0),
79 mFilename(filename), mPreviewProc(0), mKilled(false)
81 Q_UNUSED(name)
83 setButtons(Ok| Cancel);
84 setDefaultButton( Ok);
85 setModal(false);
86 int slash = filename.lastIndexOf('/');
87 if (slash >= 0)
88 mConfigFile = filename.mid(slash+1);
89 else
90 mConfigFile = filename;
92 mExeName = mConfigFile;
93 mConfigFile += "rc";
94 connect( this,SIGNAL(okClicked()),this,SLOT(slotOk()));
95 connect( this,SIGNAL(cancelClicked()),this,SLOT(slotCancel()));
98 bool KXSConfigDialog::create()
100 QWidget *main = new QWidget(this);
101 setMainWidget(main);
102 QVBoxLayout *topLayout = new QVBoxLayout(main);
103 topLayout->setSpacing(spacingHint());
104 QHBoxLayout *layout = new QHBoxLayout();
105 topLayout->addLayout(layout);
106 layout->setSpacing(spacingHint());
107 KVBox *controlLayout = new KVBox(main);
108 controlLayout->setSpacing(spacingHint());
109 layout->addWidget(controlLayout);
110 ((QBoxLayout*)controlLayout->layout())->addStrut(120);
112 KConfig config(mConfigFile);
114 QString xmlFile = "/doesntexist";
115 #ifdef XSCREENSAVER_CONFIG_DIR
116 xmlFile = XSCREENSAVER_CONFIG_DIR;
117 #endif
119 xmlFile += "/" + mExeName + ".xml";
120 if ( QFile::exists( xmlFile ) ) {
121 // We can use the xscreensaver xml config files.
122 KXSXml xmlParser(controlLayout);
123 xmlParser.parse( xmlFile );
124 mConfigItemList = xmlParser.items();
125 QWidget *spacer = new QWidget(controlLayout);
126 controlLayout->setStretchFactor(spacer, 1 );
127 QString descr = xmlParser.description();
128 if ( !descr.isEmpty() ) {
129 descr = descr.replace('\n', ' ').simplified();
130 QLabel *l = new QLabel( i18n( descr.toUtf8() ), main );
131 l->setWordWrap( 1 );
132 topLayout->addWidget( l );
134 } else {
135 // fall back to KDE's old config files.
136 int idx = 0;
137 while (true) {
138 QString group = QString("Arg%1").arg(idx);
139 if (config.hasGroup(group)) {
140 KConfigGroup grp = config.group(group);
141 QString type = grp.readEntry("Type");
142 if (type == "Range") {
143 KXSRangeControl *rc = new KXSRangeControl(controlLayout, group, config);
144 mConfigItemList.append(rc);
145 } else if (type == "DoubleRange") {
146 KXSDoubleRangeControl *rc =
147 new KXSDoubleRangeControl(controlLayout, group, config);
148 mConfigItemList.append(rc);
149 } else if (type == "Check") {
150 KXSCheckBoxControl *cc = new KXSCheckBoxControl(controlLayout, group,
151 config);
152 mConfigItemList.append(cc);
153 } else if (type == "DropList") {
154 KXSDropListControl *dl = new KXSDropListControl(controlLayout, group,
155 config);
156 mConfigItemList.append(dl);
158 } else {
159 break;
161 idx++;
163 if ( idx == 0 )
164 return false;
167 for ( int i = 0; i < mConfigItemList.size(); i++ ) {
168 KXSConfigItem *item = mConfigItemList[i];
169 item->read( config );
170 QWidget *widget = dynamic_cast<QWidget*>( item );
171 if ( widget ) {
172 connect( widget, SIGNAL(changed()), SLOT(slotChanged()) );
176 mPreviewProc = new KProcess;
177 connect(mPreviewProc, SIGNAL(finished(int,QProcess::ExitStatus)),
178 SLOT(slotPreviewProcFinished(int,QProcess::ExitStatus)));
180 mPreviewTimer = new QTimer(this);
181 mPreviewTimer->setSingleShot(true);
182 connect(mPreviewTimer, SIGNAL(timeout()), SLOT(slotNewPreview()));
184 mPreview = new QWidget(main);
185 mPreview->setFixedSize(250, 200);
187 QPalette palette;
188 palette.setColor(mPreview->backgroundRole(), Qt::black);
189 mPreview->setPalette(palette);
192 layout->addWidget(mPreview);
193 show();
195 // So that hacks can XSelectInput ButtonPressMask
196 XSelectInput(QX11Info::display(), mPreview->winId(), widgetEventMask );
198 startProcess();
199 return true;
202 //---------------------------------------------------------------------------
203 KXSConfigDialog::~KXSConfigDialog()
205 if (mPreviewProc && mPreviewProc->state() == QProcess::Running) {
206 mPreviewProc->kill();
207 mPreviewProc->waitForFinished(5000);
208 delete mPreviewProc;
212 //---------------------------------------------------------------------------
213 QString KXSConfigDialog::command()
215 QString cmd;
217 for (int i = 0; i < mConfigItemList.size(); i++)
219 if (mConfigItemList[i]) {
220 cmd += " " + mConfigItemList[i]->command();
224 return cmd;
227 //---------------------------------------------------------------------------
228 void KXSConfigDialog::startProcess()
230 mKilled = false;
231 mPreviewProc->clearProgram();
232 QString saver = QString( "%1 -window-id 0x%2" )
233 .arg( mFilename )
234 .arg( long(mPreview->winId()), 0, 16 );
235 saver += command();
236 saver = saver.trimmed();
238 kDebug() << "Command: " << saver;
240 int i = 0;
241 QString exe;
242 while ( !saver[i].isSpace() ) {
243 exe += saver[i++];
245 // work around a KStandarDirs::findExe() "feature" where it looks in
246 // $KDEDIR/bin first no matter what and sometimes finds the wrong executable
247 QFileInfo checkExe;
248 QString saverdir = QString(XSCREENSAVER_HACKS_DIR "/") + exe;
249 QString path;
250 checkExe.setFile(saverdir);
251 if (checkExe.exists() && checkExe.isExecutable() && checkExe.isFile())
253 path = saverdir;
255 if (!path.isEmpty()) {
256 (*mPreviewProc) << path;
258 (*mPreviewProc) << KShell::splitArgs(saver.mid(i));
260 mPreviewProc->start();
264 //---------------------------------------------------------------------------
265 void KXSConfigDialog::slotPreviewProcFinished(int exitCode, QProcess::ExitStatus exitStatus)
267 Q_UNUSED(exitCode)
268 Q_UNUSED(exitStatus)
270 if ( mKilled ) {
271 startProcess();
272 } else {
273 // stops us from spawning the hack really fast, but still not the best
274 QString path = KStandardDirs::findExe(mFilename, XSCREENSAVER_HACKS_DIR);
275 if ( QFile::exists(path) ) {
276 mKilled = true;
277 slotChanged();
282 //---------------------------------------------------------------------------
283 void KXSConfigDialog::slotNewPreview()
285 if (mPreviewProc->state() == QProcess::Running) {
286 mKilled = true;
287 mPreviewProc->kill(); // restarted in slotPreviewExited()
288 } else {
289 startProcess();
293 //---------------------------------------------------------------------------
294 void KXSConfigDialog::slotChanged()
296 mPreviewTimer->start(1000);
299 //---------------------------------------------------------------------------
300 void KXSConfigDialog::slotOk()
302 KConfig config(mConfigFile);
304 for (int i = 0; i < mConfigItemList.size(); i++)
306 if (mConfigItemList[i]) {
307 mConfigItemList[i]->save(config);
311 kapp->quit();
314 //---------------------------------------------------------------------------
315 void KXSConfigDialog::slotCancel()
317 kapp->quit();
321 //===========================================================================
323 static const char appName[] = "kxsconfig";
325 static const char description[] = I18N_NOOP("KDE X Screen Saver Configuration tool");
327 static const char version[] = "3.0.0";
329 static const char *defaults[] = {
330 #include "XScreenSaver_ad.h"
334 const char *progname = 0;
335 const char *progclass = "XScreenSaver";
336 XrmDatabase db;
338 int main(int argc, char *argv[])
340 KCmdLineArgs::init(argc, argv, appName, 0, ki18n("KXSConfig"), version, ki18n(description));
343 KCmdLineOptions options;
345 options.add("+screensaver", ki18n("Filename of the screen saver to configure"));
347 options.add("+[savername]", ki18n("Optional screen saver name used in messages"));
349 KCmdLineArgs::addCmdLineOptions(options);
351 KApplication app;
353 KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
354 if(args->count()==0)
355 exit(1);
357 /* We must read exactly the same resources as xscreensaver.
358 That means we must have both the same progclass *and* progname,
359 at least as far as the resource database is concerned. So,
360 put "xscreensaver" in argv[0] while initializing Xt.
362 const char *dummyargs[] = { "xscreensaver" };
363 int dummyargc = 1;
364 progname = dummyargs[0];
366 // Teach Xt to use the Display that Qt has already opened.
367 XtToolkitInitialize ();
368 XtAppContext xtApp = XtCreateApplicationContext ();
369 Display *dpy = QX11Info::display();
370 XtAppSetFallbackResources (xtApp, const_cast<char**>(defaults));
371 XtDisplayInitialize (xtApp, dpy, progname, progclass, 0, 0,
372 &dummyargc,
373 const_cast<char**>(dummyargs));
374 Widget toplevel_shell = XtAppCreateShell (progname, progclass,
375 applicationShellWidgetClass,
376 dpy, 0, 0);
377 dpy = XtDisplay (toplevel_shell);
378 db = XtDatabase (dpy);
379 XtGetApplicationNameAndClass (dpy, const_cast<char**>(&progname),
380 const_cast<char**>(&progclass));
382 QString name = args->arg(args->count() - 1);
383 KXSConfigDialog *dialog=new KXSConfigDialog(args->arg(0), name);
384 if ( dialog->create() ) {
385 dialog->show();
386 app.exec();
387 } else {
388 KMessageBox::sorry(0,
389 i18n("No configuration available for %1", name),
390 name );
393 delete dialog;
396 #include "kxsconfig.moc"