📄 kjs_debugwin.cpp
字号:
/* * This file is part of the KDE libraries * Copyright (C) 2000-2001 Harri Porten (porten@kde.org) * Copyright (C) 2001,2003 Peter Kelly (pmk@post.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; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */#include "kjs_debugwin.h"#include "kjs_proxy.h"#ifdef KJS_DEBUGGER#include <assert.h>#include <stdlib.h>#include <qlayout.h>#include <qpushbutton.h>#include <qtextedit.h>#include <qlistbox.h>#include <qmultilineedit.h>#include <qapplication.h>#include <qsplitter.h>#include <qcombobox.h>#include <qbitmap.h>#include <qwidgetlist.h>#include <qlabel.h>#include <qdatastream.h>#include <qcstring.h>#include <qpainter.h>#include <qscrollbar.h>#include <klocale.h>#include <kdebug.h>#include <kiconloader.h>#include <kglobal.h>#include <kmessagebox.h>#include <kguiitem.h>#include <kpopupmenu.h>#include <kmenubar.h>#include <kaction.h>#include <kactioncollection.h>#include <kglobalsettings.h>#include <kshortcut.h>#include <kconfig.h>#include <kconfigbase.h>#include <kapplication.h>#include <dcop/dcopclient.h>#include <kstringhandler.h> #include "kjs_dom.h"#include "kjs_binding.h"#include "khtml_part.h"#include "khtmlview.h"#include "khtml_pagecache.h"#include "khtml_settings.h"#include "khtml_factory.h"#include "misc/decoder.h"#include <kjs/ustring.h>#include <kjs/object.h>#include <kjs/function.h>#include <kjs/interpreter.h>using namespace KJS;using namespace khtml;SourceDisplay::SourceDisplay(KJSDebugWin *debugWin, QWidget *parent, const char *name) : QScrollView(parent,name), m_currentLine(-1), m_sourceFile(0), m_debugWin(debugWin), m_font(KGlobalSettings::fixedFont()){ verticalScrollBar()->setLineStep(QFontMetrics(m_font).height()); viewport()->setBackgroundMode(Qt::NoBackground); m_breakpointIcon = KGlobal::iconLoader()->loadIcon("stop",KIcon::Small);}SourceDisplay::~SourceDisplay(){ if (m_sourceFile) { m_sourceFile->deref(); m_sourceFile = 0L; }}void SourceDisplay::setSource(SourceFile *sourceFile){ if ( sourceFile ) sourceFile->ref(); if (m_sourceFile) m_sourceFile->deref(); m_sourceFile = sourceFile; if ( m_sourceFile ) m_sourceFile->ref(); if (!m_sourceFile || !m_debugWin->isVisible()) { return; } QString code = sourceFile->getCode(); const QChar *chars = code.unicode(); uint len = code.length(); QChar newLine('\n'); QChar cr('\r'); QChar tab('\t'); QString tabstr(" "); QString line; m_lines.clear(); int width = 0; QFontMetrics metrics(m_font); for (uint pos = 0; pos < len; pos++) { QChar c = chars[pos]; if (c == cr) { if (pos < len-1 && chars[pos+1] == newLine) continue; else c = newLine; } if (c == newLine) { m_lines.append(line); int lineWidth = metrics.width(line); if (lineWidth > width) width = lineWidth; line = ""; } else if (c == tab) { line += tabstr; } else { line += c; } } if (line.length()) { m_lines.append(line); int lineWidth = metrics.width(line); if (lineWidth > width) width = lineWidth; } int linenoDisplayWidth = metrics.width("888888"); resizeContents(linenoDisplayWidth+4+width,metrics.height()*m_lines.count()); update(); sourceFile->deref();}void SourceDisplay::setCurrentLine(int lineno, bool doCenter){ m_currentLine = lineno; if (doCenter && m_currentLine >= 0) { QFontMetrics metrics(m_font); int height = metrics.height(); center(0,height*m_currentLine+height/2); } updateContents();}void SourceDisplay::contentsMousePressEvent(QMouseEvent *e){ QScrollView::mouseDoubleClickEvent(e); QFontMetrics metrics(m_font); int lineno = e->y()/metrics.height(); emit lineDoubleClicked(lineno+1); // line numbers start from 1}void SourceDisplay::showEvent(QShowEvent *){ setSource(m_sourceFile);}void SourceDisplay::drawContents(QPainter *p, int clipx, int clipy, int clipw, int cliph){ if (!m_sourceFile) { p->fillRect(clipx,clipy,clipw,cliph,palette().active().base()); return; } QFontMetrics metrics(m_font); int height = metrics.height(); int bottom = clipy + cliph; int right = clipx + clipw; int firstLine = clipy/height-1; if (firstLine < 0) firstLine = 0; int lastLine = bottom/height+2; if (lastLine > (int)m_lines.count()) lastLine = m_lines.count(); p->setFont(m_font); int linenoWidth = metrics.width("888888"); for (int lineno = firstLine; lineno <= lastLine; lineno++) { QString linenoStr = QString().sprintf("%d",lineno+1); p->fillRect(0,height*lineno,linenoWidth,height,palette().active().mid()); p->setPen(palette().active().text()); p->drawText(0,height*lineno,linenoWidth,height,Qt::AlignRight,linenoStr); QColor bgColor; QColor textColor; if (lineno == m_currentLine) { bgColor = palette().active().highlight(); textColor = palette().active().highlightedText(); } else if (m_debugWin->haveBreakpoint(m_sourceFile,lineno+1,lineno+1)) { bgColor = palette().active().text(); textColor = palette().active().base(); p->drawPixmap(2,height*lineno+height/2-m_breakpointIcon.height()/2,m_breakpointIcon); } else { bgColor = palette().active().base(); textColor = palette().active().text(); } p->fillRect(linenoWidth,height*lineno,right-linenoWidth,height,bgColor); p->setPen(textColor); p->drawText(linenoWidth+4,height*lineno,contentsWidth()-linenoWidth-4,height, Qt::AlignLeft,m_lines[lineno]); } int remainingTop = height*(lastLine+1); p->fillRect(0,remainingTop,linenoWidth,bottom-remainingTop,palette().active().mid()); p->fillRect(linenoWidth,remainingTop, right-linenoWidth,bottom-remainingTop,palette().active().base());}//-------------------------------------------------------------------------KJSDebugWin * KJSDebugWin::kjs_html_debugger = 0;QString SourceFile::getCode(){ if (interpreter) { KHTMLPart *part = ::qt_cast<KHTMLPart*>(static_cast<ScriptInterpreter*>(interpreter)->part()); if (part && url == part->url().url() && KHTMLPageCache::self()->isValid(part->cacheId())) { Decoder *decoder = part->createDecoder(); QByteArray data; QDataStream stream(data,IO_WriteOnly); KHTMLPageCache::self()->saveData(part->cacheId(),&stream); QString str; if (data.size() == 0) str = ""; else str = decoder->decode(data.data(),data.size()) + decoder->flush(); delete decoder; return str; } } return code;}//-------------------------------------------------------------------------SourceFragment::SourceFragment(int sid, int bl, int el, SourceFile *sf){ sourceId = sid; baseLine = bl; errorLine = el; sourceFile = sf; sourceFile->ref();}SourceFragment::~SourceFragment(){ sourceFile->deref(); sourceFile = 0L;}//-------------------------------------------------------------------------KJSErrorDialog::KJSErrorDialog(QWidget *parent, const QString& errorMessage, bool showDebug) : KDialogBase(parent,0,true,i18n("JavaScript Error"), showDebug ? KDialogBase::Ok|KDialogBase::User1 : KDialogBase::Ok, KDialogBase::Ok,false,KGuiItem("&Debug","gear")){ QWidget *page = new QWidget(this); setMainWidget(page); QLabel *iconLabel = new QLabel("",page); iconLabel->setPixmap(KGlobal::iconLoader()->loadIcon("messagebox_critical", KIcon::NoGroup,KIcon::SizeMedium, KIcon::DefaultState,0,true)); QWidget *contents = new QWidget(page); QLabel *label = new QLabel(errorMessage,contents); m_dontShowAgainCb = new QCheckBox(i18n("&Do not show this message again"),contents); QVBoxLayout *vl = new QVBoxLayout(contents,0,spacingHint()); vl->addWidget(label); vl->addWidget(m_dontShowAgainCb); QHBoxLayout *topLayout = new QHBoxLayout(page,0,spacingHint()); topLayout->addWidget(iconLabel); topLayout->addWidget(contents); topLayout->addStretch(10); m_debugSelected = false;}KJSErrorDialog::~KJSErrorDialog(){}void KJSErrorDialog::slotUser1(){ m_debugSelected = true; close();}//-------------------------------------------------------------------------EvalMultiLineEdit::EvalMultiLineEdit(QWidget *parent) : QMultiLineEdit(parent) {}void EvalMultiLineEdit::keyPressEvent(QKeyEvent * e){ if (e->key() == Qt::Key_Return) { if (hasSelectedText()) { m_code = selectedText(); } else { int para, index; getCursorPosition(¶, &index); m_code = text(para); } end(); } QMultiLineEdit::keyPressEvent(e);}//-------------------------------------------------------------------------KJSDebugWin::KJSDebugWin(QWidget *parent, const char *name) : KMainWindow(parent, name, WType_TopLevel), KInstance("kjs_debugger"){ m_breakpoints = 0; m_breakpointCount = 0; m_curSourceFile = 0; m_mode = Continue; m_nextSourceUrl = ""; m_nextSourceBaseLine = 1; m_execs = 0; m_execsCount = 0; m_execsAlloc = 0; m_steppingDepth = 0; m_stopIcon = KGlobal::iconLoader()->loadIcon("stop",KIcon::Small); m_emptyIcon = QPixmap(m_stopIcon.width(),m_stopIcon.height()); QBitmap emptyMask(m_stopIcon.width(),m_stopIcon.height(),true); m_emptyIcon.setMask(emptyMask); setCaption(i18n("JavaScript Debugger")); QWidget *mainWidget = new QWidget(this); setCentralWidget(mainWidget); QVBoxLayout *vl = new QVBoxLayout(mainWidget,5); // frame list & code
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -