kxmlcommanddlg.cpp

00001 /*
00002  *  This file is part of the KDE libraries
00003  *  Copyright (c) 2001 Michael Goffioul <kdeprint@swing.be>
00004  *
00005  *  This library is free software; you can redistribute it and/or
00006  *  modify it under the terms of the GNU Library General Public
00007  *  License version 2 as published by the Free Software Foundation.
00008  *
00009  *  This library is distributed in the hope that it will be useful,
00010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  *  Library General Public License for more details.
00013  *
00014  *  You should have received a copy of the GNU Library General Public License
00015  *  along with this library; see the file COPYING.LIB.  If not, write to
00016  *  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00017  *  Boston, MA 02110-1301, USA.
00018  **/
00019 
00020 #include "kxmlcommanddlg.h"
00021 #include "driver.h"
00022 #include "kxmlcommand.h"
00023 
00024 #include <qlayout.h>
00025 #include <qheader.h>
00026 #include <qlabel.h>
00027 #include <qlineedit.h>
00028 #include <qcombobox.h>
00029 #include <qgroupbox.h>
00030 #include <qwidgetstack.h>
00031 #include <qtoolbutton.h>
00032 #include <kpushbutton.h>
00033 #include <qtooltip.h>
00034 #include <qcheckbox.h>
00035 #include <ktextedit.h>
00036 #include <qregexp.h>
00037 #include <qwhatsthis.h>
00038 #include <qapplication.h>
00039 
00040 #include <klistview.h>
00041 #include <klocale.h>
00042 #include <kiconloader.h>
00043 #include <kdialogbase.h>
00044 #include <kseparator.h>
00045 #include <klistbox.h>
00046 #include <kmimetype.h>
00047 #include <kmessagebox.h>
00048 #include <kapplication.h>
00049 #include <kdebug.h>
00050 #include <kguiitem.h>
00051 
00052 QString generateId(const QMap<QString, DrBase*>& map)
00053 {
00054     int index(-1);
00055     while (map.contains(QString::fromLatin1("item%1").arg(++index))) ;
00056     return QString::fromLatin1("item%1").arg(index);
00057 }
00058 
00059 QListViewItem* findPrev(QListViewItem *item)
00060 {
00061     QListViewItem   *prev = item->itemAbove();
00062     while (prev && prev->depth() > item->depth())
00063         prev = prev->itemAbove();
00064     if (prev && prev->depth() == item->depth())
00065         return prev;
00066     else
00067         return 0;
00068 }
00069 
00070 QListViewItem* findNext(QListViewItem *item)
00071 {
00072     QListViewItem   *next = item->itemBelow();
00073     while (next && next->depth() > item->depth())
00074         next = next->itemBelow();
00075     if (next && next->depth() == item->depth())
00076         return next;
00077     else
00078         return 0;
00079 }
00080 
00081 KXmlCommandAdvancedDlg::KXmlCommandAdvancedDlg(QWidget *parent, const char *name)
00082 : QWidget(parent, name)
00083 {
00084     m_xmlcmd = 0;
00085 
00086     m_command = new QLineEdit(this);
00087     m_view = new KListView(this);
00088     m_view->addColumn("");
00089     m_view->header()->hide();
00090     m_view->setSorting(-1);
00091     m_apply = new QToolButton(this);
00092     m_apply->setIconSet( QApplication::reverseLayout()? SmallIconSet( "forward" ) : SmallIconSet("back"));
00093     m_addgrp = new QToolButton(this);
00094     m_addgrp->setIconSet(SmallIconSet("folder"));
00095     m_addopt = new QToolButton(this);
00096     m_addopt->setIconSet(SmallIconSet("document"));
00097     m_delopt = new QToolButton(this);
00098     m_delopt->setIconSet(SmallIconSet("editdelete"));
00099     m_up = new QToolButton(this);
00100     m_up->setIconSet(SmallIconSet("up"));
00101     m_down = new QToolButton(this);
00102     m_down->setIconSet(SmallIconSet("down"));
00103     m_dummy = new QWidget(this);
00104     m_desc = new QLineEdit(m_dummy);
00105     m_name = new QLineEdit(m_dummy);
00106     m_type = new QComboBox(m_dummy);
00107     m_type->insertItem(i18n("String"));
00108     m_type->insertItem(i18n("Integer"));
00109     m_type->insertItem(i18n("Float"));
00110     m_type->insertItem(i18n("List"));
00111     m_type->insertItem(i18n("Boolean"));
00112     m_format = new QLineEdit(m_dummy);
00113     m_default = new QLineEdit(m_dummy);
00114     QLabel  *m_namelab = new QLabel(i18n("&Name:"), m_dummy);
00115     QLabel  *m_desclab = new QLabel(i18n("&Description:"), m_dummy);
00116     QLabel  *m_formatlab = new QLabel(i18n("&Format:"), m_dummy);
00117     QLabel  *m_typelab = new QLabel(i18n("&Type:"), m_dummy);
00118     QLabel  *m_defaultlab = new QLabel(i18n("Default &value:"), m_dummy);
00119     QLabel  *m_commandlab = new QLabel(i18n("Co&mmand:"), this);
00120     m_namelab->setBuddy(m_name);
00121     m_desclab->setBuddy(m_desc);
00122     m_formatlab->setBuddy(m_format);
00123     m_typelab->setBuddy(m_type);
00124     m_defaultlab->setBuddy(m_default);
00125     m_commandlab->setBuddy(m_command);
00126     m_persistent = new QCheckBox( i18n( "&Persistent option" ), m_dummy );
00127 
00128     QGroupBox   *gb = new QGroupBox(0, Qt::Horizontal, i18n("Va&lues"), m_dummy);
00129     m_stack = new QWidgetStack(gb);
00130     QWidget *w1 = new QWidget(m_stack), *w2 = new QWidget(m_stack), *w3 = new QWidget(m_stack);
00131     m_stack->addWidget(w1, 1);
00132     m_stack->addWidget(w2, 2);
00133     m_stack->addWidget(w3, 3);
00134     m_edit1 = new QLineEdit(w1);
00135     m_edit2 = new QLineEdit(w1);
00136     QLabel  *m_editlab1 = new QLabel(i18n("Minimum v&alue:"), w1);
00137     QLabel  *m_editlab2 = new QLabel(i18n("Ma&ximum value:"), w1);
00138     m_editlab1->setBuddy(m_edit1);
00139     m_editlab2->setBuddy(m_edit2);
00140     m_values = new KListView(w2);
00141     m_values->addColumn(i18n("Name"));
00142     m_values->addColumn(i18n("Description"));
00143     m_values->setAllColumnsShowFocus(true);
00144     m_values->setSorting(-1);
00145     m_values->setMaximumHeight(110);
00146     m_addval = new QToolButton(w2);
00147     m_addval->setIconSet(SmallIconSet("editcopy"));
00148     m_delval = new QToolButton(w2);
00149     m_delval->setIconSet(SmallIconSet("editdelete"));
00150     QToolTip::add(m_addval, i18n("Add value"));
00151     QToolTip::add(m_delval, i18n("Delete value"));
00152 
00153     QToolTip::add(m_apply, i18n("Apply changes"));
00154     QToolTip::add(m_addgrp, i18n("Add group"));
00155     QToolTip::add(m_addopt, i18n("Add option"));
00156     QToolTip::add(m_delopt, i18n("Delete item"));
00157     QToolTip::add(m_up, i18n("Move up"));
00158     QToolTip::add(m_down, i18n("Move down"));
00159 
00160     KSeparator  *sep1 = new KSeparator(KSeparator::HLine, m_dummy);
00161 
00162     QGroupBox   *gb_input = new QGroupBox(0, Qt::Horizontal, i18n("&Input From"), this);
00163     QGroupBox   *gb_output = new QGroupBox(0, Qt::Horizontal, i18n("O&utput To"), this);
00164     QLabel  *m_inputfilelab = new QLabel(i18n("File:"), gb_input);
00165     QLabel  *m_inputpipelab = new QLabel(i18n("Pipe:"), gb_input);
00166     QLabel  *m_outputfilelab = new QLabel(i18n("File:"), gb_output);
00167     QLabel  *m_outputpipelab = new QLabel(i18n("Pipe:"), gb_output);
00168     m_inputfile = new QLineEdit(gb_input);
00169     m_inputpipe = new QLineEdit(gb_input);
00170     m_outputfile = new QLineEdit(gb_output);
00171     m_outputpipe = new QLineEdit(gb_output);
00172 
00173     m_comment = new KTextEdit( this );
00174     m_comment->setTextFormat( Qt::PlainText );
00175     QLabel *m_commentlab = new QLabel( i18n( "Comment:" ), this );
00176 
00177     QVBoxLayout *l2 = new QVBoxLayout(this, 0, KDialog::spacingHint());
00178     QHBoxLayout *l3 = new QHBoxLayout(0, 0, KDialog::spacingHint());
00179     QVBoxLayout *l7 = new QVBoxLayout(0, 0, 0);
00180     l2->addLayout(l3, 0);
00181     l3->addWidget(m_commandlab);
00182     l3->addWidget(m_command);
00183     QHBoxLayout *l0 = new QHBoxLayout(0, 0, KDialog::spacingHint());
00184     QGridLayout *l10 = new QGridLayout(0, 2, 2, 0, KDialog::spacingHint());
00185     l2->addLayout(l0, 1);
00186     l0->addLayout(l10);
00187     l10->addMultiCellWidget(m_view, 0, 0, 0, 1);
00188     l10->addWidget(gb_input, 1, 0);
00189     l10->addWidget(gb_output, 1, 1);
00190     l10->setRowStretch(0, 1);
00191     l0->addLayout(l7);
00192     l7->addWidget(m_apply);
00193     l7->addSpacing(5);
00194     l7->addWidget(m_addgrp);
00195     l7->addWidget(m_addopt);
00196     l7->addWidget(m_delopt);
00197     l7->addSpacing(5);
00198     l7->addWidget(m_up);
00199     l7->addWidget(m_down);
00200     l7->addStretch(1);
00201     l0->addWidget(m_dummy, 1);
00202     QGridLayout *l1 = new QGridLayout(m_dummy, 9, 2, 0, KDialog::spacingHint());
00203     l1->addWidget(m_desclab, 0, 0, Qt::AlignRight|Qt::AlignVCenter);
00204     l1->addWidget(m_desc, 0, 1);
00205     l1->addMultiCellWidget(sep1, 1, 1, 0, 1);
00206     l1->addWidget(m_namelab, 2, 0, Qt::AlignRight|Qt::AlignVCenter);
00207     l1->addWidget(m_name, 2, 1);
00208     l1->addWidget(m_typelab, 3, 0, Qt::AlignRight|Qt::AlignVCenter);
00209     l1->addWidget(m_type, 3, 1);
00210     l1->addWidget(m_formatlab, 4, 0, Qt::AlignRight|Qt::AlignVCenter);
00211     l1->addWidget(m_format, 4, 1);
00212     l1->addWidget(m_defaultlab, 5, 0, Qt::AlignRight|Qt::AlignVCenter);
00213     l1->addWidget(m_default, 5, 1);
00214     l1->addWidget( m_persistent, 6, 1 );
00215     l1->addMultiCellWidget(gb, 7, 7, 0, 1);
00216     l1->setRowStretch(8, 1);
00217 
00218     QHBoxLayout *l4 = new QHBoxLayout(w2, 0, KDialog::spacingHint());
00219     l4->addWidget(m_values);
00220     QVBoxLayout *l6 = new QVBoxLayout(0, 0, 0);
00221     l4->addLayout(l6);
00222     l6->addWidget(m_addval);
00223     l6->addWidget(m_delval);
00224     l6->addStretch(1);
00225     QGridLayout *l5 = new QGridLayout(w1, 3, 2, 0, KDialog::spacingHint());
00226     l5->setRowStretch(2, 1);
00227     l5->addWidget(m_editlab1, 0, 0, Qt::AlignRight|Qt::AlignVCenter);
00228     l5->addWidget(m_editlab2, 1, 0, Qt::AlignRight|Qt::AlignVCenter);
00229     l5->addWidget(m_edit1, 0, 1);
00230     l5->addWidget(m_edit2, 1, 1);
00231 
00232     QGridLayout *l8 = new QGridLayout(gb_input->layout(), 2, 2,
00233         KDialog::spacingHint());
00234     QGridLayout *l9 = new QGridLayout(gb_output->layout(), 2, 2,
00235         KDialog::spacingHint());
00236     l8->addWidget(m_inputfilelab, 0, 0);
00237     l8->addWidget(m_inputpipelab, 1, 0);
00238     l8->addWidget(m_inputfile, 0, 1);
00239     l8->addWidget(m_inputpipe, 1, 1);
00240     l9->addWidget(m_outputfilelab, 0, 0);
00241     l9->addWidget(m_outputpipelab, 1, 0);
00242     l9->addWidget(m_outputfile, 0, 1);
00243     l9->addWidget(m_outputpipe, 1, 1);
00244 
00245     QVBoxLayout *l11 = new QVBoxLayout(gb->layout());
00246     l11->addWidget(m_stack);
00247 
00248     QVBoxLayout *l12 = new QVBoxLayout( 0, 0, 0 );
00249     l2->addSpacing( 10 );
00250     l2->addLayout( l12 );
00251     l12->addWidget( m_commentlab );
00252     l12->addWidget( m_comment );
00253 
00254     connect(m_view, SIGNAL(selectionChanged(QListViewItem*)), SLOT(slotSelectionChanged(QListViewItem*)));
00255     connect(m_values, SIGNAL(selectionChanged(QListViewItem*)), SLOT(slotValueSelected(QListViewItem*)));
00256     connect(m_type, SIGNAL(activated(int)), SLOT(slotTypeChanged(int)));
00257     connect(m_addval, SIGNAL(clicked()), SLOT(slotAddValue()));
00258     connect(m_delval, SIGNAL(clicked()), SLOT(slotRemoveValue()));
00259     connect(m_apply, SIGNAL(clicked()), SLOT(slotApplyChanges()));
00260     connect(m_addgrp, SIGNAL(clicked()), SLOT(slotAddGroup()));
00261     connect(m_addopt, SIGNAL(clicked()), SLOT(slotAddOption()));
00262     connect(m_delopt, SIGNAL(clicked()), SLOT(slotRemoveItem()));
00263     connect(m_up, SIGNAL(clicked()), SLOT(slotMoveUp()));
00264     connect(m_down, SIGNAL(clicked()), SLOT(slotMoveDown()));
00265     connect(m_command, SIGNAL(textChanged(const QString&)), SLOT(slotCommandChanged(const QString&)));
00266     connect(m_view, SIGNAL(itemRenamed(QListViewItem*,int)), SLOT(slotOptionRenamed(QListViewItem*,int)));
00267     connect(m_desc, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00268     connect(m_name, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00269     connect(m_format, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00270     connect(m_default, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00271     connect(m_edit1, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00272     connect(m_edit2, SIGNAL(textChanged(const QString&)), SLOT(slotChanged()));
00273     connect(m_type, SIGNAL(activated(int)), SLOT(slotChanged()));
00274     connect(m_addval, SIGNAL(clicked()), SLOT(slotChanged()));
00275     connect(m_delval, SIGNAL(clicked()), SLOT(slotChanged()));
00276     connect( m_persistent, SIGNAL( toggled(bool) ), SLOT( slotChanged() ) );
00277     m_dummy->setEnabled(false);
00278     viewItem(0);
00279 
00283     QWhatsThis::add( m_name, i18n(
00284                 "An identification string. Use only alphanumeric characters except spaces. "
00285                 "The string <b>__root__</b> is reserved for internal use." ) );
00286     QWhatsThis::add( m_namelab, QWhatsThis::textFor( m_name ) );
00287     QWhatsThis::add( m_desc, i18n(
00288                 "A description string. This string is shown in the interface, and should "
00289                 "be explicit enough about the role of the corresponding option." ) );
00290     QWhatsThis::add( m_desclab, QWhatsThis::textFor( m_desc ) );
00291     QWhatsThis::add( m_type, i18n(
00292                 "The type of the option. This determines how the option is presented "
00293                 "graphically to the user." ) );
00294     QWhatsThis::add( m_typelab, QWhatsThis::textFor( m_type ) );
00295     QWhatsThis::add( m_format, i18n(
00296                 "The format of the option. This determines how the option is formatted "
00297                 "for inclusion in the global command line. The tag <b>%value</b> can be used "
00298                 "to represent the user selection. This tag will be replaced at run-time by a "
00299                 "string representation of the option value." ) );
00300     QWhatsThis::add( m_formatlab, QWhatsThis::textFor( m_format ) );
00301     QWhatsThis::add( m_default, i18n(
00302                 "The default value of the option. For non persistent options, nothing is "
00303                 "added to the command line if the option has that default value. If this "
00304                 "value does not correspond to the actual default value of the underlying "
00305                 "utility, make the option persistent to avoid unwanted effects." ) );
00306     QWhatsThis::add( m_defaultlab, QWhatsThis::textFor( m_default ) );
00307     QWhatsThis::add( m_persistent, i18n(
00308                 "Make the option persistent. A persistent option is always written to the "
00309                 "command line, whatever its value. This is useful when the chosen default "
00310                 "value does not match with the actual default value of the underlying utility." ) );
00311     QWhatsThis::add( m_command, i18n(
00312                 "The full command line to execute the associated underlying utility. This "
00313                 "command line is based on a mechanism of tags that are replaced at run-time. "
00314                 "The supported tags are:<ul>"
00315                 "<li><b>%filterargs</b>: command options</li>"
00316                 "<li><b>%filterinput</b>: input specification</li>"
00317                 "<li><b>%filteroutput</b>: output specification</li>"
00318                 "<li><b>%psu</b>: the page size in upper case</li>"
00319                 "<li><b>%psl</b>: the page size in lower case</li></ul>" ) );
00320     QWhatsThis::add( m_commandlab, QWhatsThis::textFor( m_command ) );
00321     QWhatsThis::add( m_inputfile, i18n(
00322                 "Input specification when the underlying utility reads input data from a file. Use "
00323                 "the tag <b>%in</b> to represent the input filename." ) );
00324     QWhatsThis::add( m_inputfilelab, QWhatsThis::textFor( m_inputfile ) );
00325     QWhatsThis::add( m_outputfile, i18n(
00326                 "Output specification when the underlying utility writes output data to a file. Use "
00327                 "the tag <b>%out</b> to represent the output filename." ) );
00328     QWhatsThis::add( m_outputfilelab, QWhatsThis::textFor( m_outputfile ) );
00329     QWhatsThis::add( m_inputpipe, i18n(
00330                 "Input specification when the underlying utility reads input data from its "
00331                 "standard input." ) );
00332     QWhatsThis::add( m_inputpipelab, QWhatsThis::textFor( m_inputpipe ) );
00333     QWhatsThis::add( m_outputpipe, i18n(
00334                 "Output specification when the underlying utility writes output data to its "
00335                 "standard output." ) );
00336     QWhatsThis::add( m_outputpipelab, QWhatsThis::textFor( m_outputpipe ) );
00337     QWhatsThis::add( m_comment, i18n(
00338                 "A comment about the underlying utility, which can be viewed by the user "
00339                 "from the interface. This comment string supports basic HTML tags like "
00340                 "&lt;a&gt;, &lt;b&gt; or &lt;i&gt;." ) );
00341     QWhatsThis::add( m_commentlab, QWhatsThis::textFor( m_comment ) );
00342 
00343     resize(660, 200);
00344 }
00345 
00346 KXmlCommandAdvancedDlg::~KXmlCommandAdvancedDlg()
00347 {
00348     if (m_opts.count() > 0)
00349     {
00350         kdDebug() << "KXmlCommandAdvancedDlg: " << m_opts.count() << " items remaining" << endl;
00351         for (QMap<QString,DrBase*>::ConstIterator it=m_opts.begin(); it!=m_opts.end(); ++it)
00352         {
00353             //kdDebug() << "Item: name=" << (*it)->name() << endl;
00354             delete (*it);
00355         }
00356     }
00357 }
00358 
00359 void KXmlCommandAdvancedDlg::setCommand(KXmlCommand *xmlcmd)
00360 {
00361     m_xmlcmd = xmlcmd;
00362     if (m_xmlcmd)
00363         parseXmlCommand(m_xmlcmd);
00364 }
00365 
00366 void KXmlCommandAdvancedDlg::parseXmlCommand(KXmlCommand *xmlcmd)
00367 {
00368     m_view->clear();
00369     QListViewItem   *root = new QListViewItem(m_view, xmlcmd->name(), xmlcmd->name());
00370     DrMain  *driver = xmlcmd->driver();
00371 
00372     root->setPixmap(0, SmallIcon("fileprint"));
00373     root->setOpen(true);
00374     if (driver)
00375     {
00376         DrMain  *clone = driver->cloneDriver();
00377         if (!clone->get("text").isEmpty())
00378             root->setText(0, clone->get("text"));
00379         root->setText(1, "__root__");
00380         clone->setName("__root__");
00381         m_opts["__root__"] = clone;
00382         parseGroupItem(clone, root);
00383         clone->flatten();
00384     }
00385     m_command->setText(xmlcmd->command());
00386     m_inputfile->setText(xmlcmd->io(true, false));
00387     m_inputpipe->setText(xmlcmd->io(true, true));
00388     m_outputfile->setText(xmlcmd->io(false, false));
00389     m_outputpipe->setText(xmlcmd->io(false, true));
00390     m_comment->setText( xmlcmd->comment() );
00391 
00392     viewItem(0);
00393 }
00394 
00395 void KXmlCommandAdvancedDlg::parseGroupItem(DrGroup *grp, QListViewItem *parent)
00396 {
00397     QListViewItem   *item(0);
00398 
00399     QPtrListIterator<DrGroup>   git(grp->groups());
00400     for (; git.current(); ++git)
00401     {
00402         QString namestr = git.current()->name();
00403         if (namestr.isEmpty())
00404         {
00405             namestr = "group_"+kapp->randomString(4);
00406         }
00407         git.current()->setName(namestr);
00408         item = new QListViewItem(parent, item, git.current()->get("text"), git.current()->name());
00409         item->setPixmap(0, SmallIcon("folder"));
00410         item->setOpen(true);
00411         item->setRenameEnabled(0, true);
00412         parseGroupItem(git.current(), item);
00413         m_opts[namestr] = git.current();
00414     }
00415 
00416     QPtrListIterator<DrBase>    oit(grp->options());
00417     for (; oit.current(); ++oit)
00418     {
00419         QString namestr = oit.current()->name().mid(m_xmlcmd->name().length()+6);
00420         if (namestr.isEmpty())
00421         {
00422             namestr = "option_"+kapp->randomString(4);
00423         }
00424         oit.current()->setName(namestr);
00425         item = new QListViewItem(parent, item, oit.current()->get("text"), namestr);
00426         item->setPixmap(0, SmallIcon("document"));
00427         item->setRenameEnabled(0, true);
00428         m_opts[namestr] = oit.current();
00429     }
00430 }
00431 
00432 void KXmlCommandAdvancedDlg::slotSelectionChanged(QListViewItem *item)
00433 {
00434     if (item && item->depth() == 0)
00435         item = 0;
00436     viewItem(item);
00437 }
00438 
00439 void KXmlCommandAdvancedDlg::viewItem(QListViewItem *item)
00440 {
00441     m_dummy->setEnabled((item != 0));
00442     m_name->setText("");
00443     m_desc->setText("");
00444     m_format->setText("");
00445     m_default->setText("");
00446     m_values->clear();
00447     m_edit1->setText("");
00448     m_edit2->setText("");
00449     m_persistent->setChecked( false );
00450     int typeId(-1);
00451     if (item)
00452     {
00453         m_name->setText(item->text(1));
00454         m_desc->setText(item->text(0));
00455 
00456         DrBase  *opt = (m_opts.contains(item->text(1)) ? m_opts[item->text(1)] : 0);
00457         if (opt)
00458         {
00459             bool    isgroup = (opt->type() < DrBase::String);
00460             if (!isgroup)
00461             {
00462                 m_type->setCurrentItem(opt->type() - DrBase::String);
00463                 typeId = m_type->currentItem();
00464                 m_format->setText(opt->get("format"));
00465                 m_default->setText(opt->get("default"));
00466             }
00467             m_type->setEnabled(!isgroup);
00468             m_default->setEnabled(!isgroup);
00469             m_format->setEnabled(!isgroup);
00470             m_stack->setEnabled(!isgroup);
00471 
00472             switch (opt->type())
00473             {
00474                 case DrBase::Float:
00475                 case DrBase::Integer:
00476                     m_edit1->setText(opt->get("minval"));
00477                     m_edit2->setText(opt->get("maxval"));
00478                     break;
00479                 case DrBase::Boolean:
00480                 case DrBase::List:
00481                     {
00482                         QPtrListIterator<DrBase>    it(*(static_cast<DrListOption*>(opt)->choices()));
00483                         QListViewItem   *item(0);
00484                         for (; it.current(); ++it)
00485                         {
00486                             item = new QListViewItem(m_values, item, it.current()->name(), it.current()->get("text"));
00487                             item->setRenameEnabled(0, true);
00488                             item->setRenameEnabled(1, true);
00489                         }
00490                         break;
00491                     }
00492                 default:
00493                     break;
00494             }
00495 
00496             m_addgrp->setEnabled(isgroup);
00497             m_addopt->setEnabled(isgroup);
00498 
00499             QListViewItem   *prevItem = findPrev(item), *nextItem = findNext(item);
00500             DrBase  *prevOpt = (prevItem && m_opts.contains(prevItem->text(1)) ? m_opts[prevItem->text(1)] : 0);
00501             DrBase  *nextOpt = (nextItem && m_opts.contains(nextItem->text(1)) ? m_opts[nextItem->text(1)] : 0);
00502             m_up->setEnabled(prevOpt && !(prevOpt->type() < DrBase::String && opt->type() >= DrBase::String));
00503             m_down->setEnabled(nextOpt && !(isgroup && nextOpt->type() >= DrBase::String));
00504 
00505             m_persistent->setChecked( opt->get( "persistent" ) == "1" );
00506         }
00507 
00508         m_delopt->setEnabled(true);
00509         m_dummy->setEnabled(opt);
00510     }
00511     else
00512     {
00513         m_delopt->setEnabled(false);
00514         m_addopt->setEnabled(m_view->currentItem() && m_view->isEnabled());
00515         m_addgrp->setEnabled(m_view->currentItem() && m_view->isEnabled());
00516         m_up->setEnabled(false);
00517         m_down->setEnabled(false);
00518     }
00519     slotTypeChanged(typeId);
00520     m_apply->setEnabled(false);
00521 }
00522 
00523 void KXmlCommandAdvancedDlg::slotTypeChanged(int ID)
00524 {
00525     int wId(3);
00526     ID += DrBase::String;
00527     switch (ID)
00528     {
00529         case DrBase::Float:
00530         case DrBase::Integer:
00531             wId = 1;
00532             break;
00533         case DrBase::Boolean:
00534         case DrBase::List:
00535             wId = 2;
00536             slotValueSelected(m_values->currentItem());
00537             break;
00538     }
00539     m_stack->raiseWidget(wId);
00540 }
00541 
00542 void KXmlCommandAdvancedDlg::slotAddValue()
00543 {
00544     QListViewItem   *item = new QListViewItem(m_values, m_values->lastItem(), i18n("Name"), i18n("Description"));
00545     item->setRenameEnabled(0, true);
00546     item->setRenameEnabled(1, true);
00547     m_values->ensureItemVisible(item);
00548     slotValueSelected(item);
00549     item->startRename(0);
00550 }
00551 
00552 void KXmlCommandAdvancedDlg::slotRemoveValue()
00553 {
00554     QListViewItem   *item = m_values->currentItem();
00555     if (item)
00556         delete item;
00557     slotValueSelected(m_values->currentItem());
00558 }
00559 
00560 void KXmlCommandAdvancedDlg::slotApplyChanges()
00561 {
00562     QListViewItem   *item = m_view->currentItem();
00563     if (item)
00564     {
00565         if (m_name->text().isEmpty() || m_name->text() == "__root__")
00566         {
00567             KMessageBox::error(this, i18n("Invalid identification name. Empty strings and \"__root__\" are not allowed."));
00568             return;
00569         }
00570 
00571         m_apply->setEnabled(false);
00572 
00573         DrBase  *opt = (m_opts.contains(item->text(1)) ? m_opts[item->text(1)] : 0);
00574         m_opts.remove(item->text(1));
00575         delete opt;
00576 
00577         // update tree item
00578         item->setText(0, m_desc->text());
00579         item->setText(1, m_name->text());
00580 
00581         // recreate option
00582         if (m_type->isEnabled())
00583         {
00584             int type = m_type->currentItem() + DrBase::String;
00585             switch (type)
00586             {
00587                 case DrBase::Integer:
00588                 case DrBase::Float:
00589                     if (type == DrBase::Integer)
00590                         opt = new DrIntegerOption;
00591                     else
00592                         opt = new DrFloatOption;
00593                     opt->set("minval", m_edit1->text());
00594                     opt->set("maxval", m_edit2->text());
00595                     break;
00596                 case DrBase::List:
00597                 case DrBase::Boolean:
00598                     {
00599                         if (type == DrBase::List)
00600                             opt = new DrListOption;
00601                         else
00602                             opt = new DrBooleanOption;
00603                         DrListOption    *lopt = static_cast<DrListOption*>(opt);
00604                         QListViewItem   *item = m_values->firstChild();
00605                         while (item)
00606                         {
00607                             DrBase  *choice = new DrBase;
00608                             choice->setName(item->text(0));
00609                             choice->set("text", item->text(1));
00610                             lopt->addChoice(choice);
00611                             item = item->nextSibling();
00612                         }
00613                         break;
00614                     }
00615                 case DrBase::String:
00616                     opt = new DrStringOption;
00617                     break;
00618 
00619             }
00620             opt->set("format", m_format->text());
00621             opt->set("default", m_default->text());
00622             opt->setValueText(opt->get("default"));
00623         }
00624         else
00625             opt = new DrGroup;
00626 
00627         opt->setName((m_name->text().isEmpty() ? generateId(m_opts) : m_name->text()));
00628         opt->set("text", m_desc->text());
00629         opt->set( "persistent", m_persistent->isChecked() ? "1" : "0" );
00630 
00631         m_opts[opt->name()] = opt;
00632     }
00633 }
00634 
00635 void KXmlCommandAdvancedDlg::slotChanged()
00636 {
00637     m_apply->setEnabled(true);
00638 }
00639 
00640 void KXmlCommandAdvancedDlg::slotAddGroup()
00641 {
00642     if (m_view->currentItem())
00643     {
00644         QString ID = generateId(m_opts);
00645 
00646         DrGroup *grp = new DrGroup;
00647         grp->setName(ID);
00648         grp->set("text", i18n("New Group"));
00649         m_opts[ID] = grp;
00650 
00651         QListViewItem   *item = new QListViewItem(m_view->currentItem(), i18n("New Group"), ID);
00652         item->setRenameEnabled(0, true);
00653         item->setPixmap(0, SmallIcon("folder"));
00654         m_view->ensureItemVisible(item);
00655         item->startRename(0);
00656     }
00657 }
00658 
00659 void KXmlCommandAdvancedDlg::slotAddOption()
00660 {
00661     if (m_view->currentItem())
00662     {
00663         QString ID = generateId(m_opts);
00664 
00665         DrBase  *opt = new DrStringOption;
00666         opt->setName(ID);
00667         opt->set("text", i18n("New Option"));
00668         m_opts[ID] = opt;
00669 
00670         QListViewItem   *item = new QListViewItem(m_view->currentItem(), i18n("New Option"), ID);
00671         item->setRenameEnabled(0, true);
00672         item->setPixmap(0, SmallIcon("document"));
00673         m_view->ensureItemVisible(item);
00674         item->startRename(0);
00675     }
00676 }
00677 
00678 void KXmlCommandAdvancedDlg::slotRemoveItem()
00679 {
00680     QListViewItem   *item = m_view->currentItem();
00681     if (item)
00682     {
00683         QListViewItem   *newCurrent(item->nextSibling());
00684         if (!newCurrent)
00685             newCurrent = item->parent();
00686         removeItem(item);
00687         delete item;
00688         m_view->setSelected(newCurrent, true);
00689     }
00690 }
00691 
00692 void KXmlCommandAdvancedDlg::removeItem(QListViewItem *item)
00693 {
00694     delete m_opts[item->text(1)];
00695     m_opts.remove(item->text(1));
00696     QListViewItem   *child = item->firstChild();
00697     while (child && item)
00698     {
00699         removeItem(child);
00700                 if ( item )
00701                     item = item->nextSibling();
00702     }
00703 }
00704 
00705 void KXmlCommandAdvancedDlg::slotMoveUp()
00706 {
00707     QListViewItem   *item = m_view->currentItem(), *prev = 0;
00708     if (item && (prev=findPrev(item)))
00709     {
00710         QListViewItem   *after(0);
00711         if ((after=findPrev(prev)) != 0)
00712             item->moveItem(after);
00713         else
00714         {
00715             QListViewItem   *parent = item->parent();
00716             parent->takeItem(item);
00717             parent->insertItem(item);
00718         }
00719         m_view->setSelected(item, true);
00720         slotSelectionChanged(item);
00721     }
00722 }
00723 
00724 void KXmlCommandAdvancedDlg::slotMoveDown()
00725 {
00726     QListViewItem   *item = m_view->currentItem(), *next = 0;
00727     if (item && (next=findNext(item)))
00728     {
00729         item->moveItem(next);
00730         m_view->setSelected(item, true);
00731         slotSelectionChanged(item);
00732     }
00733 }
00734 
00735 void KXmlCommandAdvancedDlg::slotCommandChanged(const QString& cmd)
00736 {
00737     m_inputfile->parentWidget()->setEnabled(cmd.find("%filterinput") != -1);
00738     m_outputfile->parentWidget()->setEnabled(cmd.find("%filteroutput") != -1);
00739     m_view->setEnabled(cmd.find("%filterargs") != -1);
00740     m_name->parentWidget()->setEnabled(m_view->isEnabled());
00741     slotSelectionChanged((m_view->isEnabled() ? m_view->currentItem() : 0));
00742     m_view->setOpen(m_view->firstChild(), m_view->isEnabled());
00743 }
00744 
00745 void KXmlCommandAdvancedDlg::slotValueSelected(QListViewItem *item)
00746 {
00747     m_addval->setEnabled(m_type->currentItem() != 4 || m_values->childCount() < 2);
00748     m_delval->setEnabled(item != 0);
00749 }
00750 
00751 void KXmlCommandAdvancedDlg::slotOptionRenamed(QListViewItem *item, int)
00752 {
00753     if (item && m_opts.contains(item->text(1)))
00754     {
00755         DrBase  *opt = m_opts[item->text(1)];
00756         opt->set("text", item->text(0));
00757         slotSelectionChanged(item);
00758     }
00759 }
00760 
00761 void KXmlCommandAdvancedDlg::recreateGroup(QListViewItem *item, DrGroup *grp)
00762 {
00763     if (!item)
00764         return;
00765 
00766     QListViewItem   *child = item->firstChild();
00767     while (child)
00768     {
00769         DrBase  *opt = (m_opts.contains(child->text(1)) ? m_opts[child->text(1)] : 0);
00770         if (opt)
00771         {
00772             if (opt->type() == DrBase::Group)
00773             {
00774                 DrGroup *childGroup = static_cast<DrGroup*>(opt);
00775                 recreateGroup(child, childGroup);
00776                 grp->addGroup(childGroup);
00777             }
00778             else
00779             {
00780                 opt->setName("_kde-"+m_xmlcmd->name()+"-"+opt->name());
00781                 grp->addOption(opt);
00782             }
00783             m_opts.remove(child->text(1));
00784         }
00785         child = child->nextSibling();
00786     }
00787 }
00788 
00789 bool KXmlCommandAdvancedDlg::editCommand(KXmlCommand *xmlcmd, QWidget *parent)
00790 {
00791     if (!xmlcmd)
00792         return false;
00793 
00794     KDialogBase dlg(parent, 0, true, i18n("Command Edit for %1").arg(xmlcmd->name()), KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Ok, false);
00795     KXmlCommandAdvancedDlg  *xmldlg = new KXmlCommandAdvancedDlg(&dlg);
00796     dlg.setMainWidget(xmldlg);
00797     //dlg.enableButton(KDialogBase::Ok, false);
00798     xmldlg->setCommand(xmlcmd);
00799     if (dlg.exec())
00800     {
00801         xmlcmd->setCommand(xmldlg->m_command->text());
00802         xmlcmd->setIo(xmldlg->m_inputfile->text(), true, false);
00803         xmlcmd->setIo(xmldlg->m_inputpipe->text(), true, true);
00804         xmlcmd->setIo(xmldlg->m_outputfile->text(), false, false);
00805         xmlcmd->setIo(xmldlg->m_outputpipe->text(), false, true);
00806         xmlcmd->setComment( xmldlg->m_comment->text().replace( QRegExp( "\n" ), " " ) );
00807 
00808         // need to recreate the driver tree structure
00809         DrMain  *driver = (xmldlg->m_opts.contains("__root__") ? static_cast<DrMain*>(xmldlg->m_opts["__root__"]) : 0);
00810         if (!driver && xmldlg->m_opts.count() > 0)
00811         {
00812             kdDebug() << "KXmlCommandAdvancedDlg: driver structure not found, creating one" << endl;
00813             driver = new DrMain;
00814             driver->setName(xmlcmd->name());
00815         }
00816         xmldlg->recreateGroup(xmldlg->m_view->firstChild(), driver);
00817         xmldlg->m_opts.remove("__root__");
00818         xmlcmd->setDriver(driver);
00819 
00820         // remaining options will be removed in destructor
00821 
00822         return true;
00823     }
00824     return false;
00825 }
00826 
00827 //-----------------------------------------------------------------------------------------------------
00828 
00829 KXmlCommandDlg::KXmlCommandDlg(QWidget *parent, const char *name)
00830 : KDialogBase(parent, name, true, QString::null, Ok|Cancel|Details, Ok, true)
00831 {
00832     setButtonText(Details, i18n("&Mime Type Settings"));
00833     m_cmd = 0;
00834 
00835     QWidget *dummy = new QWidget(this, "TopDetail");
00836     QWidget *topmain = new QWidget(this, "TopMain");
00837 
00838     QGroupBox   *m_gb1 = new QGroupBox(0, Qt::Horizontal, i18n("Supported &Input Formats"), dummy);
00839     QGroupBox   *m_gb2 = new QGroupBox(0, Qt::Horizontal, i18n("Requirements"), topmain);
00840 
00841     m_description = new QLineEdit(topmain);
00842     m_idname = new QLabel(topmain);
00843     m_requirements = new KListView(m_gb2);
00844     m_requirements->addColumn("");
00845     m_requirements->header()->hide();
00846     m_addreq = new QToolButton(m_gb2);
00847     m_addreq->setIconSet(SmallIconSet("filenew"));
00848     m_removereq = new QToolButton(m_gb2);
00849     m_removereq->setIconSet(SmallIconSet("editdelete"));
00850     QPushButton *m_edit = new KPushButton(KGuiItem(i18n("&Edit Command..."), "edit"), topmain);
00851     m_mimetype = new QComboBox(dummy);
00852     m_availablemime = new KListBox(m_gb1);
00853     m_selectedmime = new KListBox(m_gb1);
00854     m_addmime = new QToolButton(m_gb1);
00855     m_addmime->setIconSet(QApplication::reverseLayout()? SmallIconSet("forward") : SmallIconSet("back"));
00856     m_removemime = new QToolButton(m_gb1);
00857     m_removemime->setIconSet(QApplication::reverseLayout()? SmallIconSet("back" ) : SmallIconSet("forward"));
00858     m_gb2->setMinimumWidth(380);
00859     m_gb1->setMinimumHeight(180);
00860     m_requirements->setMaximumHeight(80);
00861     m_removereq->setEnabled(false);
00862     m_addmime->setEnabled(false);
00863     m_removemime->setEnabled(false);
00864 
00865     QLabel  *m_desclab = new QLabel(i18n("&Description:"), topmain);
00866     m_desclab->setBuddy(m_description);
00867     QLabel  *m_mimetypelab = new QLabel(i18n("Output &format:"), dummy);
00868     m_mimetypelab->setBuddy(m_mimetype);
00869     QLabel  *m_idnamelab = new QLabel(i18n("ID name:"), topmain);
00870 
00871     QFont   f(m_idname->font());
00872     f.setBold(true);
00873     m_idname->setFont(f);
00874 
00875     KSeparator  *sep1 = new KSeparator(QFrame::HLine, dummy);
00876 
00877     QVBoxLayout *l0 = new QVBoxLayout(topmain, 0, 10);
00878     QGridLayout *l5 = new QGridLayout(0, 2, 2, 0, 5);
00879     l0->addLayout(l5);
00880     l5->addWidget(m_idnamelab, 0, 0);
00881     l5->addWidget(m_idname, 0, 1);
00882     l5->addWidget(m_desclab, 1, 0);
00883     l5->addWidget(m_description, 1, 1);
00884     l0->addWidget(m_gb2);
00885     QHBoxLayout *l3 = new QHBoxLayout(0, 0, 0);
00886     l0->addLayout(l3);
00887     l3->addWidget(m_edit);
00888     l3->addStretch(1);
00889 
00890     QVBoxLayout *l7 = new QVBoxLayout(dummy, 0, 10);
00891     QHBoxLayout *l6 = new QHBoxLayout(0, 0, 5);
00892     l7->addWidget(sep1);
00893     l7->addLayout(l6);
00894     l6->addWidget(m_mimetypelab, 0);
00895     l6->addWidget(m_mimetype, 1);
00896     l7->addWidget(m_gb1);
00897     QGridLayout *l2 = new QGridLayout(m_gb1->layout(), 4, 3, 10);
00898     l2->addMultiCellWidget(m_availablemime, 0, 3, 2, 2);
00899     l2->addMultiCellWidget(m_selectedmime, 0, 3, 0, 0);
00900     l2->addWidget(m_addmime, 1, 1);
00901     l2->addWidget(m_removemime, 2, 1);
00902     l2->setRowStretch(0, 1);
00903     l2->setRowStretch(3, 1);
00904     QHBoxLayout *l4 = new QHBoxLayout(m_gb2->layout(), 10);
00905     l4->addWidget(m_requirements);
00906     QVBoxLayout *l8 = new QVBoxLayout(0, 0, 0);
00907     l4->addLayout(l8);
00908     l8->addWidget(m_addreq);
00909     l8->addWidget(m_removereq);
00910     l8->addStretch(1);
00911 
00912     connect(m_addmime, SIGNAL(clicked()), SLOT(slotAddMime()));
00913     connect(m_removemime, SIGNAL(clicked()), SLOT(slotRemoveMime()));
00914     connect(m_edit, SIGNAL(clicked()), SLOT(slotEditCommand()));
00915     connect(m_requirements, SIGNAL(selectionChanged(QListViewItem*)), SLOT(slotReqSelected(QListViewItem*)));
00916     connect(m_availablemime, SIGNAL(selectionChanged(QListBoxItem*)), SLOT(slotAvailableSelected(QListBoxItem*)));
00917     connect(m_selectedmime, SIGNAL(selectionChanged(QListBoxItem*)), SLOT(slotSelectedSelected(QListBoxItem*)));
00918     connect(m_addreq, SIGNAL(clicked()), SLOT(slotAddReq()));
00919     connect(m_removereq, SIGNAL(clicked()), SLOT(slotRemoveReq()));
00920 
00921     KMimeType::List list = KMimeType::allMimeTypes();
00922     for (QValueList<KMimeType::Ptr>::ConstIterator it=list.begin(); it!=list.end(); ++it)
00923     {
00924         QString mimetype = (*it)->name();
00925         m_mimelist << mimetype;
00926     }
00927 
00928     m_mimelist.sort();
00929     m_mimetype->insertStringList(m_mimelist);
00930     m_availablemime->insertStringList(m_mimelist);
00931 
00932     setMainWidget(topmain);
00933     setDetailsWidget(dummy);
00934 }
00935 
00936 void KXmlCommandDlg::setCommand(KXmlCommand *xmlCmd)
00937 {
00938     setCaption(i18n("Command Edit for %1").arg(xmlCmd->name()));
00939 
00940     m_cmd = xmlCmd;
00941     m_description->setText(i18n(xmlCmd->description().utf8()));
00942     m_idname->setText(xmlCmd->name());
00943 
00944     m_requirements->clear();
00945     QStringList list = xmlCmd->requirements();
00946     QListViewItem   *item(0);
00947     for (QStringList::ConstIterator it=list.begin(); it!=list.end(); ++it)
00948     {
00949         item = new QListViewItem(m_requirements, item, *it);
00950         item->setRenameEnabled(0, true);
00951     }
00952 
00953     int index = m_mimelist.findIndex(xmlCmd->mimeType());
00954     if (index != -1)
00955         m_mimetype->setCurrentItem(index);
00956     else
00957         m_mimetype->setCurrentItem(0);
00958 
00959     list = xmlCmd->inputMimeTypes();
00960     m_selectedmime->clear();
00961     m_availablemime->clear();
00962     m_availablemime->insertStringList(m_mimelist);
00963     for (QStringList::ConstIterator it=list.begin(); it!=list.end(); ++it)
00964     {
00965         m_selectedmime->insertItem(*it);
00966         delete m_availablemime->findItem(*it, Qt::ExactMatch);
00967     }
00968 }
00969 
00970 void KXmlCommandDlg::slotOk()
00971 {
00972     if (m_cmd)
00973     {
00974         m_cmd->setMimeType((m_mimetype->currentText() == "all/all" ? QString::null : m_mimetype->currentText()));
00975         m_cmd->setDescription(m_description->text());
00976         QStringList l;
00977         QListViewItem   *item = m_requirements->firstChild();
00978         while (item)
00979         {
00980             l << item->text(0);
00981             item = item->nextSibling();
00982         }
00983         m_cmd->setRequirements(l);
00984         l.clear();
00985         for (uint i=0; i<m_selectedmime->count(); i++)
00986             l << m_selectedmime->text(i);
00987         m_cmd->setInputMimeTypes(l);
00988     }
00989     KDialogBase::slotOk();
00990 }
00991 
00992 bool KXmlCommandDlg::editCommand(KXmlCommand *xmlCmd, QWidget *parent)
00993 {
00994     if (!xmlCmd)
00995         return false;
00996 
00997     KXmlCommandDlg  xmldlg(parent, 0);
00998     xmldlg.setCommand(xmlCmd);
00999 
01000     return (xmldlg.exec() == Accepted);
01001 }
01002 
01003 void KXmlCommandDlg::slotAddMime()
01004 {
01005     int index = m_availablemime->currentItem();
01006     if (index != -1)
01007     {
01008         m_selectedmime->insertItem(m_availablemime->currentText());
01009         m_availablemime->removeItem(index);
01010         m_selectedmime->sort();
01011     }
01012 }
01013 
01014 void KXmlCommandDlg::slotRemoveMime()
01015 {
01016     int index = m_selectedmime->currentItem();
01017     if (index != -1)
01018     {
01019         m_availablemime->insertItem(m_selectedmime->currentText());
01020         m_selectedmime->removeItem(index);
01021         m_availablemime->sort();
01022     }
01023 }
01024 
01025 void KXmlCommandDlg::slotEditCommand()
01026 {
01027     KXmlCommandAdvancedDlg::editCommand(m_cmd, parentWidget());
01028 }
01029 
01030 void KXmlCommandDlg::slotAddReq()
01031 {
01032     QListViewItem   *item = new QListViewItem(m_requirements, m_requirements->lastItem(), i18n("exec:/"));
01033     item->setRenameEnabled(0, true);
01034     m_requirements->ensureItemVisible(item);
01035     item->startRename(0);
01036 }
01037 
01038 void KXmlCommandDlg::slotRemoveReq()
01039 {
01040     delete m_requirements->currentItem();
01041 }
01042 
01043 void KXmlCommandDlg::slotReqSelected(QListViewItem *item)
01044 {
01045     m_removereq->setEnabled(item);
01046 }
01047 
01048 void KXmlCommandDlg::slotAvailableSelected(QListBoxItem *item)
01049 {
01050     m_addmime->setEnabled(item);
01051 }
01052 
01053 void KXmlCommandDlg::slotSelectedSelected(QListBoxItem *item)
01054 {
01055     m_removemime->setEnabled(item);
01056 }
01057 
01058 #include "kxmlcommanddlg.moc"
KDE Home | KDE Accessibility Home | Description of Access Keys