⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 kquickhelp.cpp

📁 PIXIL is a small footprint operating environment, complete with PDA PIM applications, a browser and
💻 CPP
字号:
// ---------------------------------------------------------------------------////   QuickHelp: an improved mini-help system for KDE//// ---------------------------------------------------------------------------////   This file is part of the KDE libraries////   Copyright (C) 1997 Mario Weilguni <mweilguni@kde.org>////   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., 59 Temple Place - Suite 330,//   Boston, MA 02111-1307, USA.//// ---------------------------------------------------------------------------#include "kquickhelp.h"#include <qpainter.h>#include <qpixmap.h>#include <stdio.h>#include <kapp.h>#include <qpopupmenu.h>#include <qbitmap.h>#include <qregexp.h>#ifdef HAVE_CONFIG_H#include <config.h>#endif#ifdef HAVE_UNISTD_H#include <unistd.h>#endif// this selects wheter we want shapes or not#define QH_SHAPE#ifdef QH_SHAPE  #include <X11/Xlib.h>  #include <X11/Xutil.h>  #include <X11/Xos.h>  #include <X11/extensions/shape.h>  #define X_SHADOW 6  #define Y_SHADOW 6#else  #define X_SHADOW 0  #define Y_SHADOW 0#endif// text attribute flags#define F_BOLD 1#define F_ITALIC 2#define F_UNDERLINE 4// predefined border and shadow width#define X_BORDER 10#define Y_BORDER 6// numeric representation of allowed tokensconst int TOK_BOLD_ON = 1;const int TOK_BOLD_OFF = 2;const int TOK_ITALIC_ON = 3;const int TOK_ITALIC_OFF = 4;const int TOK_UNDERLINE_ON = 5;const int TOK_UNDERLINE_OFF = 6;const int TOK_FONTSIZE_PLUS = 7;const int TOK_FONTSIZE_MINUS = 8;const int TOK_COLOR_BY_RGB = 9;const int TOK_COLOR_RED = 10;const int TOK_COLOR_GREEN = 11;const int TOK_COLOR_BLUE = 12;const int TOK_COLOR_WHITE = 13;const int TOK_COLOR_YELLOW = 14;const int TOK_COLOR_BLACK = 15;const int TOK_COLOR_BROWN = 16;const int TOK_COLOR_MAGENTA = 17;const int TOK_COLOR_CYAN = 18;const int TOK_FONT_DEFAULT = 19;const int TOK_FONT_FIXED = 20;const int TOK_INDENT_PLUS = 21;const int TOK_INDENT_MINUS = 22;const int TOK_NEWLINE = 23;const int TOK_LINK = 24;const int TOK_ENDLINK = 25;QPopupMenu *KQuickHelp::menu = 0;KQuickHelp *KQuickHelp::instance = 0;QList<KQuickTip> *KQuickHelp::tips;KQuickHelpWindow *KQuickHelp::window = 0;// the standard colorsQColor KQuickHelpWindow::stdColors[] = {  red,  green,  blue,  white,  yellow,  black,  QColor(165, 42, 42),  magenta,  cyan};KQuickHelp_Token KQuickHelpWindow::tokens[] = {  // font attributes  {"<b>", TOK_BOLD_ON},  {"</b>", TOK_BOLD_OFF},  {"<i>", TOK_ITALIC_ON},  {"</i>", TOK_ITALIC_OFF},  {"<u>", TOK_UNDERLINE_ON},  {"</u>", TOK_UNDERLINE_OFF},  // font attributes (long)  {"<bold>", TOK_BOLD_ON},  {"</bold>", TOK_BOLD_OFF},  {"<italic>", TOK_ITALIC_ON},  {"</italic>", TOK_ITALIC_OFF},  {"<underline>", TOK_UNDERLINE_ON},  {"</underline>", TOK_UNDERLINE_OFF},  // font size  {"<FONT SIZE +>", TOK_FONTSIZE_PLUS},  {"<FONT SIZE ->", TOK_FONTSIZE_MINUS},  {"<+>", TOK_FONTSIZE_PLUS},  {"<->", TOK_FONTSIZE_MINUS},  // indentation  {"<INDENT +>", TOK_INDENT_PLUS},  {"<INDENT ->", TOK_INDENT_MINUS},  {"<i+>", TOK_INDENT_PLUS},  {"<i->", TOK_INDENT_MINUS},  // color selection by RGB value  {"<COLOR #", TOK_COLOR_BY_RGB},  // color selection by color name  {"<COLOR RED>", TOK_COLOR_RED},  {"<COLOR GREEN>", TOK_COLOR_GREEN},  {"<COLOR BLUE>", TOK_COLOR_BLUE},  {"<COLOR WHITE>", TOK_COLOR_WHITE},  {"<COLOR YELLOW>", TOK_COLOR_YELLOW},  {"<COLOR BLACK>", TOK_COLOR_BLACK},  {"<COLOR BROWN>", TOK_COLOR_BROWN},  {"<COLOR MAGENTA>", TOK_COLOR_MAGENTA},  {"<COLOR CYAN>", TOK_COLOR_CYAN},  // color selection by color name (short form)  {"<RED>", TOK_COLOR_RED},  {"<GREEN>", TOK_COLOR_GREEN},  {"<BLUE>", TOK_COLOR_BLUE},  {"<WHITE>", TOK_COLOR_WHITE},  {"<YELLOW>", TOK_COLOR_YELLOW},  {"<BLACK>", TOK_COLOR_BLACK},  {"<BROWN>", TOK_COLOR_BROWN},  {"<MAGENTA>", TOK_COLOR_MAGENTA},  {"<CYAN>", TOK_COLOR_CYAN},  // font selection  {"<FONT DEFAULT>", TOK_FONT_DEFAULT},  {"<FONT FIXED>", TOK_FONT_FIXED},  {"<DEFAULT>", TOK_FONT_DEFAULT},  {"<FIXED>", TOK_FONT_FIXED},  // newline  {"<br>", TOK_NEWLINE},  // hyperlinks  {"<link ", TOK_LINK},  {"</link>", TOK_ENDLINK},    // token table terminator  {0, 0}};KQuickHelp::KQuickHelp() : QObject(0) {}const char *KQuickHelp::add(QWidget *w, const char *s) {  if(!s)    return 0;  if(w != 0) {    // make sure we have  a class instance running    if(instance == 0) {      tips = new QList<KQuickTip>;      instance = new KQuickHelp();      window = new KQuickHelpWindow();      menu = new QPopupMenu;      menu->insertItem(i18n("Quickhelp"));      connect(menu, SIGNAL(activated(int)),	      instance, SLOT(getKQuickHelp(int)));      connect(window, SIGNAL(hyperlink(QString)),	      instance, SLOT(hyperlinkRequested(QString)));      tips->setAutoDelete(true);    }    KQuickTip *qt = new KQuickTip;    qt->widget = w;    qt->txt = s;    tips->append(qt);    connect(w, SIGNAL(destroyed()),	    instance, SLOT(widgetDestroyed()));    w->installEventFilter(instance);  }  return s;}void KQuickHelp::hyperlinkRequested(QString link) {  // check protocol  if(strncasecmp("http:", link.data(), 5) == 0 ||     strncasecmp("info:", link.data(), 5) == 0 ||     strncasecmp("ftp:", link.data(), 4) == 0 ||     strncasecmp("file:", link.data(), 5) == 0 ||     strncasecmp("mailto:", link.data(), 7) == 0)    {      // lets give this URL to kfm, he knows better what      // to do with it      if(fork() > 0) {	// drop setuid, setgid	setgid(getgid());	setuid(getuid());		QString s = "kfmclient exec " + link + " &";	execlp("kfmclient", "kfmclient", "exec", link.data(), 0);	_exit(0);      }    } else {      // hmm, seems I have to do it myself :-(      QString fname = "", anchor = "";      int idx;      if((idx = link.find('#')) == -1)	fname = link;      else {	if(*link.data() == '#') {	  anchor = link.mid(1, 255);	  fname = kapp->appName() + ".html";	} else {	  fname = link.left(idx);	  anchor = link.mid(idx+1, 1024);	}      }            kapp->invokeHTMLHelp((kapp->appName() +  "/" + fname), anchor);    }}void KQuickHelp::remove(QWidget *w) {  for(unsigned i = 0; i < tips->count(); i++)    if(tips->at(i)->widget == w) {      tips->remove(i);      return;    }      }void KQuickHelp::widgetDestroyed() {  remove((QWidget *)sender());}bool KQuickHelp::eventFilter(QObject *o, QEvent *e) {  if(e->type() == Event_MouseButtonPress && ((QMouseEvent *)e)->button() == RightButton) {    for(unsigned i = 0; i < tips->count(); i++) {      if(tips->at(i)->widget == (QWidget *)o) {	current = tips->at(i)->widget;	currentText = tips->at(i)->txt;	currentPos = QCursor::pos();	menu->popup(currentPos);	return true;      }    }  }    return false;}void KQuickHelp::getKQuickHelp(int) {  window->popup(currentText, currentPos.x(), currentPos.y());}KQuickHelpWindow::KQuickHelpWindow() : QFrame(0, 0, WStyle_Customize|WStyle_Tool) {  setBackgroundColor(QColor(255, 255, 225));  defaultCursor = cursor();  linkAreas.setAutoDelete(true);}void KQuickHelpWindow::newText() {  QPixmap pm(1, 1);  QPainter p;  p.begin(&pm);  int w = 0, h = 0;  paint(&p, w, h);  p.end();  // HACK: there may have been link-areas defined. Remove them  linkAreas.clear();  // resize to appropr. size  resize(w, h);}void KQuickHelpWindow::mousePressEvent(QMouseEvent *e) {  if(e->button() == LeftButton && activeLink.length())    emit hyperlink(activeLink);  hide();}void KQuickHelpWindow::mouseMoveEvent(QMouseEvent *e) {  QPoint p = e->pos();  for(uint i = 0; i < linkAreas.count(); i++)    if(linkAreas.at(i)->area.contains(p)) {      setCursor(upArrowCursor);      activeLink = linkAreas.at(i)->link.copy();            return;    }   activeLink = "";  setCursor(defaultCursor);}void KQuickHelpWindow::keyPressEvent(QKeyEvent *e) {  e->accept();  hide();}void KQuickHelpWindow::show() {  QFrame::show();  grabMouse();  grabKeyboard();  setMouseTracking(true);}void KQuickHelpWindow::hide() {  QFrame::hide();  releaseMouse();  releaseKeyboard();  setMouseTracking(false);  // clean up  activeLink = "";  linkAreas.clear();}void KQuickHelpWindow::popup(QString text, int x, int y) {  txt = text.copy();  newText();  if(x + width() > QApplication::desktop()->width() - 8)    x = QApplication::desktop()->width() - 8 - width();  if(y + height() > QApplication::desktop()->height() - 4)    y = QApplication::desktop()->height() - 4 - height();  move(x, y);  show();}    void KQuickHelpWindow::paintEvent(QPaintEvent *) {  QPainter p;  p.begin(this);  int x, y;  paint(&p, x, y);  p.end();#ifdef QH_SHAPE  // repaint, so we can apply the Shape (don't know if necessary)  // kapp->flushX();  QBitmap bm(width(), height());  p.begin(&bm);  p.setPen(color0);  bm.fill(color1);    p.fillRect(X_SHADOW, height() - Y_SHADOW,	     width() - X_SHADOW, Y_SHADOW, Dense4Pattern);  p.fillRect(width()-X_SHADOW, Y_SHADOW,	     X_SHADOW, height()-Y_SHADOW, Dense4Pattern);  p.fillRect(width()-X_SHADOW, 0,	     X_SHADOW, Y_SHADOW, SolidPattern);  p.fillRect(0, height()-Y_SHADOW,	     X_SHADOW, Y_SHADOW, SolidPattern);  p.end();    XShapeCombineMask( x11Display(), winId(), ShapeBounding, 0, 0, bm.handle(), ShapeSet );#endif}QString KQuickHelpWindow::token() {  QString t = "";  bool  backslash = false;  while(tokIndex < (int)txt.length()) {    char c = txt[tokIndex++];    if(backslash) {      backslash = false;      t += c;    } else {      switch(c) {      case '\\':	backslash = true;	break;      case '\n':	if(t.length() == 0)	  t = "<br>";	else	  tokIndex--;	return t;      case '<':	if(t.length() == 0)	  t += c;	else {	  tokIndex--;	  return t;	}	break;      case '>':	if(t.left(1) == "<") // bad token	  t += c;	return t;      default:	t += c;      }    }  }  return t;}void KQuickHelpWindow::paint(QPainter *p, int &w, int &h) {  int posx = X_BORDER, posy = Y_BORDER;  int maxy = 0, maxx = 0, idx;  int indent = 0;  QFont f;  QColor txtColor = black;  QColor savedColor;  int txtFlags = 0;  bool wasUnderline = false;  QString link;  int pointsize = p->font().pointSize();  p->setPen(black);  tokIndex = 0;  while(tokIndex < (int)txt.length()) {    QString t = token();    if(t.left(1) == "<") { // a token            // find token      int tokenID = -1;      t = t.simplifyWhiteSpace();      for(int i = 0; tokens[i].token != 0; i++)	if(strncasecmp(t.data(), tokens[i].token, strlen(tokens[i].token)) == 0) {	  tokenID = tokens[i].tokenID;	  break;	}            switch(tokenID) {      case -1:	// ignore	fprintf(stderr, "KQuickHelp: ignoring unknown token \"%s\"!\n", t.data());	break;	// font attributes      case TOK_BOLD_ON:	txtFlags |= F_BOLD;	break;      case TOK_BOLD_OFF:	txtFlags &= ~F_BOLD;	break;      case TOK_ITALIC_ON:	txtFlags |= F_ITALIC;	break;      case TOK_ITALIC_OFF:	txtFlags &= ~F_ITALIC;	break;      case TOK_UNDERLINE_ON:	txtFlags |= F_UNDERLINE;	break;      case TOK_UNDERLINE_OFF:	txtFlags &= ~F_UNDERLINE;	break;		// font size      case TOK_FONTSIZE_PLUS:	f = p->font();	while(QFontInfo(f).pointSize() == pointsize)	  f.setPointSize(f.pointSize() + 1);	pointsize = QFontInfo(f).pointSize();	break;      case TOK_FONTSIZE_MINUS:	f = p->font();	while(QFontInfo(f).pointSize() == pointsize)	  f.setPointSize(f.pointSize() - 1);	pointsize = QFontInfo(f).pointSize();	break;	// indentation      case TOK_INDENT_PLUS:	posx += fontMetrics().width('H') * 2;	indent += fontMetrics().width('H') * 2;	break;      case TOK_INDENT_MINUS:	if(indent > 0)	  indent -= fontMetrics().width('H') * 2;	break;	// color by RGB value      case TOK_COLOR_BY_RGB:	idx = t.find(QRegExp("#[0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F][0-9a-fA-F]"));	if(idx != -1) {	  int cval, r, g, b;	  sscanf(t.data() + idx + 1, "%x", &cval);	  r = cval >> 16;	  g = (cval >> 8) & 0xff;	  b = cval & 0xff;	  txtColor = QColor(r, g, b);	}	break;      	// newline      case TOK_NEWLINE:	posx = X_BORDER + indent;	posy += maxy;	maxy = 10;	break;	// standard colors      case TOK_COLOR_RED:      case TOK_COLOR_GREEN:      case TOK_COLOR_BLUE:      case TOK_COLOR_WHITE:      case TOK_COLOR_YELLOW:      case TOK_COLOR_BLACK:      case TOK_COLOR_BROWN:      case TOK_COLOR_MAGENTA:      case TOK_COLOR_CYAN:	txtColor = stdColors[tokenID-TOK_COLOR_RED];	break;	// hyperlinks      case TOK_LINK:	idx = t.find(QRegExp(" .*>", false));	if(idx != -1) {	  link = t.mid(idx+1, t.length()-idx-2);	  savedColor = txtColor;	  wasUnderline = (txtFlags & F_UNDERLINE) != 0;	  txtColor = blue;	  txtFlags |= F_UNDERLINE;	}	break;      case TOK_ENDLINK:	txtColor = savedColor;	if(!wasUnderline)	  txtFlags &= ~F_UNDERLINE;	link = "";	break;      default:	printf("TOKEN: \"%s\", ID=%d\n", t.data(), tokenID);      }    } else { // plain text      p->setPen(txtColor);      QFont f = font();      f.setPointSize(pointsize);      f.setBold((txtFlags & F_BOLD) != 0);      f.setItalic((txtFlags & F_ITALIC) != 0);      f.setUnderline((txtFlags & F_UNDERLINE) != 0);      p->setFont(f);      QRect r;      p->drawText(posx, posy, 1024, 1024, AlignLeft|AlignTop, t.data(), -1, &r, 0);      if(link.length() > 0) {	KQuickHelp_Link *l = new KQuickHelp_Link;	l->area = r;	l->link = link;	linkAreas.append(l);      }      posx += r.width();      maxy = QMAX(maxy, p->fontMetrics().lineSpacing());      maxx = QMAX(maxx, r.right());    }  }  w = maxx + X_BORDER + X_SHADOW;  h = posy + maxy + Y_BORDER + Y_SHADOW;  // draw frame  p->setPen(QPen(black, 1));  p->drawRect(0, 0, w - X_SHADOW, h - Y_SHADOW);  p->fillRect(0, h - Y_SHADOW, w, h, QBrush(QColor(black)));  p->fillRect(w - X_SHADOW, 0, w, h, QBrush(QColor(black)));}#include "kquickhelp.moc"

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -