katedialogs.cpp

00001 /* This file is part of the KDE libraries
00002    Copyright (C) 2002, 2003 Anders Lund <anders.lund@lund.tdcadsl.dk>
00003    Copyright (C) 2003 Christoph Cullmann <cullmann@kde.org>
00004    Copyright (C) 2001 Joseph Wenninger <jowenn@kde.org>
00005 
00006    Based on work of:
00007      Copyright (C) 1999 Jochen Wilhelmy <digisnap@cs.tu-berlin.de>
00008 
00009    This library is free software; you can redistribute it and/or
00010    modify it under the terms of the GNU Library General Public
00011    License version 2 as published by the Free Software Foundation.
00012 
00013    This library is distributed in the hope that it will be useful,
00014    but WITHOUT ANY WARRANTY; without even the implied warranty of
00015    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00016    Library General Public License for more details.
00017 
00018    You should have received a copy of the GNU Library General Public License
00019    along with this library; see the file COPYING.LIB.  If not, write to
00020    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
00021    Boston, MA 02110-1301, USA.
00022 */
00023 
00024 //BEGIN Includes
00025 #include "katedialogs.h"
00026 #include "katedialogs.moc"
00027 
00028 #include "kateautoindent.h"
00029 #include "katebuffer.h"
00030 #include "kateconfig.h"
00031 #include "katedocument.h"
00032 #include "katefactory.h"
00033 #include "kateschema.h"
00034 #include "katesyntaxdocument.h"
00035 #include "kateview.h"
00036 
00037 
00038 #include <ktexteditor/configinterfaceextension.h>
00039 #include <ktexteditor/plugin.h>
00040 
00041 #include <kio/job.h>
00042 #include <kio/jobclasses.h>
00043 #include <kio/netaccess.h>
00044 
00045 #include <kaccel.h>
00046 #include <kapplication.h>
00047 #include <kbuttonbox.h>
00048 #include <kcharsets.h>
00049 #include <kcolorbutton.h>
00050 #include <kcolorcombo.h>
00051 #include <kcolordialog.h>
00052 #include <kcombobox.h>
00053 #include <kconfig.h>
00054 #include <kdebug.h>
00055 #include <kfontdialog.h>
00056 #include <kglobal.h>
00057 #include <kglobalsettings.h>
00058 #include <kiconloader.h>
00059 #include <kkeybutton.h>
00060 #include <kkeydialog.h>
00061 #include <klineedit.h>
00062 #include <klistview.h>
00063 #include <klocale.h>
00064 #include <kmessagebox.h>
00065 #include <kmimetypechooser.h>
00066 #include <knuminput.h>
00067 #include <kparts/componentfactory.h>
00068 #include <kpopupmenu.h>
00069 #include <kprocess.h>
00070 #include <kprocio.h>
00071 #include <kregexpeditorinterface.h>
00072 #include <krun.h>
00073 #include <kseparator.h>
00074 #include <kstandarddirs.h>
00075 #include <ktempfile.h>
00076 
00077 #include <qbuttongroup.h>
00078 #include <qcheckbox.h>
00079 #include <qcombobox.h>
00080 #include <qdialog.h>
00081 #include <qdom.h>
00082 #include <qfile.h>
00083 #include <qgrid.h>
00084 #include <qgroupbox.h>
00085 #include <qhbox.h>
00086 #include <qheader.h>
00087 #include <qhgroupbox.h>
00088 #include <qlabel.h>
00089 #include <qlayout.h>
00090 #include <qlineedit.h>
00091 #include <qlistbox.h>
00092 #include <qlistview.h>
00093 #include <qmap.h>
00094 #include <qobjectlist.h>
00095 #include <qpainter.h>
00096 #include <qpointarray.h>
00097 #include <qptrcollection.h>
00098 #include <qpushbutton.h>
00099 #include <qradiobutton.h>
00100 #include <qslider.h>
00101 #include <qspinbox.h>
00102 #include <qstringlist.h>
00103 #include <qtabwidget.h>
00104 #include <qtextcodec.h>
00105 #include <qtoolbutton.h>
00106 #include <qvbox.h>
00107 #include <qvgroupbox.h>
00108 #include <qwhatsthis.h>
00109 #include <qwidgetstack.h>
00110 
00111 // trailing slash is important
00112 #define HLDOWNLOADPATH "http://kate.kde.org/syntax/"
00113 
00114 //END
00115 
00116 //BEGIN KateConfigPage
00117 KateConfigPage::KateConfigPage ( QWidget *parent, const char *name )
00118   : Kate::ConfigPage (parent, name)
00119   , m_changed (false)
00120 {
00121   connect (this, SIGNAL(changed()), this, SLOT(somethingHasChanged ()));
00122 }
00123 
00124 KateConfigPage::~KateConfigPage ()
00125 {
00126 }
00127 
00128 void KateConfigPage::somethingHasChanged ()
00129 {
00130   m_changed = true;
00131   kdDebug (13000) << "TEST: something changed on the config page: " << this << endl;
00132 }
00133 //END KateConfigPage
00134 
00135 //BEGIN KateIndentConfigTab
00136 const int KateIndentConfigTab::flags[] = {
00137     KateDocument::cfSpaceIndent,
00138     KateDocument::cfKeepIndentProfile,
00139     KateDocument::cfKeepExtraSpaces,
00140     KateDocument::cfTabIndents,
00141     KateDocument::cfBackspaceIndents,
00142     KateDocumentConfig::cfDoxygenAutoTyping,
00143     KateDocumentConfig::cfMixedIndent
00144 };
00145 
00146 KateIndentConfigTab::KateIndentConfigTab(QWidget *parent)
00147   : KateConfigPage(parent)
00148 {
00149   QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00150   int configFlags = KateDocumentConfig::global()->configFlags();
00151 
00152   QVGroupBox *gbAuto = new QVGroupBox(i18n("Automatic Indentation"), this);
00153 
00154   QHBox *indentLayout = new QHBox(gbAuto);
00155   indentLayout->setSpacing(KDialog::spacingHint());
00156   QLabel *indentLabel = new QLabel(i18n("&Indentation mode:"), indentLayout);
00157   m_indentMode = new KComboBox (indentLayout);
00158   m_indentMode->insertStringList (KateAutoIndent::listModes());
00159   indentLabel->setBuddy(m_indentMode);
00160   m_configPage = new QPushButton(SmallIconSet("configure"), i18n("Configure..."), indentLayout);
00161 
00162   opt[5] = new QCheckBox(i18n("Insert leading Doxygen \"*\" when typing"), gbAuto);
00163 
00164   QVGroupBox *gbSpaces = new QVGroupBox(i18n("Indentation with Spaces"), this);
00165   QVBox *spaceLayout = new QVBox(gbSpaces);
00166   opt[0] = new QCheckBox(i18n("Use &spaces instead of tabs to indent"), spaceLayout );
00167   opt[6] = new QCheckBox(i18n("Emacs style mixed mode"), spaceLayout);
00168 
00169   indentationWidth = new KIntNumInput(KateDocumentConfig::global()->indentationWidth(), spaceLayout);
00170   indentationWidth->setRange(1, 16, 1, false);
00171   indentationWidth->setLabel(i18n("Number of spaces:"), AlignVCenter);
00172 
00173   opt[1] = new QCheckBox(i18n("Keep indent &profile"), this);
00174   opt[2] = new QCheckBox(i18n("&Keep extra spaces"), this);
00175 
00176   QVGroupBox *keys = new QVGroupBox(i18n("Keys to Use"), this);
00177   opt[3] = new QCheckBox(i18n("&Tab key indents"), keys);
00178   opt[4] = new QCheckBox(i18n("&Backspace key indents"), keys);
00179 
00180   QRadioButton *rb1, *rb2, *rb3;
00181   m_tabs = new QButtonGroup( 1, Qt::Horizontal, i18n("Tab Key Mode if Nothing Selected"), this );
00182   m_tabs->setRadioButtonExclusive( true );
00183   m_tabs->insert( rb1=new QRadioButton( i18n("Insert indent &characters"), m_tabs ), 0 );
00184   m_tabs->insert( rb2=new QRadioButton( i18n("I&nsert tab character"), m_tabs ), 1 );
00185   m_tabs->insert( rb3=new QRadioButton( i18n("Indent current &line"), m_tabs ), 2 );
00186 
00187   opt[0]->setChecked(configFlags & flags[0]);
00188   opt[1]->setChecked(configFlags & flags[1]);
00189   opt[2]->setChecked(configFlags & flags[2]);
00190   opt[3]->setChecked(configFlags & flags[3]);
00191   opt[4]->setChecked(configFlags & flags[4]);
00192   opt[5]->setChecked(configFlags & flags[5]);
00193   opt[6]->setChecked(configFlags & flags[6]);
00194 
00195   layout->addWidget(gbAuto);
00196   layout->addWidget(gbSpaces);
00197   layout->addWidget(opt[1]);
00198   layout->addWidget(opt[2]);
00199   layout->addWidget(keys);
00200   layout->addWidget(m_tabs, 0);
00201 
00202   layout->addStretch();
00203 
00204   // What is this? help
00205   QWhatsThis::add(opt[0], i18n(
00206         "Check this if you want to indent with spaces rather than tabs."));
00207   QWhatsThis::add(opt[2], i18n(
00208         "Indentations of more than the selected number of spaces will not be "
00209         "shortened."));
00210   QWhatsThis::add(opt[3], i18n(
00211         "This allows the <b>Tab</b> key to be used to increase the indentation "
00212         "level."));
00213   QWhatsThis::add(opt[4], i18n(
00214         "This allows the <b>Backspace</b> key to be used to decrease the "
00215         "indentation level."));
00216   QWhatsThis::add(opt[5], i18n(
00217         "Automatically inserts a leading \"*\" while typing within a Doxygen "
00218         "style comment."));
00219   QWhatsThis::add( opt[6], i18n(
00220       "Use a mix of tab and space characters for indentation.") );
00221   QWhatsThis::add(indentationWidth, i18n("The number of spaces to indent with."));
00222 
00223   QWhatsThis::add(m_configPage, i18n(
00224         "If this button is enabled, additional indenter specific options are "
00225         "available and can be configured in an extra dialog.") );
00226 
00227   reload ();
00228 
00229   //
00230   // after initial reload, connect the stuff for the changed () signal
00231   //
00232 
00233   connect(m_indentMode, SIGNAL(activated(int)), this, SLOT(slotChanged()));
00234   connect(m_indentMode, SIGNAL(activated(int)), this, SLOT(indenterSelected(int)));
00235 
00236   connect( opt[0], SIGNAL(toggled(bool)), this, SLOT(somethingToggled()));
00237 
00238   connect( opt[0], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00239   connect( opt[1], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00240   connect( opt[2], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00241   connect( opt[3], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00242   connect( opt[4], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00243   connect( opt[5], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00244   connect( opt[6], SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00245 
00246   connect(indentationWidth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00247 
00248   connect(rb1, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00249   connect(rb2, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00250   connect(rb3, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00251 
00252   connect(m_configPage, SIGNAL(clicked()), this, SLOT(configPage()));
00253 }
00254 
00255 void KateIndentConfigTab::somethingToggled() {
00256   indentationWidth->setEnabled(opt[0]->isChecked());
00257   opt[6]->setEnabled(opt[0]->isChecked());
00258 }
00259 
00260 void KateIndentConfigTab::indenterSelected (int index)
00261 {
00262   if (index == KateDocumentConfig::imCStyle || index == KateDocumentConfig::imCSAndS)
00263     opt[5]->setEnabled(true);
00264   else
00265     opt[5]->setEnabled(false);
00266 
00267   m_configPage->setEnabled( KateAutoIndent::hasConfigPage(index) );
00268 }
00269 
00270 void KateIndentConfigTab::configPage()
00271 {
00272   uint index = m_indentMode->currentItem();
00273   if ( KateAutoIndent::hasConfigPage(index) )
00274   {
00275     KDialogBase dlg(this, "indenter_config_dialog", true, i18n("Configure Indenter"),
00276       KDialogBase::Ok|KDialogBase::Cancel, KDialogBase::Cancel, true);
00277 
00278     QVBox *box = new QVBox(&dlg);
00279     box->setSpacing( KDialog::spacingHint() );
00280     dlg.setMainWidget(box);
00281     new QLabel("<qt><b>" + KateAutoIndent::modeDescription(index) + "</b></qt>", box);
00282     new KSeparator(KSeparator::HLine, box);
00283 
00284     IndenterConfigPage* page = KateAutoIndent::configPage(box, index);
00285 
00286     if (!page) return;
00287     box->setStretchFactor(page, 1);
00288 
00289     connect( &dlg, SIGNAL(okClicked()), page, SLOT(apply()) );
00290 
00291     dlg.resize(400, 300);
00292     dlg.exec();
00293   }
00294 }
00295 
00296 void KateIndentConfigTab::apply ()
00297 {
00298   // nothing changed, no need to apply stuff
00299   if (!changed())
00300     return;
00301   m_changed = false;
00302 
00303   KateDocumentConfig::global()->configStart ();
00304 
00305   int configFlags, z;
00306 
00307   configFlags = KateDocumentConfig::global()->configFlags();
00308   for (z = 0; z < numFlags; z++) {
00309     configFlags &= ~flags[z];
00310     if (opt[z]->isChecked()) configFlags |= flags[z];
00311   }
00312 
00313   KateDocumentConfig::global()->setConfigFlags(configFlags);
00314   KateDocumentConfig::global()->setIndentationWidth(indentationWidth->value());
00315 
00316   KateDocumentConfig::global()->setIndentationMode(m_indentMode->currentItem());
00317 
00318   KateDocumentConfig::global()->setConfigFlags (KateDocumentConfig::cfTabIndentsMode, 2 == m_tabs->id (m_tabs->selected()));
00319   KateDocumentConfig::global()->setConfigFlags (KateDocumentConfig::cfTabInsertsTab, 1 == m_tabs->id (m_tabs->selected()));
00320 
00321   KateDocumentConfig::global()->configEnd ();
00322 }
00323 
00324 void KateIndentConfigTab::reload ()
00325 {
00326   if (KateDocumentConfig::global()->configFlags() & KateDocumentConfig::cfTabIndentsMode)
00327     m_tabs->setButton (2);
00328   else if (KateDocumentConfig::global()->configFlags() & KateDocumentConfig::cfTabInsertsTab)
00329     m_tabs->setButton (1);
00330   else
00331     m_tabs->setButton (0);
00332 
00333   m_indentMode->setCurrentItem (KateDocumentConfig::global()->indentationMode());
00334 
00335   somethingToggled ();
00336   indenterSelected (m_indentMode->currentItem());
00337 }
00338 //END KateIndentConfigTab
00339 
00340 //BEGIN KateSelectConfigTab
00341 const int KateSelectConfigTab::flags[] = {};
00342 
00343 KateSelectConfigTab::KateSelectConfigTab(QWidget *parent)
00344   : KateConfigPage(parent)
00345 {
00346   int configFlags = KateDocumentConfig::global()->configFlags();
00347 
00348   QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00349 
00350   QVGroupBox *gbCursor = new QVGroupBox(i18n("Text Cursor Movement"), this);
00351 
00352   opt[0] = new QCheckBox(i18n("Smart ho&me and smart end"), gbCursor);
00353   opt[0]->setChecked(configFlags & KateDocumentConfig::cfSmartHome);
00354   connect(opt[0], SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00355 
00356   opt[1] = new QCheckBox(i18n("Wrap c&ursor"), gbCursor);
00357   opt[1]->setChecked(configFlags & KateDocumentConfig::cfWrapCursor);
00358   connect(opt[1], SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00359 
00360   e6 = new QCheckBox(i18n("&PageUp/PageDown moves cursor"), gbCursor);
00361   e6->setChecked(KateDocumentConfig::global()->pageUpDownMovesCursor());
00362   connect(e6, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00363 
00364   e4 = new KIntNumInput(KateViewConfig::global()->autoCenterLines(), gbCursor);
00365   e4->setRange(0, 1000000, 1, false);
00366   e4->setLabel(i18n("Autocenter cursor (lines):"), AlignVCenter);
00367   connect(e4, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00368 
00369   layout->addWidget(gbCursor);
00370 
00371   QRadioButton *rb1, *rb2;
00372 
00373   m_tabs = new QButtonGroup( 1, Qt::Horizontal, i18n("Selection Mode"), this );
00374   layout->add (m_tabs);
00375 
00376   m_tabs->setRadioButtonExclusive( true );
00377   m_tabs->insert( rb1=new QRadioButton( i18n("&Normal"), m_tabs ), 0 );
00378   m_tabs->insert( rb2=new QRadioButton( i18n("&Persistent"), m_tabs ), 1 );
00379 
00380   layout->addStretch();
00381 
00382   QWhatsThis::add(rb1, i18n(
00383         "Selections will be overwritten by typed text and will be lost on "
00384         "cursor movement."));
00385   QWhatsThis::add(rb2, i18n(
00386         "Selections will stay even after cursor movement and typing."));
00387 
00388   QWhatsThis::add(e4, i18n(
00389         "Sets the number of lines to maintain visible above and below the "
00390         "cursor when possible."));
00391 
00392   QWhatsThis::add(opt[0], i18n(
00393         "When selected, pressing the home key will cause the cursor to skip "
00394         "whitespace and go to the start of a line's text. "
00395         "The same applies for the end key."));
00396 
00397     QWhatsThis::add(opt[1], i18n(
00398         "When on, moving the insertion cursor using the <b>Left</b> and "
00399         "<b>Right</b> keys will go on to previous/next line at beginning/end of "
00400         "the line, similar to most editors.<p>When off, the insertion cursor "
00401         "cannot be moved left of the line start, but it can be moved off the "
00402         "line end, which can be very handy for programmers."));
00403 
00404   QWhatsThis::add(e6, i18n("Selects whether the PageUp and PageDown keys should alter the vertical position of the cursor relative to the top of the view."));
00405 
00406 
00407   reload ();
00408 
00409   //
00410   // after initial reload, connect the stuff for the changed () signal
00411   //
00412 
00413   connect(rb1, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00414   connect(rb2, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00415 }
00416 
00417 void KateSelectConfigTab::apply ()
00418 {
00419   // nothing changed, no need to apply stuff
00420   if (!changed())
00421     return;
00422   m_changed = false;
00423 
00424   KateViewConfig::global()->configStart ();
00425   KateDocumentConfig::global()->configStart ();
00426 
00427   int configFlags = KateDocumentConfig::global()->configFlags();
00428 
00429   configFlags &= ~KateDocumentConfig::cfSmartHome;
00430   configFlags &= ~KateDocumentConfig::cfWrapCursor;
00431 
00432   if (opt[0]->isChecked()) configFlags |= KateDocumentConfig::cfSmartHome;
00433   if (opt[1]->isChecked()) configFlags |= KateDocumentConfig::cfWrapCursor;
00434 
00435   KateDocumentConfig::global()->setConfigFlags(configFlags);
00436 
00437   KateViewConfig::global()->setAutoCenterLines(kMax(0, e4->value()));
00438   KateDocumentConfig::global()->setPageUpDownMovesCursor(e6->isChecked());
00439 
00440   KateViewConfig::global()->setPersistentSelection (m_tabs->id (m_tabs->selected()) == 1);
00441 
00442   KateDocumentConfig::global()->configEnd ();
00443   KateViewConfig::global()->configEnd ();
00444 }
00445 
00446 void KateSelectConfigTab::reload ()
00447 {
00448   if (KateViewConfig::global()->persistentSelection())
00449     m_tabs->setButton (1);
00450   else
00451     m_tabs->setButton (0);
00452 }
00453 //END KateSelectConfigTab
00454 
00455 //BEGIN KateEditConfigTab
00456 const int KateEditConfigTab::flags[] = {KateDocument::cfWordWrap,
00457   KateDocument::cfAutoBrackets, KateDocument::cfShowTabs,
00458   KateDocumentConfig::cfReplaceTabsDyn, KateDocumentConfig::cfRemoveTrailingDyn};
00459 
00460 KateEditConfigTab::KateEditConfigTab(QWidget *parent)
00461   : KateConfigPage(parent)
00462 {
00463   QVBoxLayout *mainLayout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00464   int configFlags = KateDocumentConfig::global()->configFlags();
00465 
00466   QVGroupBox *gbWhiteSpace = new QVGroupBox(i18n("Tabulators"), this);
00467 
00468   opt[3] = new QCheckBox( i18n("&Insert spaces instead of tabulators"), gbWhiteSpace );
00469   opt[3]->setChecked( configFlags & KateDocumentConfig::cfReplaceTabsDyn );
00470   connect( opt[3], SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
00471 
00472   opt[2] = new QCheckBox(i18n("&Show tabulators"), gbWhiteSpace);
00473   opt[2]->setChecked(configFlags & flags[2]);
00474   connect(opt[2], SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00475 
00476   e2 = new KIntNumInput(KateDocumentConfig::global()->tabWidth(), gbWhiteSpace);
00477   e2->setRange(1, 16, 1, false);
00478   e2->setLabel(i18n("Tab width:"), AlignVCenter);
00479   connect(e2, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00480 
00481   mainLayout->addWidget(gbWhiteSpace);
00482 
00483   QVGroupBox *gbWordWrap = new QVGroupBox(i18n("Static Word Wrap"), this);
00484 
00485   opt[0] = new QCheckBox(i18n("Enable static &word wrap"), gbWordWrap);
00486   opt[0]->setChecked(KateDocumentConfig::global()->wordWrap());
00487   connect(opt[0], SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00488 
00489   m_wwmarker = new QCheckBox( i18n("&Show static word wrap marker (if applicable)"), gbWordWrap );
00490   m_wwmarker->setChecked( KateRendererConfig::global()->wordWrapMarker() );
00491   connect(m_wwmarker, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00492 
00493   e1 = new KIntNumInput(KateDocumentConfig::global()->wordWrapAt(), gbWordWrap);
00494   e1->setRange(20, 200, 1, false);
00495   e1->setLabel(i18n("Wrap words at:"), AlignVCenter);
00496   connect(e1, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00497 
00498   mainLayout->addWidget(gbWordWrap);
00499 
00500   opt[4] = new QCheckBox( i18n("Remove &trailing spaces"), this );
00501   mainLayout->addWidget( opt[4] );
00502   opt[4]->setChecked( configFlags & KateDocumentConfig::cfRemoveTrailingDyn );
00503   connect( opt[4], SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
00504 
00505   opt[1] = new QCheckBox(i18n("Auto &brackets"), this);
00506   mainLayout->addWidget(opt[1]);
00507   opt[1]->setChecked(configFlags & flags[1]);
00508   connect(opt[1], SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00509 
00510   e3 = new KIntNumInput(e2, KateDocumentConfig::global()->undoSteps(), this);
00511   e3->setRange(0, 1000000, 1, false);
00512   e3->setSpecialValueText( i18n("Unlimited") );
00513   e3->setLabel(i18n("Maximum undo steps:"), AlignVCenter);
00514   mainLayout->addWidget(e3);
00515   connect(e3, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00516 
00517   QHBoxLayout *e5Layout = new QHBoxLayout(mainLayout);
00518   QLabel *e5Label = new QLabel(i18n("Smart search t&ext from:"), this);
00519   e5Layout->addWidget(e5Label);
00520   e5 = new KComboBox (this);
00521   e5->insertItem( i18n("Nowhere") );
00522   e5->insertItem( i18n("Selection Only") );
00523   e5->insertItem( i18n("Selection, then Current Word") );
00524   e5->insertItem( i18n("Current Word Only") );
00525   e5->insertItem( i18n("Current Word, then Selection") );
00526   e5->setCurrentItem(KateViewConfig::global()->textToSearchMode());
00527   e5Layout->addWidget(e5);
00528   e5Label->setBuddy(e5);
00529   connect(e5, SIGNAL(activated(int)), this, SLOT(slotChanged()));
00530 
00531   mainLayout->addStretch();
00532 
00533   // What is this? help
00534   QWhatsThis::add(opt[0], i18n(
00535         "Automatically start a new line of text when the current line exceeds "
00536         "the length specified by the <b>Wrap words at:</b> option."
00537         "<p>This option does not wrap existing lines of text - use the <b>Apply "
00538         "Static Word Wrap</b> option in the <b>Tools</b> menu for that purpose."
00539         "<p>If you want lines to be <i>visually wrapped</i> instead, according "
00540         "to the width of the view, enable <b>Dynamic Word Wrap</b> in the "
00541         "<b>View Defaults</b> config page."));
00542   QWhatsThis::add(e1, i18n(
00543         "If the Word Wrap option is selected this entry determines the length "
00544         "(in characters) at which the editor will automatically start a new line."));
00545   QWhatsThis::add(opt[1], i18n(
00546         "When the user types a left bracket ([,(, or {) KateView automatically "
00547         "enters the right bracket (}, ), or ]) to the right of the cursor."));
00548   QWhatsThis::add(opt[2], i18n(
00549         "The editor will display a symbol to indicate the presence of a tab in "
00550         "the text."));
00551 
00552   QWhatsThis::add(e3, i18n(
00553         "Sets the number of undo/redo steps to record. More steps uses more memory."));
00554 
00555   QString gstfwt = i18n(
00556         "This determines where KateView will get the search text from "
00557         "(this will be automatically entered into the Find Text dialog): "
00558         "<br>"
00559         "<ul>"
00560         "<li><b>Nowhere:</b> Don't guess the search text."
00561         "</li>"
00562         "<li><b>Selection Only:</b> Use the current text selection, "
00563         "if available."
00564         "</li>"
00565         "<li><b>Selection, then Current Word:</b> Use the current "
00566         "selection if available, otherwise use the current word."
00567         "</li>"
00568         "<li><b>Current Word Only:</b> Use the word that the cursor "
00569         "is currently resting on, if available."
00570         "</li>"
00571         "<li><b>Current Word, then Selection:</b> Use the current "
00572         "word if available, otherwise use the current selection."
00573         "</li>"
00574         "</ul>"
00575         "Note that, in all the above modes, if a search string has "
00576         "not been or cannot be determined, then the Find Text Dialog "
00577         "will fall back to the last search text.");
00578   QWhatsThis::add(e5Label, gstfwt);
00579   QWhatsThis::add(e5, gstfwt);
00580   QWhatsThis::add( opt[3], i18n(
00581       "If this is enabled, the editor will calculate the number of spaces up to "
00582       "the next tab position as defined by the tab width, and insert that number "
00583       "of spaces instead of a TAB character." ) );
00584   QWhatsThis::add( opt[4], i18n(
00585       "If this is enabled, the editor will remove any trailing whitespace on "
00586       "lines when they are left by the insertion cursor.") );
00587   QWhatsThis::add( m_wwmarker, i18n(
00588         "<p>If this option is checked, a vertical line will be drawn at the word "
00589         "wrap column as defined in the <strong>Editing</strong> properties."
00590         "<p>Note that the word wrap marker is only drawn if you use a fixed "
00591         "pitch font." ));
00592 }
00593 
00594 void KateEditConfigTab::apply ()
00595 {
00596   // nothing changed, no need to apply stuff
00597   if (!changed())
00598     return;
00599   m_changed = false;
00600 
00601   KateViewConfig::global()->configStart ();
00602   KateDocumentConfig::global()->configStart ();
00603 
00604   int configFlags, z;
00605 
00606   configFlags = KateDocumentConfig::global()->configFlags();
00607   for (z = 1; z < numFlags; z++) {
00608     configFlags &= ~flags[z];
00609     if (opt[z]->isChecked()) configFlags |= flags[z];
00610   }
00611   KateDocumentConfig::global()->setConfigFlags(configFlags);
00612 
00613   KateDocumentConfig::global()->setWordWrapAt(e1->value());
00614   KateDocumentConfig::global()->setWordWrap (opt[0]->isChecked());
00615   KateDocumentConfig::global()->setTabWidth(e2->value());
00616 
00617   if (e3->value() <= 0)
00618     KateDocumentConfig::global()->setUndoSteps(0);
00619   else
00620     KateDocumentConfig::global()->setUndoSteps(e3->value());
00621 
00622   KateViewConfig::global()->setTextToSearchMode(e5->currentItem());
00623 
00624   KateRendererConfig::global()->setWordWrapMarker (m_wwmarker->isChecked());
00625 
00626   KateDocumentConfig::global()->configEnd ();
00627   KateViewConfig::global()->configEnd ();
00628 }
00629 
00630 void KateEditConfigTab::reload ()
00631 {
00632 }
00633 //END KateEditConfigTab
00634 
00635 //BEGIN KateViewDefaultsConfig
00636 KateViewDefaultsConfig::KateViewDefaultsConfig(QWidget *parent)
00637   :KateConfigPage(parent)
00638 {
00639   QRadioButton *rb1;
00640   QRadioButton *rb2;
00641 
00642   QVBoxLayout *blay=new QVBoxLayout(this,0,KDialog::spacingHint());
00643 
00644   QVGroupBox *gbWordWrap = new QVGroupBox(i18n("Word Wrap"), this);
00645 
00646   m_dynwrap=new QCheckBox(i18n("&Dynamic word wrap"),gbWordWrap);
00647 
00648   QHBox *m_dynwrapIndicatorsLay = new QHBox (gbWordWrap);
00649   m_dynwrapIndicatorsLabel = new QLabel( i18n("Dynamic word wrap indicators (if applicable):"), m_dynwrapIndicatorsLay );
00650   m_dynwrapIndicatorsCombo = new KComboBox( m_dynwrapIndicatorsLay );
00651   m_dynwrapIndicatorsCombo->insertItem( i18n("Off") );
00652   m_dynwrapIndicatorsCombo->insertItem( i18n("Follow Line Numbers") );
00653   m_dynwrapIndicatorsCombo->insertItem( i18n("Always On") );
00654   m_dynwrapIndicatorsLabel->setBuddy(m_dynwrapIndicatorsCombo);
00655 
00656   m_dynwrapAlignLevel = new KIntNumInput(gbWordWrap);
00657   m_dynwrapAlignLevel->setLabel(i18n("Vertically align dynamically wrapped lines to indentation depth:"));
00658   m_dynwrapAlignLevel->setRange(0, 80, 10);
00659   // xgettext:no-c-format
00660   m_dynwrapAlignLevel->setSuffix(i18n("% of View Width"));
00661   m_dynwrapAlignLevel->setSpecialValueText(i18n("Disabled"));
00662 
00663   blay->addWidget(gbWordWrap);
00664 
00665   QVGroupBox *gbFold = new QVGroupBox(i18n("Code Folding"), this);
00666 
00667   m_folding=new QCheckBox(i18n("Show &folding markers (if available)"), gbFold );
00668   m_collapseTopLevel = new QCheckBox( i18n("Collapse toplevel folding nodes"), gbFold );
00669   m_collapseTopLevel->hide ();
00670 
00671   blay->addWidget(gbFold);
00672 
00673   QVGroupBox *gbBar = new QVGroupBox(i18n("Borders"), this);
00674 
00675   m_icons=new QCheckBox(i18n("Show &icon border"),gbBar);
00676   m_line=new QCheckBox(i18n("Show &line numbers"),gbBar);
00677   m_scrollBarMarks=new QCheckBox(i18n("Show &scrollbar marks"),gbBar);
00678 
00679   blay->addWidget(gbBar);
00680 
00681   m_bmSort = new QButtonGroup( 1, Qt::Horizontal, i18n("Sort Bookmarks Menu"), this );
00682   m_bmSort->setRadioButtonExclusive( true );
00683   m_bmSort->insert( rb1=new QRadioButton( i18n("By &position"), m_bmSort ), 0 );
00684   m_bmSort->insert( rb2=new QRadioButton( i18n("By c&reation"), m_bmSort ), 1 );
00685 
00686   blay->addWidget(m_bmSort, 0 );
00687 
00688   m_showIndentLines = new QCheckBox(i18n("Show indentation lines"), this);
00689   m_showIndentLines->setChecked(KateRendererConfig::global()->showIndentationLines());
00690   blay->addWidget(m_showIndentLines);
00691 
00692   blay->addStretch(1000);
00693 
00694   QWhatsThis::add(m_dynwrap,i18n(
00695         "If this option is checked, the text lines will be wrapped at the view "
00696         "border on the screen."));
00697   QString wtstr = i18n("Choose when the Dynamic Word Wrap Indicators should be displayed");
00698   QWhatsThis::add(m_dynwrapIndicatorsLabel, wtstr);
00699   QWhatsThis::add(m_dynwrapIndicatorsCombo, wtstr);
00700   // xgettext:no-c-format
00701   QWhatsThis::add(m_dynwrapAlignLevel, i18n(
00702         "<p>Enables the start of dynamically wrapped lines to be aligned "
00703         "vertically to the indentation level of the first line.  This can help "
00704         "to make code and markup more readable.</p><p>Additionally, this allows "
00705         "you to set a maximum width of the screen, as a percentage, after which "
00706         "dynamically wrapped lines will no longer be vertically aligned.  For "
00707         "example, at 50%, lines whose indentation levels are deeper than 50% of "
00708         "the width of the screen will not have vertical alignment applied to "
00709         "subsequent wrapped lines.</p>"));
00710   QWhatsThis::add(m_line,i18n(
00711         "If this option is checked, every new view will display line numbers "
00712         "on the left hand side."));
00713   QWhatsThis::add(m_icons,i18n(
00714         "If this option is checked, every new view will display an icon border "
00715         "on the left hand side.<br><br>The icon border shows bookmark signs, "
00716         "for instance."));
00717   QWhatsThis::add(m_scrollBarMarks,i18n(
00718         "If this option is checked, every new view will show marks on the "
00719         "vertical scrollbar.<br><br>These marks will, for instance, show "
00720         "bookmarks."));
00721   QWhatsThis::add(m_folding,i18n(
00722         "If this option is checked, every new view will display marks for code "
00723         "folding, if code folding is available."));
00724   QWhatsThis::add(m_bmSort,i18n(
00725         "Choose how the bookmarks should be ordered in the <b>Bookmarks</b> menu."));
00726   QWhatsThis::add(rb1,i18n(
00727         "The bookmarks will be ordered by the line numbers they are placed at."));
00728   QWhatsThis::add(rb2,i18n(
00729         "Each new bookmark will be added to the bottom, independently from "
00730         "where it is placed in the document."));
00731   QWhatsThis::add(m_showIndentLines, i18n(
00732         "If this is enabled, the editor will display vertical lines to help "
00733         "identify indent lines.") );
00734 
00735   reload();
00736 
00737   //
00738   // after initial reload, connect the stuff for the changed () signal
00739   //
00740 
00741   connect(m_dynwrap, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00742   connect(m_dynwrapIndicatorsCombo, SIGNAL(activated(int)), this, SLOT(slotChanged()));
00743   connect(m_dynwrapAlignLevel, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00744   connect(m_icons, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00745   connect(m_scrollBarMarks, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00746   connect(m_line, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00747   connect(m_folding, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00748   connect(m_collapseTopLevel, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
00749   connect(rb1, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00750   connect(rb2, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00751   connect(m_showIndentLines, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00752 }
00753 
00754 KateViewDefaultsConfig::~KateViewDefaultsConfig()
00755 {
00756 }
00757 
00758 void KateViewDefaultsConfig::apply ()
00759 {
00760   // nothing changed, no need to apply stuff
00761   if (!changed())
00762     return;
00763   m_changed = false;
00764 
00765   KateViewConfig::global()->configStart ();
00766   KateRendererConfig::global()->configStart ();
00767 
00768   KateViewConfig::global()->setDynWordWrap (m_dynwrap->isChecked());
00769   KateViewConfig::global()->setDynWordWrapIndicators (m_dynwrapIndicatorsCombo->currentItem ());
00770   KateViewConfig::global()->setDynWordWrapAlignIndent(m_dynwrapAlignLevel->value());
00771   KateViewConfig::global()->setLineNumbers (m_line->isChecked());
00772   KateViewConfig::global()->setIconBar (m_icons->isChecked());
00773   KateViewConfig::global()->setScrollBarMarks (m_scrollBarMarks->isChecked());
00774   KateViewConfig::global()->setFoldingBar (m_folding->isChecked());
00775   KateViewConfig::global()->setBookmarkSort (m_bmSort->id (m_bmSort->selected()));
00776 
00777   KateRendererConfig::global()->setShowIndentationLines(m_showIndentLines->isChecked());
00778 
00779   KateRendererConfig::global()->configEnd ();
00780   KateViewConfig::global()->configEnd ();
00781 }
00782 
00783 void KateViewDefaultsConfig::reload ()
00784 {
00785   m_dynwrap->setChecked(KateViewConfig::global()->dynWordWrap());
00786   m_dynwrapIndicatorsCombo->setCurrentItem( KateViewConfig::global()->dynWordWrapIndicators() );
00787   m_dynwrapAlignLevel->setValue(KateViewConfig::global()->dynWordWrapAlignIndent());
00788   m_line->setChecked(KateViewConfig::global()->lineNumbers());
00789   m_icons->setChecked(KateViewConfig::global()->iconBar());
00790   m_scrollBarMarks->setChecked(KateViewConfig::global()->scrollBarMarks());
00791   m_folding->setChecked(KateViewConfig::global()->foldingBar());
00792   m_bmSort->setButton( KateViewConfig::global()->bookmarkSort() );
00793   m_showIndentLines->setChecked(KateRendererConfig::global()->showIndentationLines());
00794 }
00795 
00796 void KateViewDefaultsConfig::reset () {;}
00797 
00798 void KateViewDefaultsConfig::defaults (){;}
00799 //END KateViewDefaultsConfig
00800 
00801 //BEGIN KateEditKeyConfiguration
00802 
00803 KateEditKeyConfiguration::KateEditKeyConfiguration( QWidget* parent, KateDocument* doc )
00804   : KateConfigPage( parent )
00805 {
00806   m_doc = doc;
00807   m_ready = false;
00808 }
00809 
00810 void KateEditKeyConfiguration::showEvent ( QShowEvent * )
00811 {
00812   if (!m_ready)
00813   {
00814     (new QVBoxLayout(this))->setAutoAdd(true);
00815     KateView* view = (KateView*)m_doc->views().at(0);
00816     m_ac = view->editActionCollection();
00817     m_keyChooser = new KKeyChooser( m_ac, this, false );
00818     connect( m_keyChooser, SIGNAL( keyChange() ), this, SLOT( slotChanged() ) );
00819     m_keyChooser->show ();
00820 
00821     m_ready = true;
00822   }
00823 
00824   QWidget::show ();
00825 }
00826 
00827 void KateEditKeyConfiguration::apply()
00828 {
00829   if ( ! changed() )
00830     return;
00831   m_changed = false;
00832 
00833   if (m_ready)
00834   {
00835     m_keyChooser->commitChanges();
00836     m_ac->writeShortcutSettings( "Katepart Shortcuts" );
00837   }
00838 }
00839 //END KateEditKeyConfiguration
00840 
00841 //BEGIN KateSaveConfigTab
00842 KateSaveConfigTab::KateSaveConfigTab( QWidget *parent )
00843   : KateConfigPage( parent )
00844 {
00845   int configFlags = KateDocumentConfig::global()->configFlags();
00846   QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
00847 
00848   QVGroupBox *gbEnc = new QVGroupBox(i18n("File Format"), this);
00849   layout->addWidget( gbEnc );
00850 
00851   QHBox *e5Layout = new QHBox(gbEnc);
00852   QLabel *e5Label = new QLabel(i18n("&Encoding:"), e5Layout);
00853   m_encoding = new KComboBox (e5Layout);
00854   e5Label->setBuddy(m_encoding);
00855 
00856   e5Layout = new QHBox(gbEnc);
00857   e5Label = new QLabel(i18n("End &of line:"), e5Layout);
00858   m_eol = new KComboBox (e5Layout);
00859   e5Label->setBuddy(m_eol);
00860 
00861   allowEolDetection = new QCheckBox(i18n("&Automatic end of line detection"), gbEnc);
00862 
00863   m_eol->insertItem (i18n("UNIX"));
00864   m_eol->insertItem (i18n("DOS/Windows"));
00865   m_eol->insertItem (i18n("Macintosh"));
00866 
00867   QVGroupBox *gbMem = new QVGroupBox(i18n("Memory Usage"), this);
00868   layout->addWidget( gbMem );
00869 
00870   e5Layout = new QHBox(gbMem);
00871   e5Layout->setSpacing (32);
00872   blockCountLabel = new QLabel(i18n("Maximum loaded &blocks per file:"), e5Layout);
00873   blockCount = new QSpinBox (4, 512, 4, e5Layout);
00874 
00875   blockCount->setValue (KateBuffer::maxLoadedBlocks());
00876   blockCountLabel->setBuddy(blockCount);
00877 
00878   QVGroupBox *gbWhiteSpace = new QVGroupBox(i18n("Automatic Cleanups on Load/Save"), this);
00879   layout->addWidget( gbWhiteSpace );
00880 
00881   removeSpaces = new QCheckBox(i18n("Re&move trailing spaces"), gbWhiteSpace);
00882   removeSpaces->setChecked(configFlags & KateDocument::cfRemoveSpaces);
00883 
00884   QVGroupBox *dirConfigBox = new QVGroupBox(i18n("Folder Config File"), this);
00885   layout->addWidget( dirConfigBox );
00886 
00887   dirSearchDepth = new KIntNumInput(KateDocumentConfig::global()->searchDirConfigDepth(), dirConfigBox);
00888   dirSearchDepth->setRange(-1, 64, 1, false);
00889   dirSearchDepth->setSpecialValueText( i18n("Do not use config file") );
00890   dirSearchDepth->setLabel(i18n("Se&arch depth for config file:"), AlignVCenter);
00891 
00892   QGroupBox *gb = new QGroupBox( 1, Qt::Horizontal, i18n("Backup on Save"), this );
00893   layout->addWidget( gb );
00894   cbLocalFiles = new QCheckBox( i18n("&Local files"), gb );
00895   cbRemoteFiles = new QCheckBox( i18n("&Remote files"), gb );
00896 
00897   QHBox *hbBuPrefix = new QHBox( gb );
00898   QLabel *lBuPrefix = new QLabel( i18n("&Prefix:"), hbBuPrefix );
00899   leBuPrefix = new QLineEdit( hbBuPrefix );
00900   lBuPrefix->setBuddy( leBuPrefix );
00901 
00902   QHBox *hbBuSuffix = new QHBox( gb );
00903   QLabel *lBuSuffix = new QLabel( i18n("&Suffix:"), hbBuSuffix );
00904   leBuSuffix = new QLineEdit( hbBuSuffix );
00905   lBuSuffix->setBuddy( leBuSuffix );
00906 
00907   layout->addStretch();
00908 
00909   QWhatsThis::add(removeSpaces, i18n(
00910         "The editor will automatically eliminate extra spaces at the ends of "
00911         "lines of text while loading/saving the file."));
00912   QWhatsThis::add( gb, i18n(
00913         "<p>Backing up on save will cause Kate to copy the disk file to "
00914         "'&lt;prefix&gt;&lt;filename&gt;&lt;suffix&gt;' before saving changes."
00915         "<p>The suffix defaults to <strong>~</strong> and prefix is empty by default" ) );
00916   QWhatsThis::add( allowEolDetection, i18n(
00917         "Check this if you want the editor to autodetect the end of line type."
00918         "The first found end of line type will be used for the whole file.") );
00919   QWhatsThis::add( cbLocalFiles, i18n(
00920         "Check this if you want backups of local files when saving") );
00921   QWhatsThis::add( cbRemoteFiles, i18n(
00922         "Check this if you want backups of remote files when saving") );
00923   QWhatsThis::add( leBuPrefix, i18n(
00924         "Enter the prefix to prepend to the backup file names" ) );
00925   QWhatsThis::add( leBuSuffix, i18n(
00926         "Enter the suffix to add to the backup file names" ) );
00927   QWhatsThis::add(dirSearchDepth, i18n(
00928         "The editor will search the given number of folder levels upwards for .kateconfig file"
00929         " and load the settings line from it." ));
00930   QWhatsThis::add(blockCount, i18n(
00931         "The editor will load given number of blocks (of around 2048 lines) of text into memory;"
00932         " if the filesize is bigger than this the other blocks are swapped "
00933         " to disk and loaded transparently as-needed.<br>"
00934         " This can cause little delays while navigating in the document; a larger block count"
00935         " increases the editing speed at the cost of memory. <br>For normal usage, just choose the highest possible"
00936         " block count: limit it only if you have problems with the memory usage."));
00937 
00938   reload();
00939 
00940   //
00941   // after initial reload, connect the stuff for the changed () signal
00942   //
00943 
00944   connect(m_encoding, SIGNAL(activated(int)), this, SLOT(slotChanged()));
00945   connect(m_eol, SIGNAL(activated(int)), this, SLOT(slotChanged()));
00946   connect( allowEolDetection, SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00947   connect(blockCount, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00948   connect(removeSpaces, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
00949   connect( cbLocalFiles, SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00950   connect( cbRemoteFiles, SIGNAL( toggled(bool) ), this, SLOT( slotChanged() ) );
00951   connect(dirSearchDepth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
00952   connect( leBuPrefix, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00953   connect( leBuSuffix, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
00954 }
00955 
00956 void KateSaveConfigTab::apply()
00957 {
00958   // nothing changed, no need to apply stuff
00959   if (!changed())
00960     return;
00961   m_changed = false;
00962 
00963   KateBuffer::setMaxLoadedBlocks (blockCount->value());
00964 
00965   KateDocumentConfig::global()->configStart ();
00966 
00967   if ( leBuSuffix->text().isEmpty() && leBuPrefix->text().isEmpty() ) {
00968     KMessageBox::information(
00969                 this,
00970                 i18n("You did not provide a backup suffix or prefix. Using default suffix: '~'"),
00971                 i18n("No Backup Suffix or Prefix")
00972                         );
00973     leBuSuffix->setText( "~" );
00974   }
00975 
00976   uint f( 0 );
00977   if ( cbLocalFiles->isChecked() )
00978     f |= KateDocumentConfig::LocalFiles;
00979   if ( cbRemoteFiles->isChecked() )
00980     f |= KateDocumentConfig::RemoteFiles;
00981 
00982   KateDocumentConfig::global()->setBackupFlags(f);
00983   KateDocumentConfig::global()->setBackupPrefix(leBuPrefix->text());
00984   KateDocumentConfig::global()->setBackupSuffix(leBuSuffix->text());
00985 
00986   KateDocumentConfig::global()->setSearchDirConfigDepth(dirSearchDepth->value());
00987 
00988   int configFlags = KateDocumentConfig::global()->configFlags();
00989 
00990   configFlags &= ~KateDocument::cfRemoveSpaces; // clear flag
00991   if (removeSpaces->isChecked()) configFlags |= KateDocument::cfRemoveSpaces; // set flag if checked
00992 
00993   KateDocumentConfig::global()->setConfigFlags(configFlags);
00994 
00995   KateDocumentConfig::global()->setEncoding((m_encoding->currentItem() == 0) ? "" : KGlobal::charsets()->encodingForName(m_encoding->currentText()));
00996 
00997   KateDocumentConfig::global()->setEol(m_eol->currentItem());
00998   KateDocumentConfig::global()->setAllowEolDetection(allowEolDetection->isChecked());
00999 
01000   KateDocumentConfig::global()->configEnd ();
01001 }
01002 
01003 void KateSaveConfigTab::reload()
01004 {
01005   // encoding
01006   m_encoding->clear ();
01007   m_encoding->insertItem (i18n("KDE Default"));
01008   m_encoding->setCurrentItem(0);
01009   QStringList encodings (KGlobal::charsets()->descriptiveEncodingNames());
01010   int insert = 1;
01011   for (uint i=0; i < encodings.count(); i++)
01012   {
01013     bool found = false;
01014     QTextCodec *codecForEnc = KGlobal::charsets()->codecForName(KGlobal::charsets()->encodingForName(encodings[i]), found);
01015 
01016     if (found)
01017     {
01018       m_encoding->insertItem (encodings[i]);
01019 
01020       if ( codecForEnc->name() == KateDocumentConfig::global()->encoding() )
01021       {
01022         m_encoding->setCurrentItem(insert);
01023       }
01024 
01025       insert++;
01026     }
01027   }
01028 
01029   // eol
01030   m_eol->setCurrentItem(KateDocumentConfig::global()->eol());
01031   allowEolDetection->setChecked(KateDocumentConfig::global()->allowEolDetection());
01032 
01033   dirSearchDepth->setValue(KateDocumentConfig::global()->searchDirConfigDepth());
01034 
01035   // other stuff
01036   uint f ( KateDocumentConfig::global()->backupFlags() );
01037   cbLocalFiles->setChecked( f & KateDocumentConfig::LocalFiles );
01038   cbRemoteFiles->setChecked( f & KateDocumentConfig::RemoteFiles );
01039   leBuPrefix->setText( KateDocumentConfig::global()->backupPrefix() );
01040   leBuSuffix->setText( KateDocumentConfig::global()->backupSuffix() );
01041 }
01042 
01043 void KateSaveConfigTab::reset()
01044 {
01045 }
01046 
01047 void KateSaveConfigTab::defaults()
01048 {
01049   cbLocalFiles->setChecked( true );
01050   cbRemoteFiles->setChecked( false );
01051   leBuPrefix->setText( "" );
01052   leBuSuffix->setText( "~" );
01053 }
01054 
01055 //END KateSaveConfigTab
01056 
01057 //BEGIN PluginListItem
01058 class KatePartPluginListItem : public QCheckListItem
01059 {
01060   public:
01061     KatePartPluginListItem(bool checked, uint i, const QString &name, QListView *parent);
01062     uint pluginIndex () const { return index; }
01063 
01064   protected:
01065     void stateChange(bool);
01066 
01067   private:
01068     uint index;
01069     bool silentStateChange;
01070 };
01071 
01072 KatePartPluginListItem::KatePartPluginListItem(bool checked, uint i, const QString &name, QListView *parent)
01073   : QCheckListItem(parent, name, CheckBox)
01074   , index(i)
01075   , silentStateChange(false)
01076 {
01077   silentStateChange = true;
01078   setOn(checked);
01079   silentStateChange = false;
01080 }
01081 
01082 void KatePartPluginListItem::stateChange(bool b)
01083 {
01084   if(!silentStateChange)
01085     static_cast<KatePartPluginListView *>(listView())->stateChanged(this, b);
01086 }
01087 //END
01088 
01089 //BEGIN PluginListView
01090 KatePartPluginListView::KatePartPluginListView(QWidget *parent, const char *name)
01091   : KListView(parent, name)
01092 {
01093 }
01094 
01095 void KatePartPluginListView::stateChanged(KatePartPluginListItem *item, bool b)
01096 {
01097   emit stateChange(item, b);
01098 }
01099 //END
01100 
01101 //BEGIN KatePartPluginConfigPage
01102 KatePartPluginConfigPage::KatePartPluginConfigPage (QWidget *parent) : KateConfigPage (parent, "")
01103 {
01104   // sizemanagment
01105   QGridLayout *grid = new QGridLayout( this, 1, 1 );
01106   grid->setSpacing( KDialogBase::spacingHint() );
01107 
01108   listView = new KatePartPluginListView(this);
01109   listView->addColumn(i18n("Name"));
01110   listView->addColumn(i18n("Comment"));
01111 
01112   grid->addWidget( listView, 0, 0);
01113 
01114   for (uint i=0; i<KateFactory::self()->plugins().count(); i++)
01115   {
01116     KatePartPluginListItem *item = new KatePartPluginListItem(KateDocumentConfig::global()->plugin(i), i, (KateFactory::self()->plugins())[i]->name(), listView);
01117     item->setText(0, (KateFactory::self()->plugins())[i]->name());
01118     item->setText(1, (KateFactory::self()->plugins())[i]->comment());
01119 
01120     m_items.append (item);
01121   }
01122 
01123   // configure button
01124 
01125   btnConfigure = new QPushButton( i18n("Configure..."), this );
01126   btnConfigure->setEnabled( false );
01127   grid->addWidget( btnConfigure, 1, 0, Qt::AlignRight );
01128   connect( btnConfigure, SIGNAL(clicked()), this, SLOT(slotConfigure()) );
01129 
01130   connect( listView, SIGNAL(selectionChanged(QListViewItem*)), this, SLOT(slotCurrentChanged(QListViewItem*)) );
01131   connect( listView, SIGNAL(stateChange(KatePartPluginListItem *, bool)),
01132     this, SLOT(slotStateChanged(KatePartPluginListItem *, bool)));
01133   connect(listView, SIGNAL(stateChange(KatePartPluginListItem *, bool)), this, SLOT(slotChanged()));
01134 }
01135 
01136 KatePartPluginConfigPage::~KatePartPluginConfigPage ()
01137 {
01138 }
01139 
01140 void KatePartPluginConfigPage::apply ()
01141 {
01142   // nothing changed, no need to apply stuff
01143   if (!changed())
01144     return;
01145   m_changed = false;
01146 
01147   KateDocumentConfig::global()->configStart ();
01148 
01149   for (uint i=0; i < m_items.count(); i++)
01150     KateDocumentConfig::global()->setPlugin (m_items.at(i)->pluginIndex(), m_items.at(i)->isOn());
01151 
01152   KateDocumentConfig::global()->configEnd ();
01153 }
01154 
01155 void KatePartPluginConfigPage::slotStateChanged( KatePartPluginListItem *item, bool b )
01156 {
01157   if ( b )
01158     slotCurrentChanged( (QListViewItem*)item );
01159 }
01160 
01161 void KatePartPluginConfigPage::slotCurrentChanged( QListViewItem* i )
01162 {
01163   KatePartPluginListItem *item = static_cast<KatePartPluginListItem *>(i);
01164   if ( ! item ) return;
01165 
01166     bool b = false;
01167   if ( item->isOn() )
01168   {
01169 
01170     // load this plugin, and see if it has config pages
01171     KTextEditor::Plugin *plugin = KTextEditor::createPlugin(QFile::encodeName((KateFactory::self()->plugins())[item->pluginIndex()]->library()));
01172     if ( plugin ) {
01173       KTextEditor::ConfigInterfaceExtension *cie = KTextEditor::configInterfaceExtension( plugin );
01174       b = ( cie && cie->configPages() );
01175     }
01176 
01177   }
01178     btnConfigure->setEnabled( b );
01179 }
01180 
01181 void KatePartPluginConfigPage::slotConfigure()
01182 {
01183   KatePartPluginListItem *item = static_cast<KatePartPluginListItem*>(listView->currentItem());
01184   KTextEditor::Plugin *plugin =
01185     KTextEditor::createPlugin(QFile::encodeName((KateFactory::self()->plugins())[item->pluginIndex()]->library()));
01186 
01187   if ( ! plugin ) return;
01188 
01189   KTextEditor::ConfigInterfaceExtension *cife =
01190     KTextEditor::configInterfaceExtension( plugin );
01191 
01192   if ( ! cife )
01193     return;
01194 
01195   if ( ! cife->configPages() )
01196     return;
01197 
01198   // If we have only one page, we use a simple dialog, else an icon list type
01199   KDialogBase::DialogType dt =
01200     cife->configPages() > 1 ?
01201       KDialogBase::IconList :     // still untested
01202       KDialogBase::Plain;
01203 
01204   QString name = (KateFactory::self()->plugins())[item->pluginIndex()]->name();
01205   KDialogBase *kd = new KDialogBase ( dt,
01206               i18n("Configure %1").arg( name ),
01207               KDialogBase::Ok | KDialogBase::Cancel | KDialogBase::Help,
01208               KDialogBase::Ok,
01209               this );
01210 
01211   QPtrList<KTextEditor::ConfigPage> editorPages;
01212 
01213   for (uint i = 0; i < cife->configPages (); i++)
01214   {
01215     QWidget *page;
01216     if ( dt == KDialogBase::IconList )
01217     {
01218       QStringList path;
01219       path.clear();
01220       path << cife->configPageName( i );
01221       page = kd->addVBoxPage( path, cife->configPageFullName (i),
01222                                 cife->configPagePixmap(i, KIcon::SizeMedium) );
01223     }
01224     else
01225     {
01226       page = kd->plainPage();
01227       QVBoxLayout *_l = new QVBoxLayout( page );
01228       _l->setAutoAdd( true );
01229     }
01230 
01231     editorPages.append( cife->configPage( i, page ) );
01232   }
01233 
01234   if (kd->exec())
01235   {
01236 
01237     for( uint i=0; i<editorPages.count(); i++ )
01238     {
01239       editorPages.at( i )->apply();
01240     }
01241   }
01242 
01243   delete kd;
01244 }
01245 //END KatePartPluginConfigPage
01246 
01247 //BEGIN KateHlConfigPage
01248 KateHlConfigPage::KateHlConfigPage (QWidget *parent, KateDocument *doc)
01249  : KateConfigPage (parent, "")
01250  , hlData (0)
01251  , m_doc (doc)
01252 {
01253   QVBoxLayout *layout = new QVBoxLayout(this, 0, KDialog::spacingHint() );
01254 
01255   // hl chooser
01256   QHBox *hbHl = new QHBox( this );
01257   layout->add (hbHl);
01258 
01259   hbHl->setSpacing( KDialog::spacingHint() );
01260   QLabel *lHl = new QLabel( i18n("H&ighlight:"), hbHl );
01261   hlCombo = new QComboBox( false, hbHl );
01262   lHl->setBuddy( hlCombo );
01263   connect( hlCombo, SIGNAL(activated(int)),
01264            this, SLOT(hlChanged(int)) );
01265 
01266   for( int i = 0; i < KateHlManager::self()->highlights(); i++) {
01267     if (KateHlManager::self()->hlSection(i).length() > 0)
01268       hlCombo->insertItem(KateHlManager::self()->hlSection(i) + QString ("/") + KateHlManager::self()->hlNameTranslated(i));
01269     else
01270       hlCombo->insertItem(KateHlManager::self()->hlNameTranslated(i));
01271   }
01272 
01273   QGroupBox *gbInfo = new QGroupBox( 1, Qt::Horizontal, i18n("Information"), this );
01274   layout->add (gbInfo);
01275 
01276   // author
01277   QHBox *hb1 = new QHBox( gbInfo);
01278   new QLabel( i18n("Author:"), hb1 );
01279   author  = new QLabel (hb1);
01280   author->setTextFormat (Qt::RichText);
01281 
01282   // license
01283   QHBox *hb2 = new QHBox( gbInfo);
01284   new QLabel( i18n("License:"), hb2 );
01285   license  = new QLabel (hb2);
01286 
01287   QGroupBox *gbProps = new QGroupBox( 1, Qt::Horizontal, i18n("Properties"), this );
01288   layout->add (gbProps);
01289 
01290   // file & mime types
01291   QHBox *hbFE = new QHBox( gbProps);
01292   QLabel *lFileExts = new QLabel( i18n("File e&xtensions:"), hbFE );
01293   wildcards  = new QLineEdit( hbFE );
01294   lFileExts->setBuddy( wildcards );
01295 
01296   QHBox *hbMT = new QHBox( gbProps );
01297   QLabel *lMimeTypes = new QLabel( i18n("MIME &types:"), hbMT);
01298   mimetypes = new QLineEdit( hbMT );
01299   lMimeTypes->setBuddy( mimetypes );
01300 
01301   QHBox *hbMT2 = new QHBox( gbProps );
01302   QLabel *lprio = new QLabel( i18n("Prio&rity:"), hbMT2);
01303   priority = new KIntNumInput( hbMT2 );
01304 
01305   lprio->setBuddy( priority );
01306 
01307   QToolButton *btnMTW = new QToolButton(hbMT);
01308   btnMTW->setIconSet(QIconSet(SmallIcon("wizard")));
01309   connect(btnMTW, SIGNAL(clicked()), this, SLOT(showMTDlg()));
01310 
01311   // download/new buttons
01312   QHBox *hbBtns = new QHBox( this );
01313   layout->add (hbBtns);
01314 
01315   ((QBoxLayout*)hbBtns->layout())->addStretch(1); // hmm.
01316   hbBtns->setSpacing( KDialog::spacingHint() );
01317   QPushButton *btnDl = new QPushButton(i18n("Do&wnload..."), hbBtns);
01318   connect( btnDl, SIGNAL(clicked()), this, SLOT(hlDownload()) );
01319 
01320   int currentHl = m_doc ? m_doc->hlMode() : 0;
01321   hlCombo->setCurrentItem( currentHl );
01322   hlChanged( currentHl );
01323 
01324   QWhatsThis::add( hlCombo, i18n(
01325         "Choose a <em>Syntax Highlight mode</em> from this list to view its "
01326         "properties below.") );
01327   QWhatsThis::add( wildcards, i18n(
01328         "The list of file extensions used to determine which files to highlight "
01329         "using the current syntax highlight mode.") );
01330   QWhatsThis::add( mimetypes, i18n(
01331         "The list of Mime Types used to determine which files to highlight "
01332         "using the current highlight mode.<p>Click the wizard button on the "
01333         "left of the entry field to display the MimeType selection dialog.") );
01334   QWhatsThis::add( btnMTW, i18n(
01335         "Display a dialog with a list of all available mime types to choose from."
01336         "<p>The <strong>File Extensions</strong> entry will automatically be "
01337         "edited as well.") );
01338   QWhatsThis::add( btnDl, i18n(
01339         "Click this button to download new or updated syntax highlight "
01340         "descriptions from the Kate website.") );
01341 
01342   layout->addStretch ();
01343 
01344   connect( wildcards, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
01345   connect( mimetypes, SIGNAL( textChanged ( const QString & ) ), this, SLOT( slotChanged() ) );
01346   connect( priority, SIGNAL( valueChanged ( int ) ), this, SLOT( slotChanged() ) );
01347 }
01348 
01349 KateHlConfigPage::~KateHlConfigPage ()
01350 {
01351 }
01352 
01353 void KateHlConfigPage::apply ()
01354 {
01355   // nothing changed, no need to apply stuff
01356   if (!changed())
01357     return;
01358   m_changed = false;
01359 
01360   writeback();
01361 
01362   for ( QIntDictIterator<KateHlData> it( hlDataDict ); it.current(); ++it )
01363     KateHlManager::self()->getHl( it.currentKey() )->setData( it.current() );
01364 
01365   KateHlManager::self()->getKConfig()->sync ();
01366 }
01367 
01368 void KateHlConfigPage::reload ()
01369 {
01370 }
01371 
01372 void KateHlConfigPage::hlChanged(int z)
01373 {
01374   writeback();
01375 
01376   KateHighlighting *hl = KateHlManager::self()->getHl( z );
01377 
01378   if (!hl)
01379   {
01380     hlData = 0;
01381     return;
01382   }
01383 
01384   if ( !hlDataDict.find( z ) )
01385     hlDataDict.insert( z, hl->getData() );
01386 
01387   hlData = hlDataDict.find( z );
01388   wildcards->setText(hlData->wildcards);
01389   mimetypes->setText(hlData->mimetypes);
01390   priority->setValue(hlData->priority);
01391 
01392   // split author string if needed into multiple lines !
01393   QStringList l= QStringList::split (QRegExp("[,;]"), hl->author());
01394   author->setText (l.join ("<br>"));
01395 
01396   license->setText (hl->license());
01397 }
01398 
01399 void KateHlConfigPage::writeback()
01400 {
01401   if (hlData)
01402   {
01403     hlData->wildcards = wildcards->text();
01404     hlData->mimetypes = mimetypes->text();
01405     hlData->priority = priority->value();
01406   }
01407 }
01408 
01409 void KateHlConfigPage::hlDownload()
01410 {
01411   KateHlDownloadDialog diag(this,"hlDownload",true);
01412   diag.exec();
01413 }
01414 
01415 void KateHlConfigPage::showMTDlg()
01416 {
01417   QString text = i18n("Select the MimeTypes you want highlighted using the '%1' syntax highlight rules.\nPlease note that this will automatically edit the associated file extensions as well.").arg( hlCombo->currentText() );
01418   QStringList list = QStringList::split( QRegExp("\\s*;\\s*"), mimetypes->text() );
01419   KMimeTypeChooserDialog *d = new KMimeTypeChooserDialog( i18n("Select Mime Types"), text, list, "text", this );
01420 
01421   if ( d->exec() == KDialogBase::Accepted ) {
01422     // do some checking, warn user if mime types or patterns are removed.
01423     // if the lists are empty, and the fields not, warn.
01424     wildcards->setText(d->chooser()->patterns().join(";"));
01425     mimetypes->setText(d->chooser()->mimeTypes().join(";"));
01426   }
01427 }
01428 //END KateHlConfigPage
01429 
01430 //BEGIN KateHlDownloadDialog
01431 KateHlDownloadDialog::KateHlDownloadDialog(QWidget *parent, const char *name, bool modal)
01432   :KDialogBase(KDialogBase::Swallow, i18n("Highlight Download"), User1|Close, User1, parent, name, modal, true, i18n("&Install"))
01433 {
01434   QVBox* vbox = new QVBox(this);
01435   setMainWidget(vbox);
01436   vbox->setSpacing(spacingHint());
01437   new QLabel(i18n("Select the syntax highlighting files you want to update:"), vbox);
01438   list = new QListView(vbox);
01439   list->addColumn("");
01440   list->addColumn(i18n("Name"));
01441   list->addColumn(i18n("Installed"));
01442   list->addColumn(i18n("Latest"));
01443   list->setSelectionMode(QListView::Multi);
01444   list->setAllColumnsShowFocus(true);
01445 
01446   new QLabel(i18n("<b>Note:</b> New versions are selected automatically."), vbox);
01447   actionButton (User1)->setIconSet(SmallIconSet("ok"));
01448 
01449   transferJob = KIO::get(
01450     KURL(QString(HLDOWNLOADPATH)
01451        + QString("update-")
01452        + QString(KATEPART_VERSION)
01453        + QString(".xml")), true, true );
01454   connect(transferJob, SIGNAL(data(KIO::Job *, const QByteArray &)),
01455     this, SLOT(listDataReceived(KIO::Job *, const QByteArray &)));
01456 //        void data( KIO::Job *, const QByteArray &data);
01457   resize(450, 400);
01458 }
01459 
01460 KateHlDownloadDialog::~KateHlDownloadDialog(){}
01461 
01462 void KateHlDownloadDialog::listDataReceived(KIO::Job *, const QByteArray &data)
01463 {
01464   if (!transferJob || transferJob->isErrorPage())
01465   {
01466     actionButton(User1)->setEnabled(false);
01467     return;
01468   }
01469 
01470   listData+=QString(data);
01471   kdDebug(13000)<<QString("CurrentListData: ")<<listData<<endl<<endl;
01472   kdDebug(13000)<<QString("Data length: %1").arg(data.size())<<endl;
01473   kdDebug(13000)<<QString("listData length: %1").arg(listData.length())<<endl;
01474   if (data.size()==0)
01475   {
01476     if (listData.length()>0)
01477     {
01478       QString installedVersion;
01479       KateHlManager *hlm=KateHlManager::self();
01480       QDomDocument doc;
01481       doc.setContent(listData);
01482       QDomElement DocElem=doc.documentElement();
01483       QDomNode n=DocElem.firstChild();
01484       KateHighlighting *hl = 0;
01485 
01486       if (n.isNull()) kdDebug(13000)<<"There is no usable childnode"<<endl;
01487       while (!n.isNull())
01488       {
01489         installedVersion="    --";
01490 
01491         QDomElement e=n.toElement();
01492         if (!e.isNull())
01493         kdDebug(13000)<<QString("NAME: ")<<e.tagName()<<QString(" - ")<<e.attribute("name")<<endl;
01494         n=n.nextSibling();
01495 
01496         QString Name=e.attribute("name");
01497 
01498         for (int i=0;i<hlm->highlights();i++)
01499         {
01500           hl=hlm->getHl(i);
01501           if (hl && hl->name()==Name)
01502           {
01503             installedVersion="    "+hl->version();
01504             break;
01505           }
01506           else hl = 0;
01507         }
01508 
01509         // autoselect entry if new or updated.
01510         QListViewItem* entry = new QListViewItem(
01511           list, "", e.attribute("name"), installedVersion,
01512           e.attribute("version"),e.attribute("url"));
01513         if (!hl || hl->version() < e.attribute("version"))
01514         {
01515           entry->setSelected(true);
01516           entry->setPixmap(0, SmallIcon(("knewstuff")));
01517         }
01518       }
01519     }
01520   }
01521 }
01522 
01523 void KateHlDownloadDialog::slotUser1()
01524 {
01525   QString destdir=KGlobal::dirs()->saveLocation("data","katepart/syntax/");
01526   for (QListViewItem *it=list->firstChild();it;it=it->nextSibling())
01527   {
01528     if (list->isSelected(it))
01529     {
01530       KURL src(it->text(4));
01531       QString filename=src.fileName(false);
01532       QString dest = destdir+filename;
01533 
01534       KIO::NetAccess::download(src,dest, this);
01535     }
01536   }
01537 
01538   // update Config !!
01539   KateSyntaxDocument doc (true);
01540 }
01541 //END KateHlDownloadDialog
01542 
01543 //BEGIN KateGotoLineDialog
01544 KateGotoLineDialog::KateGotoLineDialog(QWidget *parent, int line, int max)
01545   : KDialogBase(parent, 0L, true, i18n("Go to Line"), Ok | Cancel, Ok) {
01546 
01547   QWidget *page = new QWidget(this);
01548   setMainWidget(page);
01549 
01550   QVBoxLayout *topLayout = new QVBoxLayout( page, 0, spacingHint() );
01551   e1 = new KIntNumInput(line, page);
01552   e1->setRange(1, max);
01553   e1->setEditFocus(true);
01554 
01555   QLabel *label = new QLabel( e1,i18n("&Go to line:"), page );
01556   topLayout->addWidget(label);
01557   topLayout->addWidget(e1);
01558   topLayout->addSpacing(spacingHint()); // A little bit extra space
01559   topLayout->addStretch(10);
01560   e1->setFocus();
01561 }
01562 
01563 int KateGotoLineDialog::getLine() {
01564   return e1->value();
01565 }
01566 //END KateGotoLineDialog
01567 
01568 //BEGIN KateModOnHdPrompt
01569 KateModOnHdPrompt::KateModOnHdPrompt( KateDocument *doc,
01570                                       int modtype,
01571                                       const QString &reason,
01572                                       QWidget *parent )
01573   : KDialogBase( parent, "", true, "", Ok|Apply|Cancel|User1 ),
01574     m_doc( doc ),
01575     m_modtype ( modtype ),
01576     m_tmpfile( 0 )
01577 {
01578   QString title, btnOK, whatisok;
01579   if ( modtype == 3 ) // deleted
01580   {
01581     title = i18n("File Was Deleted on Disk");
01582     btnOK = i18n("&Save File As...");
01583     whatisok = i18n("Lets you select a location and save the file again.");
01584   } else {
01585     title = i18n("File Changed on Disk");
01586     btnOK = i18n("&Reload File");
01587     whatisok = i18n("Reload the file from disk. If you have unsaved changes, "
01588         "they will be lost.");
01589   }
01590 
01591   setButtonText( Ok, btnOK);
01592   setButtonText( Apply, i18n("&Ignore") );
01593 
01594   setButtonWhatsThis( Ok, whatisok );
01595   setButtonWhatsThis( Apply, i18n("Ignore the changes. You will not be prompted again.") );
01596   setButtonWhatsThis( Cancel, i18n("Do nothing. Next time you focus the file, "
01597       "or try to save it or close it, you will be prompted again.") );
01598 
01599   enableButtonSeparator( true );
01600   setCaption( title );
01601 
01602   QFrame *w = makeMainWidget();
01603   QVBoxLayout *lo = new QVBoxLayout( w );
01604   QHBoxLayout *lo1 = new QHBoxLayout( lo );
01605   QLabel *icon = new QLabel( w );
01606   icon->setPixmap( DesktopIcon("messagebox_warning" ) );
01607   lo1->addWidget( icon );
01608   lo1->addWidget( new QLabel( reason + "\n\n" + i18n("What do you want to do?"), w ) );
01609 
01610   // If the file isn't deleted, present a diff button, and a overwrite action.
01611   if ( modtype != 3 )
01612   {
01613     QHBoxLayout *lo2 = new QHBoxLayout( lo );
01614     QPushButton *btnDiff = new QPushButton( i18n("&View Difference"), w );
01615     lo2->addStretch( 1 );
01616     lo2->addWidget( btnDiff );
01617     connect( btnDiff, SIGNAL(clicked()), this, SLOT(slotDiff()) );
01618     QWhatsThis::add( btnDiff, i18n(
01619         "Calculates the difference between the editor contents and the disk "
01620         "file using diff(1) and opens the diff file with the default application "
01621         "for that.") );
01622 
01623     setButtonText( User1, i18n("Overwrite") );
01624     setButtonWhatsThis( User1, i18n("Overwrite the disk file with the editor content.") );
01625   }
01626   else
01627     showButton( User1, false );
01628 }
01629 
01630 KateModOnHdPrompt::~KateModOnHdPrompt()
01631 {
01632 }
01633 
01634 void KateModOnHdPrompt::slotDiff()
01635 {
01636   // Start a KProcess that creates a diff
01637   KProcIO *p = new KProcIO();
01638   p->setComm( KProcess::All );
01639   *p << "diff" << "-u" << "-" <<  m_doc->url().path();
01640   connect( p, SIGNAL(processExited(KProcess*)), this, SLOT(slotPDone(KProcess*)) );
01641   connect( p, SIGNAL(readReady(KProcIO*)), this, SLOT(slotPRead(KProcIO*)) );
01642 
01643   setCursor( WaitCursor );
01644 
01645   p->start( KProcess::NotifyOnExit, true );
01646 
01647   uint lastln =  m_doc->numLines();
01648   for ( uint l = 0; l <  lastln; l++ )
01649     p->writeStdin( m_doc->textLine( l ) );
01650 
01651   p->closeWhenDone();
01652 }
01653 
01654 void KateModOnHdPrompt::slotPRead( KProcIO *p)
01655 {
01656   // create a file for the diff if we haven't one allready
01657   if ( ! m_tmpfile )
01658     m_tmpfile = new KTempFile();
01659   // put all the data we have in it
01660   QString stmp;
01661   bool dataRead = false;
01662   while ( p->readln( stmp, false ) > -1 )
01663   {
01664     *m_tmpfile->textStream() << stmp << endl;
01665     dataRead = true;
01666   }
01667 
01668   // dominik: only ackRead(), when we *really* read data, otherwise, this slot
01669   // is called initity times, which leads to a crash
01670   if( dataRead )
01671     p->ackRead();
01672 }
01673 
01674 void KateModOnHdPrompt::slotPDone( KProcess *p )
01675 {
01676   setCursor( ArrowCursor );
01677   if( ! m_tmpfile )
01678   {
01679     // dominik: there were only whitespace changes, so that the diff returned by
01680     // diff(1) has 0 bytes. So slotPRead() is never called, as there is
01681     // no data, so that m_tmpfile was never created and thus is NULL.
01682     // NOTE: would be nice, if we could produce a fake-diff, so that kompare
01683     //       tells us "The files are identical". Right now, we get an ugly
01684     //       "Could not parse diff output".
01685     m_tmpfile = new KTempFile();
01686   }
01687   m_tmpfile->close();
01688 
01689   if ( ! p->normalExit() /*|| p->exitStatus()*/ )
01690   {
01691     KMessageBox::sorry( this,
01692                         i18n("The diff command failed. Please make sure that "
01693                              "diff(1) is installed and in your PATH."),
01694                         i18n("Error Creating Diff") );
01695     return;
01696   }
01697 
01698   KRun::runURL( m_tmpfile->name(), "text/x-diff", true );
01699   delete m_tmpfile;
01700   m_tmpfile = 0;
01701 }
01702 
01703 void KateModOnHdPrompt::slotApply()
01704 {
01705   if ( KMessageBox::warningContinueCancel(
01706        this,
01707        i18n("Ignoring means that you will not be warned again (unless "
01708             "the disk file changes once more): if you save the document, you "
01709             "will overwrite the file on disk; if you do not save then the disk file "
01710             "(if present) is what you have."),
01711        i18n("You Are on Your Own"),
01712        KStdGuiItem::cont(),
01713        "kate_ignore_modonhd" ) != KMessageBox::Continue )
01714     return;
01715 
01716   done(Ignore);
01717 }
01718 
01719 void KateModOnHdPrompt::slotOk()
01720 {
01721   done( m_modtype == 3 ? Save : Reload );
01722 }
01723 
01724 void KateModOnHdPrompt::slotUser1()
01725 {
01726   done( Overwrite );
01727 }
01728 
01729 //END KateModOnHdPrompt
01730 
01731 // kate: space-indent on; indent-width 2; replace-tabs on;
KDE Home | KDE Accessibility Home | Description of Access Keys