KDevelop API Documentation

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(this);
00112     menu->insertTitle(i18n("Debug Toolbar"));
00113         menu->insertItem(i18n("Dock to Panel"),
00114                          parent(), SLOT(slotDock()));
00115         menu->insertItem(i18n("Dock to Panel && Iconify KDevelop"),
00116                          parent(), SLOT(slotIconifyAndDock()));
00117         menu->popup(e->globalPos());
00118     } else {
00119         moving_ = true;
00120         offset_ = parentWidget()->pos() - e->globalPos();
00121         setFrameStyle(QFrame::Panel|QFrame::Sunken);
00122         QApplication::setOverrideCursor(QCursor(sizeAllCursor));
00123         setPalette(QPalette(colorGroup().background()));
00124         repaint();
00125     }
00126 }
00127 
00128 // **************************************************************************
00129 
00130 void DbgMoveHandle::mouseReleaseEvent(QMouseEvent *e)
00131 {
00132     QFrame::mouseReleaseEvent(e);
00133     moving_ = false;
00134     offset_ = QPoint(0,0);
00135     setFrameStyle(QFrame::Panel|QFrame::Raised);
00136     QApplication::restoreOverrideCursor();
00137     setPalette(QPalette(colorGroup().background()));
00138     repaint();
00139 }
00140 
00141 // **************************************************************************
00142 
00143 void DbgMoveHandle::mouseMoveEvent(QMouseEvent *e)
00144 {
00145     QFrame::mouseMoveEvent(e);
00146     if (!moving_)
00147         return;
00148 
00149     toolBar_->move(e->globalPos() + offset_);
00150 }
00151 
00152 // **************************************************************************
00153 // **************************************************************************
00154 // **************************************************************************
00155 
00156 // This class adds text _and_ a pixmap to a button. Why doesn't QPushButton
00157 // support that? It only allowed text _or_ pixmap.
00158 class DbgButton : public QPushButton
00159 {
00160 public:
00161     DbgButton(const QPixmap &pixmap, const QString &text,
00162               DbgToolBar *parent, const char *name=0);
00163     virtual ~DbgButton() {};
00164     void drawButtonLabel(QPainter *painter);
00165     QSize sizeHint() const;
00166 
00167 private:
00168     QPixmap pixmap_;
00169 };
00170 
00171 // **************************************************************************
00172 
00173 DbgButton::DbgButton(const QPixmap& pixmap, const QString& text,
00174                      DbgToolBar* parent, const char* name)
00175     : QPushButton(parent, name),
00176       pixmap_(pixmap)
00177 {
00178     setText(text);
00179 }
00180 
00181 // **************************************************************************
00182 
00183 void DbgButton::drawButtonLabel(QPainter *painter)
00184 {
00185     // We always have a pixmap (today...)
00186     // Centre it if there's no text
00187 
00188     bool hasText = !text().isEmpty();
00189     int x = ((hasText ? height() : width()) - pixmap_.width()) / 2;
00190     int y = (height() - pixmap_.height()) / 2;
00191     painter->drawPixmap(x, y, pixmap_);
00192 
00193     if (hasText) {
00194         painter->setPen(colorGroup().text());
00195         painter->drawText(height()+2, 0, width()-(height()+2), height(), AlignLeft|AlignVCenter, text());
00196     }
00197 }
00198 
00199 // **************************************************************************
00200 
00201 QSize DbgButton::sizeHint() const
00202 {
00203     if (text().isEmpty())
00204         return pixmap_.size();
00205     else
00206         return QPushButton::sizeHint();
00207 }
00208 
00209 // **************************************************************************
00210 // **************************************************************************
00211 // **************************************************************************
00212 
00213 DbgDocker::DbgDocker(QWidget* parent, DbgToolBar* toolBar, const QPixmap& pixmap) :
00214     KSystemTray(parent, "DbgDocker"),
00215     toolBar_(toolBar)
00216 {
00217     setPixmap(pixmap);
00218     QToolTip::add( this, i18n("KDevelop debugger: Click to execute one line of code (\"step\")") );
00219 }
00220 
00221 // **************************************************************************
00222 
00223 void DbgDocker::mousePressEvent(QMouseEvent *e)
00224 {
00225     if (!rect().contains( e->pos()))
00226         return;
00227 
00228     switch (e->button()) {
00229     case LeftButton:
00230         {
00231             // Not really a click, but it'll hold for the time being !!!
00232             emit clicked();
00233             break;
00234         }
00235     case RightButton:
00236         {
00237             KPopupMenu* menu = new KPopupMenu(this);
00238         menu->insertTitle(i18n("Debug Toolbar"));
00239             menu->insertItem(i18n("Activate"),                        toolBar_, SLOT(slotUndock()));
00240             menu->insertItem(i18n("Activate (KDevelop gets focus)"),  toolBar_, SLOT(slotActivateAndUndock()));
00241             menu->popup(e->globalPos());
00242             break;
00243         }
00244     default:
00245         break;
00246     }
00247 }
00248 
00249 // **************************************************************************
00250 // **************************************************************************
00251 // **************************************************************************
00252 
00253 DbgToolBar::DbgToolBar(DebuggerPart* part,
00254                        QWidget* parent, const char* name)
00255     : QFrame(0, name),
00256       part_(part),
00257       activeWindow_(0),
00258       winModule_(0),
00259       bKDevFocus_(0),
00260       bPrevFocus_(0),
00261       appIsActive_(false),
00262       docked_(false),
00263       docker_(0),
00264       dockWindow_(new KSystemTray(parent))
00265 {
00266     winModule_  = new KWinModule(this);
00267     docker_ = new DbgDocker(parent, this, BarIcon("dbgnext"));
00268     connect(docker_, SIGNAL(clicked()), part_, SLOT(slotStepOver()));
00269 
00270     // Must have noFocus set so that we can see what window was active.
00271     // see slotDbgKdevFocus() for more comments
00272     // I do not want the user to be able to "close" this widget. If we have any
00273     // decoration then they can and that is bad.
00274     // This widget is closed when the debugger finishes i.e. they press "Stop"
00275 
00276     // Do we need NoFocus???
00277     KWin::setState(winId(), NET::StaysOnTop | NET::Modal | NET::SkipTaskbar);
00278 //    KWin::setType(winId(), NET::Override);    // So it has no decoration
00279     KWin::setType(winId(), NET::Dock);
00280 
00281     setFocusPolicy(NoFocus);
00282     setFrameStyle( QFrame::Box | QFrame::Plain );
00283     setLineWidth(4);
00284     setMidLineWidth(0);
00285 
00286     QBoxLayout* topLayout     = new QVBoxLayout(this);
00287 
00288     QBoxLayout* nextLayout    = new QHBoxLayout();
00289     QBoxLayout* stepLayout    = new QHBoxLayout();
00290     QBoxLayout* focusLayout   = new QHBoxLayout();
00291 
00292     DbgMoveHandle*  moveHandle= new DbgMoveHandle(this);
00293 
00294     QPushButton*  bRun        = new DbgButton(BarIcon("dbgrun"),        i18n("Run"),        this);
00295     QPushButton*  bInterrupt  = new DbgButton(BarIcon("player_pause"),  i18n("Interrupt"),  this);
00296     QPushButton*  bNext       = new DbgButton(BarIcon("dbgnext"),       QString::null,      this);
00297     QPushButton*  bNexti      = new DbgButton(BarIcon("dbgnextinst"),   QString::null,      this);
00298     QPushButton*  bStep       = new DbgButton(BarIcon("dbgstep"),       QString::null,      this);
00299     QPushButton*  bStepi      = new DbgButton(BarIcon("dbgstepinst"),   QString::null,      this);
00300     QPushButton*  bFinish     = new DbgButton(BarIcon("dbgstepout"),    i18n("Step Out"),   this);
00301     QPushButton*  bRunTo      = new DbgButton(BarIcon("dbgrunto"),      i18n("Run to Cursor"),   this);
00302     QPushButton*  bView       = new DbgButton(BarIcon("dbgmemview"),    i18n("Viewers"),    this);
00303     bKDevFocus_ = new DbgButton(BarIcon("kdevelop"),      QString::null,      this);
00304     bPrevFocus_ = new DbgButton(BarIcon("dbgmemview"),    QString::null,      this);
00305 
00306   connect(bRun,        SIGNAL(clicked()), part_,  SLOT(slotRun()));
00307   connect(bInterrupt,  SIGNAL(clicked()), part_,  SLOT(slotPause()));
00308   connect(bNext,       SIGNAL(clicked()), part_,  SLOT(slotStepOver()));
00309   connect(bNexti,      SIGNAL(clicked()), part_,  SLOT(slotStepOverInstruction()));
00310   connect(bStep,       SIGNAL(clicked()), part_,  SLOT(slotStepInto()));
00311   connect(bStepi,      SIGNAL(clicked()), part_,  SLOT(slotStepIntoInstruction()));
00312   connect(bFinish,     SIGNAL(clicked()), part_,  SLOT(slotStepOut()));
00313   connect(bRunTo,      SIGNAL(clicked()), part_,  SLOT(slotRunToCursor()));
00314   connect(bView,       SIGNAL(clicked()), part_,  SLOT(slotMemoryView()));
00315   connect(bKDevFocus_, SIGNAL(clicked()), this,   SLOT(slotKdevFocus()));
00316   connect(bPrevFocus_, SIGNAL(clicked()), this,   SLOT(slotPrevFocus()));
00317 
00318     QToolTip::add( bRun,        i18n("Continue with application execution, may start the application") );
00319     QToolTip::add( bInterrupt,  i18n("Interrupt the application execution") );
00320     QToolTip::add( bNext,       i18n("Execute one line of code, but run through functions") );
00321     QToolTip::add( bNexti,      i18n("Execute one assembler instruction, but run through functions") );
00322     QToolTip::add( bStep,       i18n("Execute one line of code, stepping into functions if appropriate") );
00323     QToolTip::add( bStepi,      i18n("Execute one assembler instruction, stepping into functions if appropriate") );
00324     QToolTip::add( bFinish,     i18n("Execute to end of current stack frame") );
00325     QToolTip::add( bRunTo,      i18n("Continues execution until the cursor position is reached.") );
00326     QToolTip::add( bView,       i18n("Memory, dissemble, registers, library viewers") );
00327     QToolTip::add( bKDevFocus_, i18n("Set focus on KDevelop") );
00328     QToolTip::add( bPrevFocus_, i18n("Set focus on window that had focus when KDevelop got focus") );
00329 
00330     QWhatsThis::add( bRun,        i18n("Continue with application execution. May start the application.") );
00331     QWhatsThis::add( bInterrupt,  i18n("Interrupt the application execution.") );
00332     QWhatsThis::add( bNext,       i18n("Execute one line of code, but run through functions.") );
00333     QWhatsThis::add( bNexti,      i18n("Execute one assembler instruction, but run through functions.") );
00334     QWhatsThis::add( bStep,       i18n("Execute one line of code, stepping into functions if appropriate.") );
00335     QWhatsThis::add( bStepi,      i18n("Execute one assembler instruction, stepping into functions if appropriate.") );
00336     QWhatsThis::add( bFinish,     i18n("Execute to end of current stack frame.") );
00337     QWhatsThis::add( bRunTo,      i18n("Continues execution until the cursor position is reached.") );
00338     QWhatsThis::add( bView,       i18n("Memory, dissemble, registers, library viewers.") );
00339     QWhatsThis::add( bKDevFocus_, i18n("Set focus on KDevelop.") );
00340     QWhatsThis::add( bPrevFocus_, i18n("Set focus on window that had focus when KDevelop got focus.") );
00341 
00342     topLayout->addWidget(moveHandle);
00343     topLayout->addWidget(bRun);
00344     topLayout->addLayout(nextLayout);
00345     topLayout->addLayout(stepLayout);
00346     topLayout->addWidget(bFinish);
00347     topLayout->addWidget(bRunTo);
00348     topLayout->addWidget(bView);
00349     topLayout->addWidget(bInterrupt);
00350     topLayout->addLayout(focusLayout);
00351 
00352     focusLayout->addWidget(bKDevFocus_);
00353     focusLayout->addWidget(bPrevFocus_);
00354 
00355     stepLayout->addWidget(bStep);
00356     stepLayout->addWidget(bStepi);
00357 
00358     nextLayout->addWidget(bNext);
00359     nextLayout->addWidget(bNexti);
00360 
00361 //     int w = QMAX(bRun->sizeHint().width(), bFinish->sizeHint().width());
00362 //     w = QMAX(w, bInterrupt->sizeHint().width());
00363 //     w = QMAX(w, bView->sizeHint().width());
00364 
00365     // they should have the same height, so don't be too fussy
00366 //     int h = bFinish->sizeHint().height();
00367 //
00368 //     bNext->setMinimumHeight(h);
00369 //     bNexti->setMinimumHeight(h);
00370 //     bStep->setMinimumHeight(h);
00371 //     bStepi->setMinimumHeight(h);
00372 //     bKDevFocus_->setMinimumHeight(h);
00373 //     bPrevFocus_->setMinimumHeight(h);
00374 
00375 //    setMinimumSize(w+10, h*7);
00376 //    setMaximumSize(w+10, h*7);
00377 
00378     setAppIndicator(appIsActive_);
00379     topLayout->activate();
00380 }
00381 
00382 // **************************************************************************
00383 
00384 DbgToolBar::~DbgToolBar()
00385 {
00386     slotUndock();
00387 }
00388 
00389 // **************************************************************************
00390 
00391 void DbgToolBar::slotKdevFocus()
00392 {
00393     // I really want to be able to set the focus on the _application_ being debugged
00394     // but this is the best compromise I can come up with. All we do is save the
00395     // window that had focus when they switch to the kdevelop window. To do this
00396     // the toolbar _cannot_ accept focus.
00397     // If anyone has a way of determining what window the app is _actually_ running on
00398     // then please fix and send a patch.
00399 
00400     if (winModule_->activeWindow() != topLevelWidget()->winId())
00401         activeWindow_ = winModule_->activeWindow();
00402 
00403     KWin::activateWindow(topLevelWidget()->winId());
00404 }
00405 
00406 // **************************************************************************
00407 
00408 void DbgToolBar::slotPrevFocus()
00409 {
00410     KWin::activateWindow(activeWindow_);
00411 }
00412 
00413 // **************************************************************************
00414 
00415 // If the app is active then the app button is highlighted, otherwise
00416 // kdev button is highlighted.
00417 void DbgToolBar::slotDbgStatus(const QString&, int state)
00418 {
00419     bool appIndicator = state & s_appBusy;
00420     if (appIndicator != appIsActive_) {
00421         setAppIndicator(appIndicator);
00422         appIsActive_ = appIndicator;
00423     }
00424 }
00425 
00426 // **************************************************************************
00427 
00428 void DbgToolBar::setAppIndicator(bool appIndicator)
00429 {
00430     if (appIndicator) {
00431         bPrevFocus_->setPalette(QPalette(colorGroup().mid()));
00432         bKDevFocus_->setPalette(QPalette(colorGroup().background()));
00433     } else {
00434         bPrevFocus_->setPalette(QPalette(colorGroup().background()));
00435         bKDevFocus_->setPalette(QPalette(colorGroup().mid()));
00436     }
00437 }
00438 
00439 // **************************************************************************
00440 
00441 void DbgToolBar::slotDock()
00442 {
00443     if (docked_)
00444         return;
00445 
00446     //  Q_ASSERT(!docker_);
00447     hide();
00448 
00449     docker_->show();
00450     docked_ = true;
00451 }
00452 
00453 // **************************************************************************
00454 
00455 void DbgToolBar::slotIconifyAndDock()
00456 {
00457     if (docked_)
00458         return;
00459 
00460     //  KWin::iconifyWindow(ckDevelop_->winId(), true);
00461     slotDock();
00462 }
00463 
00464 // **************************************************************************
00465 
00466 void DbgToolBar::slotUndock()
00467 {
00468     if (!docked_)
00469         return;
00470 
00471     show();
00472     docker_->hide();
00473     docked_ = false;
00474 }
00475 
00476 // **************************************************************************
00477 
00478 void DbgToolBar::slotActivateAndUndock()
00479 {
00480     if (!docked_)
00481         return;
00482 
00483     KWin::activateWindow(topLevelWidget()->winId());
00484     slotUndock();
00485 }
00486 
00487 }
00488 
00489 // **************************************************************************
00490 #include "dbgtoolbar.moc"
KDE Logo
This file is part of the documentation for KDevelop Version 3.1.2.
Documentation copyright © 1996-2004 the KDE developers.
Generated on Tue Feb 22 09:22:29 2005 by doxygen 1.3.9.1 written by Dimitri van Heesch, © 1997-2003