diff --git a/doc/kate/configuring.docbook b/doc/kate/configuring.docbook
index ed2f40af0..9849c00ab 100644
--- a/doc/kate/configuring.docbook
+++ b/doc/kate/configuring.docbook
@@ -1,626 +1,621 @@
&Anders.Lund; &Anders.Lund.mail;
Configuring &kate;
Overview
configure
settings
preferences
&kate; offers several means of tweaking the application to behave as desired.
The most important ones are:
The Configuration Dialog
The main configuration tool, allowing you to configure the &kate; application,
the editor component and the usage of plugins.
The Settings Menu
Allows you to change often used settings, and to
launch the configuration dialogs.
The View Menu
Allows you to split the current frame, as well as to
display the icons and line numbers pane for the currently edited
document.
The embedded terminal is using the configuration defined in the
&systemsettings;, and may be configured by clicking the
right mouse button to display a context menu.
The Main Configuration Dialog
The &kate; configuration dialog displays a tree of topics on the
left, and a configuration page corresponding to the selected topic on
the right.
The configuration is divided into two groups, namely
Application configuration
Editor component configuration
The &kate; Application Configuration
This group contains pages to configure the main &kate; application
General
This section contains a few global options for &kate;
Behavior
Warn about files modified by foreign processes
When enabled, &kate; will notify you about files modified
from outside the application whenever the main window receives input focus.
You will be able to deal with several modified files at once, you
can reload, save or discard changed files in groups.
If not enabled, &kate; will prompt you for action when a externally
modified file receives focus within the application.
Meta Information
Keep meta-information past sessions
When enabled, &kate; will store meta data such as bookmarks
and session configuration even when you close your documents. The data
will be used if the document is unchanged when reopened.
Delete unused meta information after
Set the maximum number of days to keep meta information
for unopen files. This helps keeping the database of meta information
reasonably sized.
Default text-editing component
Select the text-editing component used by &kate;. By
default, it is configured to use the system default text-editing component as
configured in &systemsettings;.
Sessions
This section contains options related to using sessions.
Elements of Sessions
Include window configuration
If enabled, &kate; will save the window configuration
with each session.
Behavior on Application Startup
Select how you want &kate; to behave at startup. This setting can be
overridden by specifying what to do on the command line.
Start new session
With this option, &kate; will start a new, unnamed session
when you start it.
Load last-used session
&kate; will use the most recently opened session at
startup. This is good if you want to use the same session always or switch
rarely.
Manually choose a session
&kate; will display a small dialog that lets you choose
your preferred session, or load the default session if none have been saved.
This is the default behavior. Nice if you use a lot of different sessions
frequently.
The changes to the session data (opened files and if enabled,
window configuration) will always be saved.
Tree View
Background Shading
This section allows you to enable or disable the background
shading visualization of your recent activity, and chose which colors to use if
enabled. See the section about The Document List for more about
this feature.
Sort By
Set how you want the document list sorted. This can be set
from the &RMB; menu in the document list as well.
Show Full Path
When enabled, in tree mode, top level folders will show up
with their full path rather than just the last folder name.
Plugins
This page provides a list of installed plugins for the &kate;
application. Each plug-in is represented with its name and a short description.
You can check the checkbox with an item to enable the plug-in it represents.
If a plug-in provides configuration options, a section to access those
will appear as a child of this page.
Terminal
This page is only displayed by the Terminal Tool View plugin, which is
enabled by default.
Automatically synchronize the terminal with the current document when possible
This will cause the built-in terminal to
cd into the directory of the active document when
launched and when a new document gets the focus. If not enabled, you
have to do all your navigation in the terminal on your own.
Set EDITOR environment variable to 'kate -b'
This sets the EDITOR environment variable so programs
run in the built-in terminal that automatically open a file in an editor will open
them in &kate; instead of the default editor configured in your shell. You will
not be able to continue using the terminal until you have closed the file in &kate;,
so the calling program is aware you have finished editing the file.
&configuring-part-sections;
Configuring With Document Variables
&kappname; variables is katepart's implementation of document variables, similar
to emacs and vi modelines. In katepart, the lines have the following format:
kate: VARIABLENAME VALUE; [ VARIABLENAME VALUE; ... ]
The lines can of course be in a comment, if the file is in a format with comments.
Variable names are single words (no whitespace), and anything up to the next
semicolon is the value. The semicolon is required.
Here is an example variable line, forcing indentation settings for a C++,
java or javascript file:
// kate: replace-tabs on; indent-width 4; indent-mode cstyle;
Only the first and last 10 lines are searched for variable lines.
Additionally, document variables can be placed in a file called
.kateconfig in any directory, and the configured settings will
be applied as if the modelines were entered on every file in the directory and its
subdirectories, as far down as the
configured search depth.
Document variables in .kateconfig use the same syntax as
in modelines.
There are variables to support almost all configurations in katepart, and
additionally plugins can use variables, in which case it should be documented in
the plugin's documentation.
How &kappname; uses Variables
When reading configuration, katepart looks in the following places
(in that order):
The global configuration.
Optional session data.
The "Filetype" configuration.
Document variables in .kateconfig.
Document variables in the document itself.
Settings made during editing from menu or command line.
As you see, document variables are only overriden by changes made at runtime.
Whenever a document is saved, the document variables are reread, and will
overwrite changes made using menu items or the command line.
Any variable not listed below is stored in the document and can be queried
by other objects such as plugins, which can use them for their own purpose.
For example, the variable indent mode uses document variables for its
configuration.
The variables listed here documents &kappname; version 3.7. More variables
may be added in the future. There are 3 possible types of values for variables,
with the following valid expressions:
BOOL - on|off|true|false|1|0
INTEGER - any integer number
STRING - anything else
Available Variables
-
-auto-bracketsBOOL
-Set auto insertion of brackets on or off.
-
-
auto-center-linesINT
Set the number of autocenter lines.
auto-insert-doxygenBOOL
Turn insertion of the leading asterisk in doxygen comments on or
off. This has no effect unless you use the C-style auto-indenter.
background-colorSTRING
Set the document background color. The value must be something
that can be evaluated to a valid color, for example #ff0000.
backspace-indentsBOOL
Enable or disable unindenting when &Backspace; is pressed.
block-selectionBOOL
Turn block selection
on or off.
bom | byte-order-markerBOOL
Enable/disable the byte order marker when saving files in unicode format
(utf8, utf16, utf32).
Since: Kate 3.4 (KDE 4.4)
encodingSTRING
Set the encoding used for loading or saving the file.
As the variables in the document will be read after loading, this impacts only the saving.
If you place it in a .kateconfig file, it will have an effect for the loading, too.
Since: Kate 3.10 (KDE 4.10)
bracket-highlight-colorSTRING
Set the color for the bracket highlight. The value must be
something that can be evaluated to a valid color, for example #ff0000.
current-line-colorSTRING
Set the color for the current line. The value must be
something that can be evaluated to a valid color, for example #ff0000
default-dictionarySTRING
Sets the default dictionary used for spell checking.
Since: Kate 3.4 (KDE 4.4)
dynamic-word-wrapBOOL
Turns dynamic word wrap on or
off.
eol | end-of-lineSTRING
Set the end of line mode. Valid settings are
unix, mac and dos
folding-markersBOOL
Set the display of
folding markers
on or off.
font-sizeINT
Set the point size of the document font.
fontSTRING
Set the font of the document. The value should be a valid font
name, for example courier.
hl | syntaxSTRING
Set the syntax highlighting. Valid strings are all the names available
in the menus. For instance, for C++ simply write C++.
icon-bar-colorSTRING
Set the icon bar color. The value must be something that can
be evaluated to a valid color, for example #ff0000.
icon-borderBOOL
Set the display of the icon border on or off.
indent-modeSTRING
Set the auto-indentation mode. The options none,
normal, cstyle, haskell,
lilypond, lisp, python,
ruby and xml are recognized. See the section
for details.
indent-widthINT
Set the indentation width.
line-numbersBOOL
Set the display of line numbers on or off.
mixed-indentBOOL
Set mixed indentation ala Emacs on or off.
Note: Deprecated since Kate 3 in KDE4. This variable is ignored, set replace-tabs on; instead for the future.
newline-at-eofBOOL
Add an empty line at the end of the file (EOF) when saving the document.
Since: &kate; 3.9 (KDE 4.9)
overwrite-modeBOOL
Set overwrite mode on or off.
persistent-selectionBOOL
Set persistent selection
on or off.
remove-trailing-spaceBOOL
Set dynamic end of line cleanup on or off.
Note: Deprecated since KDE 4.10. Please use
remove-trailing-spaces with the desired choice instead.
remove-trailing-spacesSTRING
Removes trailing spaces when saving the document. Valid options are:
none, - or 0: never remove trailing spaces.
modified, mod, + or 1: remove trailing spaces only in
modified lines. The modified lines are marked by the line modification system.
all, * or 2: remove trailing spaces in the entire document.
Since: KDE 4.10. This deprecates the options remove-trailing-space and replace-trailing-space-save.
replace-tabs-saveBOOL
Set tab to space conversion on save on or off.
replace-tabsBOOL
Set dynamic tab to space conversion on or off.
replace-trailing-space-saveBOOL
Set end of line cleanup on save on or off.
Note: Deprecated since KDE 4.10. Please use
remove-trailing-spaces with the desired choice instead.
schemeSTRING
Set the color scheme. The string must be the name of a color
scheme that exists in your configuration to have any effect.
selection-colorSTRING
Set the selection color. The value must be something that can
be evaluated to a valid color, for example #ff0000.
show-tabsBOOL
Set the visual tab character on or off.
smart-homeBOOL
Set smart home navigation
on or off.
space-indentBOOL
Set indentation with spaces on or off.
Note: Deprecated since Kate 3 in KDE4. Mixed indentation is the default behavior.
Set replace-tabs on; to achieve space-only indentation.
tab-indentsBOOL
Set 	 key indentation on or off.
tab-widthINT
Set the tab character display width.
undo-stepsINT
Set the number of undo steps to remember.
Note: Deprecated since Kate 3 in KDE4. This variable is ignored. The maximal count of undo steps is unlimited.
word-wrap-columnINT
Set the static word wrap
width.
word-wrap-marker-colorSTRING
Set the word wrap marker color. The value must be something
that can be evaluated to a valid color, for example #ff0000.
word-wrapBOOL
Set static word wrapping on or off.
diff --git a/ktexteditor/configinterface.h b/ktexteditor/configinterface.h
index 24183e0ab..205900c7a 100644
--- a/ktexteditor/configinterface.h
+++ b/ktexteditor/configinterface.h
@@ -1,132 +1,131 @@
/* This file is part of the KDE project
Copyright (C) 2006 Matt Broadstone (mbroadst@gmail.com)
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef KDELIBS_KTEXTEDITOR_CONFIGINTERFACE_H
#define KDELIBS_KTEXTEDITOR_CONFIGINTERFACE_H
#include
#include
#include
namespace KTextEditor
{
/**
* \brief Config interface extension for the Document and View.
*
* \ingroup kte_group_view_extensions
* \ingroup kte_group_doc_extensions
*
* \section config_intro Introduction
*
* The ConfigInterface provides methods to access and modify the low level
* config information for a given Document or View. Examples of this config data can be
* displaying the icon bar, showing line numbers, etc. This generally allows
* access to settings that otherwise are only accessible during runtime.
*
* \section config_access Accessing the Interface
*
* The ConfigInterface is supposed to be an extension interface for a Document or View,
* i.e. the Document or View inherits the interface \e provided that the
* KTextEditor library in use implements the interface. Use qobject_cast to access
* the interface:
* \code
* // ptr is of type KTextEditor::Document* or KTextEditor::View*
* KTextEditor::ConfigInterface *iface =
* qobject_cast( ptr );
*
* if( iface ) {
*
* // the implementation supports the interface
* // do stuff
* }
* \endcode
*
* \section config_data Accessing Data
*
* A list of available config variables (or keys) can be optained by calling
* configKeys(). For all available keys configValue() returns the corresponding
* value as QVariant. A value for a given key can be set by calling
* setConfigValue(). Right now, when using KatePart as editor component,
* KTextEditor::View has support for the following tuples:
* - line-numbers [bool], show/hide line numbers
* - icon-bar [bool], show/hide icon bar
* - dynamic-word-wrap [bool], enable/disable dynamic word wrap
* - background-color [QColor], read/set the default background color
* - selection-color [QColor], read/set the default color for selections
* - search-highlight-color [QColor], read/set the background color for search
* - replace-highlight-color [QColor], read/set the background color for replaces
* - default-mark-type [uint], read/set the default mark type
* - allow-mark-menu [bool], enable/disable the menu shown when right clicking
* on the left gutter. When disabled, click on the gutter will always set
* or clear the mark of default type.
*
* KTextEditor::Document has support for the following:
- * - auto-brackets [bool], enable/disable automatic bracket completion
* - backup-on-save-local [bool], enable/disable backup when saving local files
* - backup-on-save-remote [bool], enable/disable backup when saving remote files
* - backup-on-save-suffix [string], set the suffix for file backups, e.g. "~"
* - backup-on-save-prefix [string], set the prefix for file backups, e.g. "."
*
* Either interface should emit the \p configChanged signal when appropriate.
* TODO: Add to interface in KDE 5.
*
* For instance, if you want to enable dynamic word wrap of a KTextEditor::View
* simply call
* \code
* iface->setConfigValue("dynamic-word-wrap", true);
* \endcode
*
* \see KTextEditor::View, KTextEditor::Document
* \author Matt Broadstone \
*/
class KTEXTEDITOR_EXPORT ConfigInterface
{
public:
ConfigInterface ();
/**
* Virtual destructor.
*/
virtual ~ConfigInterface ();
public:
/**
* Get a list of all available keys.
*/
virtual QStringList configKeys() const = 0;
/**
* Get a value for the \p key.
*/
virtual QVariant configValue(const QString &key) = 0;
/**
* Set a the \p key's value to \p value.
*/
virtual void setConfigValue(const QString &key, const QVariant &value) = 0;
private:
class ConfigInterfacePrivate* const d;
};
}
Q_DECLARE_INTERFACE(KTextEditor::ConfigInterface, "org.kde.KTextEditor.ConfigInterface")
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/part/dialogs/editconfigwidget.ui b/part/dialogs/editconfigwidget.ui
index 5b679669f..ff1e4b788 100644
--- a/part/dialogs/editconfigwidget.ui
+++ b/part/dialogs/editconfigwidget.ui
@@ -1,149 +1,139 @@
EditConfigWidget
0
0
321
377
0
-
Static Word Wrap
-
<p>Automatically start a new line of text when the current line exceeds the length specified by the <b>Wrap words at:</b> option.</p><p>This option does not wrap existing lines of text - use the <b>Apply Static Word Wrap</b> option in the <b>Tools</b> menu for that purpose.</p><p>If you want lines to be <i>visually wrapped</i> instead, according to the width of the view, enable <b>Dynamic Word Wrap</b> in the <b>Appearance</b> config page.</p>
Enable static &word wrap
-
<p>If this option is checked, a vertical line will be drawn at the word wrap column as defined in the <strong>Editing</strong> properties.</p><p>Note that the word wrap marker is only drawn if you use a fixed pitch font.</p>
Show static word wra&p marker (if applicable)
-
0
-
W&rap words at:
sbWordWrap
-
If the Word Wrap option is selected this entry determines the length (in characters) at which the editor will automatically start a new line.
20
200
76
-
Qt::Horizontal
1
0
-
Misc
-
-
-
-
- When the user types a left bracket ([,(, or {) KateView automatically enters the right bracket (}, ), or ]) to the right of the cursor.
-
-
- Auto &brackets
-
-
-
-
Copy/Cut the current line if no selection
-
Allow scrolling past the end of the document
-
Qt::Vertical
0
1
KIntSpinBox
QSpinBox
diff --git a/part/dialogs/katedialogs.cpp b/part/dialogs/katedialogs.cpp
index 99a04bdbc..41d45d246 100644
--- a/part/dialogs/katedialogs.cpp
+++ b/part/dialogs/katedialogs.cpp
@@ -1,1601 +1,1597 @@
/* This file is part of the KDE libraries
Copyright (C) 2002, 2003 Anders Lund
Copyright (C) 2003 Christoph Cullmann
Copyright (C) 2001 Joseph Wenninger
Copyright (C) 2006 Dominik Haumann
Copyright (C) 2007 Mirko Stocker
Copyright (C) 2009 Michel Ludwig
Copyright (C) 2009 Erlend Hamberg
Based on work of:
Copyright (C) 1999 Jochen Wilhelmy
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
//BEGIN Includes
#include "katedialogs.h"
#include "katedialogs.moc"
#include "kateautoindent.h"
#include "katebuffer.h"
#include "kateconfig.h"
#include "katedocument.h"
#include "kateglobal.h"
#include "kateviglobal.h"
#include "katevikeyparser.h"
#include "kateschema.h"
#include "katesyntaxdocument.h"
#include "katemodeconfigpage.h"
#include "kateview.h"
#include "katepartpluginmanager.h"
#include "kpluginselector.h"
#include "spellcheck/spellcheck.h"
// auto generated ui files
#include "ui_modonhdwidget.h"
#include "ui_textareaappearanceconfigwidget.h"
#include "ui_bordersappearanceconfigwidget.h"
#include "ui_cursorconfigwidget.h"
#include "ui_editconfigwidget.h"
#include "ui_indentationconfigwidget.h"
#include "ui_completionconfigtab.h"
#include "ui_opensaveconfigwidget.h"
#include "ui_opensaveconfigadvwidget.h"
#include "ui_viinputmodeconfigwidget.h"
#include "ui_spellcheckconfigwidget.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
// trailing slash is important
#define HLDOWNLOADPATH "http://kate.kde.org/syntax/"
//END
//BEGIN KateConfigPage
KateConfigPage::KateConfigPage ( QWidget *parent, const char * )
: KTextEditor::ConfigPage (parent)
, m_changed (false)
{
connect (this, SIGNAL(changed()), this, SLOT(somethingHasChanged()));
}
KateConfigPage::~KateConfigPage ()
{
}
void KateConfigPage::slotChanged()
{
emit changed();
}
void KateConfigPage::somethingHasChanged ()
{
m_changed = true;
kDebug (13000) << "TEST: something changed on the config page: " << this;
}
//END KateConfigPage
//BEGIN KateIndentConfigTab
KateIndentConfigTab::KateIndentConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
// This will let us have more separation between this page and
// the KTabWidget edge (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::IndentationConfigWidget();
ui->setupUi( newWidget );
ui->cmbMode->addItems (KateAutoIndent::listModes());
ui->label->setTextInteractionFlags(Qt::LinksAccessibleByMouse | Qt::LinksAccessibleByKeyboard);
connect(ui->label, SIGNAL(linkActivated(QString)), this, SLOT(showWhatsThis(QString)));
// What's This? help can be found in the ui file
reload ();
//
// after initial reload, connect the stuff for the changed () signal
//
connect(ui->cmbMode, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect(ui->rbIndentWithTabs, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbIndentWithSpaces, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbIndentMixed, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbIndentWithTabs, SIGNAL(toggled(bool)), ui->sbIndentWidth, SLOT(setDisabled(bool)));
connect(ui->chkKeepExtraSpaces, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkIndentPaste, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkBackspaceUnindents, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->sbTabWidth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect(ui->sbIndentWidth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect(ui->rbTabAdvances, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbTabIndents, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbTabSmart, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
layout->addWidget(newWidget);
setLayout(layout);
}
KateIndentConfigTab::~KateIndentConfigTab()
{
delete ui;
}
void KateIndentConfigTab::slotChanged()
{
if (ui->rbIndentWithTabs->isChecked())
ui->sbIndentWidth->setValue(ui->sbTabWidth->value());
KateConfigPage::slotChanged();
}
void KateIndentConfigTab::showWhatsThis(const QString& text)
{
QWhatsThis::showText(QCursor::pos(), text);
}
void KateIndentConfigTab::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateDocumentConfig::global()->configStart ();
KateDocumentConfig::global()->setKeepExtraSpaces(ui->chkKeepExtraSpaces->isChecked());
KateDocumentConfig::global()->setBackspaceIndents(ui->chkBackspaceUnindents->isChecked());
KateDocumentConfig::global()->setIndentPastedText(ui->chkIndentPaste->isChecked());
KateDocumentConfig::global()->setIndentationWidth(ui->sbIndentWidth->value());
KateDocumentConfig::global()->setIndentationMode(KateAutoIndent::modeName(ui->cmbMode->currentIndex()));
KateDocumentConfig::global()->setTabWidth(ui->sbTabWidth->value());
KateDocumentConfig::global()->setReplaceTabsDyn(ui->rbIndentWithSpaces->isChecked());
if (ui->rbTabAdvances->isChecked())
KateDocumentConfig::global()->setTabHandling( KateDocumentConfig::tabInsertsTab );
else if (ui->rbTabIndents->isChecked())
KateDocumentConfig::global()->setTabHandling( KateDocumentConfig::tabIndents );
else
KateDocumentConfig::global()->setTabHandling( KateDocumentConfig::tabSmart );
KateDocumentConfig::global()->configEnd ();
}
void KateIndentConfigTab::reload ()
{
ui->sbTabWidth->setSuffix(ki18np(" character", " characters"));
ui->sbTabWidth->setValue(KateDocumentConfig::global()->tabWidth());
ui->sbIndentWidth->setSuffix(ki18np(" character", " characters"));
ui->sbIndentWidth->setValue(KateDocumentConfig::global()->indentationWidth());
ui->chkKeepExtraSpaces->setChecked(KateDocumentConfig::global()->keepExtraSpaces());
ui->chkIndentPaste->setChecked(KateDocumentConfig::global()->indentPastedText());
ui->chkBackspaceUnindents->setChecked(KateDocumentConfig::global()->backspaceIndents());
ui->rbTabAdvances->setChecked( KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabInsertsTab );
ui->rbTabIndents->setChecked( KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabIndents );
ui->rbTabSmart->setChecked( KateDocumentConfig::global()->tabHandling() == KateDocumentConfig::tabSmart );
ui->cmbMode->setCurrentIndex (KateAutoIndent::modeNumber (KateDocumentConfig::global()->indentationMode()));
if (KateDocumentConfig::global()->replaceTabsDyn())
ui->rbIndentWithSpaces->setChecked (true);
else
{
if (KateDocumentConfig::global()->indentationWidth() == KateDocumentConfig::global()->tabWidth())
ui->rbIndentWithTabs->setChecked (true);
else
ui->rbIndentMixed->setChecked (true);
}
ui->sbIndentWidth->setEnabled(!ui->rbIndentWithTabs->isChecked());
}
//END KateIndentConfigTab
//BEGIN KateCompletionConfigTab
KateCompletionConfigTab::KateCompletionConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
// This will let us have more separation between this page and
// the KTabWidget edge (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::CompletionConfigTab ();
ui->setupUi( newWidget );
// What's This? help can be found in the ui file
reload ();
//
// after initial reload, connect the stuff for the changed () signal
//
connect(ui->chkAutoCompletionEnabled, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->gbWordCompletion, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->minimalWordLength, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
layout->addWidget(newWidget);
setLayout(layout);
}
KateCompletionConfigTab::~KateCompletionConfigTab()
{
delete ui;
}
void KateCompletionConfigTab::showWhatsThis(const QString& text)
{
QWhatsThis::showText(QCursor::pos(), text);
}
void KateCompletionConfigTab::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateViewConfig::global()->configStart ();
KateViewConfig::global()->setAutomaticCompletionInvocation (ui->chkAutoCompletionEnabled->isChecked());
KateViewConfig::global()->setWordCompletion (ui->gbWordCompletion->isChecked());
KateViewConfig::global()->setWordCompletionMinimalWordLength (ui->minimalWordLength->value());
KateViewConfig::global()->configEnd ();
}
void KateCompletionConfigTab::reload ()
{
ui->chkAutoCompletionEnabled->setChecked( KateViewConfig::global()->automaticCompletionInvocation () );
ui->gbWordCompletion->setChecked( KateViewConfig::global()->wordCompletion () );
ui->minimalWordLength->setValue (KateViewConfig::global()->wordCompletionMinimalWordLength ());
}
//END KateCompletionConfigTab
//BEGIN KateViInputModeConfigTab
KateViInputModeConfigTab::KateViInputModeConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
// This will let us have more separation between this page and
// the KTabWidget edge (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::ViInputModeConfigWidget ();
ui->setupUi( newWidget );
// What's This? help can be found in the ui file
reload ();
//
// after initial reload, connect the stuff for the changed () signal
//
connect(ui->chkViInputModeDefault, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkViCommandsOverride, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkViStatusBarHide, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->tblNormalModeMappings, SIGNAL(cellChanged(int,int)), this, SLOT(slotChanged()));
connect(ui->btnAddNewNormal, SIGNAL(clicked()), this, SLOT(addNewNormalModeMappingRow()));
connect(ui->btnAddNewNormal, SIGNAL(clicked()), this, SLOT(slotChanged()));
connect(ui->btnRemoveSelectedNormal, SIGNAL(clicked()), this, SLOT(removeSelectedNormalMappingRow()));
connect(ui->btnRemoveSelectedNormal, SIGNAL(clicked()), this, SLOT(slotChanged()));
connect(ui->btnImportNormal, SIGNAL(clicked()), this, SLOT(importNormalMappingRow()));
connect(ui->btnImportNormal, SIGNAL(clicked()), this, SLOT(slotChanged()));
layout->addWidget(newWidget);
setLayout(layout);
}
KateViInputModeConfigTab::~KateViInputModeConfigTab()
{
delete ui;
}
void KateViInputModeConfigTab::showWhatsThis(const QString& text)
{
QWhatsThis::showText(QCursor::pos(), text);
}
void KateViInputModeConfigTab::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateViewConfig::global()->configStart ();
KateViewConfig::global()->setViInputMode (ui->chkViInputModeDefault->isChecked());
KateViewConfig::global()->setViInputModeStealKeys (ui->chkViCommandsOverride->isChecked());
KateViewConfig::global()->setViInputModeHideStatusBar (ui->chkViStatusBarHide->isChecked());
KateGlobal::self()->viInputModeGlobal()->clearMappings( NormalMode );
for ( int i = 0; i < ui->tblNormalModeMappings->rowCount(); i++ ) {
QTableWidgetItem* from = ui->tblNormalModeMappings->item( i, 0 );
QTableWidgetItem* to = ui->tblNormalModeMappings->item( i, 1 );
if ( from && to ) {
KateGlobal::self()->viInputModeGlobal()->addMapping( NormalMode, from->text(), to->text() );
}
}
KateViewConfig::global()->configEnd ();
}
void KateViInputModeConfigTab::reload ()
{
ui->chkViInputModeDefault->setChecked( KateViewConfig::global()->viInputMode () );
ui->chkViCommandsOverride->setChecked( KateViewConfig::global()->viInputModeStealKeys () );
ui->chkViStatusBarHide->setChecked( KateViewConfig::global()->viInputModeHideStatusBar () );
ui->chkViCommandsOverride->setEnabled(ui->chkViInputModeDefault->isChecked());
ui->chkViStatusBarHide->setEnabled(ui->chkViInputModeDefault->isChecked());
QStringList l = KateGlobal::self()->viInputModeGlobal()->getMappings( NormalMode );
ui->tblNormalModeMappings->setRowCount( l.size() );
// make the two columns fill the entire table width
ui->tblNormalModeMappings->setColumnWidth( 0, ui->tblNormalModeMappings->width()/3 );
ui->tblNormalModeMappings->horizontalHeader()->setStretchLastSection( true );
int i = 0;
foreach( const QString &f, l ) {
QTableWidgetItem *from
= new QTableWidgetItem( KateViKeyParser::self()->decodeKeySequence( f ) );
QString s = KateGlobal::self()->viInputModeGlobal()->getMapping( NormalMode, f );
QTableWidgetItem *to =
new QTableWidgetItem( KateViKeyParser::self()->decodeKeySequence( s ) );
ui->tblNormalModeMappings->setItem(i, 0, from);
ui->tblNormalModeMappings->setItem(i++, 1, to);
}
}
void KateViInputModeConfigTab::addNewNormalModeMappingRow()
{
int rows = ui->tblNormalModeMappings->rowCount();
ui->tblNormalModeMappings->insertRow( rows );
ui->tblNormalModeMappings->setCurrentCell( rows, 0 );
ui->tblNormalModeMappings->editItem( ui->tblNormalModeMappings->currentItem() );
}
void KateViInputModeConfigTab::importNormalMappingRow()
{
QString fileName = KFileDialog::getOpenFileName();
if(fileName.isEmpty()) return;
QFile configFile(fileName);
if(! configFile.open(QIODevice::ReadOnly | QIODevice::Text)) {
KMessageBox::error(this, i18n("Unable to open the config file for reading."), i18n("Unable to open file"));
return;
}
QTextStream stream(&configFile);
while(! stream.atEnd()) {
QStringList line = stream.readLine().split(" ");
if(line.size() > 2 && (line[0] == "noremap" || line[0] == "no"
|| line[0] == "nnoremap" || line [0] == "nn")) {
int rows = ui->tblNormalModeMappings->rowCount();
ui->tblNormalModeMappings->insertRow( rows );
ui->tblNormalModeMappings->setItem(rows, 0, new QTableWidgetItem(line[1]));
ui->tblNormalModeMappings->setItem(rows, 1, new QTableWidgetItem(line[2]));
}
}
}
void KateViInputModeConfigTab::removeSelectedNormalMappingRow()
{
QList l = ui->tblNormalModeMappings->selectedRanges();
foreach( const QTableWidgetSelectionRange &range, l ) {
for ( int i = 0; i < range.bottomRow()-range.topRow()+1; i++ ) {
ui->tblNormalModeMappings->removeRow( range.topRow() );
}
}
}
//END KateViInputModeConfigTab
//BEGIN KateSpellCheckConfigTab
KateSpellCheckConfigTab::KateSpellCheckConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
// This will let us have more separation between this page and
// the KTabWidget edge (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::SpellCheckConfigWidget();
ui->setupUi(newWidget);
// What's This? help can be found in the ui file
reload();
//
// after initial reload, connect the stuff for the changed () signal
m_sonnetConfigWidget = new Sonnet::ConfigWidget(KGlobal::config().data(), this);
connect(m_sonnetConfigWidget, SIGNAL(configChanged()), this, SLOT(slotChanged()));
layout->addWidget(m_sonnetConfigWidget);
layout->addWidget(newWidget);
setLayout(layout);
}
KateSpellCheckConfigTab::~KateSpellCheckConfigTab()
{
delete ui;
}
void KateSpellCheckConfigTab::showWhatsThis(const QString& text)
{
QWhatsThis::showText(QCursor::pos(), text);
}
void KateSpellCheckConfigTab::apply()
{
if (!hasChanged()) {
// nothing changed, no need to apply stuff
return;
}
m_changed = false;
KateDocumentConfig::global()->configStart();
m_sonnetConfigWidget->save();
KateDocumentConfig::global()->configEnd();
foreach (KateDocument *doc, KateGlobal::self()->kateDocuments()) {
doc->refreshOnTheFlyCheck();
}
}
void KateSpellCheckConfigTab::reload()
{
// does nothing
}
//END KateSpellCheckConfigTab
//BEGIN KateSelectConfigTab
KateSelectConfigTab::KateSelectConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
// This will let us having more separation between this page and
// the KTabWidget edge (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::CursorConfigWidget();
ui->setupUi( newWidget );
// What's This? Help is in the ui-files
reload ();
//
// after initial reload, connect the stuff for the changed () signal
//
connect(ui->rbNormal, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->rbPersistent, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkSmartHome, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkPagingMovesCursor, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->sbAutoCenterCursor, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
layout->addWidget(newWidget);
setLayout(layout);
}
KateSelectConfigTab::~KateSelectConfigTab()
{
delete ui;
}
void KateSelectConfigTab::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateViewConfig::global()->configStart ();
KateDocumentConfig::global()->configStart ();
KateDocumentConfig::global()->setSmartHome(ui->chkSmartHome->isChecked());
KateViewConfig::global()->setAutoCenterLines(qMax(0, ui->sbAutoCenterCursor->value()));
KateDocumentConfig::global()->setPageUpDownMovesCursor(ui->chkPagingMovesCursor->isChecked());
KateViewConfig::global()->setPersistentSelection (ui->rbPersistent->isChecked());
KateDocumentConfig::global()->configEnd ();
KateViewConfig::global()->configEnd ();
}
void KateSelectConfigTab::reload ()
{
ui->rbNormal->setChecked( ! KateViewConfig::global()->persistentSelection() );
ui->rbPersistent->setChecked( KateViewConfig::global()->persistentSelection() );
ui->chkSmartHome->setChecked(KateDocumentConfig::global()->smartHome());
ui->chkPagingMovesCursor->setChecked(KateDocumentConfig::global()->pageUpDownMovesCursor());
ui->sbAutoCenterCursor->setValue(KateViewConfig::global()->autoCenterLines());
}
//END KateSelectConfigTab
//BEGIN KateEditGeneralConfigTab
KateEditGeneralConfigTab::KateEditGeneralConfigTab(QWidget *parent)
: KateConfigPage(parent)
{
QVBoxLayout *layout = new QVBoxLayout;
QWidget *newWidget = new QWidget(this);
ui = new Ui::EditConfigWidget();
ui->setupUi( newWidget );
reload();
connect(ui->chkStaticWordWrap, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkShowStaticWordWrapMarker, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->sbWordWrap, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
- connect(ui->chkAutoBrackets, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkSmartCopyCut, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(ui->chkScrollPastEnd, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
// "What's this?" help is in the ui-file
layout->addWidget(newWidget);
setLayout(layout);
}
KateEditGeneralConfigTab::~KateEditGeneralConfigTab()
{
delete ui;
}
void KateEditGeneralConfigTab::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateViewConfig::global()->configStart ();
KateDocumentConfig::global()->configStart ();
- KateDocumentConfig::global()->setAutoBrackets(ui->chkAutoBrackets->isChecked());
-
KateDocumentConfig::global()->setWordWrapAt(ui->sbWordWrap->value());
KateDocumentConfig::global()->setWordWrap(ui->chkStaticWordWrap->isChecked());
KateRendererConfig::global()->setWordWrapMarker (ui->chkShowStaticWordWrapMarker->isChecked());
KateDocumentConfig::global()->configEnd ();
KateViewConfig::global()->setSmartCopyCut(ui->chkSmartCopyCut->isChecked());
KateViewConfig::global()->setScrollPastEnd(ui->chkScrollPastEnd->isChecked());
KateViewConfig::global()->configEnd ();
}
void KateEditGeneralConfigTab::reload ()
{
ui->chkStaticWordWrap->setChecked(KateDocumentConfig::global()->wordWrap());
ui->chkShowStaticWordWrapMarker->setChecked( KateRendererConfig::global()->wordWrapMarker() );
ui->sbWordWrap->setSuffix(ki18ncp("Wrap words at", " character", " characters"));
ui->sbWordWrap->setValue( KateDocumentConfig::global()->wordWrapAt() );
- ui->chkAutoBrackets->setChecked( KateDocumentConfig::global()->autoBrackets() );
ui->chkSmartCopyCut->setChecked( KateViewConfig::global()->smartCopyCut() );
ui->chkScrollPastEnd->setChecked( KateViewConfig::global()->scrollPastEnd() );
}
//END KateEditGeneralConfigTab
//BEGIN KateEditConfigTab
KateEditConfigTab::KateEditConfigTab(QWidget *parent)
: KateConfigPage(parent)
, editConfigTab(new KateEditGeneralConfigTab(this))
, selectConfigTab(new KateSelectConfigTab(this))
, indentConfigTab(new KateIndentConfigTab(this))
, completionConfigTab (new KateCompletionConfigTab(this))
, viInputModeConfigTab(new KateViInputModeConfigTab(this))
, spellCheckConfigTab(new KateSpellCheckConfigTab(this))
{
QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin(0);
KTabWidget *tabWidget = new KTabWidget(this);
// add all tabs
tabWidget->insertTab(0, editConfigTab, i18n("General"));
tabWidget->insertTab(1, selectConfigTab, i18n("Cursor && Selection"));
tabWidget->insertTab(2, indentConfigTab, i18n("Indentation"));
tabWidget->insertTab(3, completionConfigTab, i18n("Auto Completion"));
tabWidget->insertTab(4, viInputModeConfigTab, i18n("Vi Input Mode"));
tabWidget->insertTab(5, spellCheckConfigTab, i18n("Spellcheck"));
connect(editConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
connect(selectConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
connect(indentConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
connect(completionConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
connect(viInputModeConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
connect(spellCheckConfigTab, SIGNAL(changed()), this, SLOT(slotChanged()));
layout->addWidget(tabWidget);
setLayout(layout);
}
KateEditConfigTab::~KateEditConfigTab()
{
}
void KateEditConfigTab::apply ()
{
// try to update the rest of tabs
editConfigTab->apply();
selectConfigTab->apply();
indentConfigTab->apply();
completionConfigTab->apply();
viInputModeConfigTab->apply();
spellCheckConfigTab->apply();
}
void KateEditConfigTab::reload ()
{
editConfigTab->reload();
selectConfigTab->reload();
indentConfigTab->reload();
completionConfigTab->reload();
viInputModeConfigTab->reload();
spellCheckConfigTab->reload();
}
void KateEditConfigTab::reset ()
{
editConfigTab->reset();
selectConfigTab->reset();
indentConfigTab->reset();
completionConfigTab->reset();
viInputModeConfigTab->reset();
spellCheckConfigTab->reset();
}
void KateEditConfigTab::defaults ()
{
editConfigTab->defaults();
selectConfigTab->defaults();
indentConfigTab->defaults();
completionConfigTab->defaults();
viInputModeConfigTab->defaults();
spellCheckConfigTab->defaults();
}
//END KateEditConfigTab
//BEGIN KateViewDefaultsConfig
KateViewDefaultsConfig::KateViewDefaultsConfig(QWidget *parent)
: KateConfigPage(parent)
, textareaUi(new Ui::TextareaAppearanceConfigWidget())
, bordersUi(new Ui::BordersAppearanceConfigWidget())
{
QLayout *layout = new QVBoxLayout( this );
QTabWidget *tabWidget = new QTabWidget( this );
layout->addWidget( tabWidget );
layout->setMargin( 0 );
QWidget *textareaTab = new QWidget( tabWidget );
textareaUi->setupUi( textareaTab );
tabWidget->addTab( textareaTab, i18n("General") );
QWidget *bordersTab = new QWidget( tabWidget );
bordersUi->setupUi( bordersTab );
tabWidget->addTab( bordersTab, i18n("Borders") );
if (KateDocument::simpleMode ())
bordersUi->gbSortBookmarks->hide ();
textareaUi->cmbDynamicWordWrapIndicator->addItem( i18n("Off") );
textareaUi->cmbDynamicWordWrapIndicator->addItem( i18n("Follow Line Numbers") );
textareaUi->cmbDynamicWordWrapIndicator->addItem( i18n("Always On") );
// hide power user mode if activated anyway
if (!KateGlobal::self()->simpleMode ())
textareaUi->chkDeveloperMode->hide ();
// What's This? help is in the ui-file
reload();
//
// after initial reload, connect the stuff for the changed () signal
//
connect(textareaUi->gbWordWrap, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(textareaUi->cmbDynamicWordWrapIndicator, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect(textareaUi->sbDynamicWordWrapDepth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect(textareaUi->chkShowTabs, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(textareaUi->chkShowSpaces, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(textareaUi->chkShowIndentationLines, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(textareaUi->chkShowWholeBracketExpression, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(textareaUi->chkDeveloperMode, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkIconBorder, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkScrollbarMarks, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkScrollbarMiniMap, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkScrollbarMiniMapAll, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
bordersUi->chkScrollbarMiniMapAll->hide(); // this is temporary until the feature is done
connect(bordersUi->spBoxMiniMapWidth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect(bordersUi->chkLineNumbers, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkShowLineModification, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->chkShowFoldingMarkers, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->rbSortBookmarksByPosition, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect(bordersUi->rbSortBookmarksByCreation, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
}
KateViewDefaultsConfig::~KateViewDefaultsConfig()
{
delete bordersUi;
delete textareaUi;
}
void KateViewDefaultsConfig::apply ()
{
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateViewConfig::global()->configStart ();
KateRendererConfig::global()->configStart ();
KateViewConfig::global()->setDynWordWrap (textareaUi->gbWordWrap->isChecked());
KateViewConfig::global()->setDynWordWrapIndicators (textareaUi->cmbDynamicWordWrapIndicator->currentIndex ());
KateViewConfig::global()->setDynWordWrapAlignIndent(textareaUi->sbDynamicWordWrapDepth->value());
KateDocumentConfig::global()->setShowTabs (textareaUi->chkShowTabs->isChecked());
KateDocumentConfig::global()->setShowSpaces (textareaUi->chkShowSpaces->isChecked());
KateViewConfig::global()->setLineNumbers (bordersUi->chkLineNumbers->isChecked());
KateViewConfig::global()->setIconBar (bordersUi->chkIconBorder->isChecked());
KateViewConfig::global()->setScrollBarMarks (bordersUi->chkScrollbarMarks->isChecked());
KateViewConfig::global()->setScrollBarMiniMap (bordersUi->chkScrollbarMiniMap->isChecked());
KateViewConfig::global()->setScrollBarMiniMapAll (bordersUi->chkScrollbarMiniMapAll->isChecked());
KateViewConfig::global()->setScrollBarMiniMapWidth (bordersUi->spBoxMiniMapWidth->value());
KateViewConfig::global()->setFoldingBar (bordersUi->chkShowFoldingMarkers->isChecked());
KateViewConfig::global()->setLineModification(bordersUi->chkShowLineModification->isChecked());
KateViewConfig::global()->setBookmarkSort (bordersUi->rbSortBookmarksByPosition->isChecked()?0:1);
KateRendererConfig::global()->setShowIndentationLines(textareaUi->chkShowIndentationLines->isChecked());
KateRendererConfig::global()->setShowWholeBracketExpression(textareaUi->chkShowWholeBracketExpression->isChecked());
// warn user that he needs restart the application
if (!textareaUi->chkDeveloperMode->isChecked() != KateDocumentConfig::global()->allowSimpleMode())
{
// inform...
KMessageBox::information(
this,
i18n("Changing the power user mode affects only newly opened / created documents. In KWrite a restart is recommended."),
i18n("Power user mode changed"));
KateDocumentConfig::global()->setAllowSimpleMode (!textareaUi->chkDeveloperMode->isChecked());
}
KateRendererConfig::global()->configEnd ();
KateViewConfig::global()->configEnd ();
}
void KateViewDefaultsConfig::reload ()
{
textareaUi->gbWordWrap->setChecked(KateViewConfig::global()->dynWordWrap());
textareaUi->cmbDynamicWordWrapIndicator->setCurrentIndex( KateViewConfig::global()->dynWordWrapIndicators() );
textareaUi->sbDynamicWordWrapDepth->setValue(KateViewConfig::global()->dynWordWrapAlignIndent());
textareaUi->chkShowTabs->setChecked(KateDocumentConfig::global()->showTabs());
textareaUi->chkShowSpaces->setChecked(KateDocumentConfig::global()->showSpaces());
bordersUi->chkLineNumbers->setChecked(KateViewConfig::global()->lineNumbers());
bordersUi->chkIconBorder->setChecked(KateViewConfig::global()->iconBar());
bordersUi->chkScrollbarMarks->setChecked(KateViewConfig::global()->scrollBarMarks());
bordersUi->chkScrollbarMiniMap->setChecked(KateViewConfig::global()->scrollBarMiniMap());
bordersUi->chkScrollbarMiniMapAll->setChecked(KateViewConfig::global()->scrollBarMiniMapAll());
bordersUi->spBoxMiniMapWidth->setValue(KateViewConfig::global()->scrollBarMiniMapWidth());
bordersUi->chkShowFoldingMarkers->setChecked(KateViewConfig::global()->foldingBar());
bordersUi->chkShowLineModification->setChecked(KateViewConfig::global()->lineModification());
bordersUi->rbSortBookmarksByPosition->setChecked(KateViewConfig::global()->bookmarkSort()==0);
bordersUi->rbSortBookmarksByCreation->setChecked(KateViewConfig::global()->bookmarkSort()==1);
textareaUi->chkShowIndentationLines->setChecked(KateRendererConfig::global()->showIndentationLines());
textareaUi->chkShowWholeBracketExpression->setChecked(KateRendererConfig::global()->showWholeBracketExpression());
textareaUi->chkDeveloperMode->setChecked(!KateDocumentConfig::global()->allowSimpleMode());
}
void KateViewDefaultsConfig::reset () {;}
void KateViewDefaultsConfig::defaults (){;}
//END KateViewDefaultsConfig
//BEGIN KateSaveConfigTab
KateSaveConfigTab::KateSaveConfigTab( QWidget *parent )
: KateConfigPage( parent )
, modeConfigPage( new ModeConfigPage( this ) )
{
// FIXME: Is really needed to move all this code below to another class,
// since it is another tab itself on the config dialog. This means we should
// initialize, add and work with as we do with modeConfigPage (ereslibre)
QVBoxLayout *layout = new QVBoxLayout;
layout->setMargin(0);
KTabWidget *tabWidget = new KTabWidget(this);
QWidget *tmpWidget = new QWidget(tabWidget);
QVBoxLayout *internalLayout = new QVBoxLayout;
QWidget *newWidget = new QWidget(tabWidget);
ui = new Ui::OpenSaveConfigWidget();
ui->setupUi( newWidget );
QWidget *tmpWidget2 = new QWidget(tabWidget);
QVBoxLayout *internalLayout2 = new QVBoxLayout;
QWidget *newWidget2 = new QWidget(tabWidget);
uiadv = new Ui::OpenSaveConfigAdvWidget();
uiadv->setupUi( newWidget2 );
// What's this help is added in ui/opensaveconfigwidget.ui
reload();
//
// after initial reload, connect the stuff for the changed () signal
//
connect( ui->cmbEncoding, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect( ui->cmbEncodingDetection, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect( ui->cmbEncodingFallback, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect( ui->cmbEOL, SIGNAL(activated(int)), this, SLOT(slotChanged()));
connect( ui->chkDetectEOL, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
connect( ui->chkEnableBOM, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
connect( ui->lineLengthLimit, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect( ui->cbRemoveTrailingSpaces, SIGNAL(currentIndexChanged(int)), this, SLOT(slotChanged()));
connect( ui->chkNewLineAtEof, SIGNAL(toggled(bool)), this, SLOT(slotChanged()));
connect( uiadv->chkBackupLocalFiles, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
connect( uiadv->chkBackupRemoteFiles, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
connect( uiadv->sbConfigFileSearchDepth, SIGNAL(valueChanged(int)), this, SLOT(slotChanged()));
connect( uiadv->edtBackupPrefix, SIGNAL(textChanged(QString)), this, SLOT(slotChanged()) );
connect( uiadv->edtBackupSuffix, SIGNAL(textChanged(QString)), this, SLOT(slotChanged()) );
connect( uiadv->chkNoSync, SIGNAL(toggled(bool)), this, SLOT(slotChanged()) );
internalLayout->addWidget(newWidget);
tmpWidget->setLayout(internalLayout);
internalLayout2->addWidget(newWidget2);
tmpWidget2->setLayout(internalLayout2);
// add all tabs
tabWidget->insertTab(0, tmpWidget, i18n("General"));
tabWidget->insertTab(1, tmpWidget2, i18n("Advanced"));
tabWidget->insertTab(2, modeConfigPage, i18n("Modes && Filetypes"));
connect(modeConfigPage, SIGNAL(changed()), this, SLOT(slotChanged()));
layout->addWidget(tabWidget);
setLayout(layout);
}
KateSaveConfigTab::~KateSaveConfigTab()
{
delete ui;
}
void KateSaveConfigTab::apply()
{
modeConfigPage->apply();
// nothing changed, no need to apply stuff
if (!hasChanged())
return;
m_changed = false;
KateGlobalConfig::global()->configStart ();
KateDocumentConfig::global()->configStart ();
if ( uiadv->edtBackupSuffix->text().isEmpty() && uiadv->edtBackupPrefix->text().isEmpty() ) {
KMessageBox::information(
this,
i18n("You did not provide a backup suffix or prefix. Using default suffix: '~'"),
i18n("No Backup Suffix or Prefix")
);
uiadv->edtBackupSuffix->setText( "~" );
}
uint f( 0 );
if ( uiadv->chkBackupLocalFiles->isChecked() )
f |= KateDocumentConfig::LocalFiles;
if ( uiadv->chkBackupRemoteFiles->isChecked() )
f |= KateDocumentConfig::RemoteFiles;
KateDocumentConfig::global()->setBackupFlags(f);
KateDocumentConfig::global()->setBackupPrefix(uiadv->edtBackupPrefix->text());
KateDocumentConfig::global()->setBackupSuffix(uiadv->edtBackupSuffix->text());
KateDocumentConfig::global()->setSwapFileNoSync(uiadv->chkNoSync->isChecked());
KateDocumentConfig::global()->setSearchDirConfigDepth(uiadv->sbConfigFileSearchDepth->value());
KateDocumentConfig::global()->setRemoveSpaces(ui->cbRemoveTrailingSpaces->currentIndex());
KateDocumentConfig::global()->setNewLineAtEof(ui->chkNewLineAtEof->isChecked());
// set both standard and fallback encoding
KateDocumentConfig::global()->setEncoding((ui->cmbEncoding->currentIndex() == 0) ? "" : KGlobal::charsets()->encodingForName(ui->cmbEncoding->currentText()));
KateGlobalConfig::global()->setProberType((KEncodingProber::ProberType)ui->cmbEncodingDetection->currentIndex());
KateGlobalConfig::global()->setFallbackEncoding(KGlobal::charsets()->encodingForName(ui->cmbEncodingFallback->currentText()));
KateDocumentConfig::global()->setEol(ui->cmbEOL->currentIndex());
KateDocumentConfig::global()->setAllowEolDetection(ui->chkDetectEOL->isChecked());
KateDocumentConfig::global()->setBom(ui->chkEnableBOM->isChecked());
KateDocumentConfig::global()->setLineLengthLimit(ui->lineLengthLimit->value());
KateDocumentConfig::global()->configEnd ();
KateGlobalConfig::global()->configEnd ();
}
void KateSaveConfigTab::reload()
{
modeConfigPage->reload();
// encodings
ui->cmbEncoding->clear ();
ui->cmbEncoding->addItem (i18n("KDE Default"));
ui->cmbEncoding->setCurrentIndex(0);
ui->cmbEncodingFallback->clear ();
QStringList encodings (KGlobal::charsets()->descriptiveEncodingNames());
int insert = 1;
for (int i=0; i < encodings.count(); i++)
{
bool found = false;
QTextCodec *codecForEnc = KGlobal::charsets()->codecForName(KGlobal::charsets()->encodingForName(encodings[i]), found);
if (found)
{
ui->cmbEncoding->addItem (encodings[i]);
ui->cmbEncodingFallback->addItem (encodings[i]);
if ( codecForEnc->name() == KateDocumentConfig::global()->encoding() )
{
ui->cmbEncoding->setCurrentIndex(insert);
}
if ( codecForEnc == KateGlobalConfig::global()->fallbackCodec() )
{
// adjust index for fallback config, has no default!
ui->cmbEncodingFallback->setCurrentIndex(insert-1);
}
insert++;
}
}
// encoding detection
ui->cmbEncodingDetection->clear ();
bool found = false;
for (int i = 0; !KEncodingProber::nameForProberType ((KEncodingProber::ProberType) i).isEmpty(); ++i) {
ui->cmbEncodingDetection->addItem (KEncodingProber::nameForProberType ((KEncodingProber::ProberType) i));
if (i == KateGlobalConfig::global()->proberType()) {
ui->cmbEncodingDetection->setCurrentIndex(ui->cmbEncodingDetection->count()-1);
found = true;
}
}
if (!found)
ui->cmbEncodingDetection->setCurrentIndex(KEncodingProber::Universal);
// eol
ui->cmbEOL->setCurrentIndex(KateDocumentConfig::global()->eol());
ui->chkDetectEOL->setChecked(KateDocumentConfig::global()->allowEolDetection());
ui->chkEnableBOM->setChecked(KateDocumentConfig::global()->bom());
ui->lineLengthLimit->setValue(KateDocumentConfig::global()->lineLengthLimit());
ui->cbRemoveTrailingSpaces->setCurrentIndex(KateDocumentConfig::global()->removeSpaces());
ui->chkNewLineAtEof->setChecked(KateDocumentConfig::global()->newLineAtEof());
uiadv->sbConfigFileSearchDepth->setValue(KateDocumentConfig::global()->searchDirConfigDepth());
// other stuff
uint f ( KateDocumentConfig::global()->backupFlags() );
uiadv->chkBackupLocalFiles->setChecked( f & KateDocumentConfig::LocalFiles );
uiadv->chkBackupRemoteFiles->setChecked( f & KateDocumentConfig::RemoteFiles );
uiadv->edtBackupPrefix->setText( KateDocumentConfig::global()->backupPrefix() );
uiadv->edtBackupSuffix->setText( KateDocumentConfig::global()->backupSuffix() );
uiadv->chkNoSync->setChecked( KateDocumentConfig::global()->swapFileNoSync() );
}
void KateSaveConfigTab::reset()
{
modeConfigPage->reset();
}
void KateSaveConfigTab::defaults()
{
modeConfigPage->defaults();
ui->cbRemoveTrailingSpaces->setCurrentIndex(0);
uiadv->chkBackupLocalFiles->setChecked( true );
uiadv->chkBackupRemoteFiles->setChecked( false );
uiadv->edtBackupPrefix->setText( "" );
uiadv->edtBackupSuffix->setText( "~" );
uiadv->chkNoSync->setChecked( false );
}
//END KateSaveConfigTab
//BEGIN KatePartPluginConfigPage
KatePartPluginConfigPage::KatePartPluginConfigPage (QWidget *parent)
: KateConfigPage (parent, "")
{
QVBoxLayout *generalLayout = new QVBoxLayout;
generalLayout->setMargin(0);
KTabWidget *tabWidget = new KTabWidget(this);
QWidget *tmpWidget = new QWidget(tabWidget);
QVBoxLayout *internalLayout = new QVBoxLayout;
QWidget *newWidget = new QWidget(tabWidget);
QVBoxLayout *layout = new QVBoxLayout;
newWidget->setLayout(layout);
layout->setMargin(0);
plugins.clear();
int i = 0;
foreach (const KatePartPluginInfo &info, KatePartPluginManager::self()->pluginList())
{
KPluginInfo it(info.service());
it.setPluginEnabled(info.load);
plugins.append(it);
i++;
}
selector = new KPluginSelector(0);
connect(selector, SIGNAL(changed(bool)), this, SLOT(slotChanged()));
connect(selector, SIGNAL(configCommitted(QByteArray)), this, SLOT(slotChanged()));
selector->addPlugins(plugins, KPluginSelector::IgnoreConfigFile, i18n("Editor Plugins"), "Editor");
layout->addWidget(selector);
internalLayout->addWidget(newWidget);
tmpWidget->setLayout(internalLayout);
// add all tabs
tabWidget->insertTab(0, tmpWidget, i18n("Plugins"));
generalLayout->addWidget(tabWidget);
setLayout(generalLayout);
}
KatePartPluginConfigPage::~KatePartPluginConfigPage ()
{
}
void KatePartPluginConfigPage::apply ()
{
selector->updatePluginsState();
KatePartPluginList &katePluginList = KatePartPluginManager::self()->pluginList();
for (int i=0; i < plugins.count(); i++) {
if (plugins[i].isPluginEnabled()) {
if (!katePluginList[i].load) {
KatePartPluginManager::self()->loadPlugin(katePluginList[i]);
KatePartPluginManager::self()->enablePlugin(katePluginList[i]);
}
} else {
if (katePluginList[i].load) {
KatePartPluginManager::self()->disablePlugin(katePluginList[i]);
KatePartPluginManager::self()->unloadPlugin(katePluginList[i]);
}
}
}
}
void KatePartPluginConfigPage::reload ()
{
selector->load();
}
void KatePartPluginConfigPage::reset ()
{
selector->load();
}
void KatePartPluginConfigPage::defaults ()
{
selector->defaults();
}
//END KatePartPluginConfigPage
//BEGIN KateHlDownloadDialog
KateHlDownloadDialog::KateHlDownloadDialog(QWidget *parent, const char *name, bool modal)
: KDialog( parent )
{
setCaption( i18n("Highlight Download") );
setButtons( User1 | Close );
setButtonGuiItem( User1, KGuiItem(i18n("&Install")) );
setDefaultButton( User1 );
setObjectName( name );
setModal( modal );
KVBox* vbox = new KVBox(this);
setMainWidget(vbox);
vbox->setSpacing(-1);
new QLabel(i18n("Select the syntax highlighting files you want to update:"), vbox);
list = new QTreeWidget(vbox);
list->setColumnCount(4);
list->setHeaderLabels(QStringList() << "" << i18n("Name") << i18n("Installed") << i18n("Latest"));
list->setSelectionMode(QAbstractItemView::MultiSelection);
list->setAllColumnsShowFocus(true);
list->setRootIsDecorated(false);
list->setColumnWidth(0, 22);
new QLabel(i18n("Note: New versions are selected automatically."), vbox);
setButtonIcon(User1, KIcon("dialog-ok"));
transferJob = KIO::get(
KUrl(QString(HLDOWNLOADPATH)
+ QString("update-")
+ KateGlobal::katePartVersion()
+ QString(".xml")), KIO::Reload );
connect(transferJob, SIGNAL(data(KIO::Job*,QByteArray)),
this, SLOT(listDataReceived(KIO::Job*,QByteArray)));
// void data( KIO::Job *, const QByteArray &data);
resize(450, 400);
connect(this,SIGNAL(user1Clicked()),this,SLOT(slotUser1()));
}
KateHlDownloadDialog::~KateHlDownloadDialog(){}
void KateHlDownloadDialog::listDataReceived(KIO::Job *, const QByteArray &data)
{
if (!transferJob || transferJob->isErrorPage())
{
enableButton( User1, false );
if (data.size()==0)
KMessageBox::error(this,i18n("The list of highlightings could not be found on / retrieved from the server"));
return;
}
listData+=QString(data);
kDebug(13000)<0)
{
QString installedVersion;
KateHlManager *hlm=KateHlManager::self();
QDomDocument doc;
doc.setContent(listData);
QDomElement DocElem=doc.documentElement();
QDomNode n=DocElem.firstChild();
KateHighlighting *hl = 0;
if (n.isNull()) kDebug(13000)<<"There is no usable childnode";
while (!n.isNull())
{
installedVersion=" --";
QDomElement e=n.toElement();
if (!e.isNull())
kDebug(13000)<highlights();i++)
{
hl=hlm->getHl(i);
if (hl && hl->name()==Name)
{
installedVersion=" "+hl->version();
break;
}
else hl = 0;
}
// autoselect entry if new or updated.
QTreeWidgetItem* entry = new QTreeWidgetItem(list);
entry->setText(0, "");
entry->setText(1, e.attribute("name"));
entry->setText(2, installedVersion);
entry->setText(3, e.attribute("version"));
entry->setText(4, e.attribute("url"));
if (!hl || hl->version() < e.attribute("version"))
{
entry->treeWidget()->setItemSelected(entry, true);
entry->setIcon(0, SmallIcon(("get-hot-new-stuff")));
}
}
list->resizeColumnToContents(1);
list->sortItems(1, Qt::AscendingOrder);
}
}
}
void KateHlDownloadDialog::slotUser1()
{
QString destdir=KGlobal::dirs()->saveLocation("data","katepart/syntax/");
foreach (QTreeWidgetItem *it, list->selectedItems())
{
KUrl src(it->text(4));
QString filename=src.fileName(KUrl::ObeyTrailingSlash);
QString dest = destdir+filename;
KIO::NetAccess::download(src,dest, this);
}
// update Config !!
// this rewrites the cache....
KateSyntaxDocument doc (KateHlManager::self()->getKConfig(), true);
}
//END KateHlDownloadDialog
//BEGIN KateGotoBar
KateGotoBar::KateGotoBar(KTextEditor::View *view, QWidget *parent)
: KateViewBarWidget( true, parent )
, m_view( view )
{
Q_ASSERT( m_view != 0 ); // this bar widget is pointless w/o a view
QHBoxLayout *topLayout = new QHBoxLayout( centralWidget() );
topLayout->setMargin(0);
gotoRange = new KIntSpinBox(centralWidget());
QLabel *label = new QLabel(i18n("&Go to line:"), centralWidget() );
label->setBuddy(gotoRange);
QToolButton *btnOK = new QToolButton(centralWidget());
btnOK->setAutoRaise(true);
btnOK->setIcon(QIcon(SmallIcon("go-jump")));
btnOK->setText(i18n("Go"));
btnOK->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
connect(btnOK, SIGNAL(clicked()), this, SLOT(gotoLine()));
topLayout->addWidget(label);
topLayout->addWidget(gotoRange, 1);
topLayout->setStretchFactor( gotoRange, 0 );
topLayout->addWidget(btnOK);
topLayout->addStretch();
setFocusProxy(gotoRange);
}
void KateGotoBar::updateData()
{
gotoRange->setMaximum(m_view->document()->lines());
if (!isVisible())
{
gotoRange->setValue(m_view->cursorPosition().line() + 1);
gotoRange->adjustSize(); // ### does not respect the range :-(
}
gotoRange->setFocus(Qt::OtherFocusReason);
gotoRange->selectAll();
}
void KateGotoBar::keyPressEvent(QKeyEvent* event)
{
int key = event->key();
if (key == Qt::Key_Return || key == Qt::Key_Enter) {
gotoLine();
return;
}
KateViewBarWidget::keyPressEvent(event);
}
void KateGotoBar::gotoLine()
{
KateView *kv = qobject_cast(m_view);
if (kv && kv->selection() && !kv->config()->persistentSelection()) {
kv->clearSelection();
}
m_view->setCursorPosition( KTextEditor::Cursor(gotoRange->value() - 1, 0) );
m_view->setFocus();
emit hideMe();
}
//END KateGotoBar
//BEGIN KateDictionaryBar
KateDictionaryBar::KateDictionaryBar(KateView* view, QWidget *parent)
: KateViewBarWidget( true, parent )
, m_view( view )
{
Q_ASSERT(m_view != 0); // this bar widget is pointless w/o a view
QHBoxLayout *topLayout = new QHBoxLayout(centralWidget());
topLayout->setMargin(0);
//topLayout->setSpacing(spacingHint());
m_dictionaryComboBox = new Sonnet::DictionaryComboBox(centralWidget());
connect(m_dictionaryComboBox, SIGNAL(dictionaryChanged(QString)),
this, SLOT(dictionaryChanged(QString)));
connect(view->doc(), SIGNAL(defaultDictionaryChanged(KateDocument*)),
this, SLOT(updateData()));
QLabel *label = new QLabel(i18n("Dictionary:"), centralWidget());
label->setBuddy(m_dictionaryComboBox);
topLayout->addWidget(label);
topLayout->addWidget(m_dictionaryComboBox, 1);
topLayout->setStretchFactor(m_dictionaryComboBox, 0);
topLayout->addStretch();
}
KateDictionaryBar::~KateDictionaryBar()
{
}
void KateDictionaryBar::updateData()
{
KateDocument *document = m_view->doc();
QString dictionary = document->defaultDictionary();
if(dictionary.isEmpty()) {
dictionary = Sonnet::Speller().defaultLanguage();
}
m_dictionaryComboBox->setCurrentByDictionary(dictionary);
}
void KateDictionaryBar::dictionaryChanged(const QString& dictionary)
{
KTextEditor::Range selection = m_view->selectionRange();
if(selection.isValid() && !selection.isEmpty()) {
m_view->doc()->setDictionary(dictionary, selection);
}
else {
m_view->doc()->setDefaultDictionary(dictionary);
}
}
//END KateGotoBar
//BEGIN KateModOnHdPrompt
KateModOnHdPrompt::KateModOnHdPrompt( KateDocument *doc,
KTextEditor::ModificationInterface::ModifiedOnDiskReason modtype,
const QString &reason,
QWidget *parent )
: KDialog( parent ),
m_doc( doc ),
m_modtype ( modtype ),
m_proc( 0 ),
m_diffFile( 0 )
{
setButtons( Ok | Apply | Cancel | User1 );
QString title, okText, okIcon, okToolTip;
if ( modtype == KTextEditor::ModificationInterface::OnDiskDeleted )
{
title = i18n("File Was Deleted on Disk");
okText = i18n("&Save File As...");
okIcon = "document-save-as";
okToolTip = i18n("Lets you select a location and save the file again.");
} else {
title = i18n("File Changed on Disk");
okText = i18n("&Reload File");
okIcon = "view-refresh";
okToolTip = i18n("Reload the file from disk. If you have unsaved changes, "
"they will be lost.");
}
setButtonText( Ok, okText );
setButtonIcon( Ok, KIcon( okIcon ) );
setButtonText( Apply, i18n("&Ignore Changes") );
setButtonIcon( Apply, KIcon( "dialog-warning" ) );
setButtonToolTip( Ok, okToolTip );
setButtonToolTip( Apply, i18n("Ignore the changes. You will not be prompted again.") );
setButtonToolTip( Cancel, i18n("Do nothing. Next time you focus the file, "
"or try to save it or close it, you will be prompted again.") );
setCaption( title );
QWidget *w = new QWidget(this);
ui = new Ui::ModOnHdWidget();
ui->setupUi( w );
setMainWidget( w );
ui->lblIcon->setPixmap( DesktopIcon("dialog-warning" ) );
ui->lblText->setText( reason + "\n\n" + i18n("What do you want to do?") );
// If the file isn't deleted, present a diff button, and a overwrite action.
if ( modtype != KTextEditor::ModificationInterface::OnDiskDeleted )
{
setButtonGuiItem( User1, KStandardGuiItem::overwrite() );
setButtonToolTip( User1, i18n("Overwrite the disk file with the editor content.") );
connect( ui->btnDiff, SIGNAL(clicked()), this, SLOT(slotDiff()) );
}
else
{
ui->chkIgnoreWhiteSpaces->setVisible( false );
ui->btnDiff->setVisible( false );
showButton( User1, false );
}
}
KateModOnHdPrompt::~KateModOnHdPrompt()
{
delete m_proc;
m_proc = 0;
if (m_diffFile) {
m_diffFile->setAutoRemove(true);
delete m_diffFile;
m_diffFile = 0;
}
delete ui;
}
void KateModOnHdPrompt::slotDiff()
{
if (m_diffFile)
return;
m_diffFile = new KTemporaryFile();
m_diffFile->open();
// Start a KProcess that creates a diff
m_proc = new KProcess( this );
m_proc->setOutputChannelMode( KProcess::MergedChannels );
*m_proc << "diff" << QString(ui->chkIgnoreWhiteSpaces->isChecked() ? "-ub" : "-u")
<< "-" << m_doc->url().toLocalFile();
connect( m_proc, SIGNAL(readyRead()), this, SLOT(slotDataAvailable()) );
connect( m_proc, SIGNAL(finished(int,QProcess::ExitStatus)), this, SLOT(slotPDone()) );
setCursor( Qt::WaitCursor );
// disable the button and checkbox, to hinder the user to run it twice.
ui->chkIgnoreWhiteSpaces->setEnabled( false );
ui->btnDiff->setEnabled( false );
m_proc->start();
QTextStream ts(m_proc);
int lastln = m_doc->lines();
for ( int l = 0; l < lastln; ++l )
ts << m_doc->line( l ) << '\n';
ts.flush();
m_proc->closeWriteChannel();
}
void KateModOnHdPrompt::slotDataAvailable()
{
m_diffFile->write(m_proc->readAll());
}
void KateModOnHdPrompt::slotPDone()
{
setCursor( Qt::ArrowCursor );
ui->chkIgnoreWhiteSpaces->setEnabled( true );
ui->btnDiff->setEnabled( true );
const QProcess::ExitStatus es = m_proc->exitStatus();
delete m_proc;
m_proc = 0;
if ( es != QProcess::NormalExit )
{
KMessageBox::sorry( this,
i18n("The diff command failed. Please make sure that "
"diff(1) is installed and in your PATH."),
i18n("Error Creating Diff") );
delete m_diffFile;
m_diffFile = 0;
return;
}
if ( m_diffFile->size() == 0 )
{
KMessageBox::information( this,
i18n("Besides white space changes, the files are identical."),
i18n("Diff Output") );
delete m_diffFile;
m_diffFile = 0;
return;
}
m_diffFile->setAutoRemove(false);
KUrl url = KUrl::fromPath(m_diffFile->fileName());
delete m_diffFile;
m_diffFile = 0;
// KRun::runUrl should delete the file, once the client exits
KRun::runUrl( url, "text/x-patch", this, true );
}
void KateModOnHdPrompt::slotButtonClicked(int button)
{
switch(button)
{
case Default:
case Ok:
done( (m_modtype == KTextEditor::ModificationInterface::OnDiskDeleted) ?
Save : Reload );
break;
case Apply:
{
if ( KMessageBox::warningContinueCancel(
this,
i18n("Ignoring means that you will not be warned again (unless "
"the disk file changes once more): if you save the document, you "
"will overwrite the file on disk; if you do not save then the disk "
"file (if present) is what you have."),
i18n("You Are on Your Own"),
KStandardGuiItem::cont(),
KStandardGuiItem::cancel(),
"kate_ignore_modonhd" ) != KMessageBox::Continue )
return;
done( Ignore );
break;
}
case User1:
done( Overwrite );
break;
default:
KDialog::slotButtonClicked(button);
}
}
//END KateModOnHdPrompt
// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/part/document/katedocument.cpp b/part/document/katedocument.cpp
index bc8292241..26d33653d 100644
--- a/part/document/katedocument.cpp
+++ b/part/document/katedocument.cpp
@@ -1,5505 +1,5429 @@
/* This file is part of the KDE libraries
Copyright (C) 2001-2004 Christoph Cullmann
Copyright (C) 2001 Joseph Wenninger
Copyright (C) 1999 Jochen Wilhelmy
Copyright (C) 2006 Hamish Rodda
Copyright (C) 2007 Mirko Stocker
Copyright (C) 2009-2010 Michel Ludwig
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02111-13020, USA.
*/
//BEGIN includes
#include "katedocument.h"
#include "katedocument.moc"
#include "kateglobal.h"
#include "katedialogs.h"
#include "katehighlight.h"
#include "kateview.h"
#include "kateautoindent.h"
#include "katetextline.h"
#include "katedocumenthelpers.h"
#include "kateprinter.h"
#include "katerenderer.h"
#include "kateregexp.h"
#include "kateplaintextsearch.h"
#include "kateregexpsearch.h"
#include "kateconfig.h"
#include "katemodemanager.h"
#include "kateschema.h"
#include "katetemplatehandler.h"
#include "katebuffer.h"
#include "kateundomanager.h"
#include "katepartpluginmanager.h"
#include "katevireplacemode.h"
#include "spellcheck/prefixstore.h"
#include "spellcheck/ontheflycheck.h"
#include "spellcheck/spellcheck.h"
#include "katescriptmanager.h"
#include "kateswapfile.h"
#include "documentcursor.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//END includes
#if 0
#define EDIT_DEBUG kDebug()
#else
#define EDIT_DEBUG if (0) kDebug()
#endif
static int dummy = 0;
class KateTemplateScript;
inline bool isStartBracket( const QChar& c ) { return c == '{' || c == '[' || c == '('; }
inline bool isEndBracket ( const QChar& c ) { return c == '}' || c == ']' || c == ')'; }
inline bool isBracket ( const QChar& c ) { return isStartBracket( c ) || isEndBracket( c ); }
class KateDocument::LoadSaveFilterCheckPlugins
{
public:
LoadSaveFilterCheckPlugins() {
KService::List traderList = KServiceTypeTrader::self()->query("KTextEditor/LoadSaveFilterCheckPlugin");
foreach(const KService::Ptr &ptr, traderList)
{
QString libname;
libname=ptr->library();
libname=libname.right(libname.length()-12); //ktexteditor_ == 12
m_plugins[libname]=0;//new KatePythonEncodingCheck();
m_plugins2Service[libname] = ptr;
}
}
~LoadSaveFilterCheckPlugins() {
if ( m_plugins.count()==0) return;
QHashIteratori(m_plugins);
while (i.hasNext())
i.next();
delete i.value();
m_plugins.clear();
}
bool preSavePostDialogFilterCheck(const QString& pluginName,KateDocument *document,QWidget *parentWidget) {
KTextEditor::LoadSaveFilterCheckPlugin *plug=getPlugin(pluginName);
if (!plug) {
if (KMessageBox::warningContinueCancel (parentWidget
, i18n ("The filter/check plugin '%1' could not be found, still continue saving of %2", pluginName,document->url().pathOrUrl())
, i18n ("Saving problems")
, KGuiItem(i18n("Save Nevertheless"))
, KStandardGuiItem::cancel()) != KMessageBox::Continue)
return false;
else
return true;
}
return plug->preSavePostDialogFilterCheck(document);
}
void postLoadFilter(const QString& pluginName,KateDocument *document) {
KTextEditor::LoadSaveFilterCheckPlugin *plug=getPlugin(pluginName);
if (!plug) return;
plug->postLoadFilter(document);
}
bool postSaveFilterCheck(const QString& pluginName,KateDocument *document,bool saveas) {
KTextEditor::LoadSaveFilterCheckPlugin *plug=getPlugin(pluginName);
if (!plug) return false;
return plug->postSaveFilterCheck(document,saveas);
}
private:
KTextEditor::LoadSaveFilterCheckPlugin *getPlugin(const QString & pluginName)
{
if (!m_plugins.contains(pluginName)) return 0;
if (!m_plugins.value(pluginName, 0)) {
m_plugins[pluginName]=m_plugins2Service.value(pluginName)->createInstance();
}
return m_plugins.value(pluginName);
}
QHash m_plugins;
QHash m_plugins2Service;
};
//BEGIN d'tor, c'tor
//
// KateDocument Constructor
//
KateDocument::KateDocument ( bool bSingleViewMode, bool bBrowserView,
bool bReadOnly, QWidget *parentWidget,
QObject *parent)
: KTextEditor::Document (parent),
m_bSingleViewMode(bSingleViewMode),
m_bBrowserView(bBrowserView),
m_bReadOnly(bReadOnly),
m_activeView(0),
editSessionNumber(0),
editIsRunning(false),
m_undoManager(new KateUndoManager(this)),
m_editableMarks(markType01),
m_annotationModel(0),
m_saveAs(false),
m_isasking(0),
m_buffer(new KateBuffer(this)),
m_indenter(new KateAutoIndent(this)),
m_hlSetByUser(false),
m_bomSetByUser(false),
m_indenterSetByUser(false),
m_userSetEncodingForNextReload(false),
m_modOnHd(false),
m_modOnHdReason(OnDiskUnmodified),
m_docName("need init"),
m_docNameNumber(0),
m_fileTypeSetByUser(false),
m_reloading(false),
m_config(new KateDocumentConfig(this)),
m_fileChangedDialogsActivated(false),
m_savingToUrl(false),
m_onTheFlyChecker(0),
m_filePerhapsStillLoading (false)
{
setComponentData ( KateGlobal::self()->componentData () );
/**
* avoid spamming plasma and other window managers with progress dialogs
* we show such stuff inline in the views!
*/
setProgressInfoEnabled (false);
QString pathName ("/Kate/Document/%1");
pathName = pathName.arg (++dummy);
// my dbus object
QDBusConnection::sessionBus().registerObject (pathName, this, QDBusConnection::ExportAdaptors | QDBusConnection::ExportScriptableSlots);
// register doc at factory
KateGlobal::self()->registerDocument(this);
// normal hl
m_buffer->setHighlight (0);
// swap file
m_swapfile = new Kate::SwapFile(this);
new KateBrowserExtension( this ); // deleted by QObject memory management
// important, fill in the config into the indenter we use...
m_indenter->updateConfig ();
// some nice signals from the buffer
connect(m_buffer, SIGNAL(tagLines(int,int)), this, SLOT(tagLines(int,int)));
connect(m_buffer, SIGNAL(respellCheckBlock(int,int)), this , SLOT(respellCheckBlock(int,int)));
connect(m_buffer, SIGNAL(codeFoldingUpdated()),this,SIGNAL(codeFoldingUpdated()));
connect(this,SIGNAL(aboutToReload(KTextEditor::Document*)),foldingTree(),SLOT(saveFoldingState()));
connect(this,SIGNAL(reloaded(KTextEditor::Document*)),foldingTree(),SLOT(applyFoldingState()));
// if the user changes the highlight with the dialog, notify the doc
connect(KateHlManager::self(),SIGNAL(changed()),SLOT(internalHlChanged()));
// signals for mod on hd
connect( KateGlobal::self()->dirWatch(), SIGNAL(dirty(QString)),
this, SLOT(slotModOnHdDirty(QString)) );
connect( KateGlobal::self()->dirWatch(), SIGNAL(created(QString)),
this, SLOT(slotModOnHdCreated(QString)) );
connect( KateGlobal::self()->dirWatch(), SIGNAL(deleted(QString)),
this, SLOT(slotModOnHdDeleted(QString)) );
connect (this, SIGNAL(started(KIO::Job*)), this, SLOT(slotStarted(KIO::Job*)));
connect (this, SIGNAL(completed()), this, SLOT(slotCompleted()));
connect (this, SIGNAL(canceled(QString)), this, SLOT(slotCanceled()));
// update doc name
setDocName (QString());
// if single view mode, like in the konqui embedding, create a default view ;)
// be lazy, only create it now, if any parentWidget is given, otherwise widget()
// will create it on demand...
if ( m_bSingleViewMode && parentWidget )
{
KTextEditor::View *view = (KTextEditor::View*)createView( parentWidget );
insertChildClient( view );
view->show();
setWidget( view );
}
connect(m_undoManager, SIGNAL(undoChanged()), this, SIGNAL(undoChanged()));
connect(m_undoManager, SIGNAL(undoStart(KTextEditor::Document*)), this, SIGNAL(exclusiveEditStart(KTextEditor::Document*)));
connect(m_undoManager, SIGNAL(undoEnd(KTextEditor::Document*)), this, SIGNAL(exclusiveEditEnd(KTextEditor::Document*)));
connect(m_undoManager, SIGNAL(redoStart(KTextEditor::Document*)), this, SIGNAL(exclusiveEditStart(KTextEditor::Document*)));
connect(m_undoManager, SIGNAL(redoEnd(KTextEditor::Document*)), this, SIGNAL(exclusiveEditEnd(KTextEditor::Document*)));
connect(this,SIGNAL(sigQueryClose(bool*,bool*)),this,SLOT(slotQueryClose_save(bool*,bool*)));
onTheFlySpellCheckingEnabled(config()->onTheFlySpellCheck());
// register document in plugins
KatePartPluginManager::self()->addDocument(this);
}
//
// KateDocument Destructor
//
KateDocument::~KateDocument()
{
/**
* we are about to delete cursors/ranges/...
*/
emit aboutToDeleteMovingInterfaceContent (this);
// kill it early, it has ranges!
delete m_onTheFlyChecker;
m_onTheFlyChecker = NULL;
clearDictionaryRanges();
// Tell the world that we're about to close (== destruct)
// Apps must receive this in a direct signal-slot connection, and prevent
// any further use of interfaces once they return.
emit aboutToClose(this);
// remove file from dirwatch
deactivateDirWatch ();
// thanks for offering, KPart, but we're already self-destructing
setAutoDeleteWidget(false);
setAutoDeletePart(false);
// clean up remaining views
while (!m_views.isEmpty()) {
delete m_views.takeFirst();
}
// de-register from plugin
KatePartPluginManager::self()->removeDocument(this);
// cu marks
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
delete i.value();
m_marks.clear();
delete m_config;
KateGlobal::self()->deregisterDocument (this);
}
//END
// on-demand view creation
QWidget *KateDocument::widget()
{
// no singleViewMode -> no widget()...
if (!singleViewMode())
return 0;
// does a widget exist already? use it!
if (KTextEditor::Document::widget())
return KTextEditor::Document::widget();
// create and return one...
KTextEditor::View *view = (KTextEditor::View*)createView(0);
insertChildClient( view );
setWidget( view );
return view;
}
//BEGIN KTextEditor::Document stuff
KTextEditor::View *KateDocument::createView( QWidget *parent )
{
KateView* newView = new KateView( this, parent);
if ( m_fileChangedDialogsActivated )
connect( newView, SIGNAL(focusIn(KTextEditor::View*)), this, SLOT(slotModifiedOnDisk()) );
emit viewCreated (this, newView);
// post existing messages to the new view, if no specific view is given
foreach (KTextEditor::Message *message, m_messageHash.keys()) {
if (!message->view())
newView->postMessage(message, m_messageHash[message]);
}
return newView;
}
const QList &KateDocument::views () const
{
return m_textEditViews;
}
KTextEditor::Editor *KateDocument::editor ()
{
return KateGlobal::self();
}
KTextEditor::Range KateDocument::rangeOnLine(KTextEditor::Range range, int line) const
{
int col1 = const_cast(this)->toVirtualColumn(range.start());
int col2 = const_cast(this)->toVirtualColumn(range.end());
Kate::TextLine tl = const_cast(this)->kateTextLine(line);
col1 = tl->fromVirtualColumn(col1, config()->tabWidth());
col2 = tl->fromVirtualColumn(col2, config()->tabWidth());
return KTextEditor::Range(line, col1, line, col2);
}
//BEGIN KTextEditor::EditInterface stuff
QString KateDocument::text() const
{
return m_buffer->text ();
}
QString KateDocument::text( const KTextEditor::Range& range, bool blockwise ) const
{
if (!range.isValid()) {
kWarning() << k_funcinfo << "Text requested for invalid range" << range;
return QString();
}
QString s;
if (range.start().line() == range.end().line())
{
if (range.start().column() > range.end().column())
return QString ();
Kate::TextLine textLine = m_buffer->plainLine(range.start().line());
if ( !textLine )
return QString ();
return textLine->string(range.start().column(), range.end().column()-range.start().column());
}
else
{
for (int i = range.start().line(); (i <= range.end().line()) && (i < m_buffer->count()); ++i)
{
Kate::TextLine textLine = m_buffer->plainLine(i);
if ( !blockwise )
{
if (i == range.start().line())
s.append (textLine->string(range.start().column(), textLine->length()-range.start().column()));
else if (i == range.end().line())
s.append (textLine->string(0, range.end().column()));
else
s.append (textLine->string());
}
else
{
KTextEditor::Range subRange = rangeOnLine(range, i);
s.append(textLine->string(subRange.start().column(), subRange.columnWidth()));
}
if ( i < range.end().line() )
s.append(QChar::fromAscii('\n'));
}
}
return s;
}
QChar KateDocument::character( const KTextEditor::Cursor & position ) const
{
Kate::TextLine textLine = m_buffer->plainLine(position.line());
if ( !textLine )
return QChar();
return textLine->at(position.column());
}
QStringList KateDocument::textLines( const KTextEditor::Range & range, bool blockwise ) const
{
QStringList ret;
if (!range.isValid()) {
kWarning() << k_funcinfo << "Text requested for invalid range" << range;
return ret;
}
if ( blockwise && (range.start().column() > range.end().column()) )
return ret;
if (range.start().line() == range.end().line())
{
Q_ASSERT(range.start() <= range.end());
Kate::TextLine textLine = m_buffer->plainLine(range.start().line());
if ( !textLine )
return ret;
ret << textLine->string(range.start().column(), range.end().column() - range.start().column());
}
else
{
for (int i = range.start().line(); (i <= range.end().line()) && (i < m_buffer->count()); ++i)
{
Kate::TextLine textLine = m_buffer->plainLine(i);
if ( !blockwise )
{
if (i == range.start().line())
ret << textLine->string(range.start().column(), textLine->length() - range.start().column());
else if (i == range.end().line())
ret << textLine->string(0, range.end().column());
else
ret << textLine->string();
}
else
{
KTextEditor::Range subRange = rangeOnLine(range, i);
ret << textLine->string(subRange.start().column(), subRange.columnWidth());
}
}
}
return ret;
}
QString KateDocument::line( int line ) const
{
Kate::TextLine l = m_buffer->plainLine(line);
if (!l)
return QString();
return l->string();
}
bool KateDocument::setText(const QString &s)
{
if (!isReadWrite())
return false;
QList msave;
foreach (KTextEditor::Mark* mark, m_marks)
msave.append(*mark);
editStart ();
// delete the text
clear();
// insert the new text
insertText (KTextEditor::Cursor(), s);
editEnd ();
foreach (const KTextEditor::Mark& mark, msave)
setMark (mark.line, mark.type);
return true;
}
bool KateDocument::setText( const QStringList & text )
{
if (!isReadWrite())
return false;
QList msave;
foreach (KTextEditor::Mark* mark, m_marks)
msave.append(*mark);
editStart ();
// delete the text
clear();
// insert the new text
insertText (KTextEditor::Cursor::start(), text);
editEnd ();
foreach (const KTextEditor::Mark& mark, msave)
setMark (mark.line, mark.type);
return true;
}
bool KateDocument::clear()
{
if (!isReadWrite())
return false;
foreach (KateView *view, m_views) {
view->clear();
view->tagAll();
view->update();
}
clearMarks ();
emit aboutToInvalidateMovingInterfaceContent(this);
m_buffer->invalidateRanges();
emit aboutToRemoveText(documentRange());
return editRemoveLines(0, lastLine());
}
bool KateDocument::insertText( const KTextEditor::Cursor& position, const QString& text, bool block )
{
if (!isReadWrite())
return false;
if (text.isEmpty())
return true;
editStart();
int currentLine = position.line();
int currentLineStart = 0;
int totalLength = text.length();
int insertColumn = position.column();
if (position.line() > lines())
{
int line = lines();
while (line != position.line() + totalLength + 1)
{
editInsertLine(line,QString());
line++;
}
}
bool replacetabs = ( config()->replaceTabsDyn() );
int tabWidth = config()->tabWidth();
static const QChar newLineChar('\n');
static const QChar tabChar('\t');
static const QChar spaceChar(' ');
int insertColumnExpanded = insertColumn;
Kate::TextLine l = kateTextLine( currentLine );
if (l)
insertColumnExpanded = l->toVirtualColumn( insertColumn, tabWidth );
int pos = 0;
for (; pos < totalLength; pos++)
{
const QChar& ch = text.at(pos);
if (ch == newLineChar)
{
// Only perform the text insert if there is text to insert
if (currentLineStart < pos)
editInsertText(currentLine, insertColumn, text.mid(currentLineStart, pos - currentLineStart));
if ( !block )
{
editWrapLine(currentLine, insertColumn + pos - currentLineStart);
insertColumn = 0;
}
else
{
if ( currentLine == lastLine() )
editWrapLine(currentLine , insertColumn + pos - currentLineStart);
insertColumn = position.column(); // tab expansion might change this
}
currentLine++;
currentLineStart = pos + 1;
l = kateTextLine( currentLine );
if (l)
insertColumnExpanded = l->toVirtualColumn( insertColumn, tabWidth );
}
else
{
if ( replacetabs && ch == tabChar )
{
int spacesRequired = tabWidth - ( (insertColumnExpanded + pos - currentLineStart) % tabWidth );
editInsertText(currentLine, insertColumn, text.mid(currentLineStart, pos - currentLineStart) + QString(spacesRequired, spaceChar));
insertColumn += pos - currentLineStart + spacesRequired;
currentLineStart = pos + 1;
l = kateTextLine( currentLine );
if (l)
insertColumnExpanded = l->toVirtualColumn( insertColumn, tabWidth );
}
}
}
// Only perform the text insert if there is text to insert
if (currentLineStart < pos)
editInsertText(currentLine, insertColumn, text.mid(currentLineStart, pos - currentLineStart));
editEnd();
return true;
}
bool KateDocument::insertText( const KTextEditor::Cursor & position, const QStringList & textLines, bool block )
{
if (!isReadWrite())
return false;
// just reuse normal function
return insertText (position, textLines.join ("\n"), block);
}
bool KateDocument::removeText ( const KTextEditor::Range &_range, bool block )
{
KTextEditor::Range range = _range;
if (!isReadWrite())
return false;
// Should now be impossible to trigger with the new Range class
Q_ASSERT( range.start().line() <= range.end().line() );
if ( range.start().line() > lastLine() )
return false;
if (!block)
emit aboutToRemoveText(range);
editStart();
if ( !block )
{
if ( range.end().line() > lastLine() )
{
range.end().setPosition(lastLine()+1, 0);
}
if (range.onSingleLine())
{
editRemoveText(range.start().line(), range.start().column(), range.columnWidth());
}
else
{
int from = range.start().line();
int to = range.end().line();
// remove last line
if (to <= lastLine())
editRemoveText(to, 0, range.end().column());
// editRemoveLines() will be called on first line (to remove bookmark)
if (range.start().column() == 0 && from > 0)
--from;
// remove middle lines
editRemoveLines(from+1, to-1);
// remove first line if not already removed by editRemoveLines()
if (range.start().column() > 0 || range.start().line() == 0) {
editRemoveText(from, range.start().column(), m_buffer->plainLine(from)->length() - range.start().column());
editUnWrapLine(from);
}
}
} // if ( ! block )
else
{
int startLine = qMax(0, range.start().line());
int vc1 = toVirtualColumn(range.start());
int vc2 = toVirtualColumn(range.end());
for (int line = qMin(range.end().line(), lastLine()); line >= startLine; --line) {
Kate::TextLine tl = const_cast(this)->kateTextLine(line);
int col1 = tl->fromVirtualColumn(vc1, config()->tabWidth());
int col2 = tl->fromVirtualColumn(vc2, config()->tabWidth());
editRemoveText(line, qMin(col1, col2), qAbs(col2 - col1));
}
}
editEnd ();
return true;
}
bool KateDocument::insertLine( int l, const QString &str )
{
if (!isReadWrite())
return false;
if (l < 0 || l > lines())
return false;
return editInsertLine (l, str);
}
bool KateDocument::insertLines( int line, const QStringList & text )
{
if (!isReadWrite())
return false;
if (line < 0 || line > lines())
return false;
bool success = true;
foreach (const QString &string, text)
success &= editInsertLine (line++, string);
return success;
}
bool KateDocument::removeLine( int line )
{
if (!isReadWrite())
return false;
if (line < 0 || line > lastLine())
return false;
return editRemoveLine (line);
}
int KateDocument::totalCharacters() const
{
int l = 0;
for (int i = 0; i < m_buffer->count(); ++i)
{
Kate::TextLine line = m_buffer->plainLine(i);
if (line)
l += line->length();
}
return l;
}
int KateDocument::lines() const
{
return m_buffer->count();
}
int KateDocument::numVisLines() const
{
return m_buffer->countVisible ();
}
int KateDocument::lineLength ( int line ) const
{
if (line < 0 || line > lastLine())
return -1;
Kate::TextLine l = m_buffer->plainLine(line);
if (!l)
return -1;
return l->length();
}
//END
//BEGIN KTextEditor::EditInterface internal stuff
//
// Starts an edit session with (or without) undo, update of view disabled during session
//
void KateDocument::editStart ()
{
editSessionNumber++;
if (editSessionNumber > 1)
return;
editIsRunning = true;
m_undoManager->editStart();
foreach(KateView *view,m_views)
view->editStart ();
m_buffer->editStart ();
}
//
// End edit session and update Views
//
void KateDocument::editEnd ()
{
if (editSessionNumber == 0) {
Q_ASSERT(0);
return;
}
// wrap the new/changed text, if something really changed!
if (m_buffer->editChanged() && (editSessionNumber == 1))
if (m_undoManager->isActive() && config()->wordWrap())
wrapText (m_buffer->editTagStart(), m_buffer->editTagEnd());
editSessionNumber--;
if (editSessionNumber > 0)
return;
// end buffer edit, will trigger hl update
// this will cause some possible adjustment of tagline start/end
m_buffer->editEnd ();
m_undoManager->editEnd();
// edit end for all views !!!!!!!!!
foreach(KateView *view, m_views)
view->editEnd (m_buffer->editTagStart(), m_buffer->editTagEnd(), m_buffer->editTagFrom());
if (m_buffer->editChanged()) {
setModified(true);
emit textChanged (this);
}
editIsRunning = false;
}
void KateDocument::pushEditState ()
{
editStateStack.push(editSessionNumber);
}
void KateDocument::popEditState ()
{
if (editStateStack.isEmpty()) return;
int count = editStateStack.pop() - editSessionNumber;
while (count < 0) { ++count; editEnd(); }
while (count > 0) { --count; editStart(); }
}
void KateDocument::inputMethodStart()
{
m_undoManager->inputMethodStart();
}
void KateDocument::inputMethodEnd()
{
m_undoManager->inputMethodEnd();
}
bool KateDocument::wrapText(int startLine, int endLine)
{
if (startLine < 0 || endLine < 0)
return false;
if (!isReadWrite())
return false;
int col = config()->wordWrapAt();
if (col == 0)
return false;
editStart ();
for (int line = startLine; (line <= endLine) && (line < lines()); line++)
{
Kate::TextLine l = kateTextLine(line);
if (!l)
break;
//kDebug (13020) << "try wrap line: " << line;
if (l->virtualLength(m_buffer->tabWidth()) > col)
{
Kate::TextLine nextl = kateTextLine(line+1);
//kDebug (13020) << "do wrap line: " << line;
int eolPosition = l->length()-1;
// take tabs into account here, too
int x = 0;
const QString & t = l->string();
int z2 = 0;
for ( ; z2 < l->length(); z2++)
{
static const QChar tabChar('\t');
if (t.at(z2) == tabChar)
x += m_buffer->tabWidth() - (x % m_buffer->tabWidth());
else
x++;
if (x > col)
break;
}
const int colInChars = qMin (z2, l->length()-1);
int searchStart = colInChars;
// If where we are wrapping is an end of line and is a space we don't
// want to wrap there
if (searchStart == eolPosition && t.at(searchStart).isSpace())
searchStart--;
// Scan backwards looking for a place to break the line
// We are not interested in breaking at the first char
// of the line (if it is a space), but we are at the second
// anders: if we can't find a space, try breaking on a word
// boundary, using KateHighlight::canBreakAt().
// This could be a priority (setting) in the hl/filetype/document
int z = -1;
int nw = -1; // alternative position, a non word character
for (z=searchStart; z >= 0; z--)
{
if (t.at(z).isSpace()) break;
if ( (nw < 0) && highlight()->canBreakAt( t.at(z) , l->attribute(z) ) )
nw = z;
}
if (z >= 0)
{
// So why don't we just remove the trailing space right away?
// Well, the (view's) cursor may be directly in front of that space
// (user typing text before the last word on the line), and if that
// happens, the cursor would be moved to the next line, which is not
// what we want (bug #106261)
z++;
}
else
{
// There was no space to break at so break at a nonword character if
// found, or at the wrapcolumn ( that needs be configurable )
// Don't try and add any white space for the break
if ( (nw >= 0) && nw < colInChars ) nw++; // break on the right side of the character
z = (nw >= 0) ? nw : colInChars;
}
if (nextl && !nextl->isAutoWrapped())
{
editWrapLine (line, z, true);
editMarkLineAutoWrapped (line+1, true);
endLine++;
}
else
{
if (nextl && (nextl->length() > 0) && !nextl->at(0).isSpace() && ((l->length() < 1) || !l->at(l->length()-1).isSpace()))
editInsertText (line+1, 0, QString (" "));
bool newLineAdded = false;
editWrapLine (line, z, false, &newLineAdded);
editMarkLineAutoWrapped (line+1, true);
endLine++;
}
}
}
editEnd ();
return true;
}
bool KateDocument::editInsertText ( int line, int col, const QString &s )
{
// verbose debug
EDIT_DEBUG << "editInsertText" << line << col << s;
if (line < 0 || col < 0)
return false;
if (!isReadWrite())
return false;
Kate::TextLine l = kateTextLine(line);
if (!l)
return false;
// nothing to do, do nothing!
if (s.isEmpty())
return true;
editStart ();
QString s2 = s;
int col2 = col;
if (col2 > l->length()) {
s2 = QString(col2 - l->length(), QLatin1Char(' ')) + s;
col2 = l->length();
}
m_undoManager->slotTextInserted(line, col2, s2);
// insert text into line
m_buffer->insertText (KTextEditor::Cursor (line, col2), s2);
emit KTextEditor::Document::textInserted(this, KTextEditor::Range(line, col2, line, col2 + s2.length()));
editEnd();
return true;
}
bool KateDocument::editRemoveText ( int line, int col, int len )
{
// verbose debug
EDIT_DEBUG << "editRemoveText" << line << col << len;
if (line < 0 || col < 0 || len < 0)
return false;
if (!isReadWrite())
return false;
Kate::TextLine l = kateTextLine(line);
if (!l)
return false;
// nothing to do, do nothing!
if (len == 0)
return true;
// wrong column
if (col >= l->text().size())
return false;
// don't try to remove what's not there
len = qMin(len, l->text().size() - col);
editStart ();
QString oldText = l->string().mid(col, len);
m_undoManager->slotTextRemoved(line, col, oldText);
// remove text from line
m_buffer->removeText (KTextEditor::Range (KTextEditor::Cursor (line, col), KTextEditor::Cursor (line, col+len)));
emit KTextEditor::Document::textRemoved(this, KTextEditor::Range(line, col, line, col + len));
emit KTextEditor::Document::textRemoved(this, KTextEditor::Range(line, col, line, col + len), oldText);
editEnd ();
return true;
}
bool KateDocument::editMarkLineAutoWrapped ( int line, bool autowrapped )
{
// verbose debug
EDIT_DEBUG << "editMarkLineAutoWrapped" << line << autowrapped;
if (line < 0)
return false;
if (!isReadWrite())
return false;
Kate::TextLine l = kateTextLine(line);
if (!l)
return false;
editStart ();
m_undoManager->slotMarkLineAutoWrapped(line, autowrapped);
l->setAutoWrapped (autowrapped);
editEnd ();
return true;
}
bool KateDocument::editWrapLine ( int line, int col, bool newLine, bool *newLineAdded)
{
// verbose debug
EDIT_DEBUG << "editWrapLine" << line << col << newLine;
if (line < 0 || col < 0)
return false;
if (!isReadWrite())
return false;
Kate::TextLine l = kateTextLine(line);
if (!l)
return false;
editStart ();
Kate::TextLine nextLine = kateTextLine(line+1);
const int length = l->length();
m_undoManager->slotLineWrapped(line, col, length - col, (!nextLine || newLine));
if (!nextLine || newLine)
{
m_buffer->wrapLine (KTextEditor::Cursor (line, col));
QList list;
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
{
if( i.value()->line >= line )
{
if ((col == 0) || (i.value()->line > line))
list.append( i.value() );
}
}
for( int i=0; i < list.size(); ++i )
m_marks.take( list.at(i)->line );
for( int i=0; i < list.size(); ++i )
{
list.at(i)->line++;
m_marks.insert( list.at(i)->line, list.at(i) );
}
if( !list.isEmpty() )
emit marksChanged( this );
// yes, we added a new line !
if (newLineAdded)
(*newLineAdded) = true;
}
else
{
m_buffer->wrapLine (KTextEditor::Cursor (line, col));
m_buffer->unwrapLine (line + 2);
// no, no new line added !
if (newLineAdded)
(*newLineAdded) = false;
}
emit KTextEditor::Document::textInserted(this, KTextEditor::Range(line, col, line+1, 0));
editEnd ();
return true;
}
bool KateDocument::editUnWrapLine ( int line, bool removeLine, int length )
{
// verbose debug
EDIT_DEBUG << "editUnWrapLine" << line << removeLine << length;
if (line < 0 || length < 0)
return false;
if (!isReadWrite())
return false;
Kate::TextLine l = kateTextLine(line);
Kate::TextLine nextLine = kateTextLine(line+1);
if (!l || !nextLine)
return false;
editStart ();
int col = l->length ();
m_undoManager->slotLineUnWrapped(line, col, length, removeLine);
if (removeLine)
{
m_buffer->unwrapLine (line+1);
}
else
{
m_buffer->wrapLine (KTextEditor::Cursor (line + 1, length));
m_buffer->unwrapLine (line + 1);
}
QList list;
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
{
if( i.value()->line >= line+1 )
list.append( i.value() );
if ( i.value()->line == line+1 )
{
KTextEditor::Mark* mark = m_marks.take( line );
if (mark)
{
i.value()->type |= mark->type;
}
}
}
for( int i=0; i < list.size(); ++i )
m_marks.take( list.at(i)->line );
for( int i=0; i < list.size(); ++i )
{
list.at(i)->line--;
m_marks.insert( list.at(i)->line, list.at(i) );
}
if( !list.isEmpty() )
emit marksChanged( this );
emit KTextEditor::Document::textRemoved(this, KTextEditor::Range(line, col, line+1, 0));
emit KTextEditor::Document::textRemoved(this, KTextEditor::Range(line, col, line+1, 0), "\n");
editEnd ();
return true;
}
bool KateDocument::editInsertLine ( int line, const QString &s )
{
// verbose debug
EDIT_DEBUG << "editInsertLine" << line << s;
if (line < 0)
return false;
if (!isReadWrite())
return false;
if ( line > lines() )
return false;
editStart ();
m_undoManager->slotLineInserted(line, s);
// wrap line
if (line > 0) {
Kate::TextLine previousLine = m_buffer->line (line-1);
m_buffer->wrapLine (KTextEditor::Cursor (line-1, previousLine->text().size()));
} else {
m_buffer->wrapLine (KTextEditor::Cursor (0, 0));
}
// insert text
m_buffer->insertText (KTextEditor::Cursor (line, 0), s);
Kate::TextLine tl = m_buffer->line (line);
QList list;
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
{
if( i.value()->line >= line )
list.append( i.value() );
}
for( int i=0; i < list.size(); ++i )
m_marks.take( list.at(i)->line );
for( int i=0; i < list.size(); ++i )
{
list.at(i)->line++;
m_marks.insert( list.at(i)->line, list.at(i) );
}
if( !list.isEmpty() )
emit marksChanged( this );
KTextEditor::Range rangeInserted(line, 0, line, tl->length());
if (line) {
Kate::TextLine prevLine = plainKateTextLine(line - 1);
rangeInserted.start().setPosition(line - 1, prevLine->length());
} else {
rangeInserted.end().setPosition(line + 1, 0);
}
emit KTextEditor::Document::textInserted(this, rangeInserted);
editEnd ();
return true;
}
bool KateDocument::editRemoveLine ( int line )
{
return editRemoveLines(line, line);
}
bool KateDocument::editRemoveLines ( int from, int to )
{
// verbose debug
EDIT_DEBUG << "editRemoveLines" << from << to;
if (to < from || from < 0 || to > lastLine())
return false;
if (!isReadWrite())
return false;
if (lines() == 1)
return editRemoveText(0, 0, kateTextLine(0)->length());
editStart();
QStringList oldText;
for (int line = to; line >= from; line--) {
Kate::TextLine tl = m_buffer->line (line);
oldText.prepend(this->line(line));
m_undoManager->slotLineRemoved(line, this->line(line));
m_buffer->removeText (KTextEditor::Range (KTextEditor::Cursor (line, 0), KTextEditor::Cursor (line, tl->text().size())));
}
m_buffer->unwrapLines(from, to);
QList rmark;
QList list;
foreach (KTextEditor::Mark* mark, m_marks) {
int line = mark->line;
if (line > to)
list << line;
else if (line >= from)
rmark << line;
}
foreach (int line, rmark)
delete m_marks.take(line);
foreach (int line, list)
{
KTextEditor::Mark* mark = m_marks.take(line);
mark->line -= to - from + 1;
m_marks.insert(mark->line, mark);
}
if (!list.isEmpty())
emit marksChanged(this);
KTextEditor::Range rangeRemoved(from, 0, to + 1, 0);
if (to == lastLine() + to - from + 1) {
rangeRemoved.end().setPosition(to, oldText.last().length());
if (from > 0) {
Kate::TextLine prevLine = plainKateTextLine(from - 1);
rangeRemoved.start().setPosition(from - 1, prevLine->length());
}
}
emit KTextEditor::Document::textRemoved(this, rangeRemoved);
emit KTextEditor::Document::textRemoved(this, rangeRemoved, oldText.join("\n") + '\n');
editEnd();
return true;
}
//END
KateUndoManager* KateDocument::undoManager()
{
return m_undoManager;
}
//BEGIN KTextEditor::UndoInterface stuff
uint KateDocument::undoCount () const
{
return m_undoManager->undoCount ();
}
uint KateDocument::redoCount () const
{
return m_undoManager->redoCount ();
}
void KateDocument::undo()
{
m_undoManager->undo();
}
void KateDocument::redo()
{
m_undoManager->redo();
}
//END
//BEGIN KTextEditor::SearchInterface stuff
QVector KateDocument::searchText(
const KTextEditor::Range & range,
const QString & pattern,
const KTextEditor::Search::SearchOptions options)
{
// TODO
// * support BlockInputRange
// * support DotMatchesNewline
const bool escapeSequences = options.testFlag(KTextEditor::Search::EscapeSequences);
const bool regexMode = options.testFlag(KTextEditor::Search::Regex);
const bool backwards = options.testFlag(KTextEditor::Search::Backwards);
const bool wholeWords = options.testFlag(KTextEditor::Search::WholeWords);
const Qt::CaseSensitivity caseSensitivity = options.testFlag(KTextEditor::Search::CaseInsensitive) ? Qt::CaseInsensitive : Qt::CaseSensitive;
if (regexMode)
{
// regexp search
// escape sequences are supported by definition
KateRegExpSearch searcher(this, caseSensitivity);
return searcher.search(pattern, range, backwards);
}
if (escapeSequences)
{
// escaped search
KatePlainTextSearch searcher(this, caseSensitivity, wholeWords);
KTextEditor::Range match = searcher.search(KateRegExpSearch::escapePlaintext(pattern), range, backwards);
QVector result;
result.append(match);
return result;
}
// plaintext search
KatePlainTextSearch searcher(this, caseSensitivity, wholeWords);
KTextEditor::Range match = searcher.search(pattern, range, backwards);
QVector result;
result.append(match);
return result;
}
KTextEditor::Search::SearchOptions KateDocument::supportedSearchOptions() const
{
KTextEditor::Search::SearchOptions supported(KTextEditor::Search::Default);
supported |= KTextEditor::Search::Regex;
supported |= KTextEditor::Search::CaseInsensitive;
supported |= KTextEditor::Search::Backwards;
// supported |= KTextEditor::Search::BlockInputRange;
supported |= KTextEditor::Search::EscapeSequences;
supported |= KTextEditor::Search::WholeWords;
// supported |= KTextEditor::Search::DotMatchesNewline;
return supported;
}
//END
QWidget * KateDocument::dialogParent()
{
QWidget *w=widget();
if(!w)
{
w=activeView();
if(!w)
w=QApplication::activeWindow();
}
return w;
}
//BEGIN KTextEditor::HighlightingInterface stuff
bool KateDocument::setMode (const QString &name)
{
updateFileType (name);
return true;
}
QString KateDocument::mode () const
{
return m_fileType;
}
QStringList KateDocument::modes () const
{
QStringList m;
const QList &modeList = KateGlobal::self()->modeManager()->list();
foreach(KateFileType* type, modeList)
m << type->name;
return m;
}
bool KateDocument::setHighlightingMode (const QString &name)
{
int mode = KateHlManager::self()->nameFind(name);
if (mode == -1) {
return false;
}
m_buffer->setHighlight(mode);
return true;
}
QString KateDocument::highlightingMode () const
{
return highlight()->name ();
}
QStringList KateDocument::highlightingModes () const
{
QStringList hls;
for (int i = 0; i < KateHlManager::self()->highlights(); ++i)
hls << KateHlManager::self()->hlName (i);
return hls;
}
QString KateDocument::highlightingModeSection( int index ) const
{
return KateHlManager::self()->hlSection( index );
}
QString KateDocument::modeSection( int index ) const
{
return KateGlobal::self()->modeManager()->list().at( index )->section;
}
void KateDocument::bufferHlChanged ()
{
// update all views
makeAttribs(false);
// deactivate indenter if necessary
m_indenter->checkRequiredStyle();
emit highlightingModeChanged(this);
}
void KateDocument::setDontChangeHlOnSave()
{
m_hlSetByUser = true;
}
void KateDocument::bomSetByUser()
{
m_bomSetByUser=true;
}
//END
//BEGIN KTextEditor::SessionConfigInterface and KTextEditor::ParameterizedSessionConfigInterface stuff
void KateDocument::readSessionConfig(const KConfigGroup &kconfig)
{
readParameterizedSessionConfig(kconfig, SkipNone);
}
void KateDocument::readParameterizedSessionConfig(const KConfigGroup &kconfig,
unsigned long configParameters)
{
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipEncoding)) {
// get the encoding
QString tmpenc=kconfig.readEntry("Encoding");
if (!tmpenc.isEmpty() && (tmpenc != encoding()))
setEncoding(tmpenc);
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipUrl)) {
// restore the url
KUrl url (kconfig.readEntry("URL"));
// open the file if url valid
if (!url.isEmpty() && url.isValid())
openUrl (url);
else completed(); //perhaps this should be emitted at the end of this function
}
else {
completed(); //perhaps this should be emitted at the end of this function
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipMode)) {
// restore the filetype
if (kconfig.hasKey("Mode")) {
updateFileType (kconfig.readEntry("Mode", fileType()));
}
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipHighlighting)) {
// restore the hl stuff
if (kconfig.hasKey("Highlighting")) {
int mode = KateHlManager::self()->nameFind(kconfig.readEntry("Highlighting"));
if (mode >= 0) {
m_buffer->setHighlight(mode);
}
}
}
// indent mode
config()->setIndentationMode( kconfig.readEntry("Indentation Mode", config()->indentationMode() ) );
// Restore Bookmarks
const QList marks = kconfig.readEntry("Bookmarks", QList());
for( int i = 0; i < marks.count(); i++ )
addMark( marks.at(i), KateDocument::markType01 );
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipFolding)) {
// restore folding nodes
foldingTree()->readSessionConfig(kconfig);
}
}
void KateDocument::writeSessionConfig(KConfigGroup &kconfig)
{
writeParameterizedSessionConfig(kconfig, SkipNone);
}
void KateDocument::writeParameterizedSessionConfig(KConfigGroup &kconfig,
unsigned long configParameters)
{
if ( this->url().isLocalFile() ) {
const QString path = this->url().toLocalFile();
if ( KGlobal::dirs()->relativeLocation( "tmp", path ) != path ) {
return; // inside tmp resource, do not save
}
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipUrl)) {
// save url
kconfig.writeEntry("URL", this->url().prettyUrl() );
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipEncoding)) {
// save encoding
kconfig.writeEntry("Encoding",encoding());
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipMode)) {
// save file type
kconfig.writeEntry("Mode", m_fileType);
}
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipHighlighting)) {
// save hl
kconfig.writeEntry("Highlighting", highlight()->name());
}
// indent mode
kconfig.writeEntry("Indentation Mode", config()->indentationMode() );
// Save Bookmarks
QList marks;
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
if (i.value()->type & KTextEditor::MarkInterface::markType01)
marks << i.value()->line;
kconfig.writeEntry( "Bookmarks", marks );
if(!(configParameters & KTextEditor::ParameterizedSessionConfigInterface::SkipFolding)) {
// save folding
foldingTree()->writeSessionConfig(kconfig);
}
}
//END KTextEditor::SessionConfigInterface and KTextEditor::ParameterizedSessionConfigInterface stuff
uint KateDocument::mark( int line )
{
KTextEditor::Mark* m = m_marks.value(line);
if( !m )
return 0;
return m->type;
}
void KateDocument::setMark( int line, uint markType )
{
clearMark( line );
addMark( line, markType );
}
void KateDocument::clearMark( int line )
{
if( line > lastLine() )
return;
if( !m_marks.value(line) )
return;
KTextEditor::Mark* mark = m_marks.take( line );
emit markChanged( this, *mark, MarkRemoved );
emit marksChanged( this );
delete mark;
tagLines( line, line );
repaintViews(true);
}
void KateDocument::addMark( int line, uint markType )
{
KTextEditor::Mark *mark;
if( line > lastLine())
return;
if( markType == 0 )
return;
if( (mark = m_marks.value(line)) ) {
// Remove bits already set
markType &= ~mark->type;
if( markType == 0 )
return;
// Add bits
mark->type |= markType;
} else {
mark = new KTextEditor::Mark;
mark->line = line;
mark->type = markType;
m_marks.insert( line, mark );
}
// Emit with a mark having only the types added.
KTextEditor::Mark temp;
temp.line = line;
temp.type = markType;
emit markChanged( this, temp, MarkAdded );
emit marksChanged( this );
tagLines( line, line );
repaintViews(true);
}
void KateDocument::removeMark( int line, uint markType )
{
if( line > lastLine() )
return;
KTextEditor::Mark* mark = m_marks.value(line);
if( !mark )
return;
// Remove bits not set
markType &= mark->type;
if( markType == 0 )
return;
// Subtract bits
mark->type &= ~markType;
// Emit with a mark having only the types removed.
KTextEditor::Mark temp;
temp.line = line;
temp.type = markType;
emit markChanged( this, temp, MarkRemoved );
if( mark->type == 0 )
m_marks.remove( line );
emit marksChanged( this );
tagLines( line, line );
repaintViews(true);
}
const QHash &KateDocument::marks()
{
return m_marks;
}
void KateDocument::requestMarkTooltip( int line, QPoint position )
{
KTextEditor::Mark* mark = m_marks.value(line);
if(!mark)
return;
bool handled = false;
emit markToolTipRequested( this, *mark, position, handled );
}
bool KateDocument::handleMarkClick( int line )
{
KTextEditor::Mark* mark = m_marks.value(line);
if(!mark)
return false;
bool handled = false;
emit markClicked( this, *mark, handled );
return handled;
}
bool KateDocument::handleMarkContextMenu( int line, QPoint position )
{
KTextEditor::Mark* mark = m_marks.value(line);
if(!mark)
return false;
bool handled = false;
emit markContextMenuRequested( this, *mark, position, handled );
return handled;
}
void KateDocument::clearMarks()
{
while (!m_marks.isEmpty())
{
QHash::iterator it = m_marks.begin();
KTextEditor::Mark mark = *it.value();
delete it.value();
m_marks.erase (it);
emit markChanged( this, mark, MarkRemoved );
tagLines( mark.line, mark.line );
}
m_marks.clear();
emit marksChanged( this );
repaintViews(true);
}
void KateDocument::setMarkPixmap( MarkInterface::MarkTypes type, const QPixmap& pixmap )
{
m_markPixmaps.insert( type, pixmap );
}
void KateDocument::setMarkDescription( MarkInterface::MarkTypes type, const QString& description )
{
m_markDescriptions.insert( type, description );
}
QPixmap KateDocument::markPixmap( MarkInterface::MarkTypes type ) const
{
return m_markPixmaps.value(type, QPixmap());
}
QColor KateDocument::markColor( MarkInterface::MarkTypes type ) const
{
uint reserved = (0x1 << KTextEditor::MarkInterface::reservedMarkersCount()) - 1;
if ((uint)type >= (uint)markType01 && (uint)type <= reserved) {
return KateRendererConfig::global()->lineMarkerColor(type);
} else {
return QColor();
}
}
QString KateDocument::markDescription( MarkInterface::MarkTypes type ) const
{
return m_markDescriptions.value(type, QString());
}
void KateDocument::setEditableMarks( uint markMask )
{
m_editableMarks = markMask;
}
uint KateDocument::editableMarks() const
{
return m_editableMarks;
}
//END
//BEGIN KTextEditor::PrintInterface stuff
bool KateDocument::printDialog ()
{
return KatePrinter::print (this);
}
bool KateDocument::print ()
{
return KatePrinter::print (this);
}
//END
//BEGIN KTextEditor::DocumentInfoInterface (### unfinished)
QString KateDocument::mimeType()
{
KMimeType::Ptr result = KMimeType::defaultMimeTypePtr();
// if the document has a URL, try KMimeType::findByURL
if ( ! this->url().isEmpty() )
result = KMimeType::findByUrl( this->url() );
else if ( this->url().isEmpty() || ! this->url().isLocalFile() )
result = mimeTypeForContent();
return result->name();
}
KMimeType::Ptr KateDocument::mimeTypeForContent()
{
QByteArray buf (1024,'\0');
uint bufpos = 0;
for (int i=0; i < lines(); ++i)
{
QString line = this->line( i );
uint len = line.length() + 1;
if (bufpos + len > 1024)
len = 1024 - bufpos;
QString ld (line + QChar::fromAscii('\n'));
buf.replace(bufpos,len,ld.toLatin1()); //memcpy(buf.data() + bufpos, ld.toLatin1().constData(), len);
bufpos += len;
if (bufpos >= 1024)
break;
}
buf.resize( bufpos );
int accuracy = 0;
KMimeType::Ptr mt = KMimeType::findByContent(buf, &accuracy);
return mt ? mt : KMimeType::defaultMimeTypePtr();
}
//END KTextEditor::DocumentInfoInterface
//BEGIN KParts::ReadWrite stuff
bool KateDocument::openFile()
{
/**
* we are about to invalidate all cursors/ranges/.. => m_buffer->openFile will do so
*/
emit aboutToInvalidateMovingInterfaceContent (this);
// no open errors until now...
setOpeningError(false);
// add new m_file to dirwatch
activateDirWatch ();
// remember current encoding
QString currentEncoding = encoding();
//
// mime type magic to get encoding right
//
QString mimeType = arguments().mimeType();
int pos = mimeType.indexOf(';');
if (pos != -1 && !(m_reloading && m_userSetEncodingForNextReload))
setEncoding (mimeType.mid(pos+1));
// do we have success ?
emit KTextEditor::Document::textRemoved(this, documentRange());
emit KTextEditor::Document::textRemoved(this, documentRange(), m_buffer->text());
// update file type, we do this here PRE-LOAD, therefore pass file name for reading from
updateFileType (KateGlobal::self()->modeManager()->fileType (this, localFilePath()));
// read dir config (if possible and wanted)
// do this PRE-LOAD to get encoding info!
readDirConfig ();
// perhaps we need to re-set again the user encoding
if (m_reloading && m_userSetEncodingForNextReload && (currentEncoding != encoding()))
setEncoding (currentEncoding);
bool success = m_buffer->openFile (localFilePath(), (m_reloading && m_userSetEncodingForNextReload));
// disable view updates
foreach (KateView * view, m_views)
view->setUpdatesEnabled (false);
//
// yeah, success
//
if (success)
{
// read vars
readVariables ();
if (!m_postLoadFilterChecks.isEmpty())
{
LoadSaveFilterCheckPlugins *lscps=loadSaveFilterCheckPlugins();
foreach(const QString& checkplugin, m_postLoadFilterChecks)
{
lscps->postLoadFilter(checkplugin,this);
}
}
}
//
// update views
//
foreach (KateView * view, m_views)
{
// This is needed here because inserting the text moves the view's start position (it is a MovingCursor)
view->setCursorPosition (KTextEditor::Cursor());
view->setUpdatesEnabled (true);
view->updateView (true);
}
// emit all signals about new text after view updates
emit KTextEditor::Document::textInserted(this, documentRange());
// Inform that the text has changed (required as we're not inside the usual editStart/End stuff)
emit textChanged (this);
if (!m_reloading)
{
//
// emit the signal we need for example for kate app
//
emit documentUrlChanged (this);
//
// set doc name, dummy value as arg, don't need it
//
setDocName (QString());
}
//
// to houston, we are not modified
//
if (m_modOnHd)
{
m_modOnHd = false;
m_modOnHdReason = OnDiskUnmodified;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
//
// display errors
//
if (!success) {
QPointer message
= new KTextEditor::Message(KTextEditor::Message::Error
, i18n ("The file %1 could not be loaded, as it was not possible to read from it.
Check if you have read access to this file.", this->url().pathOrUrl()));
message->setWordWrap(true);
postMessage(message);
// remember error
setOpeningError(true);
setOpeningErrorMessage(i18n ("The file %1 could not be loaded, as it was not possible to read from it.\n\nCheck if you have read access to this file.",this->url().pathOrUrl()));
}
// warn: broken encoding
if (m_buffer->brokenEncoding()) {
// this file can't be saved again without killing it
setReadWrite( false );
QPointer message
= new KTextEditor::Message(KTextEditor::Message::Warning
, i18n ("The file %1 was opened with %2 encoding but contained invalid characters.
"
"It is set to read-only mode, as saving might destroy its content.
"
"Either reopen the file with the correct encoding chosen or enable the read-write mode again in the menu to be able to edit it.", this->url().pathOrUrl(),
QString (m_buffer->textCodec()->name ())));
message->setWordWrap(true);
postMessage(message);
// remember error
setOpeningError(true);
setOpeningErrorMessage(i18n ("The file %1 was opened with %2 encoding but contained invalid characters."
" It is set to read-only mode, as saving might destroy its content."
" Either reopen the file with the correct encoding chosen or enable the read-write mode again in the menu to be able to edit it.", this->url().pathOrUrl(), QString (m_buffer->textCodec()->name ())));
}
// warn: too long lines
if (m_buffer->tooLongLinesWrapped()) {
// this file can't be saved again without modifications
setReadWrite( false );
QPointer message
= new KTextEditor::Message(KTextEditor::Message::Warning
, i18n ("The file %1 was opened and contained lines longer than the configured Line Length Limit (%2 characters).
"
"Those lines were wrapped and the document is set to read-only mode, as saving will modify its content.", this->url().pathOrUrl(),config()->lineLengthLimit()));
message->setWordWrap(true);
postMessage(message);
// remember error
setOpeningError(true);
setOpeningErrorMessage(i18n ("The file %1 was opened and contained lines longer than the configured Line Length Limit (%2 characters)."
" Those lines were wrapped and the document is set to read-only mode, as saving will modify its content.", this->url().pathOrUrl(),config()->lineLengthLimit()));
}
//
// return the success
//
return success;
}
bool KateDocument::saveFile()
{
QWidget *parentWidget(dialogParent());
// some warnings, if file was changed by the outside!
if ( !url().isEmpty() )
{
if (m_fileChangedDialogsActivated && m_modOnHd)
{
QString str = reasonedMOHString() + "\n\n";
if (!isModified())
{
if (KMessageBox::warningContinueCancel(parentWidget,
str + i18n("Do you really want to save this unmodified file? You could overwrite changed data in the file on disk."),i18n("Trying to Save Unmodified File"),KGuiItem(i18n("Save Nevertheless"))) != KMessageBox::Continue)
return false;
}
else
{
if (KMessageBox::warningContinueCancel(parentWidget,
str + i18n("Do you really want to save this file? Both your open file and the file on disk were changed. There could be some data lost."),i18n("Possible Data Loss"),KGuiItem(i18n("Save Nevertheless"))) != KMessageBox::Continue)
return false;
}
}
}
//
// can we encode it if we want to save it ?
//
if (!m_buffer->canEncode ()
&& (KMessageBox::warningContinueCancel(parentWidget,
i18n("The selected encoding cannot encode every unicode character in this document. Do you really want to save it? There could be some data lost."),i18n("Possible Data Loss"),KGuiItem(i18n("Save Nevertheless"))) != KMessageBox::Continue))
{
return false;
}
//
// try to create backup file..
//
// local file or not is here the question
bool l ( url().isLocalFile() );
// does the user want any backup, if not, not our problem?
if ( ( l && config()->backupFlags() & KateDocumentConfig::LocalFiles )
|| ( ! l && config()->backupFlags() & KateDocumentConfig::RemoteFiles ) )
{
KUrl u( url() );
if (config()->backupPrefix().contains(QDir::separator())) {
u.setPath( config()->backupPrefix() + url().fileName() + config()->backupSuffix() );
} else {
u.setFileName( config()->backupPrefix() + url().fileName() + config()->backupSuffix() );
}
kDebug( 13020 ) << "backup src file name: " << url();
kDebug( 13020 ) << "backup dst file name: " << u;
// handle the backup...
bool backupSuccess = false;
// local file mode, no kio
if (u.isLocalFile ())
{
if (QFile::exists (url().toLocalFile ()))
{
// first: check if backupFile is already there, if true, unlink it
QFile backupFile (u.toLocalFile ());
if (backupFile.exists()) backupFile.remove ();
backupSuccess = QFile::copy (url().toLocalFile (), u.toLocalFile ());
}
else
backupSuccess = true;
}
else // remote file mode, kio
{
// get the right permissions, start with safe default
KIO::UDSEntry fentry;
if (KIO::NetAccess::stat (url(), fentry, QApplication::activeWindow())) {
// do a evil copy which will overwrite target if possible
KFileItem item (fentry, url());
KIO::FileCopyJob *job = KIO::file_copy ( url(), u, item.permissions(), KIO::Overwrite );
backupSuccess = KIO::NetAccess::synchronousRun(job, QApplication::activeWindow());
}
else
backupSuccess = true;
}
// backup has failed, ask user how to proceed
if (!backupSuccess && (KMessageBox::warningContinueCancel (parentWidget
, i18n ("For file %1 no backup copy could be created before saving."
" If an error occurs while saving, you might lose the data of this file."
" A reason could be that the media you write to is full or the directory of the file is read-only for you.", url().pathOrUrl())
, i18n ("Failed to create backup copy.")
, KGuiItem(i18n("Try to Save Nevertheless"))
, KStandardGuiItem::cancel(), "Backup Failed Warning") != KMessageBox::Continue))
{
return false;
}
}
// update file type, pass no file path, read file type content from this document
updateFileType (KateGlobal::self()->modeManager()->fileType (this, QString ()));
if (!m_preSavePostDialogFilterChecks.isEmpty())
{
LoadSaveFilterCheckPlugins *lscps=loadSaveFilterCheckPlugins();
foreach(const QString& checkplugin, m_preSavePostDialogFilterChecks)
{
if (lscps->preSavePostDialogFilterCheck(checkplugin,this,parentWidget)==false)
return false;
}
}
// remember the oldpath...
QString oldPath = m_dirWatchFile;
// read dir config (if possible and wanted)
if ( url().isLocalFile())
{
QFileInfo fo (oldPath), fn (localFilePath());
if (fo.path() != fn.path())
readDirConfig();
}
// read our vars
readVariables();
// remove file from dirwatch
deactivateDirWatch ();
// remove all trailing spaces in the document (as edit actions)
// NOTE: we need this as edit actions, since otherwise the edit actions
// in the swap file recovery may happen at invalid cursor positions
removeTrailingSpaces ();
//
// try to save
//
if (!m_buffer->saveFile (localFilePath()))
{
// add m_file again to dirwatch
activateDirWatch (oldPath);
KMessageBox::error (parentWidget, i18n ("The document could not be saved, as it was not possible to write to %1.\n\nCheck that you have write access to this file or that enough disk space is available.", this->url().pathOrUrl()));
return false;
}
// update the md5 digest
createDigest ();
// add m_file again to dirwatch
activateDirWatch ();
//
// we are not modified
//
if (m_modOnHd)
{
m_modOnHd = false;
m_modOnHdReason = OnDiskUnmodified;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
// update document name...
setDocName( QString() );
// url may have changed...
emit documentUrlChanged (this);
m_savingToUrl=true;
// (dominik) mark last undo group as not mergeable, otherwise the next
// edit action might be merged and undo will never stop at the saved state
m_undoManager->undoSafePoint();
m_undoManager->updateLineModifications();
//
// return success
//
return true;
}
void KateDocument::readDirConfig ()
{
int depth = config()->searchDirConfigDepth ();
if (this->url().isLocalFile() && (depth > -1))
{
QString currentDir = QFileInfo (localFilePath()).absolutePath();
// only search as deep as specified or not at all ;)
while (depth > -1)
{
//kDebug (13020) << "search for config file in path: " << currentDir;
// try to open config file in this dir
QFile f (currentDir + "/.kateconfig");
if (f.open (QIODevice::ReadOnly))
{
QTextStream stream (&f);
uint linesRead = 0;
QString line = stream.readLine();
while ((linesRead < 32) && !line.isNull())
{
readVariableLine( line );
line = stream.readLine();
linesRead++;
}
break;
}
QString newDir = QFileInfo (currentDir).absolutePath();
// bail out on looping (for example reached /)
if (currentDir == newDir)
break;
currentDir = newDir;
--depth;
}
}
}
void KateDocument::activateDirWatch (const QString &useFileName)
{
QString fileToUse = useFileName;
if (fileToUse.isEmpty())
fileToUse = localFilePath();
// same file as we are monitoring, return
if (fileToUse == m_dirWatchFile)
return;
// remove the old watched file
deactivateDirWatch ();
// add new file if needed
if (url().isLocalFile() && !fileToUse.isEmpty())
{
KateGlobal::self()->dirWatch ()->addFile (fileToUse);
m_dirWatchFile = fileToUse;
}
}
void KateDocument::deactivateDirWatch ()
{
if (!m_dirWatchFile.isEmpty())
KateGlobal::self()->dirWatch ()->removeFile (m_dirWatchFile);
m_dirWatchFile.clear();
}
bool KateDocument::closeUrl()
{
//
// file mod on hd
//
if ( !m_reloading && !url().isEmpty() )
{
if (m_fileChangedDialogsActivated && m_modOnHd)
{
QWidget *parentWidget(dialogParent());
if (!(KMessageBox::warningContinueCancel(
parentWidget,
reasonedMOHString() + "\n\n" + i18n("Do you really want to continue to close this file? Data loss may occur."),
i18n("Possible Data Loss"), KGuiItem(i18n("Close Nevertheless")), KStandardGuiItem::cancel(),
QString("kate_close_modonhd_%1").arg( m_modOnHdReason ) ) == KMessageBox::Continue))
return false;
}
}
//
// first call the normal kparts implementation
//
if (!KParts::ReadWritePart::closeUrl ())
return false;
// Tell the world that we're about to go ahead with the close
if (!m_reloading)
emit aboutToClose(this);
/**
* we are about to invalidate all cursors/ranges/.. => m_buffer->clear will do so
*/
emit aboutToInvalidateMovingInterfaceContent (this);
// remove file from dirwatch
deactivateDirWatch ();
//
// empty url + fileName
//
setUrl(KUrl());
setLocalFilePath(QString());
// we are not modified
if (m_modOnHd)
{
m_modOnHd = false;
m_modOnHdReason = OnDiskUnmodified;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
emit KTextEditor::Document::textRemoved(this, documentRange());
emit KTextEditor::Document::textRemoved(this, documentRange(), m_buffer->text());
{
// remove all marks
clearMarks ();
// clear the buffer
m_buffer->clear();
// clear undo/redo history
m_undoManager->clearUndo();
m_undoManager->clearRedo();
}
// no, we are no longer modified
setModified(false);
// we have no longer any hl
m_buffer->setHighlight(0);
// update all our views
foreach (KateView * view, m_views )
{
view->clearSelection(); // fix bug #118588
view->clear();
}
if (!m_reloading)
{
// uh, fileName changed
emit documentUrlChanged (this);
// update doc name
setDocName (QString());
}
// purge swap file
m_swapfile->fileClosed ();
// success
return true;
}
bool KateDocument::isDataRecoveryAvailable() const
{
return m_swapfile->shouldRecover();
}
void KateDocument::recoverData()
{
if (isDataRecoveryAvailable())
m_swapfile->recover();
}
void KateDocument::discardDataRecovery()
{
if (isDataRecoveryAvailable())
m_swapfile->discard();
}
void KateDocument::setReadWrite( bool rw )
{
if (isReadWrite() != rw)
{
KParts::ReadWritePart::setReadWrite (rw);
foreach( KateView* view, m_views)
{
view->slotUpdateUndo();
view->slotReadWriteChanged ();
}
emit readWriteChanged(this);
}
}
void KateDocument::setModified(bool m) {
if (isModified() != m) {
KParts::ReadWritePart::setModified (m);
foreach( KateView* view,m_views)
{
view->slotUpdateUndo();
}
emit modifiedChanged (this);
}
m_undoManager->setModified (m);
}
//END
//BEGIN Kate specific stuff ;)
void KateDocument::makeAttribs(bool needInvalidate)
{
foreach(KateView *view,m_views)
view->renderer()->updateAttributes ();
if (needInvalidate)
m_buffer->invalidateHighlighting();
foreach(KateView *view,m_views)
{
view->tagAll();
view->updateView (true);
}
}
// the attributes of a hl have changed, update
void KateDocument::internalHlChanged()
{
makeAttribs();
}
void KateDocument::addView(KTextEditor::View *view) {
if (!view)
return;
m_views.append( static_cast(view) );
m_textEditViews.append( view );
// apply the view & renderer vars from the file type
if (!m_fileType.isEmpty())
readVariableLine(KateGlobal::self()->modeManager()->fileType(m_fileType).varLine, true);
// apply the view & renderer vars from the file
readVariables (true);
setActiveView(view);
}
void KateDocument::removeView(KTextEditor::View *view) {
if (!view)
return;
if (activeView() == view)
setActiveView(0L);
m_views.removeAll( static_cast(view) );
m_textEditViews.removeAll( view );
}
void KateDocument::setActiveView(KTextEditor::View* view)
{
if ( m_activeView == view )
return;
m_activeView = static_cast(view);
}
bool KateDocument::ownedView(KateView *view) {
// do we own the given view?
return (m_views.contains(view));
}
uint KateDocument::toVirtualColumn( const KTextEditor::Cursor& cursor )
{
Kate::TextLine textLine = m_buffer->plainLine(cursor.line());
if (textLine)
return textLine->toVirtualColumn(cursor.column(), config()->tabWidth());
else
return 0;
}
bool KateDocument::typeChars ( KateView *view, const QString &chars )
{
Kate::TextLine textLine = m_buffer->plainLine(view->cursorPosition().line ());
-
if (!textLine)
return false;
- bool bracketInserted = false;
- QString buf;
- foreach(const QChar& ch, chars)
- {
- if (ch.isPrint() || ch == QChar::fromAscii('\t'))
- {
- buf.append (ch);
-
- if (config()->autoBrackets())
- {
- if (isEndBracket(ch) &&
- view->document()->character(view->cursorPosition()).toAscii() == ch)
- {
- del(view, view->cursorPosition());
- }
- else
- {
- if (!bracketInserted)
- {
- QChar end_ch;
-
- switch (ch.toAscii()) {
- case '(': end_ch = ')'; break;
- case '[': end_ch = ']'; break;
- case '{': end_ch = '}'; break;
- case '"': end_ch = '"'; break;
- case '\'': end_ch = '\''; break;
- }
- if (!end_ch.isNull()) {
- bracketInserted = true;
-
- if (view->selection()) {
- buf.append(view->selectionText());
- }
-
- buf.append(end_ch);
- }
- }
- }
- }
- }
- }
-
- if (buf.isEmpty())
+ if (chars.isEmpty())
return false;
editStart ();
if (!view->config()->persistentSelection() && view->selection() )
view->removeSelectedText();
KTextEditor::Cursor oldCur (view->cursorPosition());
if (config()->ovr()
|| (view->viInputMode() && view->getViInputModeManager()->getCurrentViMode() == ReplaceMode)) {
- KTextEditor::Range r = KTextEditor::Range(view->cursorPosition(), qMin(buf.length(),
+ KTextEditor::Range r = KTextEditor::Range(view->cursorPosition(), qMin(chars.length(),
textLine->length() - view->cursorPosition().column()));
// replace mode needs to know what was removed so it can be restored with backspace
if (view->viInputMode() && view->getViInputModeManager()->getCurrentViMode() == ReplaceMode
&& oldCur.column() < line( view->cursorPosition().line() ).length() ) {
QChar removed = line( view->cursorPosition().line() ).at( r.start().column() );
view->getViInputModeManager()->getViReplaceMode()->overwrittenChar( removed );
}
removeText(r);
}
- insertText(view->cursorPosition(), buf);
- if (bracketInserted)
- view->setCursorPositionInternal (view->cursorPosition() - KTextEditor::Cursor(0,1));
+ insertText(view->cursorPosition(), chars);
KTextEditor::Cursor b(view->cursorPosition());
m_indenter->userTypedChar (view, b, chars.isEmpty() ? QChar() : chars.at(chars.length() - 1));
editEnd ();
view->slotTextInserted (view, oldCur, chars);
return true;
}
void KateDocument::newLine( KateView *v )
{
editStart();
if( !v->config()->persistentSelection() && v->selection() )
v->removeSelectedText();
// query cursor position
KTextEditor::Cursor c = v->cursorPosition();
if (c.line() > (int)lastLine())
c.setLine(lastLine());
if (c.line() < 0)
c.setLine(0);
uint ln = c.line();
Kate::TextLine textLine = plainKateTextLine(ln);
if (c.column() > (int)textLine->length())
c.setColumn(textLine->length());
// first: wrap line
editWrapLine (c.line(), c.column());
// second: indent the new line, if needed...
m_indenter->userTypedChar(v, v->cursorPosition(), '\n');
editEnd();
}
void KateDocument::transpose( const KTextEditor::Cursor& cursor)
{
Kate::TextLine textLine = m_buffer->plainLine(cursor.line());
if (!textLine || (textLine->length() < 2))
return;
uint col = cursor.column();
if (col > 0)
col--;
if ((textLine->length() - col) < 2)
return;
uint line = cursor.line();
QString s;
//clever swap code if first character on the line swap right&left
//otherwise left & right
s.append (textLine->at(col+1));
s.append (textLine->at(col));
//do the swap
// do it right, never ever manipulate a textline
editStart ();
editRemoveText (line, col, 2);
editInsertText (line, col, s);
editEnd ();
}
void KateDocument::backspace( KateView *view, const KTextEditor::Cursor& c )
{
if ( !view->config()->persistentSelection() && view->selection() ) {
view->removeSelectedText();
return;
}
uint col = qMax( c.column(), 0 );
uint line = qMax( c.line(), 0 );
if ((col == 0) && (line == 0))
return;
- int complement = 0;
if (col > 0)
{
- if (config()->autoBrackets())
- {
- // if inside empty (), {}, [], '', "" delete both
- Kate::TextLine tl = m_buffer->plainLine(line);
- if(!tl) return;
- QChar prevChar = tl->at(col-1);
- QChar nextChar = tl->at(col);
-
- if ( (prevChar == '"' && nextChar == '"') ||
- (prevChar == '\'' && nextChar == '\'') ||
- (prevChar == '(' && nextChar == ')') ||
- (prevChar == '[' && nextChar == ']') ||
- (prevChar == '{' && nextChar == '}') )
- {
- complement = 1;
- }
- }
if (!(config()->backspaceIndents()))
{
// ordinary backspace
//c.cursor.col--;
- removeText(KTextEditor::Range(line, col-1, line, col+complement));
+ removeText(KTextEditor::Range(line, col-1, line, col));
}
else
{
// backspace indents: erase to next indent position
Kate::TextLine textLine = m_buffer->plainLine(line);
// don't forget this check!!!! really!!!!
if (!textLine)
return;
int colX = textLine->toVirtualColumn(col, config()->tabWidth());
int pos = textLine->firstChar();
if (pos > 0)
pos = textLine->toVirtualColumn(pos, config()->tabWidth());
if (pos < 0 || pos >= (int)colX)
{
// only spaces on left side of cursor
indent( KTextEditor::Range( line, 0, line, 0), -1);
}
else
- removeText(KTextEditor::Range(line, col-1, line, col+complement));
+ removeText(KTextEditor::Range(line, col-1, line, col));
}
}
else
{
// col == 0: wrap to previous line
if (line >= 1)
{
Kate::TextLine textLine = m_buffer->plainLine(line-1);
// don't forget this check!!!! really!!!!
if (!textLine)
return;
if (config()->wordWrap() && textLine->endsWith(QLatin1String(" ")))
{
// gg: in hard wordwrap mode, backspace must also eat the trailing space
removeText (KTextEditor::Range(line-1, textLine->length()-1, line, 0));
}
else
removeText (KTextEditor::Range(line-1, textLine->length(), line, 0));
}
}
}
void KateDocument::del( KateView *view, const KTextEditor::Cursor& c )
{
if ( !view->config()->persistentSelection() && view->selection() ) {
view->removeSelectedText();
return;
}
if( c.column() < (int) m_buffer->plainLine(c.line())->length())
{
removeText(KTextEditor::Range(c, 1));
}
else if ( c.line() < lastLine() )
{
removeText(KTextEditor::Range(c.line(), c.column(), c.line()+1, 0));
}
}
void KateDocument::paste ( KateView* view, QClipboard::Mode mode )
{
QString s = QApplication::clipboard()->text(mode);
if (s.isEmpty())
return;
int lines = s.count (QChar::fromAscii ('\n'));
m_undoManager->undoSafePoint();
editStart ();
KTextEditor::Cursor pos = view->cursorPosition();
if (!view->config()->persistentSelection() && view->selection()) {
pos = view->selectionRange().start();
if (view->blockSelection())
pos = rangeOnLine(view->selectionRange(), pos.line()).start();
view->removeSelectedText();
}
if (config()->ovr()) {
QStringList pasteLines = s.split(QLatin1Char('\n'));
if (!view->blockSelectionMode()) {
int endColumn = (pasteLines.count() == 1 ? pos.column() : 0) + pasteLines.last().length();
removeText(KTextEditor::Range(pos,
pos.line()+pasteLines.count()-1, endColumn));
} else {
int maxi = qMin(pos.line() + pasteLines.count(), this->lines());
for (int i = pos.line(); i < maxi; ++i) {
int pasteLength = pasteLines.at(i-pos.line()).length();
removeText(KTextEditor::Range(i, pos.column(),
i, qMin(pasteLength + pos.column(), lineLength(i))));
}
}
}
insertText(pos, s, view->blockSelectionMode());
editEnd();
// move cursor right for block select, as the user is moved right internal
// even in that case, but user expects other behavior in block selection
// mode !
// just let cursor stay, that was it before I changed to moving ranges!
if (view->blockSelectionMode())
view->setCursorPositionInternal(pos);
if (config()->indentPastedText())
{
KTextEditor::Range range = KTextEditor::Range(KTextEditor::Cursor(pos.line(), 0),
KTextEditor::Cursor(pos.line() + lines, 0));
m_indenter->indent(view, range);
}
if (!view->blockSelectionMode())
emit charactersSemiInteractivelyInserted (pos, s);
m_undoManager->undoSafePoint();
}
void KateDocument::indent (KTextEditor::Range range, int change)
{
- // dominik: if there is a selection, iterate afterwards over all lines and
- // remove trailing spaces
- int start = range.start().line();
- const int end = range.end().line();
+ if (!isReadWrite())
+ return;
editStart();
m_indenter->changeIndent(range, change);
editEnd();
}
void KateDocument::align(KateView *view, const KTextEditor::Range &range)
{
m_indenter->indent(view, range);
}
void KateDocument::insertTab( KateView *, const KTextEditor::Cursor& c )
{
if (!isReadWrite())
return;
editStart();
editInsertText(c.line(), c.column(), QChar('\t'));
editEnd();
}
/*
Remove a given string at the beginning
of the current line.
*/
bool KateDocument::removeStringFromBeginning(int line, const QString &str)
{
Kate::TextLine textline = m_buffer->plainLine(line);
KTextEditor::Cursor cursor (line, 0);
bool there = textline->startsWith(str);
if (!there)
{
cursor.setColumn(textline->firstChar());
there = textline->matchesAt(cursor.column(), str);
}
if (there)
{
// Remove some chars
removeText (KTextEditor::Range(cursor, str.length()));
}
return there;
}
/*
Remove a given string at the end
of the current line.
*/
bool KateDocument::removeStringFromEnd(int line, const QString &str)
{
Kate::TextLine textline = m_buffer->plainLine(line);
KTextEditor::Cursor cursor (line, 0);
bool there = textline->endsWith(str);
if (there)
{
cursor.setColumn(textline->length() - str.length());
}
else
{
cursor.setColumn(textline->lastChar() - str.length() + 1);
there = textline->matchesAt(cursor.column(), str);
}
if (there)
{
// Remove some chars
removeText (KTextEditor::Range(cursor, str.length()));
}
return there;
}
/*
Add to the current line a comment line mark at the beginning.
*/
void KateDocument::addStartLineCommentToSingleLine( int line, int attrib )
{
QString commentLineMark = highlight()->getCommentSingleLineStart(attrib);
int pos = -1;
if (highlight()->getCommentSingleLinePosition(attrib) == KateHighlighting::CSLPosColumn0)
{
pos = 0;
commentLineMark += ' ';
} else {
const Kate::TextLine l = kateTextLine(line);
pos = l->firstChar();
}
if (pos >= 0)
insertText (KTextEditor::Cursor(line, pos), commentLineMark);
}
/*
Remove from the current line a comment line mark at
the beginning if there is one.
*/
bool KateDocument::removeStartLineCommentFromSingleLine( int line, int attrib )
{
const QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
const QString longCommentMark = shortCommentMark + ' ';
editStart();
// Try to remove the long comment mark first
bool removed = (removeStringFromBeginning(line, longCommentMark)
|| removeStringFromBeginning(line, shortCommentMark));
editEnd();
return removed;
}
/*
Add to the current line a start comment mark at the
beginning and a stop comment mark at the end.
*/
void KateDocument::addStartStopCommentToSingleLine( int line, int attrib )
{
const QString startCommentMark = highlight()->getCommentStart( attrib ) + ' ';
const QString stopCommentMark = ' ' + highlight()->getCommentEnd( attrib );
editStart();
// Add the start comment mark
insertText (KTextEditor::Cursor(line, 0), startCommentMark);
// Go to the end of the line
const int col = m_buffer->plainLine(line)->length();
// Add the stop comment mark
insertText (KTextEditor::Cursor(line, col), stopCommentMark);
editEnd();
}
/*
Remove from the current line a start comment mark at
the beginning and a stop comment mark at the end.
*/
bool KateDocument::removeStartStopCommentFromSingleLine( int line, int attrib )
{
QString shortStartCommentMark = highlight()->getCommentStart( attrib );
QString longStartCommentMark = shortStartCommentMark + ' ';
QString shortStopCommentMark = highlight()->getCommentEnd( attrib );
QString longStopCommentMark = ' ' + shortStopCommentMark;
editStart();
// TODO "that's a bad idea, can lead to stray endings, FIXME"
// Try to remove the long start comment mark first
bool removedStart = (removeStringFromBeginning(line, longStartCommentMark)
|| removeStringFromBeginning(line, shortStartCommentMark));
bool removedStop = false;
if (removedStart)
{
// Try to remove the long stop comment mark first
removedStop = (removeStringFromEnd(line, longStopCommentMark)
|| removeStringFromEnd(line, shortStopCommentMark));
}
editEnd();
return (removedStart || removedStop);
}
/*
Add to the current selection a start comment mark at the beginning
and a stop comment mark at the end.
*/
void KateDocument::addStartStopCommentToSelection( KateView *view, int attrib )
{
const QString startComment = highlight()->getCommentStart( attrib );
const QString endComment = highlight()->getCommentEnd( attrib );
KTextEditor::Range range = view->selectionRange();
if ((range.end().column() == 0) && (range.end().line() > 0))
range.end().setPosition(range.end().line() - 1, lineLength(range.end().line() - 1));
editStart();
if (!view->blockSelection()) {
insertText(range.end(), endComment);
insertText(range.start(), startComment);
} else {
for (int line = range.start().line(); line <= range.end().line(); line++ ) {
KTextEditor::Range subRange = rangeOnLine(range, line);
insertText(subRange.end(), endComment);
insertText(subRange.start(), startComment);
}
}
editEnd ();
// selection automatically updated (MovingRange)
}
/*
Add to the current selection a comment line mark at the beginning of each line.
*/
void KateDocument::addStartLineCommentToSelection( KateView *view, int attrib )
{
const QString commentLineMark = highlight()->getCommentSingleLineStart( attrib ) + ' ';
int sl = view->selectionRange().start().line();
int el = view->selectionRange().end().line();
// if end of selection is in column 0 in last line, omit the last line
if ((view->selectionRange().end().column() == 0) && (el > 0))
{
el--;
}
editStart();
// For each line of the selection
for (int z = el; z >= sl; z--) {
//insertText (z, 0, commentLineMark);
addStartLineCommentToSingleLine(z, attrib );
}
editEnd ();
// selection automatically updated (MovingRange)
}
bool KateDocument::nextNonSpaceCharPos(int &line, int &col)
{
for(; line < (int)m_buffer->count(); line++) {
Kate::TextLine textLine = m_buffer->plainLine(line);
if (!textLine)
break;
col = textLine->nextNonSpaceChar(col);
if(col != -1)
return true; // Next non-space char found
col = 0;
}
// No non-space char found
line = -1;
col = -1;
return false;
}
bool KateDocument::previousNonSpaceCharPos(int &line, int &col)
{
while(true)
{
Kate::TextLine textLine = m_buffer->plainLine(line);
if (!textLine)
break;
col = textLine->previousNonSpaceChar(col);
if(col != -1) return true;
if(line == 0) return false;
--line;
col = textLine->length();
}
// No non-space char found
line = -1;
col = -1;
return false;
}
/*
Remove from the selection a start comment mark at
the beginning and a stop comment mark at the end.
*/
bool KateDocument::removeStartStopCommentFromSelection( KateView *view, int attrib )
{
const QString startComment = highlight()->getCommentStart( attrib );
const QString endComment = highlight()->getCommentEnd( attrib );
int sl = qMax (0, view->selectionRange().start().line());
int el = qMin (view->selectionRange().end().line(), lastLine());
int sc = view->selectionRange().start().column();
int ec = view->selectionRange().end().column();
// The selection ends on the char before selectEnd
if (ec != 0) {
--ec;
} else if (el > 0) {
--el;
ec = m_buffer->plainLine(el)->length() - 1;
}
const int startCommentLen = startComment.length();
const int endCommentLen = endComment.length();
// had this been perl or sed: s/^\s*$startComment(.+?)$endComment\s*/$2/
bool remove = nextNonSpaceCharPos(sl, sc)
&& m_buffer->plainLine(sl)->matchesAt(sc, startComment)
&& previousNonSpaceCharPos(el, ec)
&& ( (ec - endCommentLen + 1) >= 0 )
&& m_buffer->plainLine(el)->matchesAt(ec - endCommentLen + 1, endComment);
if (remove) {
editStart();
removeText (KTextEditor::Range(el, ec - endCommentLen + 1, el, ec + 1));
removeText (KTextEditor::Range(sl, sc, sl, sc + startCommentLen));
editEnd ();
// selection automatically updated (MovingRange)
}
return remove;
}
bool KateDocument::removeStartStopCommentFromRegion(const KTextEditor::Cursor &start,const KTextEditor::Cursor &end,int attrib)
{
const QString startComment = highlight()->getCommentStart( attrib );
const QString endComment = highlight()->getCommentEnd( attrib );
const int startCommentLen = startComment.length();
const int endCommentLen = endComment.length();
const bool remove = m_buffer->plainLine(start.line())->matchesAt(start.column(), startComment)
&& m_buffer->plainLine(end.line())->matchesAt(end.column() - endCommentLen , endComment);
if (remove) {
editStart();
removeText(KTextEditor::Range(end.line(), end.column() - endCommentLen, end.line(), end.column()));
removeText(KTextEditor::Range(start, startCommentLen));
editEnd();
}
return remove;
}
/*
Remove from the beginning of each line of the
selection a start comment line mark.
*/
bool KateDocument::removeStartLineCommentFromSelection( KateView *view, int attrib )
{
const QString shortCommentMark = highlight()->getCommentSingleLineStart( attrib );
const QString longCommentMark = shortCommentMark + ' ';
int sl = view->selectionRange().start().line();
int el = view->selectionRange().end().line();
if ((view->selectionRange().end().column() == 0) && (el > 0))
{
el--;
}
bool removed = false;
editStart();
// For each line of the selection
for (int z = el; z >= sl; z--)
{
// Try to remove the long comment mark first
removed = (removeStringFromBeginning(z, longCommentMark)
|| removeStringFromBeginning(z, shortCommentMark)
|| removed);
}
editEnd();
// selection automatically updated (MovingRange)
return removed;
}
/*
Comment or uncomment the selection or the current
line if there is no selection.
*/
void KateDocument::comment( KateView *v, uint line,uint column, int change)
{
// skip word wrap bug #105373
const bool skipWordWrap = wordWrap();
if (skipWordWrap) setWordWrap(false);
bool hassel = v->selection();
- int l = line;
int c = 0;
if ( hassel )
- {
- l = v->selectionRange().start().line();
c = v->selectionRange().start().column();
- }
int startAttrib = 0;
Kate::TextLine ln = kateTextLine( line );
if ( c < ln->length() )
startAttrib = ln->attribute( c );
else if ( !ln->ctxArray().isEmpty() )
startAttrib = highlight()->attribute( ln->ctxArray().last() );
bool hasStartLineCommentMark = !(highlight()->getCommentSingleLineStart( startAttrib ).isEmpty());
bool hasStartStopCommentMark = ( !(highlight()->getCommentStart( startAttrib ).isEmpty())
&& !(highlight()->getCommentEnd( startAttrib ).isEmpty()) );
bool removed = false;
if (change > 0) // comment
{
if ( !hassel )
{
if ( hasStartLineCommentMark )
addStartLineCommentToSingleLine( line, startAttrib );
else if ( hasStartStopCommentMark )
addStartStopCommentToSingleLine( line, startAttrib );
}
else
{
// anders: prefer single line comment to avoid nesting probs
// If the selection starts after first char in the first line
// or ends before the last char of the last line, we may use
// multiline comment markers.
// TODO We should try to detect nesting.
// - if selection ends at col 0, most likely she wanted that
// line ignored
const KTextEditor::Range sel = v->selectionRange();
if ( hasStartStopCommentMark &&
( !hasStartLineCommentMark || (
( sel.start().column() > m_buffer->plainLine( sel.start().line() )->firstChar() ) ||
( sel.end().column() > 0 &&
sel.end().column() < (m_buffer->plainLine( sel.end().line() )->length()) )
) ) )
addStartStopCommentToSelection( v, startAttrib );
else if ( hasStartLineCommentMark )
addStartLineCommentToSelection( v, startAttrib );
}
}
else // uncomment
{
if ( !hassel )
{
removed = ( hasStartLineCommentMark
&& removeStartLineCommentFromSingleLine( line, startAttrib ) )
|| ( hasStartStopCommentMark
&& removeStartStopCommentFromSingleLine( line, startAttrib ) );
if ((!removed) && foldingTree()) {
kDebug(13020)<<"easy approach for uncommenting did not work, trying harder (folding tree)";
int commentRegion=(highlight()->commentRegion(startAttrib));
if (commentRegion){
KateCodeFoldingNode *n=foldingTree()->findNodeForPosition(line,column);
if (n) {
KTextEditor::Cursor start,end;
if ((n->nodeType()==(int)commentRegion) && n->getBegin(foldingTree(), &start) && n->getEnd(foldingTree(), &end)) {
kDebug(13020)<<"Enclosing region found:"<nodeType()<<" region needed: "<selection() )
{
editStart();
// remember cursor
KTextEditor::Cursor cursor = c;
// cache the selection and cursor, so we can be sure to restore.
KTextEditor::Range selection = v->selectionRange();
KTextEditor::Range range(selection.start(), 0);
while ( range.start().line() <= selection.end().line() )
{
int start = 0;
int end = lineLength( range.start().line() );
if (range.start().line() == selection.start().line() || v->blockSelectionMode())
start = selection.start().column();
if (range.start().line() == selection.end().line() || v->blockSelectionMode())
end = selection.end().column();
if ( start > end )
{
int swapCol = start;
start = end;
end = swapCol;
}
range.start().setColumn( start );
range.end().setColumn( end );
QString s = text( range );
QString old = s;
if ( t == Uppercase )
s = s.toUpper();
else if ( t == Lowercase )
s = s.toLower();
else // Capitalize
{
Kate::TextLine l = m_buffer->plainLine( range.start().line() );
int p ( 0 );
while( p < s.length() )
{
// If bol or the character before is not in a word, up this one:
// 1. if both start and p is 0, upper char.
// 2. if blockselect or first line, and p == 0 and start-1 is not in a word, upper
// 3. if p-1 is not in a word, upper.
if ( ( ! range.start().column() && ! p ) ||
( ( range.start().line() == selection.start().line() || v->blockSelectionMode() ) &&
! p && ! highlight()->isInWord( l->at( range.start().column() - 1 )) ) ||
( p && ! highlight()->isInWord( s.at( p-1 ) ) )
) {
s[p] = s.at(p).toUpper();
}
p++;
}
}
if ( s != old )
{
removeText( range );
insertText( range.start(), s );
}
range.setBothLines(range.start().line() + 1);
}
editEnd();
// restore selection & cursor
v->setSelection( selection );
v->setCursorPosition( c );
} else { // no selection
editStart();
// get cursor
KTextEditor::Cursor cursor = c;
QString old = text( KTextEditor::Range(cursor, 1) );
QString s;
switch ( t ) {
case Uppercase:
s = old.toUpper();
break;
case Lowercase:
s = old.toLower();
break;
case Capitalize:
{
Kate::TextLine l = m_buffer->plainLine( cursor.line() );
while ( cursor.column() > 0 && highlight()->isInWord( l->at( cursor.column() - 1 ), l->attribute( cursor.column() - 1 ) ) )
cursor.setColumn(cursor.column() - 1);
old = text( KTextEditor::Range(cursor, 1) );
s = old.toUpper();
}
break;
default:
break;
}
removeText( KTextEditor::Range(cursor, 1) );
insertText( cursor, s );
editEnd();
}
}
void KateDocument::joinLines( uint first, uint last )
{
// if ( first == last ) last += 1;
editStart();
int line( first );
while ( first < last )
{
// Normalize the whitespace in the joined lines by making sure there's
// always exactly one space between the joined lines
// This cannot be done in editUnwrapLine, because we do NOT want this
// behavior when deleting from the start of a line, just when explicitly
// calling the join command
Kate::TextLine l = kateTextLine( line );
Kate::TextLine tl = kateTextLine( line + 1 );
if ( !l || !tl )
{
editEnd();
return;
}
int pos = tl->firstChar();
if ( pos >= 0 )
{
if (pos != 0)
editRemoveText( line + 1, 0, pos );
if ( !( l->length() == 0 || l->at( l->length() - 1 ).isSpace() ) )
editInsertText( line + 1, 0, " " );
}
else
{
// Just remove the whitespace and let Kate handle the rest
editRemoveText( line + 1, 0, tl->length() );
}
editUnWrapLine( line );
first++;
}
editEnd();
}
QString KateDocument::getWord( const KTextEditor::Cursor& cursor )
{
int start, end, len;
Kate::TextLine textLine = m_buffer->plainLine(cursor.line());
len = textLine->length();
start = end = cursor.column();
if (start > len) // Probably because of non-wrapping cursor mode.
return QString();
while (start > 0 && highlight()->isInWord(textLine->at(start - 1), textLine->attribute(start - 1))) start--;
while (end < len && highlight()->isInWord(textLine->at(end), textLine->attribute(end))) end++;
len = end - start;
return textLine->string().mid(start, len);
}
void KateDocument::tagLines(int start, int end)
{
foreach(KateView *view,m_views)
view->tagLines (start, end, true);
}
void KateDocument::tagLines(KTextEditor::Cursor start, KTextEditor::Cursor end)
{
// May need to switch start/end cols if in block selection mode
/* if (blockSelectionMode() && start.column() > end.column()) {
int sc = start.column();
start.setColumn(end.column());
end.setColumn(sc);
}
*/
foreach (KateView* view, m_views)
view->tagLines(start, end, true);
}
void KateDocument::repaintViews(bool paintOnlyDirty)
{
foreach(KateView *view,m_views)
view->repaintText(paintOnlyDirty);
}
/*
Bracket matching uses the following algorithm:
If in overwrite mode, match the bracket currently underneath the cursor.
Otherwise, if the character to the left is a bracket,
match it. Otherwise if the character to the right of the cursor is a
bracket, match it. Otherwise, don't match anything.
*/
void KateDocument::newBracketMark( const KTextEditor::Cursor& cursor, KTextEditor::Range& bm, int maxLines )
{
// search from cursor for brackets
KTextEditor::Range range (cursor, cursor);
// if match found, remember the range
if( findMatchingBracket( range, maxLines ) ) {
bm = range;
return;
}
// else, invalidate, if still valid
if (bm.isValid())
bm = KTextEditor::Range::invalid();
}
bool KateDocument::findMatchingBracket( KTextEditor::Range& range, int maxLines )
{
Kate::TextLine textLine = m_buffer->plainLine( range.start().line() );
if( !textLine )
return false;
QChar right = textLine->at( range.start().column() );
QChar left = textLine->at( range.start().column() - 1 );
QChar bracket;
if ( config()->ovr() ) {
if( isBracket( right ) ) {
bracket = right;
} else {
return false;
}
} else if ( isBracket( left ) ) {
range.start().setColumn(range.start().column() - 1);
bracket = left;
} else if ( isBracket( right ) ) {
bracket = right;
} else {
return false;
}
QChar opposite;
switch( bracket.toAscii() ) {
case '{': opposite = '}'; break;
case '}': opposite = '{'; break;
case '[': opposite = ']'; break;
case ']': opposite = '['; break;
case '(': opposite = ')'; break;
case ')': opposite = '('; break;
default: return false;
}
const int searchDir = isStartBracket( bracket ) ? 1 : -1;
uint nesting = 0;
int minLine = qMax( range.start().line() - maxLines, 0 );
int maxLine = qMin( range.start().line() + maxLines, documentEnd().line() );
range.end() = range.start();
KTextEditor::DocumentCursor cursor(this);
cursor.setPosition(range.start());
int validAttr = kateTextLine(cursor.line())->attribute(cursor.column());
while( cursor.line() >= minLine && cursor.line() <= maxLine ) {
if (!cursor.move(searchDir))
return false;
Kate::TextLine textLine = kateTextLine(cursor.line());
if (textLine->attribute(cursor.column()) == validAttr )
{
// Check for match
QChar c = textLine->at(cursor.column());
if( c == opposite ) {
if( nesting == 0 ) {
if (searchDir > 0) // forward
range.end() = cursor.toCursor();
else
range.start() = cursor.toCursor();
return true;
}
nesting--;
} else if( c == bracket ) {
nesting++;
}
}
}
return false;
}
// helper: remove \r and \n from visible document name (bug #170876)
inline static QString removeNewLines(const QString& str)
{
QString tmp(str);
return tmp.replace(QLatin1String("\r\n"), QLatin1String(" "))
.replace(QChar('\r'), QLatin1Char(' '))
.replace(QChar('\n'), QLatin1Char(' '));
}
void KateDocument::setDocName (const QString &_name )
{
const QString name = removeNewLines(_name);
/**
* avoid senseless name changes
*/
if ( name == m_docName )
return;
/**
* if name given, use it!
*/
if ( !name.isEmpty() ) {
m_docName = name;
emit documentNameChanged (this);
return;
}
// if the name is set, and starts with FILENAME, it should not be changed!
if ( ! url().isEmpty()
&& (m_docName == removeNewLines(url().fileName()) ||
m_docName.startsWith (removeNewLines(url().fileName()) + " (") ) ) {
return;
}
int count = -1;
foreach(KateDocument* doc, KateGlobal::self()->kateDocuments())
{
if ( (doc != this) && (doc->url().fileName() == url().fileName()) )
if ( doc->m_docNameNumber > count )
count = doc->m_docNameNumber;
}
m_docNameNumber = count + 1;
QString oldName = m_docName;
m_docName = removeNewLines(url().fileName());
if (m_docName.isEmpty())
m_docName = i18n ("Untitled");
if (m_docNameNumber > 0)
m_docName = QString(m_docName + " (%1)").arg(m_docNameNumber+1);
/**
* avoid to emit this, if name doesn't change!
*/
if (oldName != m_docName)
emit documentNameChanged (this);
}
void KateDocument::slotModifiedOnDisk( KTextEditor::View * /*v*/ )
{
if ( m_isasking < 0 )
{
m_isasking = 0;
return;
}
if ( !m_fileChangedDialogsActivated || m_isasking )
return;
if (m_modOnHd && !url().isEmpty())
{
m_isasking = 1;
QWidget *parentWidget(dialogParent());
KateModOnHdPrompt p( this, m_modOnHdReason, reasonedMOHString(), parentWidget );
switch ( p.exec() )
{
case KateModOnHdPrompt::Save:
{
m_modOnHd = false;
KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveUrlAndEncoding(config()->encoding(),
url().url(),QString(),parentWidget,i18n("Save File"));
kDebug(13020)<<"got "< tmp;
for (QHash::const_iterator i = m_marks.constBegin(); i != m_marks.constEnd(); ++i)
{
KateDocumentTmpMark m;
m.line = line (i.value()->line);
m.mark = *i.value();
tmp.append (m);
}
const QString oldMode = mode ();
const bool byUser = m_fileTypeSetByUser;
const QString hl_mode = highlightingMode ();
KTextEditor::View* oldActiveView = activeView();
m_storedVariables.clear();
// save cursor positions for all views
QVector cursorPositions;
cursorPositions.reserve(m_views.size());
foreach (KateView *v, m_views)
cursorPositions.append( v->cursorPosition() );
m_reloading = true;
KateDocument::openUrl( url() );
m_reloading = false;
// reset some flags only valid for one reload!
m_userSetEncodingForNextReload = false;
// restore cursor positions for all views
QLinkedList::iterator it = m_views.begin();
for(int i = 0; i < m_views.size(); ++i, ++it) {
setActiveView(*it);
(*it)->setCursorPositionInternal( cursorPositions.at(i), m_config->tabWidth(), false );
if ((*it)->isVisible()) {
(*it)->repaintText(false);
}
}
setActiveView(oldActiveView);
for (int z=0; z < tmp.size(); z++)
{
if (z < (int)lines())
{
if (line(tmp.at(z).mark.line) == tmp.at(z).line)
setMark (tmp.at(z).mark.line, tmp.at(z).mark.type);
}
}
if (byUser)
setMode (oldMode);
setHighlightingMode (hl_mode);
emit reloaded(this);
return true;
}
return false;
}
bool KateDocument::documentSave()
{
if( !url().isValid() || !isReadWrite() )
return documentSaveAs();
return save();
}
bool KateDocument::documentSaveAs()
{
QWidget *parentWidget(dialogParent());
KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveUrlAndEncoding(config()->encoding(),
url().url(),QString(),parentWidget,i18n("Save File"));
if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first(), parentWidget ) )
return false;
setEncoding( res.encoding );
return saveAs( res.URLs.first() );
}
void KateDocument::setWordWrap (bool on)
{
config()->setWordWrap (on);
}
bool KateDocument::wordWrap () const
{
return config()->wordWrap ();
}
void KateDocument::setWordWrapAt (uint col)
{
config()->setWordWrapAt (col);
}
unsigned int KateDocument::wordWrapAt () const
{
return config()->wordWrapAt ();
}
void KateDocument::setPageUpDownMovesCursor (bool on)
{
config()->setPageUpDownMovesCursor (on);
}
bool KateDocument::pageUpDownMovesCursor () const
{
return config()->pageUpDownMovesCursor ();
}
void KateDocument::dumpRegionTree()
{
m_buffer->foldingTree()->debugDump();
}
//END
void KateDocument::lineInfo (KateLineInfo *info, int line) const
{
m_buffer->lineInfo(info,line);
}
KateCodeFoldingTree *KateDocument::foldingTree ()
{
return m_buffer->foldingTree();
}
bool KateDocument::setEncoding (const QString &e)
{
return m_config->setEncoding(e);
}
const QString &KateDocument::encoding() const
{
return m_config->encoding();
}
void KateDocument::updateConfig ()
{
m_undoManager->updateConfig ();
// switch indenter if needed and update config....
m_indenter->setMode (m_config->indentationMode());
m_indenter->updateConfig();
// set tab width there, too
m_buffer->setTabWidth (config()->tabWidth());
// update all views, does tagAll and updateView...
foreach (KateView * view, m_views)
view->updateDocumentConfig ();
// update on-the-fly spell checking as spell checking defaults might have changes
if(m_onTheFlyChecker) {
m_onTheFlyChecker->updateConfig();
}
emit configChanged();
}
//BEGIN Variable reader
// "local variable" feature by anders, 2003
/* TODO
add config options (how many lines to read, on/off)
add interface for plugins/apps to set/get variables
add view stuff
*/
QRegExp KateDocument::kvLine = QRegExp("kate:(.*)");
QRegExp KateDocument::kvLineWildcard = QRegExp("kate-wildcard\\((.*)\\):(.*)");
QRegExp KateDocument::kvLineMime = QRegExp("kate-mimetype\\((.*)\\):(.*)");
QRegExp KateDocument::kvVar = QRegExp("([\\w\\-]+)\\s+([^;]+)");
void KateDocument::readVariables(bool onlyViewAndRenderer)
{
if (!onlyViewAndRenderer)
m_config->configStart();
// views!
KateView *v;
foreach (v,m_views)
{
v->config()->configStart();
v->renderer()->config()->configStart();
}
// read a number of lines in the top/bottom of the document
for (int i=0; i < qMin( 9, lines() ); ++i )
{
readVariableLine( line( i ), onlyViewAndRenderer );
}
if ( lines() > 10 )
{
for ( int i = qMax( 10, lines() - 10); i < lines(); i++ )
{
readVariableLine( line( i ), onlyViewAndRenderer );
}
}
if (!onlyViewAndRenderer)
m_config->configEnd();
foreach (v,m_views)
{
v->config()->configEnd();
v->renderer()->config()->configEnd();
}
}
void KateDocument::readVariableLine( QString t, bool onlyViewAndRenderer )
{
// simple check first, no regex
// no kate inside, no vars, simple...
if (!t.contains("kate"))
return;
// found vars, if any
QString s;
// now, try first the normal ones
if ( kvLine.indexIn( t ) > -1 )
{
s = kvLine.cap(1);
kDebug (13020) << "normal variable line kate: matched: " << s;
}
else if (kvLineWildcard.indexIn( t ) > -1) // regex given
{
const QStringList wildcards (kvLineWildcard.cap(1).split (';', QString::SkipEmptyParts));
const QString nameOfFile = url().fileName();
bool found = false;
foreach(const QString& pattern, wildcards)
{
QRegExp wildcard (pattern, Qt::CaseSensitive, QRegExp::Wildcard);
found = wildcard.exactMatch (nameOfFile);
}
// nothing usable found...
if (!found)
return;
s = kvLineWildcard.cap(2);
kDebug (13020) << "guarded variable line kate-wildcard: matched: " << s;
}
else if (kvLineMime.indexIn( t ) > -1) // mime-type given
{
const QStringList types (kvLineMime.cap(1).split (';', QString::SkipEmptyParts));
// no matching type found
if (!types.contains (mimeType ()))
return;
s = kvLineMime.cap(2);
kDebug (13020) << "guarded variable line kate-mimetype: matched: " << s;
}
else // nothing found
{
return;
}
QStringList vvl; // view variable names
vvl << "dynamic-word-wrap" << "dynamic-word-wrap-indicators"
<< "line-numbers" << "icon-border" << "folding-markers"
<< "bookmark-sorting" << "auto-center-lines"
<< "icon-bar-color"
// renderer
<< "background-color" << "selection-color"
<< "current-line-color" << "bracket-highlight-color"
<< "word-wrap-marker-color"
<< "font" << "font-size" << "scheme";
int spaceIndent = -1; // for backward compatibility; see below
bool replaceTabsSet = false;
int p( 0 );
QString var, val;
while ( (p = kvVar.indexIn( s, p )) > -1 )
{
p += kvVar.matchedLength();
var = kvVar.cap( 1 );
val = kvVar.cap( 2 ).trimmed();
bool state; // store booleans here
int n; // store ints here
// only apply view & renderer config stuff
if (onlyViewAndRenderer)
{
if ( vvl.contains( var ) ) // FIXME define above
setViewVariable( var, val );
}
else
{
// BOOL SETTINGS
if ( var == "word-wrap" && checkBoolValue( val, &state ) )
setWordWrap( state ); // ??? FIXME CHECK
// KateConfig::configFlags
// FIXME should this be optimized to only a few calls? how?
else if ( var == "backspace-indents" && checkBoolValue( val, &state ) )
m_config->setBackspaceIndents( state );
else if ( var == "replace-tabs" && checkBoolValue( val, &state ) )
{
m_config->setReplaceTabsDyn( state );
replaceTabsSet = true; // for backward compatibility; see below
}
else if ( var == "remove-trailing-space" && checkBoolValue( val, &state ) ) {
kWarning() << i18n("Using deprecated modeline 'remove-trailing-space'. "
"Please replace with 'remove-trailing-spaces modified;', see "
"http://docs.kde.org/stable/en/kde-baseapps/kate/config-variables.html#variable-remove-trailing-spaces");
m_config->setRemoveSpaces( state ? 1 : 0 );
}
else if ( var == "replace-trailing-space-save" && checkBoolValue( val, &state ) ) {
kWarning() << i18n("Using deprecated modeline 'replace-trailing-space-save'. "
"Please replace with 'remove-trailing-spaces all;', see "
"http://docs.kde.org/stable/en/kde-baseapps/kate/config-variables.html#variable-remove-trailing-spaces");
m_config->setRemoveSpaces( state ? 2 : 0 );
}
- else if ( var == "auto-brackets" && checkBoolValue( val, &state ) )
- m_config->setAutoBrackets( state );
else if ( var == "overwrite-mode" && checkBoolValue( val, &state ) )
m_config->setOvr( state );
else if ( var == "keep-extra-spaces" && checkBoolValue( val, &state ) )
m_config->setKeepExtraSpaces( state );
else if ( var == "tab-indents" && checkBoolValue( val, &state ) )
m_config->setTabIndents( state );
else if ( var == "show-tabs" && checkBoolValue( val, &state ) )
m_config->setShowTabs( state );
else if ( var == "show-trailing-spaces" && checkBoolValue( val, &state ) )
m_config->setShowSpaces( state );
else if ( var == "space-indent" && checkBoolValue( val, &state ) )
{
// this is for backward compatibility; see below
spaceIndent = state;
}
else if ( var == "smart-home" && checkBoolValue( val, &state ) )
m_config->setSmartHome( state );
else if ( var == "newline-at-eof" && checkBoolValue( val, &state ) )
m_config->setNewLineAtEof( state );
// INTEGER SETTINGS
else if ( var == "tab-width" && checkIntValue( val, &n ) )
m_config->setTabWidth( n );
else if ( var == "indent-width" && checkIntValue( val, &n ) )
m_config->setIndentationWidth( n );
else if ( var == "indent-mode" )
{
m_config->setIndentationMode( val );
}
else if ( var == "word-wrap-column" && checkIntValue( val, &n ) && n > 0 ) // uint, but hard word wrap at 0 will be no fun ;)
m_config->setWordWrapAt( n );
// STRING SETTINGS
else if ( var == "eol" || var == "end-of-line" )
{
QStringList l;
l << "unix" << "dos" << "mac";
if ( (n = l.indexOf( val.toLower() )) != -1 )
m_config->setEol( n );
}
else if (var == "bom" || var =="byte-order-marker")
{
if (checkBoolValue(val,&state)) {
m_config->setBom(state);
}
}
else if ( var == "remove-trailing-spaces" ) {
val = val.toLower();
if (val == "1" || val == "modified" || val == "mod" || val == "+") {
m_config->setRemoveSpaces(1);
} else if (val == "2" || val == "all" || val == "*") {
m_config->setRemoveSpaces(2);
} else {
m_config->setRemoveSpaces(0);
}
m_config->setRemoveSpaces( state ? 1 : 0 );
}
else if (var == "presave-postdialog")
setPreSavePostDialogFilterChecks(val.split(','));
else if (var == "postsave")
setPostSaveFilterChecks(val.split(','));
else if (var == "postload")
setPostLoadFilterChecks(val.split(','));
else if ( var == "syntax" || var == "hl" )
{
setHighlightingMode( val );
}
else if ( var == "mode" )
{
setMode( val );
}
else if ( var == "encoding" )
{
setEncoding( val );
}
else if ( var == "default-dictionary" )
{
setDefaultDictionary( val );
}
else if ( var == "automatic-spell-checking" && checkBoolValue( val, &state ) )
{
onTheFlySpellCheckingEnabled( state );
}
// VIEW SETTINGS
else if ( vvl.contains( var ) )
setViewVariable( var, val );
else
{
m_storedVariables.insert( var, val );
emit variableChanged( this, var, val );
}
}
}
// Backward compatibility
// If space-indent was set, but replace-tabs was not set, we assume
// that the user wants to replace tabulators and set that flag.
// If both were set, replace-tabs has precedence.
// At this point spaceIndent is -1 if it was never set,
// 0 if it was set to off, and 1 if it was set to on.
// Note that if onlyViewAndRenderer was requested, spaceIndent is -1.
if ( !replaceTabsSet && spaceIndent >= 0 )
{
m_config->setReplaceTabsDyn( spaceIndent > 0 );
}
}
void KateDocument::setViewVariable( QString var, QString val )
{
KateView *v;
bool state;
int n;
QColor c;
foreach (v,m_views)
{
if ( var == "dynamic-word-wrap" && checkBoolValue( val, &state ) )
v->config()->setDynWordWrap( state );
else if ( var == "persistent-selection" && checkBoolValue( val, &state ) )
v->config()->setPersistentSelection( state );
else if ( var == "block-selection" && checkBoolValue( val, &state ) )
v->setBlockSelectionMode( state );
//else if ( var = "dynamic-word-wrap-indicators" )
else if ( var == "line-numbers" && checkBoolValue( val, &state ) )
v->config()->setLineNumbers( state );
else if (var == "icon-border" && checkBoolValue( val, &state ) )
v->config()->setIconBar( state );
else if (var == "folding-markers" && checkBoolValue( val, &state ) )
v->config()->setFoldingBar( state );
else if ( var == "auto-center-lines" && checkIntValue( val, &n ) )
v->config()->setAutoCenterLines( n ); // FIXME uint, > N ??
else if ( var == "icon-bar-color" && checkColorValue( val, c ) )
v->renderer()->config()->setIconBarColor( c );
// RENDERER
else if ( var == "background-color" && checkColorValue( val, c ) )
v->renderer()->config()->setBackgroundColor( c );
else if ( var == "selection-color" && checkColorValue( val, c ) )
v->renderer()->config()->setSelectionColor( c );
else if ( var == "current-line-color" && checkColorValue( val, c ) )
v->renderer()->config()->setHighlightedLineColor( c );
else if ( var == "bracket-highlight-color" && checkColorValue( val, c ) )
v->renderer()->config()->setHighlightedBracketColor( c );
else if ( var == "word-wrap-marker-color" && checkColorValue( val, c ) )
v->renderer()->config()->setWordWrapMarkerColor( c );
else if ( var == "font" || ( var == "font-size" && checkIntValue( val, &n ) ) )
{
QFont _f( v->renderer()->config()->font() );
if ( var == "font" )
{
_f.setFamily( val );
_f.setFixedPitch( QFont( val ).fixedPitch() );
}
else
_f.setPointSize( n );
v->renderer()->config()->setFont( _f );
}
else if ( var == "scheme" )
{
v->renderer()->config()->setSchema( val );
}
}
}
bool KateDocument::checkBoolValue( QString val, bool *result )
{
val = val.trimmed().toLower();
QStringList l;
l << "1" << "on" << "true";
if ( l.contains( val ) )
{
*result = true;
return true;
}
l.clear();
l << "0" << "off" << "false";
if ( l.contains( val ) )
{
*result = false;
return true;
}
return false;
}
bool KateDocument::checkIntValue( QString val, int *result )
{
bool ret( false );
*result = val.toInt( &ret );
return ret;
}
bool KateDocument::checkColorValue( QString val, QColor &c )
{
c.setNamedColor( val );
return c.isValid();
}
// KTextEditor::variable
QString KateDocument::variable( const QString &name ) const
{
return m_storedVariables.value(name, QString());
}
QString KateDocument::setVariable( const QString &name, const QString &value)
{
QString s = "kate: ";
s.append(name);
s.append(" ");
s.append(value);
readVariableLine(s);
return m_storedVariables.value(name, QString());
}
//END
void KateDocument::slotModOnHdDirty (const QString &path)
{
if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != OnDiskModified))
{
// compare md5 with the one we have (if we have one)
if ( !digest().isEmpty() )
{
QByteArray oldDigest = digest();
if ( createDigest () && oldDigest == digest() ) {
return;
}
}
m_modOnHd = true;
m_modOnHdReason = OnDiskModified;
// reenable dialog if not running atm
if (m_isasking == -1)
m_isasking = false;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
}
void KateDocument::slotModOnHdCreated (const QString &path)
{
if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != OnDiskCreated))
{
m_modOnHd = true;
m_modOnHdReason = OnDiskCreated;
// reenable dialog if not running atm
if (m_isasking == -1)
m_isasking = false;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
}
void KateDocument::slotModOnHdDeleted (const QString &path)
{
if ((path == m_dirWatchFile) && (!m_modOnHd || m_modOnHdReason != OnDiskDeleted))
{
m_modOnHd = true;
m_modOnHdReason = OnDiskDeleted;
// reenable dialog if not running atm
if (m_isasking == -1)
m_isasking = false;
emit modifiedOnDisk (this, m_modOnHd, m_modOnHdReason);
}
}
const QByteArray &KateDocument::digest () const
{
return m_buffer->digest();
}
bool KateDocument::createDigest ()
{
QByteArray md5sum;
if ( url().isLocalFile() )
{
QFile f ( url().toLocalFile() );
if ( f.open( QIODevice::ReadOnly) )
{
KMD5 md5;
md5.update( f );
md5.hexDigest( md5sum );
f.close();
}
}
m_buffer->setDigest( md5sum );
return !md5sum.isEmpty();
}
QString KateDocument::reasonedMOHString() const
{
// squeeze path
QString str = KStringHandler::csqueeze(url().pathOrUrl());
switch( m_modOnHdReason )
{
case OnDiskModified:
return i18n("The file '%1' was modified by another program.", str );
break;
case OnDiskCreated:
return i18n("The file '%1' was created by another program.", str );
break;
case OnDiskDeleted:
return i18n("The file '%1' was deleted by another program.", str );
break;
default:
return QString();
}
return QString();
}
void KateDocument::removeTrailingSpaces()
{
const int remove = config()->removeSpaces();
if (remove == 0)
return;
// get cursor position of active view
KTextEditor::Cursor curPos = KTextEditor::Cursor::invalid();
if (activeView()) {
curPos = activeView()->cursorPosition();
}
editStart();
for (int line = 0; line < lines(); ++line)
{
Kate::TextLine textline = plainKateTextLine(line);
// remove trailing spaces in entire document, remove = 2
// remove trailing spaces of touched lines, remove = 1
// remove trailing spaces of lines saved on disk, remove = 1
if (remove == 2 || textline->markedAsModified() || textline->markedAsSavedOnDisk()) {
const int p = textline->lastChar() + 1;
const int l = textline->length() - p;
if (l > 0 ) {
// if the cursor is in the trailing space, only delete behind cursor
if (curPos.line() != line || curPos.column() <= p || curPos.column() > p + l) {
editRemoveText(line, p, l);
} else {
editRemoveText(line, curPos.column(), l - (curPos.column() - p));
}
}
}
}
editEnd();
}
void KateDocument::updateFileType (const QString &newType, bool user)
{
if (user || !m_fileTypeSetByUser)
{
if (!newType.isEmpty())
{
// remember that we got set by user
m_fileTypeSetByUser = user;
m_fileType = newType;
m_config->configStart();
if (!m_hlSetByUser && !KateGlobal::self()->modeManager()->fileType(newType).hl.isEmpty())
{
int hl (KateHlManager::self()->nameFind (KateGlobal::self()->modeManager()->fileType(newType).hl));
if (hl >= 0)
m_buffer->setHighlight(hl);
}
/**
* set the indentation mode, if any in the mode...
* and user did not set it before!
*/
if (!m_indenterSetByUser && !KateGlobal::self()->modeManager()->fileType(newType).indenter.isEmpty())
config()->setIndentationMode (KateGlobal::self()->modeManager()->fileType(newType).indenter);
// views!
KateView *v;
foreach (v,m_views)
{
v->config()->configStart();
v->renderer()->config()->configStart();
}
bool bom_settings = false;
if (m_bomSetByUser)
bom_settings=m_config->bom();
readVariableLine( KateGlobal::self()->modeManager()->fileType(newType).varLine );
if (m_bomSetByUser)
m_config->setBom(bom_settings);
m_config->configEnd();
foreach (v,m_views)
{
v->config()->configEnd();
v->renderer()->config()->configEnd();
}
}
}
// fixme, make this better...
emit modeChanged (this);
}
void KateDocument::slotQueryClose_save(bool *handled, bool* abortClosing) {
*handled=true;
*abortClosing=true;
if (this->url().isEmpty())
{
QWidget *parentWidget(dialogParent());
KEncodingFileDialog::Result res=KEncodingFileDialog::getSaveUrlAndEncoding(config()->encoding(),
QString(),QString(),parentWidget,i18n("Save File"));
if( res.URLs.isEmpty() || !checkOverwrite( res.URLs.first(), parentWidget ) ) {
*abortClosing=true;
return;
}
setEncoding( res.encoding );
saveAs( res.URLs.first() );
*abortClosing=false;
}
else
{
save();
*abortClosing=false;
}
}
bool KateDocument::checkOverwrite( KUrl u, QWidget *parent )
{
if( !u.isLocalFile() )
return true;
QFileInfo info( u.path() );
if( !info.exists() )
return true;
return KMessageBox::Cancel != KMessageBox::warningContinueCancel( parent,
i18n( "A file named \"%1\" already exists. "
"Are you sure you want to overwrite it?" , info.fileName() ),
i18n( "Overwrite File?" ), KStandardGuiItem::overwrite(),
KStandardGuiItem::cancel(), QString(), KMessageBox::Notify | KMessageBox::Dangerous );
}
//BEGIN KTextEditor::ConfigInterface
// BEGIN ConfigInterface stff
QStringList KateDocument::configKeys() const
{
- return QStringList() << "auto-brackets";
+ return QStringList();
}
QVariant KateDocument::configValue(const QString &key)
{
- if (key == "auto-brackets") {
- return m_config->autoBrackets();
- } else if (key == "backup-on-save-local") {
+ if (key == "backup-on-save-local") {
return m_config->backupFlags() & KateDocumentConfig::LocalFiles;
} else if (key == "backup-on-save-remote") {
return m_config->backupFlags() & KateDocumentConfig::RemoteFiles;
} else if (key == "backup-on-save-suffix") {
return m_config->backupSuffix();
} else if (key == "backup-on-save-prefix") {
return m_config->backupPrefix();
} else if (key == "replace-tabs") {
return m_config->replaceTabsDyn();
}
// return invalid variant
return QVariant();
}
void KateDocument::setConfigValue(const QString &key, const QVariant &value)
{
if (value.type() == QVariant::String) {
if (key == "backup-on-save-suffix") {
m_config->setBackupSuffix(value.toString());
} else if (key == "backup-on-save-prefix") {
m_config->setBackupPrefix(value.toString());
}
} else if (value.canConvert(QVariant::Bool)) {
const bool bValue = value.toBool();
- if (key == "auto-brackets") {
- m_config->setAutoBrackets(bValue);
- } else if (key == "backup-on-save-local" && value.type() == QVariant::String) {
+ if (key == "backup-on-save-local" && value.type() == QVariant::String) {
uint f = m_config->backupFlags();
if (bValue) {
f |= KateDocumentConfig::LocalFiles;
} else {
f ^= KateDocumentConfig::LocalFiles;
}
m_config->setBackupFlags(f);
} else if (key == "backup-on-save-remote") {
uint f = m_config->backupFlags();
if (bValue) {
f |= KateDocumentConfig::RemoteFiles;
} else {
f ^= KateDocumentConfig::RemoteFiles;
}
m_config->setBackupFlags(f);
} else if (key == "replace-tabs") {
m_config->setReplaceTabsDyn(bValue);
}
}
}
//END KTextEditor::ConfigInterface
//BEGIN KTextEditor::TemplateInterface
bool KateDocument::insertTemplateTextImplementation( const KTextEditor::Cursor &c,
const QString &templateString,
const QMap &initialValues,
KTextEditor::TemplateScript* templateScript,
KateView* view)
{
if (templateString.isEmpty()) return false;
if (!isReadWrite()) return false;
KateTemplateScript* kateTemplateScript =
KateGlobal::self()->scriptManager()->templateScript(templateScript);
// the handler will delete itself when necessary
new KateTemplateHandler(view, c, templateString, initialValues, m_undoManager, kateTemplateScript);
return true;
}
//END KTextEditor::TemplateInterface
KateView * KateDocument::activeKateView( ) const
{
return static_cast(m_activeView);
}
KTextEditor::Cursor KateDocument::documentEnd( ) const
{
return KTextEditor::Cursor(lastLine(), lineLength(lastLine()));
}
bool KateDocument::replaceText( const KTextEditor::Range & range, const QString & s, bool block )
{
// TODO more efficient?
editStart();
bool changed = removeText(range, block);
changed |= insertText(range.start(), s, block);
editEnd();
return changed;
}
void KateDocument::ignoreModifiedOnDiskOnce( )
{
m_isasking = -1;
}
KateHighlighting * KateDocument::highlight( ) const
{
return m_buffer->highlight();
}
uint KateDocument::getRealLine( unsigned int virtualLine )
{
return m_buffer->lineNumber (virtualLine);
}
uint KateDocument::getVirtualLine( unsigned int realLine )
{
return m_buffer->lineVisibleNumber (realLine);
}
uint KateDocument::visibleLines( )
{
return m_buffer->countVisible ();
}
Kate::TextLine KateDocument::kateTextLine( uint i )
{
m_buffer->ensureHighlighted (i);
return m_buffer->plainLine (i);
}
Kate::TextLine KateDocument::plainKateTextLine( uint i )
{
return m_buffer->plainLine (i);
}
bool KateDocument::isEditRunning() const
{
return editIsRunning;
}
void KateDocument::setUndoMergeAllEdits(bool merge)
{
m_undoManager->undoSafePoint();
m_undoManager->setAllowComplexMerge(merge);
}
//BEGIN KTextEditor::MovingInterface
KTextEditor::MovingCursor *KateDocument::newMovingCursor (const KTextEditor::Cursor &position, KTextEditor::MovingCursor::InsertBehavior insertBehavior)
{
return new Kate::TextCursor(buffer(), position, insertBehavior);
}
KTextEditor::MovingRange *KateDocument::newMovingRange (const KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors, KTextEditor::MovingRange::EmptyBehavior emptyBehavior)
{
return new Kate::TextRange(buffer(), range, insertBehaviors, emptyBehavior);
}
qint64 KateDocument::revision () const
{
return m_buffer->history().revision ();
}
qint64 KateDocument::lastSavedRevision () const
{
return m_buffer->history().lastSavedRevision ();
}
void KateDocument::lockRevision (qint64 revision)
{
m_buffer->history().lockRevision (revision);
}
void KateDocument::unlockRevision (qint64 revision)
{
m_buffer->history().unlockRevision (revision);
}
void KateDocument::transformCursor(int& line, int& column, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision)
{
m_buffer->history().transformCursor (line, column, insertBehavior, fromRevision, toRevision);
}
void KateDocument::transformCursor (KTextEditor::Cursor &cursor, KTextEditor::MovingCursor::InsertBehavior insertBehavior, qint64 fromRevision, qint64 toRevision)
{
int line = cursor.line(), column = cursor.column();
m_buffer->history().transformCursor (line, column, insertBehavior, fromRevision, toRevision);
cursor.setLine(line);
cursor.setColumn(column);
}
void KateDocument::transformRange (KTextEditor::Range &range, KTextEditor::MovingRange::InsertBehaviors insertBehaviors, KTextEditor::MovingRange::EmptyBehavior emptyBehavior, qint64 fromRevision, qint64 toRevision)
{
m_buffer->history().transformRange (range, insertBehaviors, emptyBehavior, fromRevision, toRevision);
}
//END
bool KateDocument::simpleMode ()
{
return KateGlobal::self()->simpleMode () && KateGlobal::self()->documentConfig()->allowSimpleMode ();
}
KateDocument::LoadSaveFilterCheckPlugins* KateDocument::loadSaveFilterCheckPlugins()
{
K_GLOBAL_STATIC(KateDocument::LoadSaveFilterCheckPlugins, s_loadSaveFilterCheckPlugins)
return s_loadSaveFilterCheckPlugins;
}
//BEGIN KTextEditor::AnnotationInterface
void KateDocument::setAnnotationModel( KTextEditor::AnnotationModel* model )
{
KTextEditor::AnnotationModel* oldmodel = m_annotationModel;
m_annotationModel = model;
emit annotationModelChanged(oldmodel, m_annotationModel);
}
KTextEditor::AnnotationModel* KateDocument::annotationModel() const
{
return m_annotationModel;
}
//END KTextEditor::AnnotationInterface
//TAKEN FROM kparts.h
bool KateDocument::queryClose()
{
if ( !isReadWrite() || !isModified() )
return true;
QString docName = documentName();
int res = KMessageBox::warningYesNoCancel( dialogParent(),
i18n( "The document \"%1\" has been modified.\n"
"Do you want to save your changes or discard them?" , docName ),
i18n( "Close Document" ), KStandardGuiItem::save(), KStandardGuiItem::discard() );
bool abortClose=false;
bool handled=false;
switch(res) {
case KMessageBox::Yes :
sigQueryClose(&handled,&abortClose);
if (!handled)
{
if (url().isEmpty())
{
KUrl url = KFileDialog::getSaveUrl(KUrl(), QString(), dialogParent());
if (url.isEmpty())
return false;
saveAs( url );
}
else
{
save();
}
} else if (abortClose) return false;
return waitSaveComplete();
case KMessageBox::No :
return true;
default : // case KMessageBox::Cancel :
return false;
}
}
void KateDocument::slotCanceled() {
// remember file loading is over now
m_filePerhapsStillLoading = false;
delete m_loadingMessage;
m_savingToUrl=false;
m_saveAs=false;
}
void KateDocument::slotCompleted() {
// remember file loading is over now
m_filePerhapsStillLoading = false;
delete m_loadingMessage;
if (m_savingToUrl) {
if (!m_postSaveFilterChecks.isEmpty())
{
LoadSaveFilterCheckPlugins *lscps1=loadSaveFilterCheckPlugins();
foreach(const QString& checkplugin, m_postSaveFilterChecks)
{
if (lscps1->postSaveFilterCheck(checkplugin,this,m_saveAs)==false)
break;
}
}
}
emit documentSavedOrUploaded(this,m_saveAs);
m_savingToUrl=false;
m_saveAs=false;
}
void KateDocument::slotStarted (KIO::Job *job)
{
// perhaps file loading started
m_filePerhapsStillLoading = true;
// perhaps show loading message, but wait one second
if (job)
QTimer::singleShot (1000, this, SLOT(slotTriggerLoadingMessage()));
}
void KateDocument::slotTriggerLoadingMessage ()
{
if (!m_filePerhapsStillLoading)
return;
m_loadingMessage = new KTextEditor::Message(KTextEditor::Message::Information
, i18n ("The file %1 is still loading.", this->url().pathOrUrl()));
m_loadingMessage->setWordWrap(true);
postMessage(m_loadingMessage);
}
bool KateDocument::save() {
// don't allow to save files that still load
if (m_filePerhapsStillLoading)
return false;
m_saveAs = false;
return KTextEditor::Document::save();
}
bool KateDocument::saveAs( const KUrl &url ) {
// don't allow to save files that still load
if (m_filePerhapsStillLoading)
return false;
m_saveAs = true;
return KTextEditor::Document::saveAs(url);
}
QString KateDocument::defaultDictionary() const
{
return m_defaultDictionary;
}
QList > KateDocument::dictionaryRanges() const
{
return m_dictionaryRanges;
}
void KateDocument::clearDictionaryRanges()
{
for(QList >::iterator i = m_dictionaryRanges.begin();
i != m_dictionaryRanges.end();++i)
{
delete (*i).first;
}
m_dictionaryRanges.clear();
if(m_onTheFlyChecker)
{
m_onTheFlyChecker->refreshSpellCheck();
}
emit dictionaryRangesPresent(false);
}
void KateDocument::setDictionary(const QString& newDictionary, const KTextEditor::Range &range)
{
KTextEditor::Range newDictionaryRange = range;
if(!newDictionaryRange.isValid() || newDictionaryRange.isEmpty())
{
return;
}
QList > newRanges;
// all ranges is 'm_dictionaryRanges' are assumed to be mutually disjoint
for(QList >::iterator i = m_dictionaryRanges.begin();
i != m_dictionaryRanges.end();)
{
kDebug(13000) << "new iteration" << newDictionaryRange;
if(newDictionaryRange.isEmpty())
{
break;
}
QPair pair = *i;
QString dictionarySet = pair.second;
KTextEditor::MovingRange *dictionaryRange = pair.first;
kDebug(13000) << *dictionaryRange << dictionarySet;
if(dictionaryRange->contains(newDictionaryRange) && newDictionary == dictionarySet)
{
kDebug(13000) << "dictionaryRange contains newDictionaryRange";
return;
}
if(newDictionaryRange.contains(*dictionaryRange))
{
delete dictionaryRange;
i = m_dictionaryRanges.erase(i);
kDebug(13000) << "newDictionaryRange contains dictionaryRange";
continue;
}
KTextEditor::Range intersection = dictionaryRange->toRange().intersect(newDictionaryRange);
if(!intersection.isEmpty() && intersection.isValid())
{
if(dictionarySet == newDictionary) // we don't have to do anything for 'intersection'
{ // except cut off the intersection
QList remainingRanges = KateSpellCheckManager::rangeDifference(newDictionaryRange, intersection);
Q_ASSERT(remainingRanges.size() == 1);
newDictionaryRange = remainingRanges.first();
++i;
kDebug(13000) << "dictionarySet == newDictionary";
continue;
}
QList remainingRanges = KateSpellCheckManager::rangeDifference(*dictionaryRange, intersection);
for(QList::iterator j = remainingRanges.begin(); j != remainingRanges.end(); ++j)
{
KTextEditor::MovingRange *remainingRange = newMovingRange(*j,
KTextEditor::MovingRange::ExpandLeft | KTextEditor::MovingRange::ExpandRight);
remainingRange->setFeedback(this);
newRanges.push_back(QPair(remainingRange, dictionarySet));
}
i = m_dictionaryRanges.erase(i);
delete dictionaryRange;
} else {
++i;
}
}
m_dictionaryRanges += newRanges;
if(!newDictionaryRange.isEmpty() && !newDictionary.isEmpty()) // we don't add anything for the default dictionary
{
KTextEditor::MovingRange *newDictionaryMovingRange = newMovingRange(newDictionaryRange,
KTextEditor::MovingRange::ExpandLeft | KTextEditor::MovingRange::ExpandRight);
newDictionaryMovingRange->setFeedback(this);
m_dictionaryRanges.push_back(QPair(newDictionaryMovingRange, newDictionary));
}
if(m_onTheFlyChecker && !newDictionaryRange.isEmpty())
{
m_onTheFlyChecker->refreshSpellCheck(newDictionaryRange);
}
emit dictionaryRangesPresent(!m_dictionaryRanges.isEmpty());
}
void KateDocument::revertToDefaultDictionary(const KTextEditor::Range &range)
{
setDictionary(QString(), range);
}
void KateDocument::setDefaultDictionary(const QString& dict)
{
if(m_defaultDictionary == dict)
{
return;
}
m_defaultDictionary = dict;
if(m_onTheFlyChecker)
{
m_onTheFlyChecker->updateConfig();
}
refreshOnTheFlyCheck();
emit defaultDictionaryChanged(this);
}
void KateDocument::onTheFlySpellCheckingEnabled(bool enable)
{
if (isOnTheFlySpellCheckingEnabled() == enable)
{
return;
}
if (enable)
{
if (!m_onTheFlyChecker) {
m_onTheFlyChecker = new KateOnTheFlyChecker(this);
}
} else {
delete m_onTheFlyChecker;
m_onTheFlyChecker = 0;
}
foreach(KateView *view, m_views) {
view->reflectOnTheFlySpellCheckStatus(enable);
}
}
bool KateDocument::isOnTheFlySpellCheckingEnabled() const
{
return m_onTheFlyChecker != 0;
}
QString KateDocument::dictionaryForMisspelledRange(const KTextEditor::Range& range) const
{
if (!m_onTheFlyChecker)
{
return QString();
} else {
return m_onTheFlyChecker->dictionaryForMisspelledRange(range);
}
}
void KateDocument::clearMisspellingForWord(const QString& word)
{
if(m_onTheFlyChecker) {
m_onTheFlyChecker->clearMisspellingForWord(word);
}
}
void KateDocument::refreshOnTheFlyCheck(const KTextEditor::Range &range)
{
if(m_onTheFlyChecker) {
m_onTheFlyChecker->refreshSpellCheck(range);
}
}
void KateDocument::rangeInvalid(KTextEditor::MovingRange *movingRange)
{
deleteDictionaryRange(movingRange);
}
void KateDocument::rangeEmpty(KTextEditor::MovingRange *movingRange)
{
deleteDictionaryRange(movingRange);
}
void KateDocument::deleteDictionaryRange(KTextEditor::MovingRange *movingRange)
{
kDebug(13020) << "deleting" << movingRange;
for(QList >::iterator i = m_dictionaryRanges.begin();
i != m_dictionaryRanges.end();)
{
KTextEditor::MovingRange *dictionaryRange = (*i).first;
if(dictionaryRange == movingRange)
{
delete movingRange;
i = m_dictionaryRanges.erase(i);
} else {
++i;
}
}
}
bool KateDocument::containsCharacterEncoding(const KTextEditor::Range& range)
{
KateHighlighting *highlighting = highlight();
Kate::TextLine textLine;
const int rangeStartLine = range.start().line();
const int rangeStartColumn = range.start().column();
const int rangeEndLine = range.end().line();
const int rangeEndColumn = range.end().column();
for(int line = range.start().line(); line <= rangeEndLine; ++line) {
textLine = kateTextLine(line);
int startColumn = (line == rangeStartLine) ? rangeStartColumn : 0;
int endColumn = (line == rangeEndLine) ? rangeEndColumn : textLine->length();
for(int col = startColumn; col < endColumn; ++col) {
int attr = textLine->attribute(col);
const KatePrefixStore& prefixStore = highlighting->getCharacterEncodingsPrefixStore(attr);
if(!prefixStore.findPrefix(textLine, col).isEmpty()) {
return true;
}
}
}
return false;
}
int KateDocument::computePositionWrtOffsets(const OffsetList& offsetList, int pos)
{
int previousOffset = 0;
for(OffsetList::const_iterator i = offsetList.begin(); i != offsetList.end(); ++i) {
if((*i).first > pos) {
break;
}
previousOffset = (*i).second;
}
return pos + previousOffset;
}
QString KateDocument::decodeCharacters(const KTextEditor::Range& range, KateDocument::OffsetList& decToEncOffsetList,
KateDocument::OffsetList& encToDecOffsetList)
{
QString toReturn;
KTextEditor::Cursor previous = range.start();
int decToEncCurrentOffset = 0, encToDecCurrentOffset = 0;
int i = 0;
int newI = 0;
KateHighlighting *highlighting = highlight();
Kate::TextLine textLine;
const int rangeStartLine = range.start().line();
const int rangeStartColumn = range.start().column();
const int rangeEndLine = range.end().line();
const int rangeEndColumn = range.end().column();
for(int line = range.start().line(); line <= rangeEndLine; ++line) {
textLine = kateTextLine(line);
int startColumn = (line == rangeStartLine) ? rangeStartColumn : 0;
int endColumn = (line == rangeEndLine) ? rangeEndColumn : textLine->length();
for(int col = startColumn; col < endColumn;) {
int attr = textLine->attribute(col);
const KatePrefixStore& prefixStore = highlighting->getCharacterEncodingsPrefixStore(attr);
const QHash& characterEncodingsHash = highlighting->getCharacterEncodings(attr);
QString matchingPrefix = prefixStore.findPrefix(textLine, col);
if(!matchingPrefix.isEmpty()) {
toReturn += text(KTextEditor::Range(previous, KTextEditor::Cursor(line, col)));
const QChar& c = characterEncodingsHash.value(matchingPrefix);
const bool isNullChar = c.isNull();
if(!c.isNull()) {
toReturn += c;
}
i += matchingPrefix.length();
col += matchingPrefix.length();
previous = KTextEditor::Cursor(line, col);
decToEncCurrentOffset = decToEncCurrentOffset - (isNullChar ? 0 : 1) + matchingPrefix.length();
encToDecCurrentOffset = encToDecCurrentOffset - matchingPrefix.length() + (isNullChar ? 0 : 1);
newI += (isNullChar ? 0 : 1);
decToEncOffsetList.push_back(QPair(newI, decToEncCurrentOffset));
encToDecOffsetList.push_back(QPair(i, encToDecCurrentOffset));
continue;
}
++col;
++i;
++newI;
}
++i;
++newI;
}
if(previous < range.end()) {
toReturn += text(KTextEditor::Range(previous, range.end()));
}
return toReturn;
}
void KateDocument::replaceCharactersByEncoding(const KTextEditor::Range& range)
{
KateHighlighting *highlighting = highlight();
Kate::TextLine textLine;
const int rangeStartLine = range.start().line();
const int rangeStartColumn = range.start().column();
const int rangeEndLine = range.end().line();
const int rangeEndColumn = range.end().column();
for(int line = range.start().line(); line <= rangeEndLine; ++line) {
textLine = kateTextLine(line);
int startColumn = (line == rangeStartLine) ? rangeStartColumn : 0;
int endColumn = (line == rangeEndLine) ? rangeEndColumn : textLine->length();
for(int col = startColumn; col < endColumn;) {
int attr = textLine->attribute(col);
const QHash& reverseCharacterEncodingsHash = highlighting->getReverseCharacterEncodings(attr);
QHash::const_iterator it = reverseCharacterEncodingsHash.find(textLine->at(col));
if(it != reverseCharacterEncodingsHash.end()) {
replaceText(KTextEditor::Range(line, col, line, col + 1), *it);
col += (*it).length();
continue;
}
++col;
}
}
}
//
// KTextEditor::HighlightInterface
//
KTextEditor::Attribute::Ptr KateDocument::defaultStyle(const KTextEditor::HighlightInterface::DefaultStyle ds) const
{
///TODO: move attributes to document, they are not view-dependant
KateView* view = activeKateView();
if ( !view ) {
kWarning() << "ATTENTION: cannot access defaultStyle() without any View (will be fixed eventually)";
return KTextEditor::Attribute::Ptr(0);
}
KTextEditor::Attribute::Ptr style = highlight()->attributes(view->renderer()->config()->schema()).at(ds);
if (!style->hasProperty(QTextFormat::BackgroundBrush)) {
// make sure the returned style has the default background color set
style.attach(new KTextEditor::Attribute(*style));
style->setBackground( QBrush(view->renderer()->config()->backgroundColor()) );
}
return style;
}
QList< KTextEditor::HighlightInterface::AttributeBlock > KateDocument::lineAttributes(const unsigned int line)
{
///TODO: move attributes to document, they are not view-dependant
QList< KTextEditor::HighlightInterface::AttributeBlock > attribs;
KateView* view = activeKateView();
if ( !view ) {
kWarning() << "ATTENTION: cannot access lineAttributes() without any View (will be fixed eventually)";
return attribs;
}
Kate::TextLine kateLine = kateTextLine(line);
if ( !kateLine ) {
return attribs;
}
const QVector & intAttrs = kateLine->attributesList();
Q_ASSERT(intAttrs.size() % 3 == 0);
for ( int i = 0; i < intAttrs.size(); i += 3 ) {
attribs << KTextEditor::HighlightInterface::AttributeBlock(
intAttrs.at(i),
intAttrs.at(i+1),
view->renderer()->attribute(intAttrs.at(i+2))
);
}
return attribs;
}
QStringList KateDocument::embeddedHighlightingModes() const
{
return highlight()->getEmbeddedHighlightingModes();
}
QString KateDocument::highlightingModeAt(const KTextEditor::Cursor& position)
{
Kate::TextLine kateLine = kateTextLine(position.line());
// const QVector< short >& attrs = kateLine->ctxArray();
// kDebug() << "----------------------------------------------------------------------";
// foreach( short a, attrs ) {
// kDebug() << a;
// }
// kDebug() << "----------------------------------------------------------------------";
// kDebug() << "col: " << position.column() << " lastchar:" << kateLine->lastChar() << " length:" << kateLine->length() << "global mode:" << highlightingMode();
int len = kateLine->length();
int pos = position.column();
if ( pos >= len ) {
const QVector< short >& ctxs = kateLine->ctxArray();
int ctxcnt = ctxs.count();
if ( ctxcnt == 0 ) {
return highlightingMode();
}
int ctx = ctxs.at(ctxcnt-1);
if ( ctx == 0 ) {
return highlightingMode();
}
return KateHlManager::self()->nameForIdentifier(highlight()->hlKeyForContext(ctx));
}
int attr = kateLine->attribute(pos);
if ( attr == 0 ) {
return mode();
}
return KateHlManager::self()->nameForIdentifier(highlight()->hlKeyForAttrib(attr));
}
Kate::SwapFile* KateDocument::swapFile()
{
return m_swapfile;
}
int KateDocument::defStyleNum(int line, int column)
{
QList attributes = highlight()->attributes(static_cast (activeView())->renderer()->config()->schema());
KTextEditor::Attribute::Ptr a = attributes[plainKateTextLine(line)->attribute(column)];
return a->property(KateExtendedAttribute::AttributeDefaultStyleIndex).toInt();
}
bool KateDocument::isComment(int line, int column)
{
const int defaultStyle = defStyleNum(line, column);
return defaultStyle == KTextEditor::HighlightInterface::dsComment;
}
//BEGIN KTextEditor::MessageInterface
bool KateDocument::postMessage(KTextEditor::Message* message)
{
// no message -> cancel
if (!message)
return false;
// make sure the desired view belongs to this document
if (message->view() && message->view()->document() != this) {
kWarning(13020) << "trying to post a message to a view of another document:" << message->text();
return false;
}
message->setParent(this);
message->setDocument(this);
// if there are no actions, add a close action by default
if (message->actions().count() == 0) {
QAction* closeAction = new QAction(KIcon("window-close"), i18n("&Close"), 0);
closeAction->setToolTip(i18n("Close document"));
message->addAction(closeAction);
}
// reparent actions, as we want full control over when they are deleted
foreach (QAction *action, message->actions()) {
action->setParent(0);
m_messageHash[message].append(QSharedPointer(action));
}
// post message to all views
foreach (KateView *view, m_views)
view->postMessage(message, m_messageHash[message]);
// also catch if the user manually calls delete message
connect(message, SIGNAL(closed(KTextEditor::Message*)), SLOT(messageDestroyed(KTextEditor::Message*)));
return true;
}
void KateDocument::messageDestroyed(KTextEditor::Message* message)
{
// KTE:Message is already in destructor
Q_ASSERT(m_messageHash.contains(message));
m_messageHash.remove(message);
}
//END KTextEditor::MessageInterface
// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/part/plugins/autobrace/autobrace.cpp b/part/plugins/autobrace/autobrace.cpp
index 92d34a7b7..ac079b69d 100644
--- a/part/plugins/autobrace/autobrace.cpp
+++ b/part/plugins/autobrace/autobrace.cpp
@@ -1,462 +1,452 @@
/**
* This file is part of the KDE libraries
* Copyright (C) 2008 Jakob Petsovits
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License version 2 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#include "autobrace.h"
#include "autobrace_config.h"
#include
#include
#include
#include
#include
#include
#include
AutoBracePlugin *AutoBracePlugin::plugin = 0;
K_PLUGIN_FACTORY_DEFINITION(AutoBracePluginFactory,
registerPlugin("ktexteditor_autobrace");
registerPlugin("ktexteditor_autobrace_config");
)
K_EXPORT_PLUGIN(AutoBracePluginFactory("ktexteditor_autobrace", "ktexteditor_plugins"))
AutoBracePlugin::AutoBracePlugin(QObject *parent, const QVariantList &args)
: KTextEditor::Plugin(parent), m_autoBrackets(true), m_autoQuotations(true)
{
Q_UNUSED(args);
plugin = this;
readConfig();
}
AutoBracePlugin::~AutoBracePlugin()
{
plugin = 0;
}
void AutoBracePlugin::addView(KTextEditor::View *view)
{
- if ( KTextEditor::ConfigInterface* confIface = qobject_cast< KTextEditor::ConfigInterface* >(view->document()) ) {
- QVariant brackets = confIface->configValue("auto-brackets");
- if ( brackets.isValid() && brackets.canConvert(QVariant::Bool) && brackets.toBool() ) {
- confIface->setConfigValue("auto-brackets", false);
- KMessageBox::information(view, i18n("The autobrace plugin supersedes the Kate-internal \"Auto Brackets\" feature.\n"
- "The setting was automatically disabled for this document."),
- i18n("Auto brackets feature disabled"), "AutoBraceSupersedesInformation");
- }
- }
-
AutoBracePluginDocument *docplugin;
// We're not storing the brace inserter by view but by document,
// which makes signal connection and destruction a bit easier.
if (m_docplugins.contains(view->document())) {
docplugin = m_docplugins.value(view->document());
}
else {
// Create Editor plugin and assign options through reference
docplugin = new AutoBracePluginDocument(view->document(),
m_autoBrackets,
m_autoQuotations);
m_docplugins.insert(view->document(), docplugin);
}
// Shouldn't be necessary in theory, but for removeView() the document
// might already be destroyed and removed. Also used as refcounter.
m_documents.insert(view, view->document());
}
void AutoBracePlugin::removeView(KTextEditor::View *view)
{
if (m_documents.contains(view))
{
KTextEditor::Document *document = m_documents.value(view);
m_documents.remove(view);
// Only detach from the document if it was the last view pointing to that.
if (m_documents.keys(document).empty()) {
AutoBracePluginDocument *docplugin = m_docplugins.value(document);
m_docplugins.remove(document);
delete docplugin;
}
}
}
void AutoBracePlugin::readConfig()
{
KConfigGroup cg(KGlobal::config(), "AutoBrace Plugin");
m_autoBrackets = cg.readEntry("autobrackets", true);
m_autoQuotations = cg.readEntry("autoquotations", false);
}
void AutoBracePlugin::writeConfig()
{
KConfigGroup cg(KGlobal::config(), "AutoBrace Plugin");
cg.writeEntry("autobrackets", m_autoBrackets);
cg.writeEntry("autoquotations", m_autoQuotations);
}
/// AutoBracePluginDocument
AutoBracePluginDocument::AutoBracePluginDocument(KTextEditor::Document* document, const bool& autoBrackets, const bool& autoQuotations)
: QObject(document), m_insertionLine(0), m_withSemicolon(false),
m_lastRange(KTextEditor::Range::invalid()), m_autoBrackets(autoBrackets), m_autoQuotations(autoQuotations)
{
connect(document, SIGNAL(exclusiveEditStart(KTextEditor::Document*)),
this, SLOT(disconnectSlots(KTextEditor::Document*)));
connect(document, SIGNAL(exclusiveEditEnd(KTextEditor::Document*)),
this, SLOT(connectSlots(KTextEditor::Document*)));
connectSlots(document);
}
AutoBracePluginDocument::~AutoBracePluginDocument()
{
disconnect(parent() /* == document */, 0, this, 0);
}
/**
* (Re-)setups slots for AutoBracePluginDocument.
* @param document Current document.
*/
void AutoBracePluginDocument::connectSlots(KTextEditor::Document *document)
{
connect(document, SIGNAL(textInserted(KTextEditor::Document*,KTextEditor::Range)),
this, SLOT(slotTextInserted(KTextEditor::Document*,KTextEditor::Range)));
connect(document, SIGNAL(textRemoved(KTextEditor::Document*,KTextEditor::Range)),
this, SLOT(slotTextRemoved(KTextEditor::Document*,KTextEditor::Range)));
}
void AutoBracePluginDocument::disconnectSlots(KTextEditor::Document* document)
{
disconnect(document, SIGNAL(textInserted(KTextEditor::Document*,KTextEditor::Range)),
this, SLOT(slotTextInserted(KTextEditor::Document*,KTextEditor::Range)));
disconnect(document, SIGNAL(textRemoved(KTextEditor::Document*,KTextEditor::Range)),
this, SLOT(slotTextRemoved(KTextEditor::Document*,KTextEditor::Range)));
disconnect(document, SIGNAL(textChanged(KTextEditor::Document*)),
this, SLOT(slotTextChanged(KTextEditor::Document*)));
}
/**
* Connected to KTextEditor::Document::textChanged() once slotTextInserted()
* found a line with an opening brace. This takes care of inserting the new
* line with its closing counterpart.
*/
void AutoBracePluginDocument::slotTextChanged(KTextEditor::Document *document) {
// Disconnect from all signals as we insert stuff by ourselves.
// Prevent infinite recursion.
disconnectSlots(document);
// Make really sure that we want to insert the brace, paste guard and all.
if (m_insertionLine != 0
&& m_insertionLine == document->activeView()->cursorPosition().line()
&& document->line(m_insertionLine).trimmed().isEmpty())
{
KTextEditor::View *view = document->activeView();
document->startEditing();
// If the document's View is a KateView then it's able to indent.
// We hereby ignore the indenter and always indent correctly. (Sorry!)
if (view->inherits("KateView")) {
// Correctly indent the empty line. Magic!
KTextEditor::Range lineRange(
m_insertionLine, 0,
m_insertionLine, document->lineLength(m_insertionLine)
);
document->replaceText(lineRange, m_indentation);
connect(this, SIGNAL(indent()), view, SLOT(indent()));
emit indent();
disconnect(this, SIGNAL(indent()), view, SLOT(indent()));
}
// The line with the closing brace. (Inserted via insertLine() in order
// to avoid space removal by potential indenters.)
document->insertLine(m_insertionLine + 1, m_indentation + '}' + (m_withSemicolon ? ";" : ""));
document->endEditing();
view->setCursorPosition(document->endOfLine(m_insertionLine));
}
m_insertionLine = 0;
// Re-enable the textInserted() slot again.
connectSlots(document);
}
/**
* Connected to KTextEditor::Documet::textRemoved. Allows to delete
* an automatically inserted closing bracket if the opening counterpart
* has been removed.
*/
void AutoBracePluginDocument::slotTextRemoved(KTextEditor::Document* document, const KTextEditor::Range& range)
{
// If last range equals the deleted text range (last range
// is last inserted bracket), we also delete the associated closing bracket.
if (m_lastRange == range) {
// avoid endless recursion
disconnectSlots(document);
// Delete the character at the same range because the opening
// bracket has already been removed so the closing bracket
// should now have been shifted to that same position
if (range.isValid()) {
document->removeText(range);
}
connectSlots(document);
}
}
/**
* Connected to KTextEditor::Document::textInserted(), which is emitted on all
* insertion changes. Line text and line breaks are emitted separately by
* KatePart, and pasted text gets the same treatment as manually entered text.
* Because of that, we discard paste operations by only remembering the
* insertion status for the last line that was entered.
*/
void AutoBracePluginDocument::slotTextInserted(KTextEditor::Document *document,
const KTextEditor::Range& range)
{
// Fill brackets map matching opening and closing brackets.
QMap brackets;
brackets["("] = ")";
brackets["["] = "]";
// latex wants {, too
if (document->mode() == "LaTeX")
brackets["{"] = "}";
// List of Tokens after which an automatic bracket expanion
// is allowed.
const static QStringList allowedNextToken = QStringList() << "]" << ")" << ","
<< "." << ";" << "\n" << "\t" << " " << "";
const QString text = document->text(range);
// An insertion operation cancels any last range removal
// operation
m_lastRange = KTextEditor::Range::invalid();
// Make sure to handle only:
// 1.) New lines after { (brace openers)
// 2.) Opening braces like '(' and '['
// 3.) Quotation marks like " and '
// Handle brace openers
if (text == "\n") {
// Remember this position as insertion candidate.
// We don't directly insert this here because of KatePart specifics:
// a) Setting the cursor position crashes at this point, and
// b) textChanged() only gets called once per edit operation, so we can
// ignore the same braces when they're being inserted via paste.
if (isInsertionCandidate(document, range.start().line())) {
m_insertionLine = range.end().line();
connect(document, SIGNAL(textChanged(KTextEditor::Document*)),
this, SLOT(slotTextChanged(KTextEditor::Document*)));
}
else {
m_insertionLine = 0;
}
}
// Opening brackets (defined in ctor)
else if (m_autoBrackets && brackets.contains(text)) {
// Only insert auto closing brackets if current text range
// is followed by one of the allowed next tokens.
if (allowedNextToken.contains(nextToken(document,range))) {
insertAutoBracket(document, range, brackets[text]);
}
}
// Check whether closing brackets are allowed.
// If a brace is not allowed remove it
// and set the cursor to the position after that text range.
// Bracket tests bases on this simple idea: A bracket can only be inserted
// if it is NOT followed by the same bracket. This results in overwriting closing brackets.
else if (m_autoBrackets && brackets.values().contains(text)) {
if (nextToken(document,range) == text) {
KTextEditor::Cursor saved = range.end();
document->removeText(range);
document->activeView()->setCursorPosition(saved);
}
}
// Insert auto-quotation marks (if enabled). Same idea as with brackets
// applies here: double quotation marks are eaten up and only inserted if not
// followed by the same quoation mark. Additionally automatic quotation marks
// are inserted only if NOT followed by a back slash (escaping character).
else if (m_autoQuotations && (text == "\"" || text == "\'") && previousToken(document, range) != "\\") {
const QString next = nextToken(document, range);
// Eat it if already there
if (next == text) {
KTextEditor::Cursor saved = range.end();
document->removeText(range);
document->activeView()->setCursorPosition(saved);
}
// Quotation marks only inserted if followed by one of the allowed
// next tokens and the number of marks in the insertion line is even
// (excluding the already inserted mark)
else if (allowedNextToken.contains(next)
&& (document->line(range.start().line()).count(text) % 2) ) {
insertAutoBracket(document, range, text);
}
}
}
/**
* Automatically inserts closing bracket. Cursor
* is placed in between the brackets.
* @param document Current document.
* @param range Inserted text range (by text-inserted slot)
* @param brace Brace to insert
*/
void AutoBracePluginDocument::insertAutoBracket(KTextEditor::Document *document,
const KTextEditor::Range& range,
const QString& brace) {
// Disconnect Slots to avoid check for redundant closing brackets
disconnectSlots(document);
// Save range to allow following remove operation to
// detect the corresponding closing bracket
m_lastRange = range;
KTextEditor::Cursor saved = range.end();
// Depending on brace, insert corresponding closing brace.
document->insertText(range.end(), brace);
document->activeView()->setCursorPosition(saved);
// Re-Enable insertion slot.
connectSlots(document);
}
/**
* Returns next character after specified text range in document.
* @param document Current document.
* @param range Inserted text range (by text-inserted slot)
* @return Next character after text range
*/
const QString AutoBracePluginDocument::nextToken(KTextEditor::Document* document, const KTextEditor::Range& range)
{
// Calculate range after insertion (exactly one character)
KTextEditor::Range afterRange(range.end(), range.end().line(), range.end().column()+1);
return (afterRange.isValid() ? document->text(afterRange) : "");
}
/**
* Returns previous character before specified text range in document.
* @param document Current document.
* @param range Inserted text range (by text-inserted slot)
* @return Next character after text range
*/
const QString AutoBracePluginDocument::previousToken(KTextEditor::Document* document, const KTextEditor::Range& range)
{
// Calculate range before insertion (exactly one character)
KTextEditor::Range beforeRange(range.start().line(), range.start().column()-1, range.start().line(),
range.start().column());
return (beforeRange.isValid() ? document->text(beforeRange) : "");
}
bool AutoBracePluginDocument::isInsertionCandidate(KTextEditor::Document *document, int openingBraceLine) {
QString line = document->line(openingBraceLine);
if (line.isEmpty() || !line.endsWith('{')) {
return false;
}
// Get the indentation prefix.
QRegExp rx("^(\\s+)");
QString indentation = (rx.indexIn(line) == -1) ? "" : rx.cap(1);
// Determine whether to insert a brace or not, depending on the indentation
// of the upcoming (non-empty) line.
bool isCandidate = true;
QString indentationLength = QString::number(indentation.length());
QString indentationLengthMinusOne = QString::number(indentation.length() - 1);
///TODO: make configurable
// these tokens must not start a line that is used to get the correct indendation width
QStringList forbiddenTokenList;
if ( line.contains("class") || line.contains("interface") || line.contains("struct") ) {
forbiddenTokenList << "private" << "public" << "protected";
if ( document->mode() == "C++" ) {
forbiddenTokenList << "signals" << "Q_SIGNALS";
} else {
// PHP and potentially others
forbiddenTokenList << "function";
}
}
if ( (document->mode() == "C++" || document->mode() == "C") && line.contains("namespace", Qt::CaseInsensitive) ) {
// C++ specific
forbiddenTokenList << "class" << "struct";
}
const QString forbiddenTokens = forbiddenTokenList.isEmpty() ? QLatin1String("") : QString(QLatin1String("(?!") + forbiddenTokenList.join(QLatin1String("|")) + QLatin1Char(')'));
for (int i = openingBraceLine + 1; i < document->lines(); ++i)
{
line = document->line(i);
if (line.trimmed().isEmpty()) {
continue; // Empty lines are not a reliable source of information.
}
if (indentation.length() == 0) {
// Inserting a brace is ok if there is a line (not starting with a
// brace) without indentation.
rx.setPattern("^(?=[^\\}\\s])"
// But it's not OK if the line starts with one of our forbidden tokens.
+ forbiddenTokens
);
}
else {
rx.setPattern("^(?:"
// Inserting a brace is ok if there is a closing brace with
// less indentation than the opener line.
"[\\s]{0," + indentationLengthMinusOne + "}\\}"
"|"
// Inserting a brace is ok if there is a line (not starting with a
// brace) with less or similar indentation as the original line.
"[\\s]{0," + indentationLength + "}(?=[^\\}\\s])"
// But it's not OK if the line starts with one of our forbidden tokens.
+ forbiddenTokens +
")"
);
}
if (rx.indexIn(line) == -1) {
// There is already a brace, or the line is indented more than the
// opener line (which means we expect a brace somewhere further down),
// or we found a forbidden token.
// So don't insert the brace, and just indent the line.
isCandidate = false;
}
// Quit the loop - a non-empty line always leads to a definitive decision.
break;
}
if (isCandidate) {
m_indentation = indentation;
// in C++ automatically add a semicolon after the closing brace when we create a new class/struct
if ( (document->mode() == "C++" || document->mode() == "C")
&& document->line(openingBraceLine).indexOf(QRegExp("(?:class|struct|enum)\\s+[^\\s]+(\\s*[:,](\\s*((public|protected|private)\\s+)?[^\\s]+))*\\s*\\{\\s*$")) != -1 )
{
m_withSemicolon = true;
} else {
m_withSemicolon = false;
}
}
return isCandidate;
}
#include "autobrace.moc"
diff --git a/part/syntax/data/modelines.xml b/part/syntax/data/modelines.xml
index d62df62c4..86c75b120 100644
--- a/part/syntax/data/modelines.xml
+++ b/part/syntax/data/modelines.xml
@@ -1,183 +1,184 @@
]>
- kate:
- - auto-brackets
+
+
- auto-insert-doxygen
- backspace-indents
- block-selection
- bom
- byte-order-marker
- folding-markers
- icon-border
- keep-extra-spaces
- line-numbers
- newline-at-eof
- overwrite-mode
- persistent-selection
- replace-tabs-save
- replace-tabs
- replace-trailing-space-save
- space-indent
- show-tabs
- tab-indents
- word-wrap
- wrap-cursor
- on
- true
- 1
- off
- false
- 0
- auto-center-lines
- font-size
- indent-width
- smart-home
- tab-width
- undo-steps
- word-wrap-column
- background-color
- bracket-highlight-color
- current-line-color
- default-dictionary
- dynamic-word-wrap
- eol
- end-of-line
- font
- hl
- icon-bar-color
- indent-mode
- scheme
- selection-color
- word-wrap-marker-color
- remove-trailing-spaces
- 0
- -
- none
- modified
- mod
- +
- 1
- all
- *
- 2
diff --git a/part/utils/kateconfig.cpp b/part/utils/kateconfig.cpp
index 0f8429c90..04bb65f8b 100644
--- a/part/utils/kateconfig.cpp
+++ b/part/utils/kateconfig.cpp
@@ -1,2427 +1,2404 @@
/* This file is part of the KDE libraries
Copyright (C) 2007, 2008 Matthew Woehlke
Copyright (C) 2003 Christoph Cullmann
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "kateconfig.h"
#include "kateglobal.h"
#include "katerenderer.h"
#include "kateview.h"
#include "katedocument.h"
#include "kateschema.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
//BEGIN KateConfig
KateConfig::KateConfig ()
: configSessionNumber (0), configIsRunning (false)
{
}
KateConfig::~KateConfig ()
{
}
void KateConfig::configStart ()
{
configSessionNumber++;
if (configSessionNumber > 1)
return;
configIsRunning = true;
}
void KateConfig::configEnd ()
{
if (configSessionNumber == 0)
return;
configSessionNumber--;
if (configSessionNumber > 0)
return;
configIsRunning = false;
updateConfig ();
}
//END
//BEGIN KateDocumentConfig
KateGlobalConfig *KateGlobalConfig::s_global = 0;
KateDocumentConfig *KateDocumentConfig::s_global = 0;
KateViewConfig *KateViewConfig::s_global = 0;
KateRendererConfig *KateRendererConfig::s_global = 0;
KateGlobalConfig::KateGlobalConfig ()
{
s_global = this;
// init with defaults from config or really hardcoded ones
KConfigGroup cg( KGlobal::config(), "Kate Part Defaults");
readConfig (cg);
}
KateGlobalConfig::~KateGlobalConfig ()
{
}
void KateGlobalConfig::readConfig (const KConfigGroup &config)
{
configStart ();
setProberType ((KEncodingProber::ProberType)config.readEntry("Encoding Prober Type", (int)KEncodingProber::Universal));
setFallbackEncoding (config.readEntry("Fallback Encoding", ""));
configEnd ();
}
void KateGlobalConfig::writeConfig (KConfigGroup &config)
{
config.writeEntry("Encoding Prober Type", (int)proberType());
config.writeEntry("Fallback Encoding", fallbackEncoding());
}
void KateGlobalConfig::updateConfig ()
{
}
void KateGlobalConfig::setProberType (KEncodingProber::ProberType proberType)
{
configStart ();
m_proberType = proberType;
configEnd ();
}
const QString &KateGlobalConfig::fallbackEncoding () const
{
return m_fallbackEncoding;
}
QTextCodec *KateGlobalConfig::fallbackCodec () const
{
if (m_fallbackEncoding.isEmpty())
return QTextCodec::codecForName("ISO 8859-15");
return KGlobal::charsets()->codecForName (m_fallbackEncoding);
}
bool KateGlobalConfig::setFallbackEncoding (const QString &encoding)
{
QTextCodec *codec;
bool found = false;
if (encoding.isEmpty())
{
codec = s_global->fallbackCodec();
found = true;
}
else
codec = KGlobal::charsets()->codecForName (encoding, found);
if (!found || !codec)
return false;
configStart ();
m_fallbackEncoding = codec->name();
configEnd ();
return true;
}
KateDocumentConfig::KateDocumentConfig ()
: m_indentationWidth (2),
m_tabWidth (8),
m_tabHandling (tabSmart),
m_configFlags (0),
m_wordWrapAt (80),
m_tabWidthSet (true),
m_indentationWidthSet (true),
m_indentationModeSet (true),
m_wordWrapSet (true),
m_wordWrapAtSet (true),
m_pageUpDownMovesCursorSet (true),
m_keepExtraSpacesSet (false),
m_indentPastedTextSet (false),
m_backspaceIndentsSet (false),
m_smartHomeSet (false),
- m_autoBracketsSet (false),
m_showTabsSet (false),
m_showSpacesSet (false),
m_replaceTabsDynSet (false),
m_removeSpacesSet (false),
m_newLineAtEofSet (false),
m_overwiteModeSet (false),
m_tabIndentsSet (false),
m_encodingSet (true),
m_eolSet (true),
m_bomSet (true),
m_allowEolDetectionSet (false),
m_allowSimpleModeSet (false),
m_backupFlagsSet (true),
m_searchDirConfigDepthSet (true),
m_backupPrefixSet (true),
m_backupSuffixSet (true),
m_swapFileNoSyncSet (true),
m_onTheFlySpellCheckSet (true),
m_lineLengthLimitSet (true),
m_doc (0)
{
s_global = this;
// init with defaults from config or really hardcoded ones
KConfigGroup cg( KGlobal::config(), "Kate Document Defaults");
readConfig (cg);
}
KateDocumentConfig::KateDocumentConfig (const KConfigGroup &cg)
: m_indentationWidth (2),
m_tabWidth (8),
m_tabHandling (tabSmart),
m_configFlags (0),
m_wordWrapAt (80),
m_tabWidthSet (true),
m_indentationWidthSet (true),
m_indentationModeSet (true),
m_wordWrapSet (true),
m_wordWrapAtSet (true),
m_pageUpDownMovesCursorSet (true),
m_keepExtraSpacesSet (false),
m_indentPastedTextSet (false),
m_backspaceIndentsSet (false),
m_smartHomeSet (false),
- m_autoBracketsSet (false),
m_showTabsSet (false),
m_showSpacesSet (false),
m_replaceTabsDynSet (false),
m_removeSpacesSet (false),
m_newLineAtEofSet (false),
m_overwiteModeSet (false),
m_tabIndentsSet (false),
m_encodingSet (true),
m_eolSet (true),
m_bomSet (true),
m_allowEolDetectionSet (false),
m_allowSimpleModeSet (false),
m_backupFlagsSet (true),
m_searchDirConfigDepthSet (true),
m_backupPrefixSet (true),
m_backupSuffixSet (true),
m_swapFileNoSyncSet (true),
m_onTheFlySpellCheckSet (true),
m_lineLengthLimitSet (true),
m_doc (0)
{
// init with defaults from config or really hardcoded ones
readConfig (cg);
}
KateDocumentConfig::KateDocumentConfig (KateDocument *doc)
: m_tabHandling (tabSmart),
m_configFlags (0),
m_tabWidthSet (false),
m_indentationWidthSet (false),
m_indentationModeSet (false),
m_wordWrapSet (false),
m_wordWrapAtSet (false),
m_pageUpDownMovesCursorSet (false),
m_keepExtraSpacesSet (false),
m_indentPastedTextSet (false),
m_backspaceIndentsSet (false),
m_smartHomeSet (false),
- m_autoBracketsSet (false),
m_showTabsSet (false),
m_showSpacesSet (false),
m_replaceTabsDynSet (false),
m_removeSpacesSet (false),
m_newLineAtEofSet (false),
m_overwiteModeSet (false),
m_tabIndentsSet (false),
m_encodingSet (false),
m_eolSet (false),
m_bomSet (false),
m_allowEolDetectionSet (false),
m_allowSimpleModeSet (false),
m_backupFlagsSet (false),
m_searchDirConfigDepthSet (false),
m_backupPrefixSet (false),
m_backupSuffixSet (false),
m_swapFileNoSyncSet (false),
m_onTheFlySpellCheckSet (false),
m_lineLengthLimitSet (false),
m_doc (doc)
{
}
KateDocumentConfig::~KateDocumentConfig ()
{
}
void KateDocumentConfig::readConfig (const KConfigGroup &config)
{
configStart ();
setTabWidth (config.readEntry("Tab Width", 8));
setIndentationWidth (config.readEntry("Indentation Width", 2));
setIndentationMode (config.readEntry("Indentation Mode", "normal"));
setTabHandling (config.readEntry("Tab Handling", int(KateDocumentConfig::tabSmart)));
setWordWrap (config.readEntry("Word Wrap", false));
setWordWrapAt (config.readEntry("Word Wrap Column", 80));
setPageUpDownMovesCursor (config.readEntry("PageUp/PageDown Moves Cursor", false));
setSmartHome (config.readEntry("Smart Home", true));
setShowTabs (config.readEntry("Show Tabs", true));
setTabIndents (config.readEntry("Indent On Tab", true));
setKeepExtraSpaces (config.readEntry("Keep Extra Spaces", false));
setIndentPastedText (config.readEntry("Indent On Text Paste", false));
setBackspaceIndents (config.readEntry("Indent On Backspace", false));
- setAutoBrackets (config.readEntry("Automatically Insert Closing Brackets", false));
setShowSpaces (config.readEntry("Show Spaces", false));
setReplaceTabsDyn (config.readEntry("ReplaceTabsDyn", false));
setRemoveSpaces (config.readEntry("Remove Spaces", 0));
setNewLineAtEof (config.readEntry("Newline At EOF", false));
setOvr (config.readEntry("Overwrite Mode", false));
setEncoding (config.readEntry("Encoding", ""));
setEol (config.readEntry("End of Line", 0));
setAllowEolDetection (config.readEntry("Allow End of Line Detection", true));
setBom (config.readEntry("BOM",false));
setAllowSimpleMode (config.readEntry("Allow Simple Mode", true));
setBackupFlags (config.readEntry("Backup Flags", 0));
setSearchDirConfigDepth (config.readEntry("Search Dir Config Depth", 3));
setBackupPrefix (config.readEntry("Backup Prefix", QString ("")));
setBackupSuffix (config.readEntry("Backup Suffix", QString ("~")));
setSwapFileNoSync (config.readEntry("No sync", false));
setOnTheFlySpellCheck(config.readEntry("On-The-Fly Spellcheck", false));
setLineLengthLimit(config.readEntry("Line Length Limit", 4096));
configEnd ();
}
void KateDocumentConfig::writeConfig (KConfigGroup &config)
{
config.writeEntry("Tab Width", tabWidth());
config.writeEntry("Indentation Width", indentationWidth());
config.writeEntry("Indentation Mode", indentationMode());
config.writeEntry("Tab Handling", tabHandling());
config.writeEntry("Word Wrap", wordWrap());
config.writeEntry("Word Wrap Column", wordWrapAt());
config.writeEntry("PageUp/PageDown Moves Cursor", pageUpDownMovesCursor());
config.writeEntry("Smart Home", smartHome());
config.writeEntry("Show Tabs", showTabs());
config.writeEntry("Indent On Tab", tabIndentsEnabled());
config.writeEntry("Keep Extra Spaces", keepExtraSpaces());
config.writeEntry("Indent On Text Paste", indentPastedText());
config.writeEntry("Indent On Backspace", backspaceIndents());
- config.writeEntry("Automatically Insert Closing Brackets", autoBrackets());
config.writeEntry("Show Spaces", showSpaces());
config.writeEntry("ReplaceTabsDyn", replaceTabsDyn());
config.writeEntry("Remove Spaces", removeSpaces());
config.writeEntry("Newline At EOF", newLineAtEof());
config.writeEntry("Overwrite Mode", ovr());
config.writeEntry("Encoding", encoding());
config.writeEntry("End of Line", eol());
config.writeEntry("Allow End of Line Detection", allowEolDetection());
config.writeEntry("BOM",bom());
config.writeEntry("Allow Simple Mode", allowSimpleMode());
config.writeEntry("Backup Flags", backupFlags());
config.writeEntry("Search Dir Config Depth", searchDirConfigDepth());
config.writeEntry("Backup Prefix", backupPrefix());
config.writeEntry("Backup Suffix", backupSuffix());
config.writeEntry("No sync", swapFileNoSync());
config.writeEntry("On-The-Fly Spellcheck", onTheFlySpellCheck());
config.writeEntry("Line Length Limit", lineLengthLimit());
}
void KateDocumentConfig::updateConfig ()
{
if (m_doc)
{
m_doc->updateConfig ();
return;
}
if (isGlobal())
{
for (int z=0; z < KateGlobal::self()->kateDocuments().size(); ++z)
(KateGlobal::self()->kateDocuments())[z]->updateConfig ();
}
}
int KateDocumentConfig::tabWidth () const
{
if (m_tabWidthSet || isGlobal())
return m_tabWidth;
return s_global->tabWidth();
}
void KateDocumentConfig::setTabWidth (int tabWidth)
{
if (tabWidth < 1)
return;
configStart ();
m_tabWidthSet = true;
m_tabWidth = tabWidth;
configEnd ();
}
int KateDocumentConfig::indentationWidth () const
{
if (m_indentationWidthSet || isGlobal())
return m_indentationWidth;
return s_global->indentationWidth();
}
void KateDocumentConfig::setIndentationWidth (int indentationWidth)
{
if (indentationWidth < 1)
return;
configStart ();
m_indentationWidthSet = true;
m_indentationWidth = indentationWidth;
configEnd ();
}
const QString &KateDocumentConfig::indentationMode () const
{
if (m_indentationModeSet || isGlobal())
return m_indentationMode;
return s_global->indentationMode();
}
void KateDocumentConfig::setIndentationMode (const QString &indentationMode)
{
configStart ();
m_indentationModeSet = true;
m_indentationMode = indentationMode;
configEnd ();
}
uint KateDocumentConfig::tabHandling () const
{
// This setting is purly a user preference,
// hence, there exists only the global setting.
if (isGlobal())
return m_tabHandling;
return s_global->tabHandling();
}
void KateDocumentConfig::setTabHandling (uint tabHandling)
{
configStart ();
m_tabHandling = tabHandling;
configEnd ();
}
bool KateDocumentConfig::wordWrap () const
{
if (m_wordWrapSet || isGlobal())
return m_wordWrap;
return s_global->wordWrap();
}
void KateDocumentConfig::setWordWrap (bool on)
{
configStart ();
m_wordWrapSet = true;
m_wordWrap = on;
configEnd ();
}
unsigned int KateDocumentConfig::wordWrapAt () const
{
if (m_wordWrapAtSet || isGlobal())
return m_wordWrapAt;
return s_global->wordWrapAt();
}
void KateDocumentConfig::setWordWrapAt (unsigned int col)
{
if (col < 1)
return;
configStart ();
m_wordWrapAtSet = true;
m_wordWrapAt = col;
configEnd ();
}
bool KateDocumentConfig::pageUpDownMovesCursor () const
{
if (m_pageUpDownMovesCursorSet || isGlobal())
return m_pageUpDownMovesCursor;
return s_global->pageUpDownMovesCursor();
}
void KateDocumentConfig::setPageUpDownMovesCursor (bool on)
{
configStart ();
m_pageUpDownMovesCursorSet = true;
m_pageUpDownMovesCursor = on;
configEnd ();
}
void KateDocumentConfig::setKeepExtraSpaces(bool on)
{
configStart ();
m_keepExtraSpacesSet = true;
m_keepExtraSpaces = on;
configEnd ();
}
bool KateDocumentConfig::keepExtraSpaces() const
{
if (m_keepExtraSpacesSet || isGlobal())
return m_keepExtraSpaces;
return s_global->keepExtraSpaces();
}
void KateDocumentConfig::setIndentPastedText(bool on)
{
configStart ();
m_indentPastedTextSet = true;
m_indentPastedText = on;
configEnd ();
}
bool KateDocumentConfig::indentPastedText() const
{
if (m_indentPastedTextSet || isGlobal())
return m_indentPastedText;
return s_global->indentPastedText();
}
void KateDocumentConfig::setBackspaceIndents(bool on)
{
configStart ();
m_backspaceIndentsSet = true;
m_backspaceIndents = on;
configEnd ();
}
bool KateDocumentConfig::backspaceIndents() const
{
if (m_backspaceIndentsSet || isGlobal())
return m_backspaceIndents;
return s_global->backspaceIndents();
}
void KateDocumentConfig::setSmartHome(bool on)
{
configStart ();
m_smartHomeSet = true;
m_smartHome = on;
configEnd ();
}
bool KateDocumentConfig::smartHome() const
{
if (m_smartHomeSet || isGlobal())
return m_smartHome;
return s_global->smartHome();
}
-void KateDocumentConfig::setAutoBrackets(bool on)
-{
- configStart ();
-
- m_autoBracketsSet = true;
- m_autoBrackets = on;
-
- configEnd ();
-}
-
-bool KateDocumentConfig::autoBrackets() const
-{
- if (m_autoBracketsSet || isGlobal())
- return m_autoBrackets;
-
- return s_global->autoBrackets();
-}
-
void KateDocumentConfig::setShowTabs(bool on)
{
configStart ();
m_showTabsSet = true;
m_showTabs = on;
configEnd ();
}
bool KateDocumentConfig::showTabs() const
{
if (m_showTabsSet || isGlobal())
return m_showTabs;
return s_global->showTabs();
}
void KateDocumentConfig::setShowSpaces(bool on)
{
configStart ();
m_showSpacesSet = true;
m_showSpaces = on;
configEnd ();
}
bool KateDocumentConfig::showSpaces() const
{
if (m_showSpacesSet || isGlobal())
return m_showSpaces;
return s_global->showSpaces();
}
void KateDocumentConfig::setReplaceTabsDyn(bool on)
{
configStart ();
m_replaceTabsDynSet = true;
m_replaceTabsDyn = on;
configEnd ();
}
bool KateDocumentConfig::replaceTabsDyn() const
{
if (m_replaceTabsDynSet || isGlobal())
return m_replaceTabsDyn;
return s_global->replaceTabsDyn();
}
void KateDocumentConfig::setRemoveSpaces(int triState)
{
configStart ();
m_removeSpacesSet = true;
m_removeSpaces = triState;
configEnd ();
}
int KateDocumentConfig::removeSpaces() const
{
if (m_removeSpacesSet || isGlobal())
return m_removeSpaces;
return s_global->removeSpaces();
}
void KateDocumentConfig::setNewLineAtEof (bool on)
{
configStart ();
m_newLineAtEofSet = true;
m_newLineAtEof = on;
configEnd ();
}
bool KateDocumentConfig::newLineAtEof () const
{
if (m_newLineAtEofSet || isGlobal())
return m_newLineAtEof;
return s_global->newLineAtEof();
}
void KateDocumentConfig::setOvr(bool on)
{
configStart ();
m_overwiteModeSet = true;
m_overwiteMode = on;
configEnd ();
}
bool KateDocumentConfig::ovr() const
{
if (m_overwiteModeSet || isGlobal())
return m_overwiteMode;
return s_global->ovr();
}
void KateDocumentConfig::setTabIndents(bool on)
{
configStart ();
m_tabIndentsSet = true;
m_tabIndents = on;
configEnd ();
}
bool KateDocumentConfig::tabIndentsEnabled() const
{
if (m_tabIndentsSet || isGlobal())
return m_tabIndents;
return s_global->tabIndentsEnabled();
}
const QString &KateDocumentConfig::encoding () const
{
if (m_encodingSet || isGlobal())
return m_encoding;
return s_global->encoding();
}
QTextCodec *KateDocumentConfig::codec () const
{
if (m_encodingSet || isGlobal())
{
if (m_encoding.isEmpty() && isGlobal())
return KGlobal::locale()->codecForEncoding();
else if (m_encoding.isEmpty())
return s_global->codec ();
else
return KGlobal::charsets()->codecForName (m_encoding);
}
return s_global->codec ();
}
bool KateDocumentConfig::setEncoding (const QString &encoding)
{
QTextCodec *codec;
bool found = false;
if (encoding.isEmpty())
{
codec = s_global->codec();
found=true;
}
else
codec = KGlobal::charsets()->codecForName (encoding, found);
if (!found || !codec)
return false;
configStart ();
m_encodingSet = true;
m_encoding = codec->name();
if (isGlobal())
KateGlobal::self()->setDefaultEncoding (m_encoding);
configEnd ();
return true;
}
bool KateDocumentConfig::isSetEncoding () const
{
return m_encodingSet;
}
int KateDocumentConfig::eol () const
{
if (m_eolSet || isGlobal())
return m_eol;
return s_global->eol();
}
QString KateDocumentConfig::eolString ()
{
if (eol() == KateDocumentConfig::eolUnix)
return QString ("\n");
else if (eol() == KateDocumentConfig::eolDos)
return QString ("\r\n");
else if (eol() == KateDocumentConfig::eolMac)
return QString ("\r");
return QString ("\n");
}
void KateDocumentConfig::setEol (int mode)
{
configStart ();
m_eolSet = true;
m_eol = mode;
configEnd ();
}
void KateDocumentConfig::setBom (bool bom)
{
configStart ();
m_bomSet = true;
m_bom = bom;
configEnd ();
}
bool KateDocumentConfig::bom() const
{
if (m_bomSet || isGlobal())
return m_bom;
return s_global->bom();
}
bool KateDocumentConfig::allowEolDetection () const
{
if (m_allowEolDetectionSet || isGlobal())
return m_allowEolDetection;
return s_global->allowEolDetection();
}
void KateDocumentConfig::setAllowEolDetection (bool on)
{
configStart ();
m_allowEolDetectionSet = true;
m_allowEolDetection = on;
configEnd ();
}
bool KateDocumentConfig::allowSimpleMode () const
{
if (m_allowSimpleModeSet || isGlobal())
return m_allowSimpleMode;
return s_global->allowSimpleMode();
}
void KateDocumentConfig::setAllowSimpleMode (bool on)
{
configStart ();
m_allowSimpleModeSet = true;
m_allowSimpleMode = on;
configEnd ();
}
uint KateDocumentConfig::backupFlags () const
{
if (m_backupFlagsSet || isGlobal())
return m_backupFlags;
return s_global->backupFlags();
}
void KateDocumentConfig::setBackupFlags (uint flags)
{
configStart ();
m_backupFlagsSet = true;
m_backupFlags = flags;
configEnd ();
}
const QString &KateDocumentConfig::backupPrefix () const
{
if (m_backupPrefixSet || isGlobal())
return m_backupPrefix;
return s_global->backupPrefix();
}
const QString &KateDocumentConfig::backupSuffix () const
{
if (m_backupSuffixSet || isGlobal())
return m_backupSuffix;
return s_global->backupSuffix();
}
void KateDocumentConfig::setBackupPrefix (const QString &prefix)
{
configStart ();
m_backupPrefixSet = true;
m_backupPrefix = prefix;
configEnd ();
}
void KateDocumentConfig::setBackupSuffix (const QString &suffix)
{
configStart ();
m_backupSuffixSet = true;
m_backupSuffix = suffix;
configEnd ();
}
bool KateDocumentConfig::swapFileNoSync() const
{
if (m_swapFileNoSyncSet || isGlobal())
return m_swapFileNoSync;
return s_global->swapFileNoSync();
}
void KateDocumentConfig::setSwapFileNoSync(bool on)
{
configStart();
m_swapFileNoSyncSet = true;
m_swapFileNoSync = on;
configEnd();
}
int KateDocumentConfig::searchDirConfigDepth () const
{
if (m_searchDirConfigDepthSet || isGlobal())
return m_searchDirConfigDepth;
return s_global->searchDirConfigDepth ();
}
void KateDocumentConfig::setSearchDirConfigDepth (int depth)
{
configStart ();
m_searchDirConfigDepthSet = true;
m_searchDirConfigDepth = depth;
configEnd ();
}
bool KateDocumentConfig::onTheFlySpellCheck() const
{
if(isGlobal()) {
// WARNING: this is slightly hackish, but it's currently the only way to
// do it, see also the KTextEdit class
KConfigGroup configGroup(KGlobal::config(), "Spelling");
return configGroup.readEntry("checkerEnabledByDefault", false);
}
if (m_onTheFlySpellCheckSet) {
return m_onTheFlySpellCheck;
}
return s_global->onTheFlySpellCheck();
}
void KateDocumentConfig::setOnTheFlySpellCheck(bool on)
{
configStart ();
m_onTheFlySpellCheckSet = true;
m_onTheFlySpellCheck = on;
configEnd ();
}
int KateDocumentConfig::lineLengthLimit() const
{
if (m_lineLengthLimitSet || isGlobal())
return m_lineLengthLimit;
return s_global->lineLengthLimit();
}
void KateDocumentConfig::setLineLengthLimit(int lineLengthLimit)
{
configStart();
m_lineLengthLimitSet = true;
m_lineLengthLimit = lineLengthLimit;
configEnd();
}
//END
//BEGIN KateViewConfig
KateViewConfig::KateViewConfig ()
:
m_dynWordWrapSet (true),
m_dynWordWrapIndicatorsSet (true),
m_dynWordWrapAlignIndentSet (true),
m_lineNumbersSet (true),
m_scrollBarMarksSet (true),
m_scrollBarMiniMapSet (true),
m_scrollBarMiniMapAllSet (true),
m_scrollBarMiniMapWidthSet (true),
m_iconBarSet (true),
m_foldingBarSet (true),
m_lineModificationSet (true),
m_bookmarkSortSet (true),
m_autoCenterLinesSet (true),
m_searchFlagsSet (true),
m_defaultMarkTypeSet (true),
m_persistentSelectionSet (true),
m_viInputModeSet (true),
m_viInputModeStealKeysSet (true),
m_automaticCompletionInvocationSet (true),
m_wordCompletionSet (true),
m_wordCompletionMinimalWordLengthSet (true),
m_smartCopyCutSet (true),
m_scrollPastEndSet (true),
m_allowMarkMenu (true),
m_view (0)
{
s_global = this;
// init with defaults from config or really hardcoded ones
KConfigGroup config( KGlobal::config(), "Kate View Defaults");
readConfig (config);
}
KateViewConfig::KateViewConfig (KateView *view)
:
m_searchFlags (PowerModePlainText),
m_maxHistorySize (100),
m_dynWordWrapSet (false),
m_dynWordWrapIndicatorsSet (false),
m_dynWordWrapAlignIndentSet (false),
m_lineNumbersSet (false),
m_scrollBarMarksSet (false),
m_scrollBarMiniMapSet (false),
m_scrollBarMiniMapAllSet (false),
m_scrollBarMiniMapWidthSet (false),
m_iconBarSet (false),
m_foldingBarSet (false),
m_lineModificationSet (false),
m_bookmarkSortSet (false),
m_autoCenterLinesSet (false),
m_searchFlagsSet (false),
m_defaultMarkTypeSet (false),
m_persistentSelectionSet (false),
m_viInputModeSet (false),
m_viInputModeStealKeysSet (false),
m_automaticCompletionInvocationSet (false),
m_wordCompletionSet (false),
m_wordCompletionMinimalWordLengthSet (false),
m_smartCopyCutSet (false),
m_scrollPastEndSet (false),
m_allowMarkMenu (true),
m_view (view)
{
}
KateViewConfig::~KateViewConfig ()
{
}
// TODO Extract more keys to constants for maintainability
static const char * const KEY_SEARCH_REPLACE_FLAGS = "Search/Replace Flags";
static const char * const KEY_PATTERN_HISTORY = "Search Pattern History";
static const char * const KEY_REPLACEMENT_HISTORY = "Replacement Text History";
void KateViewConfig::readConfig ( const KConfigGroup &config)
{
configStart ();
// default off again, until this is usable for large size documents
setDynWordWrap (config.readEntry( "Dynamic Word Wrap", false ));
setDynWordWrapIndicators (config.readEntry( "Dynamic Word Wrap Indicators", 1 ));
setDynWordWrapAlignIndent (config.readEntry( "Dynamic Word Wrap Align Indent", 80 ));
setLineNumbers (config.readEntry( "Line Numbers", false));
setScrollBarMarks (config.readEntry( "Scroll Bar Marks", false));
setScrollBarMiniMap (config.readEntry( "Scroll Bar Mini Map", false));
setScrollBarMiniMapAll (config.readEntry( "Scroll Bar Mini Map All", false));
setScrollBarMiniMapWidth (config.readEntry( "Scroll Bar Mini Map Width", 60));
setIconBar (config.readEntry( "Icon Bar", false ));
setFoldingBar (config.readEntry( "Folding Bar", true));
setLineModification (config.readEntry( "Line Modification", false));
setBookmarkSort (config.readEntry( "Bookmark Menu Sorting", 0 ));
setAutoCenterLines (config.readEntry( "Auto Center Lines", 0 ));
setSearchFlags(config.readEntry(KEY_SEARCH_REPLACE_FLAGS,
IncFromCursor|PowerMatchCase|PowerModePlainText));
m_maxHistorySize = config.readEntry("Maximum Search History Size", 100);
setDefaultMarkType (config.readEntry( "Default Mark Type", int(KTextEditor::MarkInterface::markType01) ));
setAllowMarkMenu (config.readEntry( "Allow Mark Menu", true ));
setPersistentSelection (config.readEntry( "Persistent Selection", false ));
setViInputMode (config.readEntry( "Vi Input Mode", false));
setViInputModeStealKeys (config.readEntry( "Vi Input Mode Steal Keys", false));
setViInputModeHideStatusBar (config.readEntry( "Vi Input Mode Hide Status Bar", false));
setAutomaticCompletionInvocation (config.readEntry( "Auto Completion", true ));
setWordCompletion (config.readEntry( "Word Completion", true ));
setWordCompletionMinimalWordLength (config.readEntry( "Word Completion Minimal Word Length", 3 ));
setSmartCopyCut (config.readEntry( "Smart Copy Cut", false ));
setScrollPastEnd (config.readEntry( "Scroll Past End", false ));
if (isGlobal()) {
// Read search pattern history
QStringList patternHistory = config.readEntry(KEY_PATTERN_HISTORY, QStringList());
m_patternHistoryModel.setStringList(patternHistory);
// Read replacement text history
QStringList replacementHistory = config.readEntry(KEY_REPLACEMENT_HISTORY, QStringList());
m_replacementHistoryModel.setStringList(replacementHistory);
}
configEnd ();
}
void KateViewConfig::writeConfig (KConfigGroup &config)
{
config.writeEntry( "Dynamic Word Wrap", dynWordWrap() );
config.writeEntry( "Dynamic Word Wrap Indicators", dynWordWrapIndicators() );
config.writeEntry( "Dynamic Word Wrap Align Indent", dynWordWrapAlignIndent() );
config.writeEntry( "Line Numbers", lineNumbers() );
config.writeEntry( "Scroll Bar Marks", scrollBarMarks() );
config.writeEntry( "Scroll Bar Mini Map", scrollBarMiniMap() );
config.writeEntry( "Scroll Bar Mini Map All", scrollBarMiniMapAll() );
config.writeEntry( "Scroll Bar Mini Map Width", scrollBarMiniMapWidth() );
config.writeEntry( "Icon Bar", iconBar() );
config.writeEntry( "Folding Bar", foldingBar() );
config.writeEntry( "Line Modification", lineModification() );
config.writeEntry( "Bookmark Menu Sorting", bookmarkSort() );
config.writeEntry( "Auto Center Lines", autoCenterLines() );
config.writeEntry(KEY_SEARCH_REPLACE_FLAGS, int(searchFlags()));
config.writeEntry("Maximum Search History Size", m_maxHistorySize);
config.writeEntry("Default Mark Type", defaultMarkType());
config.writeEntry("Allow Mark Menu", allowMarkMenu());
config.writeEntry("Persistent Selection", persistentSelection());
config.writeEntry( "Auto Completion", automaticCompletionInvocation());
config.writeEntry( "Word Completion", wordCompletion());
config.writeEntry( "Word Completion Minimal Word Length", wordCompletionMinimalWordLength());
config.writeEntry( "Smart Copy Cut", smartCopyCut() );
config.writeEntry( "Scroll Past End" , scrollPastEnd() );
config.writeEntry( "Vi Input Mode", viInputMode());
config.writeEntry( "Vi Input Mode Steal Keys", viInputModeStealKeys());
config.writeEntry( "Vi Input Mode Hide Status Bar", viInputModeHideStatusBar());
if (isGlobal()) {
// Write search pattern history
config.writeEntry(KEY_PATTERN_HISTORY, m_patternHistoryModel.stringList());
// Write replacement text history
config.writeEntry(KEY_REPLACEMENT_HISTORY, m_replacementHistoryModel.stringList());
}
}
void KateViewConfig::updateConfig ()
{
if (m_view)
{
m_view->updateConfig ();
return;
}
if (isGlobal())
{
for (int z=0; z < KateGlobal::self()->views().size(); ++z)
(KateGlobal::self()->views())[z]->updateConfig ();
}
}
bool KateViewConfig::dynWordWrap () const
{
if (m_dynWordWrapSet || isGlobal())
return m_dynWordWrap;
return s_global->dynWordWrap();
}
void KateViewConfig::setDynWordWrap (bool wrap)
{
configStart ();
m_dynWordWrapSet = true;
m_dynWordWrap = wrap;
configEnd ();
}
int KateViewConfig::dynWordWrapIndicators () const
{
if (m_dynWordWrapIndicatorsSet || isGlobal())
return m_dynWordWrapIndicators;
return s_global->dynWordWrapIndicators();
}
void KateViewConfig::setDynWordWrapIndicators (int mode)
{
configStart ();
m_dynWordWrapIndicatorsSet = true;
m_dynWordWrapIndicators = qBound(0, mode, 80);
configEnd ();
}
int KateViewConfig::dynWordWrapAlignIndent () const
{
if (m_dynWordWrapAlignIndentSet || isGlobal())
return m_dynWordWrapAlignIndent;
return s_global->dynWordWrapAlignIndent();
}
void KateViewConfig::setDynWordWrapAlignIndent (int indent)
{
configStart ();
m_dynWordWrapAlignIndentSet = true;
m_dynWordWrapAlignIndent = indent;
configEnd ();
}
bool KateViewConfig::lineNumbers () const
{
if (m_lineNumbersSet || isGlobal())
return m_lineNumbers;
return s_global->lineNumbers();
}
void KateViewConfig::setLineNumbers (bool on)
{
configStart ();
m_lineNumbersSet = true;
m_lineNumbers = on;
configEnd ();
}
bool KateViewConfig::scrollBarMarks () const
{
if (m_scrollBarMarksSet || isGlobal())
return m_scrollBarMarks;
return s_global->scrollBarMarks();
}
void KateViewConfig::setScrollBarMarks (bool on)
{
configStart ();
m_scrollBarMarksSet = true;
m_scrollBarMarks = on;
configEnd ();
}
bool KateViewConfig::scrollBarMiniMap () const
{
if (m_scrollBarMiniMapSet || isGlobal())
return m_scrollBarMiniMap;
return s_global->scrollBarMiniMap();
}
void KateViewConfig::setScrollBarMiniMap (bool on)
{
configStart ();
m_scrollBarMiniMapSet = true;
m_scrollBarMiniMap = on;
configEnd ();
}
bool KateViewConfig::scrollBarMiniMapAll () const
{
if (m_scrollBarMiniMapAllSet || isGlobal())
return m_scrollBarMiniMapAll;
return s_global->scrollBarMiniMapAll();
}
void KateViewConfig::setScrollBarMiniMapAll (bool on)
{
configStart ();
m_scrollBarMiniMapAllSet = true;
m_scrollBarMiniMapAll = on;
configEnd ();
}
int KateViewConfig::scrollBarMiniMapWidth () const
{
if (m_scrollBarMiniMapWidthSet || isGlobal())
return m_scrollBarMiniMapWidth;
return s_global->scrollBarMiniMapWidth();
}
void KateViewConfig::setScrollBarMiniMapWidth (int width)
{
configStart ();
m_scrollBarMiniMapWidthSet = true;
m_scrollBarMiniMapWidth = width;
configEnd ();
}
bool KateViewConfig::iconBar () const
{
if (m_iconBarSet || isGlobal())
return m_iconBar;
return s_global->iconBar();
}
void KateViewConfig::setIconBar (bool on)
{
configStart ();
m_iconBarSet = true;
m_iconBar = on;
configEnd ();
}
bool KateViewConfig::foldingBar () const
{
if (m_foldingBarSet || isGlobal())
return m_foldingBar;
return s_global->foldingBar();
}
void KateViewConfig::setFoldingBar (bool on)
{
configStart ();
m_foldingBarSet = true;
m_foldingBar = on;
configEnd ();
}
bool KateViewConfig::lineModification () const
{
if (m_lineModificationSet || isGlobal())
return m_lineModification;
return s_global->lineModification();
}
void KateViewConfig::setLineModification (bool on)
{
configStart ();
m_lineModificationSet = true;
m_lineModification = on;
configEnd ();
}
int KateViewConfig::bookmarkSort () const
{
if (m_bookmarkSortSet || isGlobal())
return m_bookmarkSort;
return s_global->bookmarkSort();
}
void KateViewConfig::setBookmarkSort (int mode)
{
configStart ();
m_bookmarkSortSet = true;
m_bookmarkSort = mode;
configEnd ();
}
int KateViewConfig::autoCenterLines () const
{
if (m_autoCenterLinesSet || isGlobal())
return m_autoCenterLines;
return s_global->autoCenterLines();
}
void KateViewConfig::setAutoCenterLines (int lines)
{
if (lines < 0)
return;
configStart ();
m_autoCenterLinesSet = true;
m_autoCenterLines = lines;
configEnd ();
}
long KateViewConfig::searchFlags () const
{
if (m_searchFlagsSet || isGlobal())
return m_searchFlags;
return s_global->searchFlags();
}
void KateViewConfig::setSearchFlags (long flags)
{
configStart ();
m_searchFlagsSet = true;
m_searchFlags = flags;
configEnd ();
}
QStringListModel *KateViewConfig::patternHistoryModel()
{
// always return global history
if (isGlobal())
return &m_patternHistoryModel;
return s_global->patternHistoryModel();
}
int KateViewConfig::maxHistorySize() const
{
return m_maxHistorySize;
}
QStringListModel *KateViewConfig::replacementHistoryModel()
{
// always return global history
if (isGlobal())
return &m_replacementHistoryModel;
return s_global->replacementHistoryModel();
}
uint KateViewConfig::defaultMarkType () const
{
if (m_defaultMarkTypeSet || isGlobal())
return m_defaultMarkType;
return s_global->defaultMarkType();
}
void KateViewConfig::setDefaultMarkType (uint type)
{
configStart ();
m_defaultMarkTypeSet = true;
m_defaultMarkType = type;
configEnd ();
}
bool KateViewConfig::allowMarkMenu() const
{
return m_allowMarkMenu;
}
void KateViewConfig::setAllowMarkMenu (bool allow)
{
m_allowMarkMenu = allow;
}
bool KateViewConfig::persistentSelection () const
{
if (m_persistentSelectionSet || isGlobal())
return m_persistentSelection;
return s_global->persistentSelection();
}
void KateViewConfig::setPersistentSelection (bool on)
{
configStart ();
m_persistentSelectionSet = true;
m_persistentSelection = on;
configEnd ();
}
bool KateViewConfig::viInputMode () const
{
if (m_viInputModeSet || isGlobal())
return m_viInputMode;
return s_global->viInputMode();
}
void KateViewConfig::setViInputMode (bool on)
{
configStart ();
m_viInputModeSet = true;
m_viInputMode = on;
// update all views and show/hide the status bar
foreach (KateView* view, KateGlobal::self()->views() ) {
if (on && !m_viInputModeHideStatusBar) {
view->showViModeBar();
} else {
view->hideViModeBar();
}
}
// make sure to turn off edits mergin when leaving vi input mode
if (!on && m_view) {
m_view->doc()->setUndoMergeAllEdits(false);
}
configEnd ();
}
bool KateViewConfig::viInputModeStealKeys () const
{
if (m_viInputModeStealKeysSet || isGlobal())
return m_viInputModeStealKeys;
return s_global->viInputModeStealKeys();
}
void KateViewConfig::setViInputModeStealKeys (bool on)
{
configStart ();
m_viInputModeStealKeysSet = true;
m_viInputModeStealKeys = on;
configEnd ();
}
bool KateViewConfig::viInputModeHideStatusBar () const
{
if (m_viInputModeHideStatusBarSet || isGlobal())
return m_viInputModeHideStatusBar;
return s_global->viInputModeHideStatusBar();
}
void KateViewConfig::setViInputModeHideStatusBar (bool on)
{
configStart ();
m_viInputModeHideStatusBarSet = true;
m_viInputModeHideStatusBar = on;
// update all views and show/hide the status bar
foreach (KateView* view, KateGlobal::self()->views() ) {
if (on && m_viInputMode) {
view->hideViModeBar();
} else if (viInputMode()) {
view->showViModeBar();
}
}
configEnd ();
}
bool KateViewConfig::automaticCompletionInvocation () const
{
if (m_automaticCompletionInvocationSet || isGlobal())
return m_automaticCompletionInvocation;
return s_global->automaticCompletionInvocation();
}
void KateViewConfig::setAutomaticCompletionInvocation (bool on)
{
configStart ();
m_automaticCompletionInvocationSet = true;
m_automaticCompletionInvocation = on;
configEnd ();
}
bool KateViewConfig::wordCompletion () const
{
if (m_wordCompletionSet || isGlobal())
return m_wordCompletion;
return s_global->wordCompletion();
}
void KateViewConfig::setWordCompletion (bool on)
{
configStart ();
m_wordCompletionSet = true;
m_wordCompletion = on;
configEnd ();
}
int KateViewConfig::wordCompletionMinimalWordLength () const
{
if (m_wordCompletionMinimalWordLengthSet || isGlobal())
return m_wordCompletionMinimalWordLength;
return s_global->wordCompletionMinimalWordLength();
}
void KateViewConfig::setWordCompletionMinimalWordLength (int length)
{
configStart ();
m_wordCompletionMinimalWordLengthSet = true;
m_wordCompletionMinimalWordLength = length;
configEnd ();
}
bool KateViewConfig::smartCopyCut () const
{
if (m_smartCopyCutSet || isGlobal())
return m_smartCopyCut;
return s_global->smartCopyCut();
}
void KateViewConfig::setSmartCopyCut (bool on)
{
configStart ();
m_smartCopyCutSet = true;
m_smartCopyCut = on;
configEnd ();
}
bool KateViewConfig::scrollPastEnd () const
{
if (m_scrollPastEndSet || isGlobal())
return m_scrollPastEnd;
return s_global->scrollPastEnd();
}
void KateViewConfig::setScrollPastEnd (bool on)
{
configStart ();
m_scrollPastEndSet = true;
m_scrollPastEnd = on;
configEnd ();
}
//END
//BEGIN KateRendererConfig
KateRendererConfig::KateRendererConfig ()
: m_fontMetrics(QFont()),
m_lineMarkerColor (KTextEditor::MarkInterface::reservedMarkersCount()),
m_schemaSet (true),
m_fontSet (true),
m_wordWrapMarkerSet (true),
m_showIndentationLinesSet (true),
m_showWholeBracketExpressionSet (true),
m_backgroundColorSet (true),
m_selectionColorSet (true),
m_highlightedLineColorSet (true),
m_highlightedBracketColorSet (true),
m_wordWrapMarkerColorSet (true),
m_tabMarkerColorSet(true),
m_indentationLineColorSet(true),
m_iconBarColorSet(true),
m_foldingColorSet(true),
m_lineNumberColorSet (true),
m_separatorColorSet (true),
m_spellingMistakeLineColorSet (true),
m_templateColorsSet(true),
m_modifiedLineColorSet(true),
m_savedLineColorSet(true),
m_searchHighlightColorSet(true),
m_replaceHighlightColorSet(true),
m_lineMarkerColorSet (m_lineMarkerColor.size()),
m_renderer (0)
{
// init bitarray
m_lineMarkerColorSet.fill (true);
s_global = this;
// init with defaults from config or really hardcoded ones
KConfigGroup config(KGlobal::config(), "Kate Renderer Defaults");
readConfig (config);
}
KateRendererConfig::KateRendererConfig (KateRenderer *renderer)
: m_fontMetrics(QFont()),
m_lineMarkerColor (KTextEditor::MarkInterface::reservedMarkersCount()),
m_schemaSet (false),
m_fontSet (false),
m_wordWrapMarkerSet (false),
m_showIndentationLinesSet (false),
m_showWholeBracketExpressionSet (false),
m_backgroundColorSet (false),
m_selectionColorSet (false),
m_highlightedLineColorSet (false),
m_highlightedBracketColorSet (false),
m_wordWrapMarkerColorSet (false),
m_tabMarkerColorSet (false),
m_indentationLineColorSet (false),
m_iconBarColorSet (false),
m_foldingColorSet (false),
m_lineNumberColorSet (false),
m_separatorColorSet (false),
m_spellingMistakeLineColorSet (false),
m_templateColorsSet(false),
m_modifiedLineColorSet(false),
m_savedLineColorSet(false),
m_searchHighlightColorSet(false),
m_replaceHighlightColorSet(false),
m_lineMarkerColorSet (m_lineMarkerColor.size()),
m_renderer (renderer)
{
// init bitarray
m_lineMarkerColorSet.fill (false);
}
KateRendererConfig::~KateRendererConfig ()
{
}
void KateRendererConfig::readConfig (const KConfigGroup &config)
{
configStart ();
// "Normal" Schema MUST BE THERE, see global kateschemarc
setSchema (config.readEntry("Schema", "Normal"));
setWordWrapMarker (config.readEntry("Word Wrap Marker", false ));
setShowIndentationLines (config.readEntry( "Show Indentation Lines", false));
setShowWholeBracketExpression (config.readEntry( "Show Whole Bracket Expression", false));
configEnd ();
}
void KateRendererConfig::writeConfig (KConfigGroup& config)
{
config.writeEntry ("Schema", schema());
config.writeEntry("Word Wrap Marker", wordWrapMarker() );
config.writeEntry("Show Indentation Lines", showIndentationLines());
config.writeEntry("Show Whole Bracket Expression", showWholeBracketExpression());
}
void KateRendererConfig::updateConfig ()
{
if (m_renderer)
{
m_renderer->updateConfig ();
return;
}
if (isGlobal())
{
for (int z=0; z < KateGlobal::self()->views().size(); ++z)
(KateGlobal::self()->views())[z]->renderer()->updateConfig ();
}
}
const QString &KateRendererConfig::schema () const
{
if (m_schemaSet || isGlobal())
return m_schema;
return s_global->schema();
}
void KateRendererConfig::setSchema (const QString &schema)
{
configStart ();
m_schemaSet = true;
m_schema = schema;
setSchemaInternal( schema );
configEnd ();
}
void KateRendererConfig::reloadSchema()
{
if ( isGlobal() ) {
setSchemaInternal( m_schema );
foreach (KateView* view, KateGlobal::self()->views() )
view->renderer()->config()->reloadSchema();
}
else if ( m_renderer && m_schemaSet )
setSchemaInternal( m_schema );
}
void KateRendererConfig::setSchemaInternal( const QString &schema )
{
m_schemaSet = true;
m_schema = schema;
KConfigGroup config = KateGlobal::self()->schemaManager()->schema(schema);
// NOTE keep in sync with KateSchemaConfigColorTab::schemaChanged
KColorScheme schemeView(QPalette::Active, KColorScheme::View);
KColorScheme schemeWindow(QPalette::Active, KColorScheme::Window);
KColorScheme schemeSelection(QPalette::Active, KColorScheme::Selection);
QColor tmp0( schemeView.background().color() );
QColor tmp1( schemeSelection.background().color() );
QColor tmp2( schemeView.background(KColorScheme::AlternateBackground).color() );
// using KColorUtils::shade wasn't working really well
qreal bgLuma = KColorUtils::luma( tmp0 );
QColor tmp3( KColorUtils::tint(tmp0, schemeView.decoration(KColorScheme::HoverColor).color()) );
QColor tmp4( KColorUtils::shade( tmp0, bgLuma > 0.3 ? -0.15 : 0.03 ) );
QColor tmp5( KColorUtils::shade( tmp0, bgLuma > 0.7 ? -0.35 : 0.3 ) );
QColor tmp6( schemeWindow.background().color() );
QColor tmp7( schemeWindow.foreground().color() );
QColor tmp8( schemeView.foreground(KColorScheme::NegativeText).color() );
QColor tmp9( schemeView.background(KColorScheme::NegativeBackground).color() );
QColor tmp10( schemeView.background(KColorScheme::PositiveBackground).color() );
QColor tmp11( schemeView.background(KColorScheme::NeutralBackground).color() );
QColor tmp12( KColorScheme(QPalette::Inactive, KColorScheme::Selection).background().color() );
QColor tmp13( schemeView.foreground(KColorScheme::InactiveText).color() );
m_backgroundColor = config.readEntry("Color Background", tmp0);
m_backgroundColorSet = true;
m_selectionColor = config.readEntry("Color Selection", tmp1);
m_selectionColorSet = true;
m_highlightedLineColor = config.readEntry("Color Highlighted Line", tmp2);
m_highlightedLineColorSet = true;
m_highlightedBracketColor = config.readEntry("Color Highlighted Bracket", tmp3);
m_highlightedBracketColorSet = true;
m_wordWrapMarkerColor = config.readEntry("Color Word Wrap Marker", tmp4);
m_wordWrapMarkerColorSet = true;
m_tabMarkerColor = config.readEntry("Color Tab Marker", tmp5);
m_tabMarkerColorSet = true;
m_indentationLineColor = config.readEntry("Color Indentation Line", tmp5);
m_indentationLineColorSet = true;
m_iconBarColor = config.readEntry("Color Icon Bar", tmp6);
m_iconBarColorSet = true;
m_foldingColor = config.readEntry("Color Code Folding", tmp12);
m_foldingColorSet = true;
m_lineNumberColor = config.readEntry("Color Line Number", tmp7);
m_lineNumberColorSet = true;
m_separatorColor = config.readEntry("Color Separator", tmp13);
m_separatorColorSet = true;
m_spellingMistakeLineColor = config.readEntry("Color Spelling Mistake Line", tmp8);
m_spellingMistakeLineColorSet = true;
m_modifiedLineColor = config.readEntry("Color Modified Lines", tmp9);
m_modifiedLineColorSet = true;
m_savedLineColor = config.readEntry("Color Saved Lines", tmp10);
m_savedLineColorSet = true;
m_searchHighlightColor = config.readEntry("Color Search Highlight", QColor(Qt::yellow)); // tmp11);
m_searchHighlightColorSet = true;
m_replaceHighlightColor = config.readEntry("Color Replace Highlight", QColor(Qt::green)); // tmp10);
m_replaceHighlightColorSet = true;
// same std colors like in KateDocument::markColor
QColor mark[7];
mark[0] = Qt::blue;
mark[1] = Qt::red;
mark[2] = Qt::yellow;
mark[3] = Qt::magenta;
mark[4] = Qt::gray;
mark[5] = Qt::green;
mark[6] = Qt::red;
for (int i = 1; i <= KTextEditor::MarkInterface::reservedMarkersCount(); i++) {
QColor col = config.readEntry(QString("Color MarkType%1").arg(i), mark[i - 1]);
int index = i-1;
m_lineMarkerColorSet[index] = true;
m_lineMarkerColor[index] = col;
}
QFont f (KGlobalSettings::fixedFont());
m_font = config.readEntry("Font", f);
m_fontMetrics = QFontMetricsF (m_font);
m_fontSet = true;
QColor c = schemeWindow.background().color();
m_templateBackgroundColor = config.readEntry(QString("Color Template Background"), c);
c = schemeView.background(KColorScheme::PositiveBackground).color();
m_templateFocusedEditablePlaceholderColor = config.readEntry(QString("Color Template Focused Editable Placeholder"), c);
c = schemeWindow.background(KColorScheme::PositiveBackground).color();
m_templateEditablePlaceholderColor = config.readEntry(QString("Color Template Editable Placeholder"), c);
c = schemeView.background(KColorScheme::NegativeBackground).color();
m_templateNotEditablePlaceholderColor = config.readEntry(QString("Color Template Not Editable Placeholder"), c);
m_templateColorsSet=true;
}
const QFont& KateRendererConfig::font() const
{
if (m_fontSet || isGlobal())
return m_font;
return s_global->font();
}
const QFontMetricsF& KateRendererConfig::fontMetrics() const
{
if (m_fontSet || isGlobal())
return m_fontMetrics;
return s_global->fontMetrics();
}
void KateRendererConfig::setFont(const QFont &font)
{
configStart ();
m_fontSet = true;
m_font = font;
m_fontMetrics = QFontMetricsF (m_font);
configEnd ();
}
bool KateRendererConfig::wordWrapMarker () const
{
if (m_wordWrapMarkerSet || isGlobal())
return m_wordWrapMarker;
return s_global->wordWrapMarker();
}
void KateRendererConfig::setWordWrapMarker (bool on)
{
configStart ();
m_wordWrapMarkerSet = true;
m_wordWrapMarker = on;
configEnd ();
}
const QColor& KateRendererConfig::backgroundColor() const
{
if (m_backgroundColorSet || isGlobal())
return m_backgroundColor;
return s_global->backgroundColor();
}
void KateRendererConfig::setBackgroundColor (const QColor &col)
{
configStart ();
m_backgroundColorSet = true;
m_backgroundColor = col;
configEnd ();
}
const QColor& KateRendererConfig::selectionColor() const
{
if (m_selectionColorSet || isGlobal())
return m_selectionColor;
return s_global->selectionColor();
}
void KateRendererConfig::setSelectionColor (const QColor &col)
{
configStart ();
m_selectionColorSet = true;
m_selectionColor = col;
configEnd ();
}
const QColor& KateRendererConfig::highlightedLineColor() const
{
if (m_highlightedLineColorSet || isGlobal())
return m_highlightedLineColor;
return s_global->highlightedLineColor();
}
void KateRendererConfig::setHighlightedLineColor (const QColor &col)
{
configStart ();
m_highlightedLineColorSet = true;
m_highlightedLineColor = col;
configEnd ();
}
const QColor& KateRendererConfig::lineMarkerColor(KTextEditor::MarkInterface::MarkTypes type) const
{
int index = 0;
if (type > 0) { while((type >> index++) ^ 1) {} }
index -= 1;
if ( index < 0 || index >= KTextEditor::MarkInterface::reservedMarkersCount() )
{
static QColor dummy;
return dummy;
}
if (m_lineMarkerColorSet[index] || isGlobal())
return m_lineMarkerColor[index];
return s_global->lineMarkerColor( type );
}
void KateRendererConfig::setLineMarkerColor (const QColor &col, KTextEditor::MarkInterface::MarkTypes type)
{
int index = static_cast( log(static_cast(type)) / log(2.0) );
Q_ASSERT( index >= 0 && index < KTextEditor::MarkInterface::reservedMarkersCount() );
configStart ();
m_lineMarkerColorSet[index] = true;
m_lineMarkerColor[index] = col;
configEnd ();
}
const QColor& KateRendererConfig::highlightedBracketColor() const
{
if (m_highlightedBracketColorSet || isGlobal())
return m_highlightedBracketColor;
return s_global->highlightedBracketColor();
}
void KateRendererConfig::setHighlightedBracketColor (const QColor &col)
{
configStart ();
m_highlightedBracketColorSet = true;
m_highlightedBracketColor = col;
configEnd ();
}
const QColor& KateRendererConfig::wordWrapMarkerColor() const
{
if (m_wordWrapMarkerColorSet || isGlobal())
return m_wordWrapMarkerColor;
return s_global->wordWrapMarkerColor();
}
void KateRendererConfig::setWordWrapMarkerColor (const QColor &col)
{
configStart ();
m_wordWrapMarkerColorSet = true;
m_wordWrapMarkerColor = col;
configEnd ();
}
const QColor& KateRendererConfig::tabMarkerColor() const
{
if (m_tabMarkerColorSet || isGlobal())
return m_tabMarkerColor;
return s_global->tabMarkerColor();
}
void KateRendererConfig::setTabMarkerColor (const QColor &col)
{
configStart ();
m_tabMarkerColorSet = true;
m_tabMarkerColor = col;
configEnd ();
}
const QColor& KateRendererConfig::indentationLineColor() const
{
if (m_indentationLineColorSet || isGlobal())
return m_indentationLineColor;
return s_global->indentationLineColor();
}
void KateRendererConfig::setIndentationLineColor (const QColor &col)
{
configStart ();
m_indentationLineColorSet = true;
m_indentationLineColor = col;
configEnd ();
}
const QColor& KateRendererConfig::iconBarColor() const
{
if (m_iconBarColorSet || isGlobal())
return m_iconBarColor;
return s_global->iconBarColor();
}
void KateRendererConfig::setIconBarColor (const QColor &col)
{
configStart ();
m_iconBarColorSet = true;
m_iconBarColor = col;
configEnd ();
}
const QColor& KateRendererConfig::foldingColor() const
{
if (m_foldingColorSet || isGlobal())
return m_foldingColor;
return s_global->foldingColor();
}
void KateRendererConfig::setFoldingColor (const QColor &col)
{
configStart ();
m_foldingColorSet = true;
m_foldingColor = col;
configEnd ();
}
const QColor &KateRendererConfig::templateBackgroundColor() const
{
if (m_templateColorsSet || isGlobal())
return m_templateBackgroundColor;
return s_global->templateBackgroundColor();
}
const QColor &KateRendererConfig::templateEditablePlaceholderColor() const
{
if (m_templateColorsSet || isGlobal())
return m_templateEditablePlaceholderColor;
return s_global->templateEditablePlaceholderColor();
}
const QColor &KateRendererConfig::templateFocusedEditablePlaceholderColor() const
{
if (m_templateColorsSet || isGlobal())
return m_templateFocusedEditablePlaceholderColor;
return s_global->templateFocusedEditablePlaceholderColor();
}
const QColor &KateRendererConfig::templateNotEditablePlaceholderColor() const
{
if (m_templateColorsSet || isGlobal())
return m_templateNotEditablePlaceholderColor;
return s_global->templateNotEditablePlaceholderColor();
}
const QColor& KateRendererConfig::lineNumberColor() const
{
if (m_lineNumberColorSet || isGlobal())
return m_lineNumberColor;
return s_global->lineNumberColor();
}
void KateRendererConfig::setLineNumberColor (const QColor &col)
{
configStart ();
m_lineNumberColorSet = true;
m_lineNumberColor = col;
configEnd ();
}
const QColor& KateRendererConfig::separatorColor() const
{
if (m_separatorColorSet || isGlobal())
return m_separatorColor;
return s_global->separatorColor();
}
void KateRendererConfig::setSeparatorColor(const QColor& col)
{
configStart ();
m_separatorColorSet = true;
m_separatorColor = col;
configEnd ();
}
const QColor& KateRendererConfig::spellingMistakeLineColor() const
{
if (m_spellingMistakeLineColorSet || isGlobal())
return m_spellingMistakeLineColor;
return s_global->spellingMistakeLineColor();
}
void KateRendererConfig::setSpellingMistakeLineColor (const QColor &col)
{
configStart ();
m_spellingMistakeLineColorSet = true;
m_spellingMistakeLineColor = col;
configEnd ();
}
const QColor& KateRendererConfig::modifiedLineColor() const
{
if (m_modifiedLineColorSet || isGlobal())
return m_modifiedLineColor;
return s_global->modifiedLineColor();
}
void KateRendererConfig::setModifiedLineColor(const QColor &col)
{
configStart ();
m_modifiedLineColorSet = true;
m_modifiedLineColor = col;
configEnd ();
}
const QColor& KateRendererConfig::savedLineColor() const
{
if (m_savedLineColorSet || isGlobal())
return m_savedLineColor;
return s_global->savedLineColor();
}
void KateRendererConfig::setSavedLineColor(const QColor &col)
{
configStart ();
m_savedLineColorSet = true;
m_savedLineColor = col;
configEnd ();
}
const QColor& KateRendererConfig::searchHighlightColor() const
{
if (m_searchHighlightColorSet || isGlobal())
return m_searchHighlightColor;
return s_global->searchHighlightColor();
}
void KateRendererConfig::setSearchHighlightColor(const QColor &col)
{
configStart ();
m_searchHighlightColorSet = true;
m_searchHighlightColor = col;
configEnd ();
}
const QColor& KateRendererConfig::replaceHighlightColor() const
{
if (m_replaceHighlightColorSet || isGlobal())
return m_replaceHighlightColor;
return s_global->replaceHighlightColor();
}
void KateRendererConfig::setReplaceHighlightColor(const QColor &col)
{
configStart ();
m_replaceHighlightColorSet = true;
m_replaceHighlightColor = col;
configEnd ();
}
bool KateRendererConfig::showIndentationLines () const
{
if (m_showIndentationLinesSet || isGlobal())
return m_showIndentationLines;
return s_global->showIndentationLines();
}
void KateRendererConfig::setShowIndentationLines (bool on)
{
configStart ();
m_showIndentationLinesSet = true;
m_showIndentationLines = on;
configEnd ();
}
bool KateRendererConfig::showWholeBracketExpression () const
{
if (m_showWholeBracketExpressionSet || isGlobal())
return m_showWholeBracketExpression;
return s_global->showWholeBracketExpression();
}
void KateRendererConfig::setShowWholeBracketExpression (bool on)
{
configStart ();
m_showWholeBracketExpressionSet = true;
m_showWholeBracketExpression = on;
configEnd ();
}
//END
// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/part/utils/kateconfig.h b/part/utils/kateconfig.h
index 260377eb5..0dcd96e1b 100644
--- a/part/utils/kateconfig.h
+++ b/part/utils/kateconfig.h
@@ -1,780 +1,775 @@
/* This file is part of the KDE libraries
Copyright (C) 2003 Christoph Cullmann
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License version 2 as published by the Free Software Foundation.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#ifndef __KATE_CONFIG_H__
#define __KATE_CONFIG_H__
#include "katepartprivate_export.h"
#include
#include
#include
#include
#include
#include
#include
#include
class KConfigGroup;
class KateView;
class KateDocument;
class KateRenderer;
class KConfig;
class QTextCodec;
/**
* Base Class for the Kate Config Classes
*/
class KateConfig
{
public:
/**
* Default Constructor
*/
KateConfig ();
/**
* Virtual Destructor
*/
virtual ~KateConfig ();
public:
/**
* start some config changes
* this method is needed to init some kind of transaction
* for config changes, update will only be done once, at
* configEnd() call
*/
void configStart ();
/**
* end a config change transaction, update the concerned
* documents/views/renderers
*/
void configEnd ();
protected:
/**
* do the real update
*/
virtual void updateConfig () = 0;
private:
/**
* recursion depth
*/
uint configSessionNumber;
/**
* is a config session running
*/
bool configIsRunning;
};
class KATEPART_TESTS_EXPORT KateGlobalConfig : public KateConfig
{
private:
friend class KateGlobal;
/**
* only used in KateGlobal for the static global fallback !!!
*/
KateGlobalConfig ();
/**
* Destructor
*/
~KateGlobalConfig ();
public:
static KateGlobalConfig *global () { return s_global; }
public:
/**
* Read config from object
*/
void readConfig (const KConfigGroup &config);
/**
* Write config to object
*/
void writeConfig (KConfigGroup &config);
protected:
void updateConfig ();
public:
KEncodingProber::ProberType proberType () const
{
return m_proberType;
}
void setProberType (KEncodingProber::ProberType proberType);
QTextCodec *fallbackCodec () const;
const QString &fallbackEncoding () const;
bool setFallbackEncoding (const QString &encoding);
private:
KEncodingProber::ProberType m_proberType;
QString m_fallbackEncoding;
private:
static KateGlobalConfig *s_global;
};
class KATEPART_TESTS_EXPORT KateDocumentConfig : public KateConfig
{
private:
friend class KateGlobal;
KateDocumentConfig ();
public:
KateDocumentConfig (const KConfigGroup &cg);
/**
* Construct a DocumentConfig
*/
KateDocumentConfig (KateDocument *doc);
/**
* Cu DocumentConfig
*/
~KateDocumentConfig ();
inline static KateDocumentConfig *global () { return s_global; }
inline bool isGlobal () const { return (this == global()); }
public:
/**
* Read config from object
*/
void readConfig (const KConfigGroup &config);
/**
* Write config to object
*/
void writeConfig (KConfigGroup &config);
protected:
void updateConfig ();
public:
int tabWidth () const;
void setTabWidth (int tabWidth);
int indentationWidth () const;
void setIndentationWidth (int indentationWidth);
const QString &indentationMode () const;
void setIndentationMode (const QString &identationMode);
enum TabHandling
{
tabInsertsTab = 0,
tabIndents = 1,
tabSmart = 2 //!< indents in leading space, otherwise inserts tab
};
uint tabHandling () const;
void setTabHandling (uint tabHandling);
bool wordWrap () const;
void setWordWrap (bool on);
unsigned int wordWrapAt () const;
void setWordWrapAt (unsigned int col);
bool pageUpDownMovesCursor () const;
void setPageUpDownMovesCursor (bool on);
void setKeepExtraSpaces (bool on);
bool keepExtraSpaces () const;
void setIndentPastedText (bool on);
bool indentPastedText () const;
void setBackspaceIndents (bool on);
bool backspaceIndents () const;
void setSmartHome (bool on);
bool smartHome () const;
- void setAutoBrackets (bool on);
- bool autoBrackets () const;
-
void setShowTabs (bool on);
bool showTabs() const;
void setShowSpaces (bool on);
bool showSpaces() const;
void setReplaceTabsDyn (bool on);
bool replaceTabsDyn() const;
/**
* Remove trailing spaces on save.
* triState = 0: never remove trailing spaces
* triState = 1: remove trailing spaces of modified lines (line modification system)
* triState = 2: remove trailing spaces in entire document
*/
void setRemoveSpaces (int triState);
int removeSpaces () const;
void setNewLineAtEof (bool on);
bool newLineAtEof () const;
void setOvr (bool on);
bool ovr () const;
void setTabIndents (bool on);
bool tabIndentsEnabled () const;
QTextCodec *codec () const;
const QString &encoding () const;
bool setEncoding (const QString &encoding);
bool isSetEncoding () const;
enum Eol
{
eolUnix = 0,
eolDos = 1,
eolMac = 2
};
int eol () const;
QString eolString ();
void setEol (int mode);
bool bom () const;
void setBom(bool bom);
bool allowEolDetection () const;
void setAllowEolDetection (bool on);
bool allowSimpleMode () const;
void setAllowSimpleMode (bool on);
enum BackupFlags
{
LocalFiles=1,
RemoteFiles=2
};
uint backupFlags () const;
void setBackupFlags (uint flags);
const QString &backupPrefix () const;
void setBackupPrefix (const QString &prefix);
const QString &backupSuffix () const;
void setBackupSuffix (const QString &suffix);
bool swapFileNoSync() const;
void setSwapFileNoSync(bool on);
/**
* Should Kate Part search for dir wide config file
* and if, how depth?
* @return search depth (< 0 no search)
*/
int searchDirConfigDepth () const;
void setSearchDirConfigDepth (int depth);
bool onTheFlySpellCheck() const;
void setOnTheFlySpellCheck(bool on);
int lineLengthLimit() const;
void setLineLengthLimit(int limit);
private:
QString m_indentationMode;
int m_indentationWidth;
int m_tabWidth;
uint m_tabHandling;
uint m_configFlags;
int m_wordWrapAt;
bool m_wordWrap;
bool m_pageUpDownMovesCursor;
bool m_allowEolDetection;
bool m_allowSimpleMode;
int m_eol;
bool m_bom;
uint m_backupFlags;
int m_searchDirConfigDepth;
QString m_encoding;
QString m_backupPrefix;
QString m_backupSuffix;
bool m_swapFileNoSync;
bool m_onTheFlySpellCheck;
int m_lineLengthLimit;
bool m_tabWidthSet : 1;
bool m_indentationWidthSet : 1;
bool m_indentationModeSet : 1;
bool m_wordWrapSet : 1;
bool m_wordWrapAtSet : 1;
bool m_pageUpDownMovesCursorSet : 1;
bool m_keepExtraSpacesSet : 1;
bool m_keepExtraSpaces : 1;
bool m_indentPastedTextSet : 1;
bool m_indentPastedText : 1;
bool m_backspaceIndentsSet : 1;
bool m_backspaceIndents : 1;
bool m_smartHomeSet : 1;
bool m_smartHome : 1;
- bool m_autoBracketsSet : 1;
- bool m_autoBrackets : 1;
bool m_showTabsSet : 1;
bool m_showTabs : 1;
bool m_showSpacesSet : 1;
bool m_showSpaces : 1;
bool m_replaceTabsDynSet : 1;
bool m_replaceTabsDyn : 1;
bool m_removeSpacesSet : 1;
uint m_removeSpaces : 2;
bool m_newLineAtEofSet : 1;
bool m_newLineAtEof : 1;
bool m_overwiteModeSet : 1;
bool m_overwiteMode : 1;
bool m_tabIndentsSet : 1;
bool m_tabIndents : 1;
bool m_encodingSet : 1;
bool m_eolSet : 1;
bool m_bomSet :1;
bool m_allowEolDetectionSet : 1;
bool m_allowSimpleModeSet : 1;
bool m_backupFlagsSet : 1;
bool m_searchDirConfigDepthSet : 1;
bool m_backupPrefixSet : 1;
bool m_backupSuffixSet : 1;
bool m_swapFileNoSyncSet : 1;
bool m_onTheFlySpellCheckSet : 1;
bool m_lineLengthLimitSet : 1;
private:
static KateDocumentConfig *s_global;
KateDocument *m_doc;
};
class KATEPART_TESTS_EXPORT KateViewConfig : public KateConfig
{
private:
friend class KateGlobal;
/**
* only used in KateGlobal for the static global fallback !!!
*/
KateViewConfig ();
public:
/**
* Construct a DocumentConfig
*/
explicit KateViewConfig (KateView *view);
/**
* Cu DocumentConfig
*/
~KateViewConfig ();
inline static KateViewConfig *global () { return s_global; }
inline bool isGlobal () const { return (this == global()); }
public:
/**
* Read config from object
*/
void readConfig (const KConfigGroup &config);
/**
* Write config to object
*/
void writeConfig (KConfigGroup &config);
protected:
void updateConfig ();
public:
bool dynWordWrap () const;
void setDynWordWrap (bool wrap);
int dynWordWrapIndicators () const;
void setDynWordWrapIndicators (int mode);
int dynWordWrapAlignIndent () const;
void setDynWordWrapAlignIndent (int indent);
bool lineNumbers () const;
void setLineNumbers (bool on);
bool scrollBarMarks () const;
void setScrollBarMarks (bool on);
bool scrollBarMiniMap () const;
void setScrollBarMiniMap (bool on);
bool scrollBarMiniMapAll () const;
void setScrollBarMiniMapAll (bool on);
int scrollBarMiniMapWidth () const;
void setScrollBarMiniMapWidth (int width);
bool iconBar () const;
void setIconBar (bool on);
bool foldingBar () const;
void setFoldingBar (bool on);
bool lineModification() const;
void setLineModification(bool on);
int bookmarkSort () const;
void setBookmarkSort (int mode);
int autoCenterLines() const;
void setAutoCenterLines (int lines);
enum SearchFlags {
IncMatchCase = 1 << 0,
IncHighlightAll = 1 << 1,
IncFromCursor = 1 << 2,
PowerMatchCase = 1 << 3,
PowerHighlightAll = 1 << 4,
PowerFromCursor = 1 << 5,
// PowerSelectionOnly = 1 << 6, Better not save to file // Sebastian
PowerModePlainText = 1 << 7,
PowerModeWholeWords = 1 << 8,
PowerModeEscapeSequences = 1 << 9,
PowerModeRegularExpression = 1 << 10,
PowerUsePlaceholders = 1 << 11
};
long searchFlags () const;
void setSearchFlags (long flags);
int maxHistorySize() const;
QStringListModel *patternHistoryModel();
QStringListModel *replacementHistoryModel();
uint defaultMarkType () const;
void setDefaultMarkType (uint type);
bool allowMarkMenu () const;
void setAllowMarkMenu (bool allow);
bool persistentSelection () const;
void setPersistentSelection (bool on);
bool viInputMode () const;
void setViInputMode (bool on);
bool viInputModeStealKeys () const;
void setViInputModeStealKeys (bool on);
bool viInputModeHideStatusBar () const;
void setViInputModeHideStatusBar (bool on);
// Do we still need the enum and related functions below?
enum TextToSearch
{
Nowhere = 0,
SelectionOnly = 1,
SelectionWord = 2,
WordOnly = 3,
WordSelection = 4
};
bool automaticCompletionInvocation () const;
void setAutomaticCompletionInvocation (bool on);
bool wordCompletion () const;
void setWordCompletion (bool on);
int wordCompletionMinimalWordLength () const;
void setWordCompletionMinimalWordLength (int length);
bool smartCopyCut() const;
void setSmartCopyCut(bool on);
bool scrollPastEnd() const;
void setScrollPastEnd(bool on);
private:
bool m_dynWordWrap;
int m_dynWordWrapIndicators;
int m_dynWordWrapAlignIndent;
bool m_lineNumbers;
bool m_scrollBarMarks;
bool m_scrollBarMiniMap;
bool m_scrollBarMiniMapAll;
int m_scrollBarMiniMapWidth;
bool m_iconBar;
bool m_foldingBar;
bool m_lineModification;
int m_bookmarkSort;
int m_autoCenterLines;
long m_searchFlags;
int m_maxHistorySize;
QStringListModel m_patternHistoryModel;
QStringListModel m_replacementHistoryModel;
uint m_defaultMarkType;
bool m_persistentSelection;
bool m_viInputMode;
bool m_viInputModeStealKeys;
bool m_viInputModeHideStatusBar;
bool m_automaticCompletionInvocation;
bool m_wordCompletion;
int m_wordCompletionMinimalWordLength;
bool m_smartCopyCut;
bool m_scrollPastEnd;
bool m_dynWordWrapSet : 1;
bool m_dynWordWrapIndicatorsSet : 1;
bool m_dynWordWrapAlignIndentSet : 1;
bool m_lineNumbersSet : 1;
bool m_scrollBarMarksSet : 1;
bool m_scrollBarMiniMapSet : 1;
bool m_scrollBarMiniMapAllSet : 1;
bool m_scrollBarMiniMapWidthSet : 1;
bool m_iconBarSet : 1;
bool m_foldingBarSet : 1;
bool m_lineModificationSet : 1;
bool m_bookmarkSortSet : 1;
bool m_autoCenterLinesSet : 1;
bool m_searchFlagsSet : 1;
bool m_defaultMarkTypeSet : 1;
bool m_persistentSelectionSet : 1;
bool m_viInputModeSet : 1;
bool m_viInputModeStealKeysSet : 1;
bool m_viInputModeHideStatusBarSet : 1;
bool m_automaticCompletionInvocationSet : 1;
bool m_wordCompletionSet : 1;
bool m_wordCompletionMinimalWordLengthSet : 1;
bool m_smartCopyCutSet : 1;
bool m_scrollPastEndSet : 1;
bool m_allowMarkMenu : 1;
private:
static KateViewConfig *s_global;
KateView *m_view;
};
class KateRendererConfig : public KateConfig
{
private:
friend class KateGlobal;
/**
* only used in KateGlobal for the static global fallback !!!
*/
KateRendererConfig ();
public:
/**
* Construct a DocumentConfig
*/
KateRendererConfig (KateRenderer *renderer);
/**
* Cu DocumentConfig
*/
~KateRendererConfig ();
inline static KateRendererConfig *global () { return s_global; }
inline bool isGlobal () const { return (this == global()); }
public:
/**
* Read config from object
*/
void readConfig (const KConfigGroup &config);
/**
* Write config to object
*/
void writeConfig (KConfigGroup &config);
protected:
void updateConfig ();
public:
const QString &schema () const;
void setSchema (const QString &schema);
/**
* Reload the schema from the schema manager.
* For the global instance, have all other instances reload.
* Used by the schema config page to apply changes.
*/
void reloadSchema();
const QFont& font() const;
const QFontMetricsF& fontMetrics() const;
void setFont(const QFont &font);
bool wordWrapMarker () const;
void setWordWrapMarker (bool on);
const QColor& backgroundColor() const;
void setBackgroundColor (const QColor &col);
const QColor& selectionColor() const;
void setSelectionColor (const QColor &col);
const QColor& highlightedLineColor() const;
void setHighlightedLineColor (const QColor &col);
const QColor& lineMarkerColor(KTextEditor::MarkInterface::MarkTypes type = KTextEditor::MarkInterface::markType01) const; // markType01 == Bookmark
void setLineMarkerColor (const QColor &col, KTextEditor::MarkInterface::MarkTypes type = KTextEditor::MarkInterface::markType01);
const QColor& highlightedBracketColor() const;
void setHighlightedBracketColor (const QColor &col);
const QColor& wordWrapMarkerColor() const;
void setWordWrapMarkerColor (const QColor &col);
const QColor& tabMarkerColor() const;
void setTabMarkerColor (const QColor &col);
const QColor& indentationLineColor() const;
void setIndentationLineColor (const QColor &col);
const QColor& iconBarColor() const;
void setIconBarColor (const QColor &col);
const QColor& foldingColor() const;
void setFoldingColor (const QColor &col);
// the line number color is used for the line numbers on the left bar
const QColor& lineNumberColor() const;
void setLineNumberColor (const QColor &col);
// the color of the separator between line numbers and icon bar
const QColor& separatorColor() const;
void setSeparatorColor(const QColor &col);
const QColor& spellingMistakeLineColor() const;
void setSpellingMistakeLineColor (const QColor &col);
bool showIndentationLines () const;
void setShowIndentationLines (bool on);
bool showWholeBracketExpression () const;
void setShowWholeBracketExpression (bool on);
const QColor &templateBackgroundColor() const;
const QColor &templateEditablePlaceholderColor() const;
const QColor &templateFocusedEditablePlaceholderColor() const;
const QColor &templateNotEditablePlaceholderColor() const;
const QColor& modifiedLineColor() const;
void setModifiedLineColor(const QColor &col);
const QColor& savedLineColor() const;
void setSavedLineColor(const QColor &col);
const QColor& searchHighlightColor() const;
void setSearchHighlightColor(const QColor &col);
const QColor& replaceHighlightColor() const;
void setReplaceHighlightColor(const QColor &col);
private:
/**
* Read the schema properties from the config file.
*/
void setSchemaInternal(const QString &schema);
QString m_schema;
QFont m_font;
QFontMetricsF m_fontMetrics;
bool m_wordWrapMarker;
bool m_showIndentationLines;
bool m_showWholeBracketExpression;
QColor m_backgroundColor;
QColor m_selectionColor;
QColor m_highlightedLineColor;
QColor m_highlightedBracketColor;
QColor m_wordWrapMarkerColor;
QColor m_tabMarkerColor;
QColor m_indentationLineColor;
QColor m_iconBarColor;
QColor m_foldingColor;
QColor m_lineNumberColor;
QColor m_separatorColor;
QColor m_spellingMistakeLineColor;
QVector m_lineMarkerColor;
QColor m_templateBackgroundColor;
QColor m_templateEditablePlaceholderColor;
QColor m_templateFocusedEditablePlaceholderColor;
QColor m_templateNotEditablePlaceholderColor;
QColor m_modifiedLineColor;
QColor m_savedLineColor;
QColor m_searchHighlightColor;
QColor m_replaceHighlightColor;
bool m_schemaSet : 1;
bool m_fontSet : 1;
bool m_wordWrapMarkerSet : 1;
bool m_showIndentationLinesSet : 1;
bool m_showWholeBracketExpressionSet : 1;
bool m_backgroundColorSet : 1;
bool m_selectionColorSet : 1;
bool m_highlightedLineColorSet : 1;
bool m_highlightedBracketColorSet : 1;
bool m_wordWrapMarkerColorSet : 1;
bool m_tabMarkerColorSet : 1;
bool m_indentationLineColorSet : 1;
bool m_iconBarColorSet : 1;
bool m_foldingColorSet : 1;
bool m_lineNumberColorSet : 1;
bool m_separatorColorSet : 1;
bool m_spellingMistakeLineColorSet : 1;
bool m_templateColorsSet : 1;
bool m_modifiedLineColorSet : 1;
bool m_savedLineColorSet : 1;
bool m_searchHighlightColorSet : 1;
bool m_replaceHighlightColorSet : 1;
QBitArray m_lineMarkerColorSet;
private:
static KateRendererConfig *s_global;
KateRenderer *m_renderer;
};
#endif
// kate: space-indent on; indent-width 2; replace-tabs on;
diff --git a/part/variableeditor/variablelineedit.cpp b/part/variableeditor/variablelineedit.cpp
index 115f95f00..44f14b639 100644
--- a/part/variableeditor/variablelineedit.cpp
+++ b/part/variableeditor/variablelineedit.cpp
@@ -1,362 +1,357 @@
/* This file is part of the KDE project
Copyright (C) 2011 Dominik Haumann
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
License as published by the Free Software Foundation; either
version 2 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Library General Public License for more details.
You should have received a copy of the GNU Library General Public License
along with this library; see the file COPYING.LIB. If not, write to
the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Boston, MA 02110-1301, USA.
*/
#include "variablelineedit.h"
#include "variableitem.h"
#include "variablelistview.h"
#include "kateautoindent.h"
#include "katesyntaxmanager.h"
#include "kateschema.h"
#include "kateview.h"
#include "katedocument.h"
#include "kateglobal.h"
#include "katerenderer.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
VariableLineEdit::VariableLineEdit(QWidget* parent)
: QWidget(parent)
{
m_listview = 0;
QHBoxLayout* hl = new QHBoxLayout();
hl->setMargin(0);
hl->setSpacing(KDialog::spacingHint());
setLayout(hl);
m_lineedit = new QLineEdit(this);
m_button= new QToolButton(this);
m_button->setIcon(KIcon("tools-wizard"));
m_button->setToolTip(i18n("Show list of valid variables."));
hl->addWidget(m_lineedit);
hl->addWidget(m_button);
m_popup = new QFrame(0, Qt::Popup);
m_popup->setFrameStyle(QFrame::StyledPanel | QFrame::Raised);
QVBoxLayout* l = new QVBoxLayout(m_popup);
l->setSpacing(0);
l->setMargin(0);
m_popup->setLayout(l);
// forward text changed signal
connect(m_lineedit, SIGNAL(textChanged(QString)), this, SIGNAL(textChanged(QString)));
// open popup on button click
connect(m_button, SIGNAL(clicked()), this, SLOT(editVariables()));
}
VariableLineEdit::~VariableLineEdit()
{
}
void VariableLineEdit::editVariables()
{
m_listview = new VariableListView(m_lineedit->text(), m_popup);
addKateItems(m_listview);
connect(m_listview, SIGNAL(aboutToHide()), this, SLOT(updateVariableLine()));
m_popup->layout()->addWidget(m_listview);
if (layoutDirection() == Qt::LeftToRight) {
QPoint topLeft = mapToGlobal(m_lineedit->geometry().bottomLeft());
const int w = m_button->geometry().right() - m_lineedit->geometry().left();
const int h = 300; //(w * 2) / 4;
m_popup->setGeometry(QRect(topLeft, QSize(w, h)));
} else {
QPoint topLeft = mapToGlobal(m_button->geometry().bottomLeft());
const int w = m_lineedit->geometry().right() - m_button->geometry().left();
const int h = 300; //(w * 2) / 4;
m_popup->setGeometry(QRect(topLeft, QSize(w, h)));
}
m_popup->show();
}
void VariableLineEdit::updateVariableLine()
{
QString variables = m_listview->variableLine();
m_lineedit->setText(variables);
m_popup->layout()->removeWidget(m_listview);
m_listview->deleteLater();
m_listview = 0;
}
void VariableLineEdit::addKateItems(VariableListView* listview)
{
VariableItem* item = 0;
// If a current active doc is available
KateView* activeView = 0;
KateDocument* activeDoc = 0;
KateDocumentConfig* docConfig = KateDocumentConfig::global();
KateViewConfig* viewConfig = KateViewConfig::global();
KateRendererConfig *rendererConfig = KateRendererConfig::global();
KTextEditor::MdiContainer *iface = qobject_cast(KateGlobal::self()->container());
if (iface) {
activeView = qobject_cast(iface->activeView());
if (activeView) {
activeDoc = activeView->doc();
viewConfig = activeView->config();
docConfig = activeDoc->config();
rendererConfig = activeView->renderer()->config();
}
}
- // Add 'auto-brackets' to list
- item = new VariableBoolItem("auto-brackets", docConfig->autoBrackets());
- item->setHelpText(i18nc("short translation please", "Set auto insertion of brackets on or off."));
- listview->addItem(item);
-
// Add 'auto-center-lines' to list
item = new VariableIntItem("auto-center-lines", viewConfig->autoCenterLines());
static_cast(item)->setRange(1, 100);
item->setHelpText(i18nc("short translation please", "Set the number of autocenter lines."));
listview->addItem(item);
// Add 'auto-insert-doxygen' to list
item = new VariableBoolItem("auto-insert-doxygen", false);
item->setHelpText(i18nc("short translation please", "Auto insert asterisk in doxygen comments."));
listview->addItem(item);
// Add 'background-color' to list
item = new VariableColorItem("background-color", rendererConfig->backgroundColor());
item->setHelpText(i18nc("short translation please", "Set the document background color."));
listview->addItem(item);
// Add 'backspace-indents' to list
item = new VariableBoolItem("backspace-indents", docConfig->backspaceIndents());
item->setHelpText(i18nc("short translation please", "Pressing backspace in leading whitespace unindents."));
listview->addItem(item);
// Add 'block-selection' to list
item = new VariableBoolItem("block-selection", false);
if (activeView) static_cast(item)->setValue(activeView->blockSelectionMode());
item->setHelpText(i18nc("short translation please", "Enable block selection mode."));
listview->addItem(item);
// Add 'byte-order-marker' (bom) to list
item = new VariableBoolItem("byte-order-marker", docConfig->bom());
item->setHelpText(i18nc("short translation please", "Enable the byte order marker when saving unicode files."));
listview->addItem(item);
// Add 'bracket-highlight-color' to list
item = new VariableColorItem("bracket-highlight-color", rendererConfig->highlightedBracketColor());
item->setHelpText(i18nc("short translation please", "Set the color for the bracket highlight."));
listview->addItem(item);
// Add 'current-line-color' to list
item = new VariableColorItem("current-line-color", rendererConfig->highlightedLineColor());
item->setHelpText(i18nc("short translation please", "Set the background color for the current line."));
listview->addItem(item);
// Add 'default-dictionary' to list
Sonnet::Speller speller;
item = new VariableSpellCheckItem("default-dictionary", speller.defaultLanguage());
item->setHelpText(i18nc("short translation please", "Set the default dictionary used for spell checking."));
listview->addItem(item);
// Add 'dynamic-word-wrap' to list
item = new VariableBoolItem("dynamic-word-wrap", viewConfig->dynWordWrap());
item->setHelpText(i18nc("short translation please", "Enable dynamic word wrap of long lines."));
listview->addItem(item);
// Add 'end-of-line' (eol) to list
item = new VariableStringListItem("end-of-line", QStringList() << "unix" << "mac" << "dos", docConfig->eolString());
item->setHelpText(i18nc("short translation please", "Sets the end of line mode."));
listview->addItem(item);
// Add 'folding-markers' to list
item = new VariableBoolItem("folding-markers", viewConfig->foldingBar());
item->setHelpText(i18nc("short translation please", "Enable folding markers in the editor border."));
listview->addItem(item);
// Add 'font-size' to list
item = new VariableIntItem("font-size", rendererConfig->font().pointSize());
static_cast(item)->setRange(4, 128);
item->setHelpText(i18nc("short translation please", "Set the point size of the document font."));
listview->addItem(item);
// Add 'font' to list
item = new VariableFontItem("font", rendererConfig->font());
item->setHelpText(i18nc("short translation please", "Set the font of the document."));
listview->addItem(item);
// Add 'syntax' (hl) to list
/* Prepare list of highlighting modes */
const int count = KateHlManager::self()->highlights();
QStringList hl;
for (int z = 0; z < count; ++z)
hl << KateHlManager::self()->hlName(z);
item = new VariableStringListItem("syntax", hl, hl.at(0));
if (activeDoc) static_cast(item)->setValue(activeDoc->highlightingMode());
item->setHelpText(i18nc("short translation please", "Set the syntax highlighting."));
listview->addItem(item);
// Add 'icon-bar-color' to list
item = new VariableColorItem("icon-bar-color", rendererConfig->iconBarColor());
item->setHelpText(i18nc("short translation please", "Set the icon bar color."));
listview->addItem(item);
// Add 'icon-border' to list
item = new VariableBoolItem("icon-border", viewConfig->iconBar());
item->setHelpText(i18nc("short translation please", "Enable the icon border in the editor view."));
listview->addItem(item);
// Add 'indent-mode' to list
item = new VariableStringListItem("indent-mode", KateAutoIndent::listIdentifiers(), docConfig->indentationMode());
item->setHelpText(i18nc("short translation please", "Set the auto indentation style."));
listview->addItem(item);
// Add 'indent-width' to list
item = new VariableIntItem("indent-width", docConfig->indentationWidth());
static_cast(item)->setRange(1, 16);
item->setHelpText(i18nc("short translation please", "Set the indentation depth for each indent level."));
listview->addItem(item);
// Add 'keep-extra-spaces' to list
item = new VariableBoolItem("keep-extra-spaces", docConfig->keepExtraSpaces());
item->setHelpText(i18nc("short translation please", "Allow odd indentation level (no multiple of indent width)."));
listview->addItem(item);
// Add 'line-numbers' to list
item = new VariableBoolItem("line-numbers", viewConfig->lineNumbers());
item->setHelpText(i18nc("short translation please", "Show line numbers."));
listview->addItem(item);
// Add 'newline-at-eof' to list
item = new VariableBoolItem("newline-at-eof", docConfig->ovr());
item->setHelpText(i18nc("short translation please", "Insert newline at end of file on save."));
listview->addItem(item);
// Add 'overwrite-mode' to list
item = new VariableBoolItem("overwrite-mode", docConfig->ovr());
item->setHelpText(i18nc("short translation please", "Enable overwrite mode in the document."));
listview->addItem(item);
// Add 'persistent-selection' to list
item = new VariableBoolItem("persistent-selection", viewConfig->persistentSelection());
item->setHelpText(i18nc("short translation please", "Enable persistent text selection."));
listview->addItem(item);
// Add 'replace-tabs-save' to list
item = new VariableBoolItem("replace-tabs-save", false);
item->setHelpText(i18nc("short translation please", "Replace tabs with spaces when saving the document."));
listview->addItem(item);
// Add 'replace-tabs' to list
item = new VariableBoolItem("replace-tabs", docConfig->replaceTabsDyn());
item->setHelpText(i18nc("short translation please", "Replace tabs with spaces."));
listview->addItem(item);
// Add 'remove-trailing-spaces' to list
item = new VariableRemoveSpacesItem("remove-trailing-spaces", docConfig->removeSpaces());
item->setHelpText(i18nc("short translation please", "Remove trailing spaces when saving the document."));
listview->addItem(item);
// Add 'scheme' to list
QStringList schemas;
Q_FOREACH (const KateSchema &schema, KateGlobal::self()->schemaManager()->list())
schemas.append (schema.rawName);
item = new VariableStringListItem("scheme", schemas, rendererConfig->schema());
item->setHelpText(i18nc("short translation please", "Set the color scheme."));
listview->addItem(item);
// Add 'selection-color' to list
item = new VariableColorItem("selection-color", rendererConfig->selectionColor());
item->setHelpText(i18nc("short translation please", "Set the text selection color."));
listview->addItem(item);
// Add 'show-tabs' to list
item = new VariableBoolItem("show-tabs", docConfig->showTabs());
item->setHelpText(i18nc("short translation please", "Visualize tabs and trailing spaces."));
listview->addItem(item);
// Add 'smart-home' to list
item = new VariableBoolItem("smart-home", docConfig->smartHome());
item->setHelpText(i18nc("short translation please", "Enable smart home navigation."));
listview->addItem(item);
// Add 'tab-indents' to list
item = new VariableBoolItem("tab-indents", docConfig->tabIndentsEnabled());
item->setHelpText(i18nc("short translation please", "Pressing TAB key indents."));
listview->addItem(item);
// Add 'tab-width' to list
item = new VariableIntItem("tab-width", docConfig->tabWidth());
static_cast(item)->setRange(1, 16);
item->setHelpText(i18nc("short translation please", "Set the tab display width."));
listview->addItem(item);
// Add 'undo-steps' to list
item = new VariableIntItem("undo-steps", 0);
static_cast(item)->setRange(0, 100);
item->setHelpText(i18nc("short translation please", "Set the number of undo steps to remember (0 equals infinity)."));
listview->addItem(item);
// Add 'word-wrap-column' to list
item = new VariableIntItem("word-wrap-column", docConfig->wordWrapAt());
static_cast(item)->setRange(20, 200);
item->setHelpText(i18nc("short translation please", "Set the word wrap column."));
listview->addItem(item);
// Add 'word-wrap-marker-color' to list
item = new VariableColorItem("word-wrap-marker-color", rendererConfig->wordWrapMarkerColor());
item->setHelpText(i18nc("short translation please", "Set the word wrap marker color."));
listview->addItem(item);
// Add 'word-wrap' to list
item = new VariableBoolItem("word-wrap", docConfig->wordWrap());
item->setHelpText(i18nc("short translation please", "Enable word wrap while typing text."));
listview->addItem(item);
}
void VariableLineEdit::setText(const QString &text)
{
m_lineedit->setText(text);
}
void VariableLineEdit::clear()
{
m_lineedit->clear();
}
QString VariableLineEdit::text()
{
return m_lineedit->text();
}
// kate: indent-width 2; replace-tabs on;