File indexing completed on 2024-05-12 16:40:53

0001 /* This file is part of the KDE project
0002    Copyright (C) 2003 Lucijan Busch <lucijan@gmx.at>
0003    Copyright (C) 2004-2005 Jarosław Staniek <staniek@kde.org>
0004    Copyright (C) 2005 Cedric Pasteur <cedric.pasteur@free.fr>
0005 
0006    This program is free software; you can redistribute it and/or
0007    modify it under the terms of the GNU Library General Public
0008    License as published by the Free Software Foundation; either
0009    version 2 of the License, or (at your option) any later version.
0010 
0011    This program is distributed in the hope that it will be useful,
0012    but WITHOUT ANY WARRANTY; without even the implied warranty of
0013    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0014    Library General Public License for more details.
0015 
0016    You should have received a copy of the GNU Library General Public License
0017    along with this program; see the file COPYING.  If not, write to
0018    the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
0019  * Boston, MA 02110-1301, USA.
0020 */
0021 
0022 #include "kexieditor.h"
0023 
0024 #include <KexiMainWindowIface.h>
0025 #include <kexiutils/utils.h>
0026 
0027 #include <QList>
0028 #include <QMenu>
0029 #include <QVBoxLayout>
0030 
0031 //uncomment this to enable KTextEdit-based editor
0032 //#define KTEXTEDIT_BASED_TEXT_EDITOR
0033 
0034 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0035 # include <KTextEdit>
0036 #else
0037 # include <KTextEditor/Document>
0038 # include <KTextEditor/Editor>
0039 # include <KTextEditor/View>
0040 # include <KTextEditor/ConfigInterface>
0041 #endif
0042 
0043 /** Used for the shared action framework to redirect shared actions like
0044 copy and paste to the editor. */
0045 class KexiEditorSharedActionConnector : public KexiSharedActionConnector
0046 {
0047 public:
0048     KexiEditorSharedActionConnector(KexiActionProxy* proxy, QObject* obj)
0049             : KexiSharedActionConnector(proxy, obj) {
0050 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0051         plugSharedAction("edit_cut", SLOT(cut()));
0052         plugSharedAction("edit_copy", SLOT(copy()));
0053         plugSharedAction("edit_paste", SLOT(paste()));
0054         plugSharedAction("edit_clear", SLOT(clear()));
0055         plugSharedAction("edit_undo", SLOT(undo()));
0056         plugSharedAction("edit_redo", SLOT(redo()));
0057         plugSharedAction("edit_select_all", SLOT(selectAll()));
0058 #else
0059         QList<QByteArray> actions;
0060         actions << "edit_cut" << "edit_copy" << "edit_paste" << "edit_clear"
0061             << "edit_undo" << "edit_redo" << "edit_select_all";
0062 //! @todo KEXI3 plugSharedActionsToExternalGUI(actions, dynamic_cast<KXMLGUIClient*>(obj));
0063 #endif
0064     }
0065 };
0066 
0067 //! @internal
0068 class Q_DECL_HIDDEN KexiEditor::Private
0069 {
0070 public:
0071     Private() {}
0072 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0073     KTextEdit *view;
0074 #else
0075     KTextEditor::Document *doc;
0076     KTextEditor::View *view;
0077 #endif
0078 };
0079 
0080 KexiEditor::KexiEditor(QWidget *parent)
0081         : KexiView(parent)
0082         , d(new Private())
0083 {
0084 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0085     d->view = new KTextEdit("", QString(), this);
0086     //adjust font
0087     connect(d->view, SIGNAL(textChanged()), this, SIGNAL(textChanged()));
0088     QFont f("Courier");
0089     f.setStyleStrategy(QFont::PreferAntialias);
0090     f.setPointSize(d->view->font().pointSize());
0091     d->view->setFont(f);
0092     d->view->setCheckSpellingEnabled(false);
0093 #else
0094     QWidget *fr = new QWidget(this);
0095     QVBoxLayout *layout = new QVBoxLayout(fr);
0096     layout->setContentsMargins(0, 0, 0, 0);
0097 
0098     KTextEditor::Editor *editor = KTextEditor::Editor::instance();
0099     if (!editor)
0100         return;
0101 //! @todo error handling!
0102 
0103     d->doc = editor->createDocument(fr);
0104     if (!d->doc)
0105         return;
0106     d->view = d->doc->createView(fr);
0107     // suppresing default saving mechanism of KTextEditor
0108     d->view->action("file_save")->setEnabled(false);
0109     // set word wrap by default
0110     KTextEditor::ConfigInterface *configIface
0111             = qobject_cast<KTextEditor::ConfigInterface*>(d->view);
0112     configIface->setConfigValue("dynamic-word-wrap", true);
0113 
0114 //! @todo KEXI3 Q3PopupMenu *pop = qobject_cast<Q3PopupMenu*>( mainWin->factory()->container("edit", mainWin) );
0115 //! @todo KEXI3 d->view->setContextMenu(pop);
0116     d->view->setContextMenu(d->view->defaultContextMenu());
0117 
0118     connect(d->doc, SIGNAL(textChanged(KTextEditor::Document*)),
0119             this, SLOT(slotTextChanged(KTextEditor::Document*)));
0120 #endif
0121     KexiEditorSharedActionConnector c(this, d->view);
0122     d->view->installEventFilter(this);
0123 
0124     layout->addWidget(d->view);
0125     setViewWidget(fr, false/*!focus*/);
0126     setFocusProxy(d->view);
0127 }
0128 
0129 KexiEditor::~KexiEditor()
0130 {
0131     delete d;
0132 }
0133 
0134 void KexiEditor::updateActions(bool activated)
0135 {
0136     KexiView::updateActions(activated);
0137 }
0138 
0139 bool KexiEditor::isAdvancedEditor()
0140 {
0141 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0142     return false;
0143 #else
0144     return true;
0145 #endif
0146 }
0147 
0148 QString KexiEditor::text()
0149 {
0150 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0151     return d->view->text();
0152 #else
0153     if (!d->doc)
0154         return QString();
0155     return d->doc->text();
0156 #endif
0157 }
0158 
0159 void KexiEditor::setText(const QString &text)
0160 {
0161 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0162     const bool was_dirty = m_parentView ? m_parentView->idDirty() : idDirty();
0163     d->view->setText(text);
0164     setDirty(was_dirty);
0165 #else
0166     if (!d->doc)
0167         return;
0168     const bool was_dirty = isDirty();
0169     d->doc->setText(text);
0170     setDirty(was_dirty);
0171 #endif
0172 }
0173 
0174 void KexiEditor::setHighlightMode(const QString& highlightmodename)
0175 {
0176 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0177 #else
0178     if (!d->doc)
0179         return;
0180     QString n = highlightmodename;
0181     if (n == "javascript" || n == "qtscript")
0182         n = "JavaScript";
0183     else if (n.size() > 0)
0184         n = n[0].toLower() + n.mid(1);
0185     if (!d->doc->setMode(n))
0186         d->doc->setMode(QString()); // don't highlight
0187     if (!d->doc->setHighlightingMode(n))
0188         d->doc->setHighlightingMode(QString()); //hl->setHlMode(0); // 0=None, don't highlight anything.
0189 
0190     //! @todo Code from 3540345ea16477d05e84, these signals no longer exist
0191     // QMetaObject::invokeMethod(d->view, "modeChanged", Q_ARG(KTextEditor::Document*, d->doc));
0192     // QMetaObject::invokeMethod(d->view, "highlightingModeChanged", Q_ARG(KTextEditor::Document*, d->doc));
0193 #endif
0194 }
0195 
0196 void KexiEditor::slotConfigureEditor()
0197 {
0198 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0199 //! @todo show configuration...
0200 #else
0201     if (!d->doc)
0202         return;
0203     KTextEditor::Editor *editor = KTextEditor::Editor::instance();
0204     if (!editor)
0205         return;
0206     editor->configDialog(this);
0207 //! @todo use d->doc->editor()->writeConfig() or KTextEditor::ConfigInterface to save changes
0208 #endif
0209 }
0210 
0211 void KexiEditor::jump(int character)
0212 {
0213 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0214     const int numRows = d->view->paragraphs();
0215     int row = 0, col = 0;
0216     for (int ch = 0; row < numRows; row++) {
0217         const int rowLen = d->view->paragraphLength(row) + 1;
0218         if ((ch + rowLen) > character) {
0219             col = character - ch;
0220             break;
0221         }
0222         ch += rowLen;
0223     }
0224     d->view->setCursorPosition(row, col);
0225 #else
0226     if (!d->doc)
0227         return;
0228     const int numRows = d->doc->lines();
0229     int row = 0, col = 0;
0230     for (int ch = 0; row < numRows; row++) {
0231         const int rowLen = d->doc->lineLength(row) + 1;
0232         if ((ch + rowLen) > character) {
0233             col = character - ch;
0234             break;
0235         }
0236         ch += rowLen;
0237     }
0238     d->view->setCursorPosition(KTextEditor::Cursor(row, col));
0239 #endif
0240 }
0241 
0242 void KexiEditor::setCursorPosition(int line, int col)
0243 {
0244 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0245     d->view->setCursorPosition(line, col);
0246 #else
0247     d->view->setCursorPosition(KTextEditor::Cursor(line, col));
0248 #endif
0249 }
0250 
0251 void KexiEditor::clearUndoRedo()
0252 {
0253 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0254     //! @todo how to remove undo/redo from a KTextEdit?
0255 #else
0256 //! @todo KEXI3 KexiEditor::clearUndoRedo()
0257 #endif
0258 }
0259 
0260 void KexiEditor::slotTextChanged(KTextEditor::Document *)
0261 {
0262     emit textChanged();
0263 }
0264 
0265 QMenu* KexiEditor::defaultContextMenu()
0266 {
0267 #ifdef KTEXTEDIT_BASED_TEXT_EDITOR
0268     return d->view->createStandardContextMenu();
0269 #else
0270     QMenu* menu = d->view->defaultContextMenu();
0271     menu->addSeparator();
0272     menu->addAction(d->view->action("edit_find"));
0273     menu->addAction(d->view->action("edit_find_next"));
0274     menu->addAction(d->view->action("edit_find_prev"));
0275     menu->addAction(d->view->action("edit_replace"));
0276     menu->addAction(d->view->action("go_goto_line"));
0277     return menu;
0278 #endif
0279 }
0280