KDevelop API Documentation

languages/cpp/debugger/dbgtoolbar.cpp

Go to the documentation of this file.
00001 /*************************************************************************** 00002 begin : Thu Dec 23 1999 00003 copyright : (C) 1999 by John Birch 00004 email : jbb@kdevelop.org 00005 ***************************************************************************/ 00006 00007 /*************************************************************************** 00008 * * 00009 * This program is free software; you can redistribute it and/or modify * 00010 * it under the terms of the GNU General Public License as published by * 00011 * the Free Software Foundation; either version 2 of the License, or * 00012 * (at your option) any later version. * 00013 * * 00014 ***************************************************************************/ 00015 00016 #include "dbgtoolbar.h" 00017 #include "debuggerpart.h" 00018 #include "dbgcontroller.h" 00019 00020 #include <kdockwindow.h> 00021 #include <kiconloader.h> 00022 #include <klocale.h> 00023 #include <kpopupmenu.h> 00024 #include <kstandarddirs.h> 00025 #include <kwin.h> 00026 #include <kwinmodule.h> 00027 00028 #include <qapplication.h> 00029 #include <qcursor.h> 00030 #include <qframe.h> 00031 #include <qlayout.h> 00032 #include <qpainter.h> 00033 #include <qpushbutton.h> 00034 #include <qtooltip.h> 00035 #include <qwhatsthis.h> 00036 00037 // ************************************************************************** 00038 // ************************************************************************** 00039 // ************************************************************************** 00040 00041 // Implements a floating toolbar for the debugger. 00042 00043 // Unfortunately, I couldn't get the KToolBar to work nicely when it 00044 // was floating, so I was forced to write these classes. I'm not sure whether 00045 // I didn't try hard enough or ... and I've forgotten what the problems were 00046 // now. 00047 00048 // The problem with using this is that it will not dock as a normal toolbar. 00049 // I'm not convince that this is a real problem though. 00050 00051 // So, if you can get it to work as a KToolBar, and it works well when the 00052 // app is running, then all these classes can be removed. 00053 00054 // This code is very specific to the internal debugger in kdevelop. 00055 00056 namespace GDBDebugger 00057 { 00058 00059 // ************************************************************************** 00060 // ************************************************************************** 00061 // ************************************************************************** 00062 00063 // This just allows the user to click on the toolbar and drag it somewhere else. 00064 // I would have preferred to use normal decoration on the toolbar and removed 00065 // the iconify, close, etc buttons from the window title but again I kept running 00066 // into problems. Instead, I used no decoration and this class. Also this looks 00067 // similar to the KToolBar floating style. 00068 class DbgMoveHandle : public QFrame 00069 { 00070 public: 00071 DbgMoveHandle(DbgToolBar *parent=0, const char * name=0, WFlags f=0); 00072 virtual ~DbgMoveHandle(); 00073 00074 virtual void mousePressEvent(QMouseEvent *e); 00075 virtual void mouseReleaseEvent(QMouseEvent *e); 00076 virtual void mouseMoveEvent(QMouseEvent *e); 00077 00078 private: 00079 DbgToolBar* toolBar_; 00080 QPoint offset_; 00081 bool moving_; 00082 }; 00083 00084 // ************************************************************************** 00085 00086 DbgMoveHandle::DbgMoveHandle(DbgToolBar *parent, const char * name, WFlags f) 00087 : QFrame(parent, name, f), 00088 toolBar_(parent), 00089 offset_(QPoint(0,0)), 00090 moving_(false) 00091 { 00092 setFrameStyle(QFrame::Panel|QFrame::Raised); 00093 setFixedHeight(12); 00094 } 00095 00096 // ************************************************************************** 00097 00098 DbgMoveHandle::~DbgMoveHandle() 00099 { 00100 } 00101 00102 // ************************************************************************** 00103 00104 void DbgMoveHandle::mousePressEvent(QMouseEvent *e) 00105 { 00106 QFrame::mousePressEvent(e); 00107 if (moving_) 00108 return; 00109 00110 if (e->button() == RightButton) { 00111 KPopupMenu *menu = new KPopupMenu(i18n("Debug Toolbar"), this); 00112 menu->insertItem(i18n("Dock to Panel"), 00113 parent(), SLOT(slotDock())); 00114 menu->insertItem(i18n("Dock to Panel && Iconify KDevelop"), 00115 parent(), SLOT(slotIconifyAndDock())); 00116 menu->popup(e->globalPos()); 00117 } else { 00118 moving_ = true; 00119 offset_ = parentWidget()->pos() - e->globalPos(); 00120 setFrameStyle(QFrame::Panel|QFrame::Sunken); 00121 QApplication::setOverrideCursor(QCursor(sizeAllCursor)); 00122 setPalette(QPalette(colorGroup().background())); 00123 repaint(); 00124 } 00125 } 00126 00127 // ************************************************************************** 00128 00129 void DbgMoveHandle::mouseReleaseEvent(QMouseEvent *e) 00130 { 00131 QFrame::mouseReleaseEvent(e); 00132 moving_ = false; 00133 offset_ = QPoint(0,0); 00134 setFrameStyle(QFrame::Panel|QFrame::Raised); 00135 QApplication::restoreOverrideCursor(); 00136 setPalette(QPalette(colorGroup().background())); 00137 repaint(); 00138 } 00139 00140 // ************************************************************************** 00141 00142 void DbgMoveHandle::mouseMoveEvent(QMouseEvent *e) 00143 { 00144 QFrame::mouseMoveEvent(e); 00145 if (!moving_) 00146 return; 00147 00148 toolBar_->move(e->globalPos() + offset_); 00149 } 00150 00151 // ************************************************************************** 00152 // ************************************************************************** 00153 // ************************************************************************** 00154 00155 // This class adds text _and_ a pixmap to a button. Why doesn't QPushButton 00156 // support that? It only allowed text _or_ pixmap. 00157 class DbgButton : public QPushButton 00158 { 00159 public: 00160 DbgButton(const QPixmap &pixmap, const QString &text, 00161 DbgToolBar *parent, const char *name=0); 00162 virtual ~DbgButton() {}; 00163 void drawButtonLabel(QPainter *painter); 00164 QSize sizeHint() const; 00165 00166 private: 00167 QPixmap pixmap_; 00168 }; 00169 00170 // ************************************************************************** 00171 00172 DbgButton::DbgButton(const QPixmap& pixmap, const QString& text, 00173 DbgToolBar* parent, const char* name) 00174 : QPushButton(parent, name), 00175 pixmap_(pixmap) 00176 { 00177 setText(text); 00178 } 00179 00180 // ************************************************************************** 00181 00182 void DbgButton::drawButtonLabel(QPainter *painter) 00183 { 00184 // We always have a pixmap (today...) 00185 // Centre it if there's no text 00186 00187 bool hasText = !text().isEmpty(); 00188 int x = ((hasText ? height() : width()) - pixmap_.width()) / 2; 00189 int y = (height() - pixmap_.height()) / 2; 00190 painter->drawPixmap(x, y, pixmap_); 00191 00192 if (hasText) { 00193 painter->setPen(colorGroup().text()); 00194 painter->drawText(height()+2, 0, width()-(height()+2), height(), AlignLeft|AlignVCenter, text()); 00195 } 00196 } 00197 00198 // ************************************************************************** 00199 00200 QSize DbgButton::sizeHint() const 00201 { 00202 if (text().isEmpty()) 00203 return pixmap_.size(); 00204 else 00205 return QPushButton::sizeHint(); 00206 } 00207 00208 // ************************************************************************** 00209 // ************************************************************************** 00210 // ************************************************************************** 00211 00212 DbgDocker::DbgDocker(QWidget* parent, DbgToolBar* toolBar, const QPixmap& pixmap) : 00213 KSystemTray(parent, "DbgDocker"), 00214 toolBar_(toolBar) 00215 { 00216 setPixmap(pixmap); 00217 QToolTip::add( this, i18n("KDevelop debugger: Click to execute one line of code (\"step\")") ); 00218 } 00219 00220 // ************************************************************************** 00221 00222 void DbgDocker::mousePressEvent(QMouseEvent *e) 00223 { 00224 if (!rect().contains( e->pos())) 00225 return; 00226 00227 switch (e->button()) { 00228 case LeftButton: 00229 { 00230 // Not really a click, but it'll hold for the time being !!! 00231 emit clicked(); 00232 break; 00233 } 00234 case RightButton: 00235 { 00236 KPopupMenu* menu = new KPopupMenu(i18n("Debug Toolbar"), this); 00237 menu->insertItem(i18n("Activate"), toolBar_, SLOT(slotUndock())); 00238 menu->insertItem(i18n("Activate (KDevelop gets focus)"), toolBar_, SLOT(slotActivateAndUndock())); 00239 menu->popup(e->globalPos()); 00240 break; 00241 } 00242 default: 00243 break; 00244 } 00245 } 00246 00247 // ************************************************************************** 00248 // ************************************************************************** 00249 // ************************************************************************** 00250 00251 DbgToolBar::DbgToolBar(DebuggerPart* part, 00252 QWidget* parent, const char* name) 00253 : QFrame(0, name), 00254 part_(part), 00255 activeWindow_(0), 00256 winModule_(0), 00257 bKDevFocus_(0), 00258 bPrevFocus_(0), 00259 appIsActive_(false), 00260 docked_(false), 00261 docker_(0), 00262 dockWindow_(new KSystemTray(parent)) 00263 { 00264 winModule_ = new KWinModule(this); 00265 docker_ = new DbgDocker(parent, this, BarIcon("dbgnext")); 00266 connect(docker_, SIGNAL(clicked()), part_, SLOT(slotStepOver())); 00267 00268 // Must have noFocus set so that we can see what window was active. 00269 // see slotDbgKdevFocus() for more comments 00270 // I do not want the user to be able to "close" this widget. If we have any 00271 // decoration then they can and that is bad. 00272 // This widget is closed when the debugger finishes i.e. they press "Stop" 00273 00274 // Do we need NoFocus??? 00275 KWin::setState(winId(), NET::StaysOnTop | NET::Modal | NET::SkipTaskbar); 00276 // KWin::setType(winId(), NET::Override); // So it has no decoration 00277 KWin::setType(winId(), NET::Dock); 00278 00279 setFocusPolicy(NoFocus); 00280 setFrameStyle( QFrame::Box | QFrame::Plain ); 00281 setLineWidth(4); 00282 setMidLineWidth(0); 00283 00284 QBoxLayout* topLayout = new QVBoxLayout(this); 00285 00286 QBoxLayout* nextLayout = new QHBoxLayout(); 00287 QBoxLayout* stepLayout = new QHBoxLayout(); 00288 QBoxLayout* focusLayout = new QHBoxLayout(); 00289 00290 DbgMoveHandle* moveHandle= new DbgMoveHandle(this); 00291 00292 QPushButton* bRun = new DbgButton(BarIcon("dbgrun"), i18n("Run"), this); 00293 QPushButton* bInterrupt = new DbgButton(BarIcon("player_pause"), i18n("Interrupt"), this); 00294 QPushButton* bNext = new DbgButton(BarIcon("dbgnext"), QString::null, this); 00295 QPushButton* bNexti = new DbgButton(BarIcon("dbgnextinst"), QString::null, this); 00296 QPushButton* bStep = new DbgButton(BarIcon("dbgstep"), QString::null, this); 00297 QPushButton* bStepi = new DbgButton(BarIcon("dbgstepinst"), QString::null, this); 00298 QPushButton* bFinish = new DbgButton(BarIcon("dbgstepout"), i18n("Step Out"), this); 00299 QPushButton* bView = new DbgButton(BarIcon("dbgmemview"), i18n("Viewers"), this); 00300 bKDevFocus_ = new DbgButton(BarIcon("kdevelop"), QString::null, this); 00301 bPrevFocus_ = new DbgButton(BarIcon("dbgmemview"), QString::null, this); 00302 00303 connect(bRun, SIGNAL(clicked()), part_, SLOT(slotRun())); 00304 connect(bInterrupt, SIGNAL(clicked()), part_, SLOT(slotPause())); 00305 connect(bNext, SIGNAL(clicked()), part_, SLOT(slotStepOver())); 00306 connect(bNexti, SIGNAL(clicked()), part_, SLOT(slotStepOverInstruction())); 00307 connect(bStep, SIGNAL(clicked()), part_, SLOT(slotStepInto())); 00308 connect(bStepi, SIGNAL(clicked()), part_, SLOT(slotStepIntoInstruction())); 00309 connect(bFinish, SIGNAL(clicked()), part_, SLOT(slotStepOut())); 00310 connect(bView, SIGNAL(clicked()), part_, SLOT(slotMemoryView())); 00311 connect(bKDevFocus_, SIGNAL(clicked()), this, SLOT(slotKdevFocus())); 00312 connect(bPrevFocus_, SIGNAL(clicked()), this, SLOT(slotPrevFocus())); 00313 00314 QToolTip::add( bRun, i18n("Continue with application execution, may start the application") ); 00315 QToolTip::add( bInterrupt, i18n("Interrupt the application execution") ); 00316 QToolTip::add( bNext, i18n("Execute one line of code, but run through functions") ); 00317 QToolTip::add( bNexti, i18n("Execute one assembler instruction, but run through functions") ); 00318 QToolTip::add( bStep, i18n("Execute one line of code, stepping into functions if appropriate") ); 00319 QToolTip::add( bStepi, i18n("Execute one assembler instruction, stepping into functions if appropriate") ); 00320 QToolTip::add( bFinish, i18n("Execute to end of current stack frame") ); 00321 QToolTip::add( bView, i18n("Memory, dissemble, registers, library viewers") ); 00322 QToolTip::add( bKDevFocus_, i18n("Set focus on KDevelop") ); 00323 QToolTip::add( bPrevFocus_, i18n("Set focus on window that had focus when KDevelop got focus") ); 00324 00325 QWhatsThis::add( bRun, i18n("Continue with application execution. May start the application.") ); 00326 QWhatsThis::add( bInterrupt, i18n("Interrupt the application execution.") ); 00327 QWhatsThis::add( bNext, i18n("Execute one line of code, but run through functions.") ); 00328 QWhatsThis::add( bNexti, i18n("Execute one assembler instruction, but run through functions.") ); 00329 QWhatsThis::add( bStep, i18n("Execute one line of code, stepping into functions if appropriate.") ); 00330 QWhatsThis::add( bStepi, i18n("Execute one assembler instruction, stepping into functions if appropriate.") ); 00331 QWhatsThis::add( bFinish, i18n("Execute to end of current stack frame.") ); 00332 QWhatsThis::add( bView, i18n("Memory, dissemble, registers, library viewers.") ); 00333 QWhatsThis::add( bKDevFocus_, i18n("Set focus on KDevelop.") ); 00334 QWhatsThis::add( bPrevFocus_, i18n("Set focus on window that had focus when KDevelop got focus.") ); 00335 00336 topLayout->addWidget(moveHandle); 00337 topLayout->addWidget(bRun); 00338 topLayout->addLayout(nextLayout); 00339 topLayout->addLayout(stepLayout); 00340 topLayout->addWidget(bFinish); 00341 topLayout->addWidget(bView); 00342 topLayout->addWidget(bInterrupt); 00343 topLayout->addLayout(focusLayout); 00344 00345 focusLayout->addWidget(bKDevFocus_); 00346 focusLayout->addWidget(bPrevFocus_); 00347 00348 stepLayout->addWidget(bStep); 00349 stepLayout->addWidget(bStepi); 00350 00351 nextLayout->addWidget(bNext); 00352 nextLayout->addWidget(bNexti); 00353 00354 // int w = QMAX(bRun->sizeHint().width(), bFinish->sizeHint().width()); 00355 // w = QMAX(w, bInterrupt->sizeHint().width()); 00356 // w = QMAX(w, bView->sizeHint().width()); 00357 00358 // they should have the same height, so don't be too fussy 00359 // int h = bFinish->sizeHint().height(); 00360 // 00361 // bNext->setMinimumHeight(h); 00362 // bNexti->setMinimumHeight(h); 00363 // bStep->setMinimumHeight(h); 00364 // bStepi->setMinimumHeight(h); 00365 // bKDevFocus_->setMinimumHeight(h); 00366 // bPrevFocus_->setMinimumHeight(h); 00367 00368 // setMinimumSize(w+10, h*7); 00369 // setMaximumSize(w+10, h*7); 00370 00371 setAppIndicator(appIsActive_); 00372 topLayout->activate(); 00373 } 00374 00375 // ************************************************************************** 00376 00377 DbgToolBar::~DbgToolBar() 00378 { 00379 slotUndock(); 00380 } 00381 00382 // ************************************************************************** 00383 00384 void DbgToolBar::slotKdevFocus() 00385 { 00386 // I really want to be able to set the focus on the _application_ being debugged 00387 // but this is the best compromise I can come up with. All we do is save the 00388 // window that had focus when they switch to the kdevelop window. To do this 00389 // the toolbar _cannot_ accept focus. 00390 // If anyone has a way of determining what window the app is _actually_ running on 00391 // then please fix and send a patch. 00392 00393 if (winModule_->activeWindow() != topLevelWidget()->winId()) 00394 activeWindow_ = winModule_->activeWindow(); 00395 00396 KWin::setActiveWindow(topLevelWidget()->winId()); 00397 } 00398 00399 // ************************************************************************** 00400 00401 void DbgToolBar::slotPrevFocus() 00402 { 00403 KWin::setActiveWindow(activeWindow_); 00404 } 00405 00406 // ************************************************************************** 00407 00408 // If the app is active then the app button is highlighted, otherwise 00409 // kdev button is highlighted. 00410 void DbgToolBar::slotDbgStatus(const QString&, int state) 00411 { 00412 bool appIndicator = state & s_appBusy; 00413 if (appIndicator != appIsActive_) { 00414 setAppIndicator(appIndicator); 00415 appIsActive_ = appIndicator; 00416 } 00417 } 00418 00419 // ************************************************************************** 00420 00421 void DbgToolBar::setAppIndicator(bool appIndicator) 00422 { 00423 if (appIndicator) { 00424 bPrevFocus_->setPalette(QPalette(colorGroup().mid())); 00425 bKDevFocus_->setPalette(QPalette(colorGroup().background())); 00426 } else { 00427 bPrevFocus_->setPalette(QPalette(colorGroup().background())); 00428 bKDevFocus_->setPalette(QPalette(colorGroup().mid())); 00429 } 00430 } 00431 00432 // ************************************************************************** 00433 00434 void DbgToolBar::slotDock() 00435 { 00436 if (docked_) 00437 return; 00438 00439 // Q_ASSERT(!docker_); 00440 hide(); 00441 00442 docker_->show(); 00443 docked_ = true; 00444 } 00445 00446 // ************************************************************************** 00447 00448 void DbgToolBar::slotIconifyAndDock() 00449 { 00450 if (docked_) 00451 return; 00452 00453 // KWin::iconifyWindow(ckDevelop_->winId(), true); 00454 slotDock(); 00455 } 00456 00457 // ************************************************************************** 00458 00459 void DbgToolBar::slotUndock() 00460 { 00461 if (!docked_) 00462 return; 00463 00464 show(); 00465 docker_->hide(); 00466 docked_ = false; 00467 } 00468 00469 // ************************************************************************** 00470 00471 void DbgToolBar::slotActivateAndUndock() 00472 { 00473 if (!docked_) 00474 return; 00475 00476 KWin::setActiveWindow(topLevelWidget()->winId()); 00477 slotUndock(); 00478 } 00479 00480 } 00481 00482 // ************************************************************************** 00483 #include "dbgtoolbar.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.0.4.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Wed Oct 6 17:39:01 2004 by doxygen 1.3.7 written by Dimitri van Heesch, © 1997-2003