You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tdeartwork/kscreensaver/kxsconfig/kxsconfig.cpp

389 lines
11 KiB

//-----------------------------------------------------------------------------
//
// KDE xscreensaver configuration dialog
//
// Copyright (c) Martin R. Jones <mjones@kde.org> 1999
//
// This program is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation;
// version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; see the file COPYING. If not, write to
// the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
// Boston, MA 02110-1301, USA.
// This file contains code copied from xscreensaver. The xscreensaver
// copyright notice follows.
/*
* xscreensaver, Copyright (c) 1993-2002 Jamie Zawinski <jwz@jwz.org>
*
* Permission to use, copy, modify, distribute, and sell this software and its
* documentation for any purpose is hereby granted without fee, provided that
* the above copyright notice appear in all copies and that both that
* copyright notice and this permission notice appear in supporting
* documentation. No representations are made about the suitability of this
* software for any purpose. It is provided "as is" without express or
* implied warranty.
*/
#include <config.h>
#include <stdlib.h>
#include <qlayout.h>
#include <qtimer.h>
#include <qvbox.h>
#include <qlabel.h>
#include <qfileinfo.h>
#include <kdebug.h>
#include <kapplication.h>
#include <kconfig.h>
#include <kdialogbase.h>
#include <kprocess.h>
#include <kstandarddirs.h>
#include <klocale.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include "kxsconfig.h"
#include "kxscontrol.h"
#include "kxsxml.h"
template class QPtrList<KXSConfigItem>;
#include <X11/Xlib.h>
#include <X11/Xatom.h>
#include <X11/IntrinsicP.h>
#include <X11/ShellP.h>
int ignoreXError(Display *, XErrorEvent *);
//===========================================================================
const uint widgetEventMask = // X event mask
(uint)(
ExposureMask |
PropertyChangeMask |
StructureNotifyMask
);
KXSConfigDialog::KXSConfigDialog(const QString &filename, const QString &name)
: KDialogBase(Plain, name, Ok| Cancel, Ok, 0, 0, false),
mFilename(filename), mPreviewProc(0), mKilled(true)
{
int slash = filename.findRev('/');
if (slash >= 0)
mConfigFile = filename.mid(slash+1);
else
mConfigFile = filename;
mExeName = mConfigFile;
mConfigFile += "rc";
}
bool KXSConfigDialog::create()
{
QVBoxLayout *topLayout = new QVBoxLayout(plainPage(), spacingHint());
QHBoxLayout *layout = new QHBoxLayout(topLayout, spacingHint());
QVBox *controlLayout = new QVBox(plainPage());
controlLayout->setSpacing(spacingHint());
layout->addWidget(controlLayout);
((QBoxLayout*)controlLayout->layout())->addStrut(120);
KConfig config(mConfigFile);
QString xmlFile = "/doesntexist";
#ifdef XSCREENSAVER_CONFIG_DIR
xmlFile = XSCREENSAVER_CONFIG_DIR;
#endif
xmlFile += "/" + mExeName + ".xml";
if ( QFile::exists( xmlFile ) ) {
// We can use the xscreensaver xml config files.
KXSXml xmlParser(controlLayout);
xmlParser.parse( xmlFile );
mConfigItemList = *xmlParser.items();
QWidget *spacer = new QWidget(controlLayout);
controlLayout->setStretchFactor(spacer, 1 );
QString descr = xmlParser.description();
if ( !descr.isEmpty() ) {
descr.replace('\n',' ');
descr = descr.simplifyWhiteSpace();
QLabel *l = new QLabel( i18n( descr.utf8() ), plainPage() );
l->setAlignment ( WordBreak );
topLayout->addWidget( l );
}
} else {
// fall back to KDE's old config files.
int idx = 0;
while (true) {
QString group = QString("Arg%1").arg(idx);
if (config.hasGroup(group)) {
config.setGroup(group);
QString type = config.readEntry("Type");
if (type == "Range") {
KXSRangeControl *rc = new KXSRangeControl(controlLayout, group, config);
mConfigItemList.append(rc);
} else if (type == "DoubleRange") {
KXSDoubleRangeControl *rc =
new KXSDoubleRangeControl(controlLayout, group, config);
mConfigItemList.append(rc);
} else if (type == "Check") {
KXSCheckBoxControl *cc = new KXSCheckBoxControl(controlLayout, group,
config);
mConfigItemList.append(cc);
} else if (type == "DropList") {
KXSDropListControl *dl = new KXSDropListControl(controlLayout, group,
config);
mConfigItemList.append(dl);
}
} else {
break;
}
idx++;
}
if ( idx == 0 )
return false;
}
QPtrListIterator<KXSConfigItem> it( mConfigItemList );
KXSConfigItem *item;
while ( (item = it.current()) != 0 ) {
++it;
item->read( config );
QWidget *i = dynamic_cast<QWidget*>(item);
if (i) {
connect( i, SIGNAL(changed()), SLOT(slotChanged()) );
}
}
mPreviewProc = new KProcess;
connect(mPreviewProc, SIGNAL(processExited(KProcess *)),
SLOT(slotPreviewExited(KProcess *)));
mPreviewTimer = new QTimer(this);
connect(mPreviewTimer, SIGNAL(timeout()), SLOT(slotNewPreview()));
mPreview = new QWidget(plainPage());
mPreview->setFixedSize(250, 200);
// mPreview->setBackgroundMode(QWidget::NoBackground);
mPreview->setBackgroundColor(Qt::black);
layout->add(mPreview);
show();
// So that hacks can XSelectInput ButtonPressMask
XSelectInput(qt_xdisplay(), mPreview->winId(), widgetEventMask );
slotPreviewExited(0);
return true;
}
//---------------------------------------------------------------------------
KXSConfigDialog::~KXSConfigDialog()
{
if (mPreviewProc && mPreviewProc->isRunning()) {
int pid = mPreviewProc->pid();
mPreviewProc->kill();
waitpid(pid, (int *)0, 0);
delete mPreviewProc;
}
}
//---------------------------------------------------------------------------
QString KXSConfigDialog::command()
{
QString cmd;
KXSConfigItem *item;
for (item = mConfigItemList.first(); item != 0; item = mConfigItemList.next())
{
cmd += " " + item->command();
}
return cmd;
}
//---------------------------------------------------------------------------
void KXSConfigDialog::slotPreviewExited(KProcess *)
{
if ( mKilled ) {
mKilled = false;
mPreviewProc->clearArguments();
QString saver;
saver.sprintf( "%s -window-id 0x%lX", mFilename.latin1(), long(mPreview->winId()) );
saver += command();
kdDebug() << "Command: " << saver << endl;
unsigned int i = 0;
QString word;
saver = saver.stripWhiteSpace();
while ( !saver[i].isSpace() ) word += saver[i++];
//work around a KStandarDirs::findExe() "feature" where it looks in $KDEDIR/bin first no matter what and sometimes finds the wrong executable
QFileInfo checkExe;
QString saverdir = QString("%1/%2").arg(XSCREENSAVER_HACKS_DIR).arg(word);
QString path;
checkExe.setFile(saverdir);
if (checkExe.exists() && checkExe.isExecutable() && checkExe.isFile())
{
path = saverdir;
}
if (!path.isEmpty()) {
(*mPreviewProc) << path;
bool inQuotes = false;
while ( i < saver.length() ) {
word = "";
while ( saver[i].isSpace() && i < saver.length() ) i++;
while ( (!saver[i].isSpace() || inQuotes) && i < saver.length() ) {
if ( saver[i] == '\"' ) {
inQuotes = !inQuotes;
} else {
word += saver[i];
}
i++;
}
if (!word.isEmpty()) {
(*mPreviewProc) << word;
}
}
mPreviewProc->start();
}
} else {
// stops us from spawning the hack really fast, but still not the best
QString path = KStandardDirs::findExe(mFilename, XSCREENSAVER_HACKS_DIR);
if ( QFile::exists(path) ) {
mKilled = true;
slotChanged();
}
}
}
//---------------------------------------------------------------------------
void KXSConfigDialog::slotNewPreview()
{
if (mPreviewProc->isRunning()) {
mKilled = true;
mPreviewProc->kill(); // restarted in slotPreviewExited()
} else {
slotPreviewExited(0);
}
}
//---------------------------------------------------------------------------
void KXSConfigDialog::slotChanged()
{
if (mPreviewTimer->isActive())
mPreviewTimer->changeInterval(1000);
else
mPreviewTimer->start(1000, true);
}
//---------------------------------------------------------------------------
void KXSConfigDialog::slotOk()
{
KXSConfigItem *item;
KConfig config(mConfigFile);
for (item = mConfigItemList.first(); item != 0; item = mConfigItemList.next())
{
item->save(config);
}
kapp->quit();
}
//---------------------------------------------------------------------------
void KXSConfigDialog::slotCancel()
{
kapp->quit();
}
//===========================================================================
static const char appName[] = "kxsconfig";
static const char description[] = I18N_NOOP("KDE X Screen Saver Configuration tool");
static const char version[] = "3.0.0";
static const KCmdLineOptions options[] =
{
{"+screensaver", I18N_NOOP("Filename of the screen saver to configure"), 0},
{"+[savername]", I18N_NOOP("Optional screen saver name used in messages"), 0},
KCmdLineLastOption
};
static const char *defaults[] = {
#include "XScreenSaver_ad.h"
0
};
const char *progname = 0;
const char *progclass = "XScreenSaver";
XrmDatabase db;
int main(int argc, char *argv[])
{
KCmdLineArgs::init(argc, argv, appName, I18N_NOOP("KXSConfig"), description, version);
KCmdLineArgs::addCmdLineOptions(options);
KApplication app;
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
if(args->count()==0)
exit(1);
/* We must read exactly the same resources as xscreensaver.
That means we must have both the same progclass *and* progname,
at least as far as the resource database is concerned. So,
put "xscreensaver" in argv[0] while initializing Xt.
*/
const char *dummyargs[] = { "xscreensaver" };
int dummyargc = 1;
progname = dummyargs[0];
// Teach Xt to use the Display that Qt has already opened.
XtToolkitInitialize ();
XtAppContext xtApp = XtCreateApplicationContext ();
Display *dpy = qt_xdisplay();
XtAppSetFallbackResources (xtApp, const_cast<char**>(defaults));
XtDisplayInitialize (xtApp, dpy, progname, progclass, 0, 0,
&dummyargc,
const_cast<char**>(dummyargs));
Widget toplevel_shell = XtAppCreateShell (progname, progclass,
applicationShellWidgetClass,
dpy, 0, 0);
dpy = XtDisplay (toplevel_shell);
db = XtDatabase (dpy);
XtGetApplicationNameAndClass (dpy, const_cast<char**>(&progname),
const_cast<char**>(&progclass));
QString name = QString::fromLocal8Bit(args->arg(args->count() - 1));
KXSConfigDialog *dialog=new KXSConfigDialog(args->arg(0), name);
if ( dialog->create() ) {
dialog->show();
app.setMainWidget(dialog);
app.exec();
} else {
KMessageBox::sorry(0,
i18n("No configuration available for %1").arg(name),
name );
}
delete dialog;
}
#include "kxsconfig.moc"