2 * Copyright (C) 2006 Nikolas Zimmermann <zimmermann@kde.org>
3 * Copyright (C) 2006 Zack Rusin <zack@kde.org>
4 * Copyright (C) 2006 Apple Computer, Inc.
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in the
15 * documentation and/or other materials provided with the distribution.
17 * THIS SOFTWARE IS PROVIDED BY APPLE COMPUTER, INC. ``AS IS'' AND ANY
18 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
20 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE COMPUTER, INC. OR
21 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
22 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
23 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
24 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
25 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 #include "EditorClientQt.h"
34 #include "qwebpage_p.h"
37 #include "EditCommandQt.h"
40 #include "FocusController.h"
42 #include "KeyboardCodes.h"
43 #include "KeyboardEvent.h"
45 #include "PlatformKeyboardEvent.h"
46 #include "NotImplemented.h"
53 #define methodDebug() qDebug("EditorClientQt: %s", __FUNCTION__);
55 static bool dumpEditingCallbacks = false;
56 static bool drt_run = false;
57 static bool acceptsEditing = true;
58 void QWEBKIT_EXPORT qt_dump_editing_callbacks(bool b)
60 dumpEditingCallbacks = b;
62 void QWEBKIT_EXPORT qt_drt_run(bool b)
67 void QWEBKIT_EXPORT qt_dump_set_accepts_editing(bool b)
73 static QString dumpPath(WebCore::Node *node)
75 QString str = node->nodeName();
77 WebCore::Node *parent = node->parentNode();
79 str.append(QLatin1String(" > "));
80 str.append(parent->nodeName());
81 parent = parent->parentNode();
86 static QString dumpRange(WebCore::Range *range)
89 return QLatin1String("(null)");
91 WebCore::ExceptionCode code;
92 str.sprintf("range from %ld of %ls to %ld of %ls",
93 range->startOffset(code), dumpPath(range->startContainer(code)).unicode(),
94 range->endOffset(code), dumpPath(range->endContainer(code)).unicode());
102 bool EditorClientQt::shouldDeleteRange(Range* range)
104 if (dumpEditingCallbacks)
105 printf("EDITING DELEGATE: shouldDeleteDOMRange:%s\n", dumpRange(range).toUtf8().constData());
110 bool EditorClientQt::shouldShowDeleteInterface(HTMLElement* element)
113 return element->className() == "needsDeletionUI";
117 bool EditorClientQt::isContinuousSpellCheckingEnabled()
122 bool EditorClientQt::isGrammarCheckingEnabled()
127 int EditorClientQt::spellCheckerDocumentTag()
132 bool EditorClientQt::shouldBeginEditing(WebCore::Range* range)
134 if (dumpEditingCallbacks)
135 printf("EDITING DELEGATE: shouldBeginEditingInDOMRange:%s\n", dumpRange(range).toUtf8().constData());
139 bool EditorClientQt::shouldEndEditing(WebCore::Range* range)
141 if (dumpEditingCallbacks)
142 printf("EDITING DELEGATE: shouldEndEditingInDOMRange:%s\n", dumpRange(range).toUtf8().constData());
146 bool EditorClientQt::shouldInsertText(const String& string, Range* range, EditorInsertAction action)
148 if (dumpEditingCallbacks) {
149 static const char *insertactionstring[] = {
150 "WebViewInsertActionTyped",
151 "WebViewInsertActionPasted",
152 "WebViewInsertActionDropped",
155 printf("EDITING DELEGATE: shouldInsertText:%s replacingDOMRange:%s givenAction:%s\n",
156 QString(string).toUtf8().constData(), dumpRange(range).toUtf8().constData(), insertactionstring[action]);
158 return acceptsEditing;
161 bool EditorClientQt::shouldChangeSelectedRange(Range* currentRange, Range* proposedRange, EAffinity selectionAffinity, bool stillSelecting)
163 if (dumpEditingCallbacks) {
164 static const char *affinitystring[] = {
165 "NSSelectionAffinityUpstream",
166 "NSSelectionAffinityDownstream"
168 static const char *boolstring[] = {
173 printf("EDITING DELEGATE: shouldChangeSelectedDOMRange:%s toDOMRange:%s affinity:%s stillSelecting:%s\n",
174 dumpRange(currentRange).toUtf8().constData(),
175 dumpRange(proposedRange).toUtf8().constData(),
176 affinitystring[selectionAffinity], boolstring[stillSelecting]);
178 return acceptsEditing;
181 bool EditorClientQt::shouldApplyStyle(WebCore::CSSStyleDeclaration* style,
182 WebCore::Range* range)
184 if (dumpEditingCallbacks)
185 printf("EDITING DELEGATE: shouldApplyStyle:%s toElementsInDOMRange:%s\n",
186 QString(style->cssText()).toUtf8().constData(), dumpRange(range).toUtf8().constData());
187 return acceptsEditing;
190 bool EditorClientQt::shouldMoveRangeAfterDelete(WebCore::Range*, WebCore::Range*)
196 void EditorClientQt::didBeginEditing()
198 if (dumpEditingCallbacks)
199 printf("EDITING DELEGATE: webViewDidBeginEditing:WebViewDidBeginEditingNotification\n");
203 void EditorClientQt::respondToChangedContents()
205 if (dumpEditingCallbacks)
206 printf("EDITING DELEGATE: webViewDidChange:WebViewDidChangeNotification\n");
207 m_page->d->modified = true;
209 m_page->d->updateEditorActions();
212 void EditorClientQt::respondToChangedSelection()
214 if (dumpEditingCallbacks)
215 printf("EDITING DELEGATE: webViewDidChangeSelection:WebViewDidChangeSelectionNotification\n");
216 // const Selection &selection = m_page->d->page->selection();
217 // char buffer[1024];
218 // selection.formatForDebugger(buffer, sizeof(buffer));
219 // printf("%s\n", buffer);
221 m_page->d->updateEditorActions();
222 emit m_page->selectionChanged();
223 emit m_page->microFocusChanged();
226 void EditorClientQt::didEndEditing()
228 if (dumpEditingCallbacks)
229 printf("EDITING DELEGATE: webViewDidEndEditing:WebViewDidEndEditingNotification\n");
233 void EditorClientQt::didWriteSelectionToPasteboard()
237 void EditorClientQt::didSetSelectionTypesForPasteboard()
241 bool EditorClientQt::selectWordBeforeMenuEvent()
247 bool EditorClientQt::isEditable()
249 return m_page->isEditable();
252 void EditorClientQt::registerCommandForUndo(WTF::PassRefPtr<WebCore::EditCommand> cmd)
254 Frame* frame = m_page->d->page->focusController()->focusedOrMainFrame();
255 if (m_inUndoRedo || (frame && !frame->editor()->lastEditCommand() /* HACK!! Don't recreate undos */)) {
258 m_page->undoStack()->push(new EditCommandQt(cmd));
261 void EditorClientQt::registerCommandForRedo(WTF::PassRefPtr<WebCore::EditCommand>)
265 void EditorClientQt::clearUndoRedoOperations()
267 return m_page->undoStack()->clear();
270 bool EditorClientQt::canUndo() const
272 return m_page->undoStack()->canUndo();
275 bool EditorClientQt::canRedo() const
277 return m_page->undoStack()->canRedo();
280 void EditorClientQt::undo()
283 m_page->undoStack()->undo();
284 m_inUndoRedo = false;
287 void EditorClientQt::redo()
290 m_page->undoStack()->redo();
291 m_inUndoRedo = false;
294 bool EditorClientQt::shouldInsertNode(Node* node, Range* range, EditorInsertAction action)
296 if (dumpEditingCallbacks) {
297 static const char *insertactionstring[] = {
298 "WebViewInsertActionTyped",
299 "WebViewInsertActionPasted",
300 "WebViewInsertActionDropped",
303 printf("EDITING DELEGATE: shouldInsertNode:%s replacingDOMRange:%s givenAction:%s\n", dumpPath(node).toUtf8().constData(),
304 dumpRange(range).toUtf8().constData(), insertactionstring[action]);
306 return acceptsEditing;
309 void EditorClientQt::pageDestroyed()
314 bool EditorClientQt::smartInsertDeleteEnabled()
320 void EditorClientQt::toggleContinuousSpellChecking()
325 void EditorClientQt::toggleGrammarChecking()
330 void EditorClientQt::handleKeyboardEvent(KeyboardEvent* event)
332 Frame* frame = m_page->d->page->focusController()->focusedOrMainFrame();
333 if (!frame || !frame->document()->focusedNode())
336 const PlatformKeyboardEvent* kevent = event->keyEvent();
337 if (!kevent || kevent->type() == PlatformKeyboardEvent::KeyUp)
340 Node* start = frame->selection()->start().node();
344 // FIXME: refactor all of this to use Actions or something like them
345 if (start->isContentEditable()) {
346 switch (kevent->windowsVirtualKeyCode()) {
348 frame->editor()->command("InsertLineBreak").execute();
351 frame->editor()->deleteWithDirection(SelectionController::BACKWARD,
352 CharacterGranularity, false, true);
355 frame->editor()->deleteWithDirection(SelectionController::FORWARD,
356 CharacterGranularity, false, true);
359 if (kevent->shiftKey())
360 frame->editor()->command("MoveLeftAndModifySelection").execute();
361 else frame->editor()->command("MoveLeft").execute();
364 if (kevent->shiftKey())
365 frame->editor()->command("MoveRightAndModifySelection").execute();
366 else frame->editor()->command("MoveRight").execute();
369 if (kevent->shiftKey())
370 frame->editor()->command("MoveUpAndModifySelection").execute();
371 else frame->editor()->command("MoveUp").execute();
374 if (kevent->shiftKey())
375 frame->editor()->command("MoveDownAndModifySelection").execute();
376 else frame->editor()->command("MoveDown").execute();
378 case VK_PRIOR: // PageUp
379 frame->editor()->command("MovePageUp").execute();
381 case VK_NEXT: // PageDown
382 frame->editor()->command("MovePageDown").execute();
387 if (kevent->type() != PlatformKeyboardEvent::KeyDown
388 && !kevent->ctrlKey() && !kevent->altKey() && !kevent->text().isEmpty()) {
389 frame->editor()->insertText(kevent->text(), event);
390 } else if (kevent->ctrlKey()) {
391 switch (kevent->windowsVirtualKeyCode()) {
393 frame->editor()->command("SelectAll").execute();
396 frame->editor()->command("ToggleBold").execute();
399 frame->editor()->command("Copy").execute();
402 frame->editor()->command("ToggleItalic").execute();
405 frame->editor()->command("Paste").execute();
408 frame->editor()->command("Cut").execute();
411 frame->editor()->command("Redo").execute();
414 frame->editor()->command("Undo").execute();
417 // catch combination AltGr+key or Ctrl+Alt+key
418 if (kevent->type() != PlatformKeyboardEvent::KeyDown && !kevent->text().isEmpty()) {
419 frame->editor()->insertText(kevent->text(), event);
427 switch (kevent->windowsVirtualKeyCode()) {
429 frame->editor()->command("MoveUp").execute();
432 frame->editor()->command("MoveDown").execute();
434 case VK_PRIOR: // PageUp
435 frame->editor()->command("MovePageUp").execute();
437 case VK_NEXT: // PageDown
438 frame->editor()->command("MovePageDown").execute();
441 if (kevent->ctrlKey())
442 frame->editor()->command("MoveToBeginningOfDocument").execute();
445 if (kevent->ctrlKey())
446 frame->editor()->command("MoveToEndOfDocument").execute();
449 if (kevent->ctrlKey()) {
450 switch (kevent->windowsVirtualKeyCode()) {
452 frame->editor()->command("SelectAll").execute();
454 case VK_C: case VK_X:
455 frame->editor()->command("Copy").execute();
463 event->setDefaultHandled();
466 void EditorClientQt::handleInputMethodKeydown(KeyboardEvent*)
470 EditorClientQt::EditorClientQt(QWebPage* page)
471 : m_page(page), m_editing(false), m_inUndoRedo(false)
475 void EditorClientQt::textFieldDidBeginEditing(Element*)
480 void EditorClientQt::textFieldDidEndEditing(Element*)
485 void EditorClientQt::textDidChangeInTextField(Element*)
489 bool EditorClientQt::doTextFieldCommandFromEvent(Element*, KeyboardEvent*)
494 void EditorClientQt::textWillBeDeletedInTextField(Element*)
498 void EditorClientQt::textDidChangeInTextArea(Element*)
502 void EditorClientQt::ignoreWordInSpellDocument(const String&)
507 void EditorClientQt::learnWord(const String&)
512 void EditorClientQt::checkSpellingOfString(const UChar*, int, int*, int*)
517 void EditorClientQt::checkGrammarOfString(const UChar*, int, Vector<GrammarDetail>&, int*, int*)
522 void EditorClientQt::updateSpellingUIWithGrammarString(const String&, const GrammarDetail&)
527 void EditorClientQt::updateSpellingUIWithMisspelledWord(const String&)
532 void EditorClientQt::showSpellingUI(bool)
537 bool EditorClientQt::spellingUIIsShowing()
543 void EditorClientQt::getGuessesForWord(const String&, Vector<String>&)
548 bool EditorClientQt::isEditing() const
553 void EditorClientQt::setInputMethodState(bool active)
555 QWidget *view = m_page->view();
557 view->setAttribute(Qt::WA_InputMethodEnabled, active);
558 emit m_page->microFocusChanged();