/*************************************************************************** begin : Thu Dec 23 1999 copyright : (C) 1999 by John Birch email : jbb@kdevelop.org ***************************************************************************/ /*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/ #ifndef TQT_MAC #include "dbgtoolbar.h" #include "debuggerpart.h" #include "dbgcontroller.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include // ************************************************************************** // ************************************************************************** // ************************************************************************** // Implements a floating toolbar for the debugger. // Unfortunately, I couldn't get the TDEToolBar to work nicely when it // was floating, so I was forced to write these classes. I'm not sure whether // I didn't try hard enough or ... and I've forgotten what the problems were // now. // The problem with using this is that it will not dock as a normal toolbar. // I'm not convince that this is a real problem though. // So, if you can get it to work as a TDEToolBar, and it works well when the // app is running, then all these classes can be removed. // This code is very specific to the internal debugger in tdevelop. namespace GDBDebugger { // ************************************************************************** // ************************************************************************** // ************************************************************************** // This just allows the user to click on the toolbar and drag it somewhere else. // I would have preferred to use normal decoration on the toolbar and removed // the iconify, close, etc buttons from the window title but again I kept running // into problems. Instead, I used no decoration and this class. Also this looks // similar to the TDEToolBar floating style. class DbgMoveHandle : public TQFrame { public: DbgMoveHandle(DbgToolBar *parent=0, const char * name=0, WFlags f=0); virtual ~DbgMoveHandle(); virtual void mousePressEvent(TQMouseEvent *e); virtual void mouseReleaseEvent(TQMouseEvent *e); virtual void mouseMoveEvent(TQMouseEvent *e); private: DbgToolBar* toolBar_; TQPoint offset_; bool moving_; }; // ************************************************************************** DbgMoveHandle::DbgMoveHandle(DbgToolBar *parent, const char * name, WFlags f) : TQFrame(parent, name, f), toolBar_(parent), offset_(TQPoint(0,0)), moving_(false) { setFrameStyle(TQFrame::Panel|TQFrame::Raised); setFixedHeight(12); } // ************************************************************************** DbgMoveHandle::~DbgMoveHandle() { } // ************************************************************************** void DbgMoveHandle::mousePressEvent(TQMouseEvent *e) { TQFrame::mousePressEvent(e); if (moving_) return; if (e->button() == Qt::RightButton) { TDEPopupMenu *menu = new TDEPopupMenu(this); menu->insertTitle(i18n("Debug Toolbar")); menu->insertItem(i18n("Dock to Panel"), parent(), TQT_SLOT(slotDock())); menu->insertItem(i18n("Dock to Panel && Iconify TDevelop"), parent(), TQT_SLOT(slotIconifyAndDock())); menu->popup(e->globalPos()); } else { moving_ = true; offset_ = parentWidget()->pos() - e->globalPos(); setFrameStyle(TQFrame::Panel|TQFrame::Sunken); TQApplication::setOverrideCursor(TQCursor(sizeAllCursor)); setPalette(TQPalette(colorGroup().background())); repaint(); } } // ************************************************************************** void DbgMoveHandle::mouseReleaseEvent(TQMouseEvent *e) { TQFrame::mouseReleaseEvent(e); moving_ = false; offset_ = TQPoint(0,0); setFrameStyle(TQFrame::Panel|TQFrame::Raised); TQApplication::restoreOverrideCursor(); setPalette(TQPalette(colorGroup().background())); repaint(); } // ************************************************************************** void DbgMoveHandle::mouseMoveEvent(TQMouseEvent *e) { TQFrame::mouseMoveEvent(e); if (!moving_) return; toolBar_->move(e->globalPos() + offset_); } // ************************************************************************** // ************************************************************************** // ************************************************************************** // This class adds text _and_ a pixmap to a button. Why doesn't TQPushButton // support that? It only allowed text _or_ pixmap. class DbgButton : public TQPushButton { public: DbgButton(const TQPixmap &pixmap, const TQString &text, DbgToolBar *parent, const char *name=0); virtual ~DbgButton() {}; void drawButtonLabel(TQPainter *painter); TQSize sizeHint() const; private: TQPixmap pixmap_; }; // ************************************************************************** DbgButton::DbgButton(const TQPixmap& pixmap, const TQString& text, DbgToolBar* parent, const char* name) : TQPushButton(parent, name), pixmap_(pixmap) { setText(text); } // ************************************************************************** void DbgButton::drawButtonLabel(TQPainter *painter) { // We always have a pixmap (today...) // Centre it if there's no text bool hasText = !text().isEmpty(); int x = ((hasText ? height() : width()) - pixmap_.width()) / 2; int y = (height() - pixmap_.height()) / 2; painter->drawPixmap(x, y, pixmap_); if (hasText) { painter->setPen(colorGroup().text()); painter->drawText(height()+2, 0, width()-(height()+2), height(), AlignLeft|AlignVCenter, text()); } } // ************************************************************************** TQSize DbgButton::sizeHint() const { if (text().isEmpty()) return pixmap_.size(); else { TQSize ps = pixmap_.size(); TQSize bs = TQPushButton::sizeHint(); TQSize result; result.setWidth( ps.width() + bs.width()+10 ); result.setHeight( ps.height() > bs.height() ? ps.height() : bs.height() ); return result; } } // ************************************************************************** // ************************************************************************** // ************************************************************************** DbgDocker::DbgDocker(TQWidget* parent, DbgToolBar* toolBar, const TQPixmap& pixmap) : KSystemTray(parent, "DbgDocker"), toolBar_(toolBar) { setPixmap(pixmap); TQToolTip::add( this, i18n("TDevelop debugger: Click to execute one line of code (\"step\")") ); } // ************************************************************************** void DbgDocker::mousePressEvent(TQMouseEvent *e) { if (!TQT_TQRECT_OBJECT(rect()).contains( e->pos())) return; switch (e->button()) { case Qt::LeftButton: { // Not really a click, but it'll hold for the time being !!! emit clicked(); break; } case Qt::RightButton: { TDEPopupMenu* menu = new TDEPopupMenu(this); menu->insertTitle(i18n("Debug Toolbar")); menu->insertItem(i18n("Activate"), toolBar_, TQT_SLOT(slotUndock())); menu->insertItem(i18n("Activate (TDevelop gets focus)"), toolBar_, TQT_SLOT(slotActivateAndUndock())); menu->popup(e->globalPos()); break; } default: break; } } // ************************************************************************** // ************************************************************************** // ************************************************************************** DbgToolBar::DbgToolBar(DebuggerPart* part, TQWidget* parent, const char* name) : TQFrame(0, name), part_(part), activeWindow_(0), winModule_(0), bKDevFocus_(0), bPrevFocus_(0), appIsActive_(false), docked_(false), docker_(0), dockWindow_(new KSystemTray(parent)) { winModule_ = new KWinModule(TQT_TQOBJECT(this)); docker_ = new DbgDocker(parent, this, BarIcon("dbgnext")); connect(docker_, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepOver())); // Must have noFocus set so that we can see what window was active. // see slotDbgKdevFocus() for more comments // I do not want the user to be able to "close" this widget. If we have any // decoration then they can and that is bad. // This widget is closed when the debugger finishes i.e. they press "Stop" // Do we need NoFocus??? KWin::setState(winId(), NET::StaysOnTop | NET::SkipTaskbar); // KWin::setType(winId(), NET::Override); // So it has no decoration KWin::setType(winId(), NET::Dock); setFocusPolicy(TQ_NoFocus); setFrameStyle( TQFrame::Box | TQFrame::Plain ); setLineWidth(4); setMidLineWidth(0); TQBoxLayout* topLayout = new TQVBoxLayout(this); TQBoxLayout* nextLayout = new TQHBoxLayout(); TQBoxLayout* stepLayout = new TQHBoxLayout(); TQBoxLayout* focusLayout = new TQHBoxLayout(); DbgMoveHandle* moveHandle= new DbgMoveHandle(this); TQPushButton* bRun = new DbgButton(BarIcon("dbgrun"), i18n("Run"), this); TQPushButton* bInterrupt = new DbgButton(BarIcon("media-playback-pause"), i18n("Interrupt"), this); TQPushButton* bNext = new DbgButton(BarIcon("dbgnext"), TQString(), this); TQPushButton* bNexti = new DbgButton(BarIcon("dbgnextinst"), TQString(), this); TQPushButton* bStep = new DbgButton(BarIcon("dbgstep"), TQString(), this); TQPushButton* bStepi = new DbgButton(BarIcon("dbgstepinst"), TQString(), this); TQPushButton* bFinish = new DbgButton(BarIcon("dbgstepout"), i18n("Step Out"), this); TQPushButton* bRunTo = new DbgButton(BarIcon("dbgrunto"), i18n("Run to Cursor"), this); TQPushButton* bView = new DbgButton(BarIcon("dbgmemview"), i18n("Viewers"), this); bKDevFocus_ = new DbgButton(BarIcon("tdevelop"), TQString(), this); bPrevFocus_ = new DbgButton(BarIcon("dbgmemview"), TQString(), this); connect(bRun, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotRun())); connect(bInterrupt, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotPause())); connect(bNext, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepOver())); connect(bNexti, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepOverInstruction())); connect(bStep, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepInto())); connect(bStepi, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepIntoInstruction())); connect(bFinish, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotStepOut())); connect(bRunTo, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotRunToCursor())); connect(bView, TQT_SIGNAL(clicked()), part_, TQT_SLOT(slotMemoryView())); connect(bKDevFocus_, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotKdevFocus())); connect(bPrevFocus_, TQT_SIGNAL(clicked()), this, TQT_SLOT(slotPrevFocus())); TQToolTip::add( bRun, i18n("Continue with application execution, may start the application") ); TQToolTip::add( bInterrupt, i18n("Interrupt the application execution") ); TQToolTip::add( bNext, i18n("Execute one line of code, but run through functions") ); TQToolTip::add( bNexti, i18n("Execute one assembler instruction, but run through functions") ); TQToolTip::add( bStep, i18n("Execute one line of code, stepping into functions if appropriate") ); TQToolTip::add( bStepi, i18n("Execute one assembler instruction, stepping into functions if appropriate") ); TQToolTip::add( bFinish, i18n("Execute to end of current stack frame") ); TQToolTip::add( bRunTo, i18n("Continues execution until the cursor position is reached.") ); TQToolTip::add( bView, i18n("Memory, dissemble, registers, library viewers") ); TQToolTip::add( bKDevFocus_, i18n("Set focus on TDevelop") ); TQToolTip::add( bPrevFocus_, i18n("Set focus on window that had focus when TDevelop got focus") ); TQWhatsThis::add( bRun, i18n("Continue with application execution. May start the application.") ); TQWhatsThis::add( bInterrupt, i18n("Interrupt the application execution.") ); TQWhatsThis::add( bNext, i18n("Execute one line of code, but run through functions.") ); TQWhatsThis::add( bNexti, i18n("Execute one assembler instruction, but run through functions.") ); TQWhatsThis::add( bStep, i18n("Execute one line of code, stepping into functions if appropriate.") ); TQWhatsThis::add( bStepi, i18n("Execute one assembler instruction, stepping into functions if appropriate.") ); TQWhatsThis::add( bFinish, i18n("Execute to end of current stack frame.") ); TQWhatsThis::add( bRunTo, i18n("Continues execution until the cursor position is reached.") ); TQWhatsThis::add( bView, i18n("Memory, dissemble, registers, library viewers.") ); TQWhatsThis::add( bKDevFocus_, i18n("Set focus on TDevelop.") ); TQWhatsThis::add( bPrevFocus_, i18n("Set focus on window that had focus when TDevelop got focus.") ); topLayout->addWidget(moveHandle); topLayout->addWidget(bRun); topLayout->addLayout(nextLayout); topLayout->addLayout(stepLayout); topLayout->addWidget(bFinish); topLayout->addWidget(bRunTo); topLayout->addWidget(bView); topLayout->addWidget(bInterrupt); topLayout->addLayout(focusLayout); focusLayout->addWidget(bKDevFocus_); focusLayout->addWidget(bPrevFocus_); stepLayout->addWidget(bStep); stepLayout->addWidget(bStepi); nextLayout->addWidget(bNext); nextLayout->addWidget(bNexti); // int w = TQMAX(bRun->sizeHint().width(), bFinish->sizeHint().width()); // w = TQMAX(w, bInterrupt->sizeHint().width()); // w = TQMAX(w, bView->sizeHint().width()); // they should have the same height, so don't be too fussy // int h = bFinish->sizeHint().height(); // // bNext->setMinimumHeight(h); // bNexti->setMinimumHeight(h); // bStep->setMinimumHeight(h); // bStepi->setMinimumHeight(h); // bKDevFocus_->setMinimumHeight(h); // bPrevFocus_->setMinimumHeight(h); // setMinimumSize(w+10, h*7); // setMaximumSize(w+10, h*7); setAppIndicator(appIsActive_); topLayout->activate(); } // ************************************************************************** DbgToolBar::~DbgToolBar() { slotUndock(); } // ************************************************************************** void DbgToolBar::slotKdevFocus() { // I really want to be able to set the focus on the _application_ being debugged // but this is the best compromise I can come up with. All we do is save the // window that had focus when they switch to the tdevelop window. To do this // the toolbar _cannot_ accept focus. // If anyone has a way of determining what window the app is _actually_ running on // then please fix and send a patch. if (winModule_->activeWindow() != topLevelWidget()->winId()) activeWindow_ = winModule_->activeWindow(); KWin::activateWindow(topLevelWidget()->winId()); } // ************************************************************************** void DbgToolBar::slotPrevFocus() { KWin::activateWindow(activeWindow_); } // ************************************************************************** // If the app is active then the app button is highlighted, otherwise // kdev button is highlighted. void DbgToolBar::slotDbgStatus(const TQString&, int state) { bool appIndicator = state & s_dbgBusy; if (appIndicator != appIsActive_) { setAppIndicator(appIndicator); appIsActive_ = appIndicator; } } // ************************************************************************** void DbgToolBar::setAppIndicator(bool appIndicator) { if (appIndicator) { bPrevFocus_->setPalette(TQPalette(colorGroup().mid())); bKDevFocus_->setPalette(TQPalette(colorGroup().background())); } else { bPrevFocus_->setPalette(TQPalette(colorGroup().background())); bKDevFocus_->setPalette(TQPalette(colorGroup().mid())); } } // ************************************************************************** void DbgToolBar::slotDock() { if (docked_) return; // Q_ASSERT(!docker_); hide(); docker_->show(); docked_ = true; } // ************************************************************************** void DbgToolBar::slotIconifyAndDock() { if (docked_) return; // KWin::iconifyWindow(ckDevelop_->winId(), true); slotDock(); } // ************************************************************************** void DbgToolBar::slotUndock() { if (!docked_) return; show(); docker_->hide(); docked_ = false; } // ************************************************************************** void DbgToolBar::slotActivateAndUndock() { if (!docked_) return; KWin::activateWindow(topLevelWidget()->winId()); slotUndock(); } } // ************************************************************************** #include "dbgtoolbar.moc" #endif