diff options
Diffstat (limited to 'src/newui')
-rw-r--r-- | src/newui/Makefile.am | 14 | ||||
-rw-r--r-- | src/newui/button.cpp | 350 | ||||
-rw-r--r-- | src/newui/button.h | 108 | ||||
-rw-r--r-- | src/newui/buttonbar.cpp | 346 | ||||
-rw-r--r-- | src/newui/buttonbar.h | 112 | ||||
-rw-r--r-- | src/newui/comdefs.h | 30 | ||||
-rw-r--r-- | src/newui/ddockwindow.cpp | 413 | ||||
-rw-r--r-- | src/newui/ddockwindow.h | 114 | ||||
-rw-r--r-- | src/newui/dmainwindow.cpp | 309 | ||||
-rw-r--r-- | src/newui/dmainwindow.h | 113 | ||||
-rw-r--r-- | src/newui/docksplitter.cpp | 175 | ||||
-rw-r--r-- | src/newui/docksplitter.h | 62 | ||||
-rw-r--r-- | src/newui/dtabwidget.cpp | 106 | ||||
-rw-r--r-- | src/newui/dtabwidget.h | 58 |
14 files changed, 2310 insertions, 0 deletions
diff --git a/src/newui/Makefile.am b/src/newui/Makefile.am new file mode 100644 index 00000000..b99b17e4 --- /dev/null +++ b/src/newui/Makefile.am @@ -0,0 +1,14 @@ +INCLUDES = -I$(top_srcdir)/lib -I$(top_srcdir)/lib/interfaces \ + -I$(top_srcdir)/lib/interfaces/extensions -I$(top_srcdir)/lib/interfaces/external \ + -I$(top_srcdir)/lib/interfaces/extras -I$(top_srcdir)/lib/util -I$(top_srcdir)/lib/widgets \ + -I$(top_srcdir)/src/profileengine/lib $(all_includes) +METASOURCES = AUTO + + +lib_LTLIBRARIES = libd.la +libd_la_LDFLAGS = $(all_libraries) + +noinst_HEADERS = dmainwindow.h ddockwindow.h buttonbar.h button.h comdefs.h docksplitter.h dtabwidget.h +libd_la_SOURCES = dmainwindow.cpp buttonbar.cpp \ + button.cpp ddockwindow.cpp docksplitter.cpp dtabwidget.cpp +libd_la_LIBADD = $(LIB_KPARTS) $(LIB_QT) $(LIB_KDECORE) $(LIB_KDEUI) diff --git a/src/newui/button.cpp b/src/newui/button.cpp new file mode 100644 index 00000000..d2403422 --- /dev/null +++ b/src/newui/button.cpp @@ -0,0 +1,350 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "button.h" + +#include <qpainter.h> +#include <qtooltip.h> +#include <qstyle.h> +#include <qapplication.h> +#include <qregexp.h> + +#include <kdebug.h> +#include <kiconloader.h> +#include <kxmlguiclient.h> +#include <kaction.h> +#include <kpopupmenu.h> +#include <kinputdialog.h> +#include <klocale.h> +#include <kapplication.h> +#include <kconfig.h> + +#include "buttonbar.h" + +namespace Ideal { + +Button::Button(ButtonBar *parent, const QString text, const QIconSet &icon, + const QString &description) + :QPushButton(icon, text, parent), m_buttonBar(parent), m_description(description), + m_place(parent->place()), m_realText(text), m_realIconSet(icon) +{ + hide(); + setFlat(true); + setToggleButton(true); + setFocusPolicy(NoFocus); + setDescription(m_description); + setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Minimum); + resize(sizeHint()); + fixDimensions(Ideal::Bottom); + + QToolTip::add(this, m_realText); + + m_assignAccelAction = new KAction(i18n("Assign Accelerator..."), 0, + this, SLOT(assignAccel()), this); + m_clearAccelAction = new KAction(i18n("Clear Accelerator"), 0, + this, SLOT(clearAccel()), this); + + KConfig *config = kapp->config(); + config->setGroup("UI"); + QString accel = config->readEntry(QString("button_%1").arg(text), ""); + if (!accel.isEmpty()) + setRealText(QString("&%1 %2").arg(accel).arg(m_realText)); +} + +Button::~Button() +{ +// m_buttonBar->removeButton(this); + KConfig *config = kapp->config(); + config->setGroup("UI"); + + QRegExp r("^&([0-9])\\s.*"); + QRegExp r2("^&[0-9]\\s"); + if (r.search(m_realText) > -1) + { + QString text = m_realText; + if (text.contains(r2)) + text.remove(r2); + config->writeEntry(QString("button_%1").arg(text), r.cap(1)); + } + else + { + config->writeEntry(QString("button_%1").arg(m_realText), ""); + } +} + +void Button::setDescription(const QString &description) +{ + m_description = description; + QToolTip::remove(this); + QToolTip::add(this, m_description); +} + +QString Button::description() const +{ + return m_description; +} + +void Button::drawButton(QPainter *p) +{ + QRect r = rect(); + QSize sh = r.size(); + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + sh.setHeight(r.width()); + sh.setWidth(r.height()); + break; + } + + QStyle::SFlags flags = QStyle::Style_Default; + if (isEnabled()) + flags |= QStyle::Style_Enabled; + if (hasFocus()) + flags |= QStyle::Style_HasFocus; + if (isDown()) + flags |= QStyle::Style_Down; + if (isOn()) + flags |= QStyle::Style_On; + if (! isFlat() && ! isDown()) + flags |= QStyle::Style_Raised; + if (isDefault()) + flags |= QStyle::Style_ButtonDefault; + + QPixmap pm(sh.width(), sh.height()); + pm.fill(eraseColor()); + QPainter p2(&pm); + + style().drawControl(QStyle::CE_PushButton,&p2,this, QRect(0,0,pm.width(),pm.height()), colorGroup(),flags); + + style().drawControl(QStyle::CE_PushButtonLabel, &p2, this, + QRect(0,0,pm.width(),pm.height()), + colorGroup(), flags, QStyleOption()); + + switch (m_place) + { + case Ideal::Left: + p->rotate(-90); + p->drawPixmap(1-pm.width(), 0, pm); + break; + case Ideal::Right: + p->rotate(90); + p->drawPixmap(0, 1-pm.height(), pm); + break; + default: + p->drawPixmap(0, 0, pm); + break; + } +} + +void Button::drawButtonLabel(QPainter */*p*/) +{ +} + +ButtonMode Button::mode() +{ + return m_buttonBar->mode(); +} + +void Button::setPlace(Ideal::Place place) +{ + Place oldPlace = m_place; + m_place = place; + fixDimensions(oldPlace); +} + +void Button::fixDimensions(Place oldPlace) +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + if ((oldPlace == Ideal::Bottom) || (oldPlace == Ideal::Top)) + { + setFixedWidth(height()); + setMinimumHeight(sizeHint().width()); + setMaximumHeight(32767); + } + break; + case Ideal::Top: + case Ideal::Bottom: + if ((oldPlace == Ideal::Left) || (oldPlace == Ideal::Right)) + { + setFixedHeight(width()); + setMinimumWidth(sizeHint().height()); + setMaximumWidth(32767); + } + break; + } +} + +QSize Button::sizeHint() const +{ + return sizeHint(text()); +} + +QSize Button::sizeHint(const QString &text) const +{ + constPolish(); + int w = 0, h = 0; + + if ( iconSet() && !iconSet()->isNull() && (m_buttonBar->mode() != Text) ) { + int iw = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).width() + 4; + int ih = iconSet()->pixmap( QIconSet::Small, QIconSet::Normal ).height(); + w += iw; + h = QMAX( h, ih ); + } + if ( isMenuButton() ) + w += style().pixelMetric(QStyle::PM_MenuButtonIndicator, this); + if ( pixmap() ) { + QPixmap *pm = (QPixmap *)pixmap(); + w += pm->width(); + h += pm->height(); + } else if (m_buttonBar->mode() != Icons) { + QString s( text ); + bool empty = s.isEmpty(); + if ( empty ) + s = QString::fromLatin1("XXXX"); + QFontMetrics fm = fontMetrics(); + QSize sz = fm.size( ShowPrefix, s ); + if(!empty || !w) + w += sz.width(); + if(!empty || !h) + h = QMAX(h, sz.height()); + } + + return (style().sizeFromContents(QStyle::CT_ToolButton, this, QSize(w, h)). + expandedTo(QApplication::globalStrut())); +} + +void Button::updateSize() +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + setMinimumHeight(sizeHint().width()); + resize(sizeHint().height(), sizeHint().width()); + break; + case Ideal::Top: + case Ideal::Bottom: + resize(sizeHint().width(), sizeHint().height()); + break; + } +} + +QString Button::realText() const +{ + return m_realText; +} + +void Button::setMode(Ideal::ButtonMode mode) +{ + switch (mode) + { + case Text: + disableIconSet(); + enableText(); + break; + case IconsAndText: + enableIconSet(); + enableText(); + break; + case Icons: + disableText(); + enableIconSet(); + break; + } +} + +void Button::enableIconSet() +{ + if (!iconSet()) + { + if (m_realIconSet.isNull()) + m_realIconSet = SmallIcon("file_new"); + setIconSet(m_realIconSet); + } +} + +void Button::disableIconSet() +{ + setIconSet(QIconSet()); +} + +void Button::disableText() +{ + if (text().length() > 0) + setText(""); +} + +void Button::enableText() +{ + setText(m_realText); +} + +void Button::contextMenuEvent(QContextMenuEvent *e) +{ + QPopupMenu menu; + + m_assignAccelAction->plug(&menu); + if (m_realText.contains(QRegExp("^&[0-9]\\s"))) + m_clearAccelAction->plug(&menu); + + emit contextMenu( &menu ); + + menu.exec(e->globalPos()); +} + +void Button::assignAccel() +{ + bool ok; + int num = KInputDialog::getInteger(i18n("Change Button Number"), i18n("New accelerator number:"), 1, 0, 10, 1, &ok, this); + if (ok) + { + QString text = realTextWithoutAccel(); + text = QString("&%1 %2").arg(num).arg(text); + setRealText(text); + } +} + +void Button::setRealText(const QString &text) +{ + m_realText = text; + setText(text); + updateSize(); +} + +void Button::clearAccel() +{ + setRealText(realTextWithoutAccel()); +} + +QString Button::realTextWithoutAccel() const +{ + QString text = m_realText; + QRegExp r("^&[0-9]\\s"); + if (text.contains(r)) + text.remove(r); + return text; +} + +} + +#include "button.moc" diff --git a/src/newui/button.h b/src/newui/button.h new file mode 100644 index 00000000..a7afbcfe --- /dev/null +++ b/src/newui/button.h @@ -0,0 +1,108 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef IDEALBUTTON_H +#define IDEALBUTTON_H + +#include <qpushbutton.h> +#include <qiconset.h> + +#include "comdefs.h" + +class KAction; + +namespace Ideal { + +class ButtonBar; + +/** +@short A button to place onto the ButtonBar + +A QPushButton derivative with a size of a QToolBar. Button can be rotated +(placed onto different places in ideal mode). +*/ +class Button : public QPushButton { + Q_OBJECT +public: + Button(ButtonBar *parent, const QString text, const QIconSet &icon = QIconSet(), + const QString &description = QString::null); + + /**Sets the description used as a tooltip.*/ + void setDescription(const QString &description); + /**Returns the description.*/ + QString description() const; + + /**Sets the place of a button.*/ + void setPlace(Ideal::Place place); + /**Sets the mode of a button.*/ + void setMode(Ideal::ButtonMode mode); + + QSize sizeHint() const; + QSize sizeHint(const QString &text) const; + + /**Updates size of a widget. Used after squeezing button's text.*/ + void updateSize(); + + /**Returns the real (i.e. not squeezed) text of a button.*/ + QString realText() const; + QString realTextWithoutAccel() const; + void setRealText(const QString &text); + +protected: + ButtonMode mode(); + + virtual void drawButton(QPainter *p); + virtual void drawButtonLabel(QPainter *p); + + virtual void contextMenuEvent(QContextMenuEvent *e); + +protected slots: + void assignAccel(); + void clearAccel(); + +signals: + void contextMenu(QPopupMenu*); + +private: + virtual ~Button(); + + void fixDimensions(Place oldPlace); + + void enableIconSet(); + void disableIconSet(); + void enableText(); + void disableText(); + + ButtonBar *m_buttonBar; + + QString m_description; + Place m_place; + + QString m_realText; + QIconSet m_realIconSet; + + KAction *m_assignAccelAction; + KAction *m_clearAccelAction; + +friend class ButtonBar; +}; + +} + +#endif diff --git a/src/newui/buttonbar.cpp b/src/newui/buttonbar.cpp new file mode 100644 index 00000000..8f60dabf --- /dev/null +++ b/src/newui/buttonbar.cpp @@ -0,0 +1,346 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "buttonbar.h" + +#include <qlayout.h> + +#include <kdebug.h> +#include <kconfig.h> +#include <kstringhandler.h> +#include <klocale.h> + +#include "button.h" + +namespace Ideal { + +//ButtonLayout class + +ButtonLayout::ButtonLayout(ButtonBar *parent, Direction d, int margin, int spacing, const char *name) + :QBoxLayout(parent, d, margin, spacing, name), m_buttonBar(parent) +{ +} + +QSize ButtonLayout::minimumSize() const +{ + QSize size = QBoxLayout::minimumSize(); + + if (!m_buttonBar->autoResize()) + return size; + + switch (m_buttonBar->place()) + { + case Ideal::Left: + case Ideal::Right: + return QSize(size.width(),0); + break; + case Ideal::Top: + case Ideal::Bottom: + return QSize(0,size.height()); + } + return QBoxLayout::minimumSize(); +} + + + +//ButtonBar class + + +ButtonBar::ButtonBar(Place place, ButtonMode mode, QWidget *parent, const char *name) + :QWidget(parent, name), m_place(place), l(0), m_shrinked(false), m_autoResize(true) +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + l = new ButtonLayout(this, QBoxLayout::TopToBottom, 0, 0); + break; + case Ideal::Top: + case Ideal::Bottom: + l = new ButtonLayout(this, QBoxLayout::LeftToRight, 0, 0); + break; + } + + l->setResizeMode(QLayout::Minimum); + setMode(mode); + + l->insertStretch(-1); +} + +ButtonBar::~ButtonBar() +{ +} + +void ButtonBar::addButton(Button *button) +{ + int buttonCount = m_buttons.count(); + + button->setMode(m_mode); + m_buttons.append(button); + l->insertWidget(buttonCount, button); + button->show(); + fixDimensions(); +} + +void ButtonBar::removeButton(Button *button) +{ + m_buttons.remove(button); + l->remove(button); + delete button; +} + +void ButtonBar::setMode(ButtonMode mode) +{ + m_mode = mode; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + (*it)->setMode(mode); +} + +ButtonMode ButtonBar::mode() const +{ + return m_mode; +} + +Place ButtonBar::place() const +{ + return m_place; +} + +void ButtonBar::fixDimensions() +{ + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + setFixedWidth(sizeHint().width()); + setMinimumHeight(sizeHint().height()); + setMaximumHeight(32767); + break; + case Ideal::Top: + case Ideal::Bottom: + setFixedHeight(sizeHint().height()); + setMinimumWidth(sizeHint().width()); + setMaximumWidth(32767); + break; + } +} + +void ButtonBar::setButtonsPlace(Ideal::Place place) +{ + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + (*it)->setPlace(place); +} + +void ButtonBar::resizeEvent(QResizeEvent *ev) +{ + int preferredDimension = 0; + int actualDimension = 0; + int oldDimension = 0; + switch (m_place) + { + case Ideal::Left: + case Ideal::Right: + preferredDimension = l->QBoxLayout::minimumSize().height(); + actualDimension = size().height(); + oldDimension = ev->oldSize().height(); + break; + case Ideal::Top: + case Ideal::Bottom: + preferredDimension = l->QBoxLayout::minimumSize().width(); + actualDimension = size().width(); + oldDimension = ev->oldSize().width(); + break; + } + + if (preferredDimension > actualDimension) + shrink(preferredDimension, actualDimension); + else if (m_shrinked && (originalDimension() < actualDimension)) + unshrink(); + else if (m_shrinked && actualDimension > oldDimension) + deshrink(preferredDimension, actualDimension); + + QWidget::resizeEvent(ev); +} + +void ButtonBar::shrink(int preferredDimension, int actualDimension) +{ + if (!preferredDimension) + return; + + m_shrinked = true; + + uint textLength = 0; + QValueList<uint> texts; + uint maxLength = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + uint length = (*it)->text().length(); + maxLength = length > maxLength ? length : maxLength ; + texts.append(length); + textLength += length; + } + + uint newPreferredLength = actualDimension * textLength / preferredDimension; + + uint newMaxLength = maxLength; + uint newTextLength; + do { + newMaxLength -= 1; + newTextLength = 0; + for (QValueList<uint>::iterator it = texts.begin(); it != texts.end(); ++it) + { + if (*it > newMaxLength) + *it = newMaxLength; + newTextLength += *it; + } + } while (newTextLength > newPreferredLength); + + int i = 0; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + (*it)->setText(KStringHandler::rsqueeze((*it)->realText(), texts[i++])); + (*it)->updateSize(); + } +} + +void ButtonBar::deshrink(int preferredDimension, int actualDimension) +{ + if (!preferredDimension) + return; + + m_shrinked = true; + + uint textLength = 0; + QValueList<uint> texts; + uint maxLength = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + uint length = (*it)->text().length(); + maxLength = length > maxLength ? length : maxLength ; + texts.append(length); + textLength += length; + } + + uint newPreferredLength = actualDimension * textLength / preferredDimension; + + if (newPreferredLength <= textLength) + return; + + uint newTextLength; + uint prevTextLength = 0; + do { + newTextLength = 0; + int i = 0; + for (QValueList<uint>::iterator it = texts.begin(); it != texts.end(); ++it, i++) + { + if (m_buttons[i]->text().contains("...")) + (*it)++; + newTextLength += *it; + } + if (newTextLength == prevTextLength) + break; + prevTextLength = newTextLength; + } while (newTextLength < newPreferredLength); + + int i = 0; + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + if (texts[i] >= (*it)->realText().length()) + (*it)->setText((*it)->realText()); + else + (*it)->setText(KStringHandler::rsqueeze((*it)->realText(), texts[i])); + (*it)->updateSize(); + ++i; + } +} + +void ButtonBar::unshrink() +{ + for (ButtonList::iterator it = m_buttons.begin(); it != m_buttons.end(); ++it) + { + (*it)->setText((*it)->realText()); + (*it)->updateSize(); + } + m_shrinked = false; +} + +int ButtonBar::originalDimension() +{ + int size = 0; + for (ButtonList::const_iterator it = m_buttons.constBegin(); it != m_buttons.constEnd(); ++it) + { + size += (*it)->sizeHint((*it)->realText()).width(); + } + return size; +} + +bool ButtonBar::autoResize() const +{ + return m_autoResize; +} + +void ButtonBar::setAutoResize(bool b) +{ + m_autoResize = b; +} + +Button *ButtonBar::firstButton() +{ + if (!m_buttons.isEmpty()) + return m_buttons.first(); + return 0; +} + +Button *ButtonBar::nextTo(Button *button) +{ + ButtonList::iterator it = m_buttons.find(button); + Button *next = 0; + if ((*it) == m_buttons.last()) + next = m_buttons.first(); + else + { + it++; + next = *it; + } + if (next->isVisible()) + return next; + else + return nextTo(next); +} + +Button *ButtonBar::prevTo(Button *button) +{ + ButtonList::iterator it = m_buttons.find(button); + Button *prev = 0; + if (it == m_buttons.begin()) + prev = m_buttons.last(); + else + { + it--; + prev = *it; + } + if (prev->isVisible()) + return prev; + else + return prevTo(prev); +} + +} + +#include "buttonbar.moc" diff --git a/src/newui/buttonbar.h b/src/newui/buttonbar.h new file mode 100644 index 00000000..5f5a7e36 --- /dev/null +++ b/src/newui/buttonbar.h @@ -0,0 +1,112 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef IDEALBUTTONBAR_H +#define IDEALBUTTONBAR_H + +#include <qwidget.h> +#include <qvaluelist.h> + +#include "comdefs.h" + +#include <qlayout.h> + +namespace Ideal { + +class Button; +class ButtonBar; + +/**@short A layout for a ButtonBar class. + +Overrides minimumSize method to allow shrinking button bar buttons.*/ +class ButtonLayout: public QBoxLayout{ +public: + ButtonLayout(ButtonBar *parent, Direction d, int margin = 0, int spacing = -1, const char * name = 0); + + virtual QSize minimumSize() const; + +private: + ButtonBar *m_buttonBar; +}; + +/** +@short A bar with tool buttons. + +Looks like a toolbar but has another behaviour. It is suitable for +placing on the left(right, bottom, top) corners of a window as a bar with slider. +*/ +class ButtonBar : public QWidget { + Q_OBJECT +public: + ButtonBar(Place place, ButtonMode mode = IconsAndText, + QWidget *parent = 0, const char *name = 0); + virtual ~ButtonBar(); + + /**Adds a button to the bar.*/ + virtual void addButton(Button *button); + /**Removes a button from the bar and deletes the button.*/ + virtual void removeButton(Button *button); + + /**Sets the mode.*/ + void setMode(ButtonMode mode); + /**@returns the mode.*/ + ButtonMode mode() const; + + /**@returns the place.*/ + Place place() const; + + bool autoResize() const; + void setAutoResize(bool b); + + /**Shrinks the button bar so all buttons are visible. Shrinking is done by + reducing the amount of text shown on buttons. Button icon size is a minimum size + of a button. If a button does not have an icon, it displays "...".*/ + virtual void shrink(int preferredDimension, int actualDimension); + virtual void deshrink(int preferredDimension, int actualDimension); + /**Restores the size of button bar buttons.*/ + virtual void unshrink(); + + Button *firstButton(); + Button *nextTo(Button *button); + Button *prevTo(Button *button); + +protected: + virtual void resizeEvent ( QResizeEvent *ev ); + + int originalDimension(); + +private: + void fixDimensions(); + void setButtonsPlace(Ideal::Place place); + + typedef QValueList<Button*> ButtonList; + ButtonList m_buttons; + + ButtonMode m_mode; + Place m_place; + + ButtonLayout *l; + + bool m_shrinked; + bool m_autoResize; +}; + +} + +#endif diff --git a/src/newui/comdefs.h b/src/newui/comdefs.h new file mode 100644 index 00000000..8233f12c --- /dev/null +++ b/src/newui/comdefs.h @@ -0,0 +1,30 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef COMDEFS_H +#define COMDEFS_H + +namespace Ideal { + + enum Place { Left=1, Right=2, Top=4, Bottom=8 }; + enum ButtonMode { Text, IconsAndText, Icons }; + +} + +#endif diff --git a/src/newui/ddockwindow.cpp b/src/newui/ddockwindow.cpp new file mode 100644 index 00000000..bb249abc --- /dev/null +++ b/src/newui/ddockwindow.cpp @@ -0,0 +1,413 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "ddockwindow.h" + +#include <qtoolbutton.h> +#include <qlayout.h> +#include <qstyle.h> +#include <qwidgetstack.h> +#include <qimage.h> +#include <qapplication.h> +#include <qpopupmenu.h> + +#include <kdebug.h> +#include <kglobal.h> +#include <kconfig.h> +#include <kcombobox.h> +#include <klocale.h> +#include <kiconloader.h> +#include <kapplication.h> + +#include "buttonbar.h" +#include "button.h" +#include "dmainwindow.h" + +DDockWindow::DDockWindow(DMainWindow *parent, Position position) + :QDockWindow(QDockWindow::InDock, parent), m_position(position), m_visible(false), + m_mainWindow(parent), m_doNotCloseActiveWidget(false), m_toggledButton(0), m_lastContextMenuButton(0) +{ + setMovingEnabled(false); + setResizeEnabled(true); + + Ideal::Place place = Ideal::Left; + switch (position) { + case DDockWindow::Bottom: + m_name = "BottomToolWindow"; + place = Ideal::Bottom; + m_internalLayout = new QVBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::BottomToTop); + break; + case DDockWindow::Left: + m_name = "LeftToolWindow"; + place = Ideal::Left; + m_internalLayout = new QHBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::LeftToRight); + break; + case DDockWindow::Right: + m_name = "RightToolWindow"; + place = Ideal::Right; + m_internalLayout = new QHBoxLayout(boxLayout(), 0); + m_internalLayout->setDirection(QBoxLayout::RightToLeft); + break; + } + + KConfig *config = kapp->config(); + config->setGroup("UI"); + int mode = config->readNumEntry("MDIStyle", 3); + Ideal::ButtonMode buttonMode = Ideal::Text; + if (mode == 0) + buttonMode = Ideal::Icons; + else if (mode == 1) + buttonMode = Ideal::Text; + else if (mode == 3) + buttonMode = Ideal::IconsAndText; + + m_bar = new Ideal::ButtonBar(place, buttonMode, this); + m_internalLayout->addWidget(m_bar); + + m_widgetStack = new QWidgetStack(this); + m_internalLayout->addWidget(m_widgetStack); + + m_moveToDockLeft = new KAction( i18n("Move to left dock"), 0, this, SLOT(moveToDockLeft()), this ); + m_moveToDockRight = new KAction( i18n("Move to right dock"), 0, this, SLOT(moveToDockRight()), this ); + m_moveToDockBottom = new KAction( i18n("Move to bottom dock"), 0, this, SLOT(moveToDockBottom()), this ); + + setVisible(m_visible); + + loadSettings(); +} + +DDockWindow::~DDockWindow() +{ +//done in DMainWindow now +// saveSettings(); +} + +void DDockWindow::setVisible(bool v) +{ + //write dock width to the config file + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + config->setGroup(group); + + if (m_visible) + config->writeEntry("ViewWidth", m_position == DDockWindow::Bottom ? height() : width() ); + setResizeEnabled(v); + setVerticallyStretchable(true); + setHorizontallyStretchable(true); + v ? m_widgetStack->show() : m_widgetStack->hide(); + m_visible = v; + + m_internalLayout->invalidate(); + if (!m_visible) + { + if (m_position == DDockWindow::Bottom) + setFixedExtentHeight(m_internalLayout->sizeHint().height()); + else + setFixedExtentWidth(m_internalLayout->sizeHint().width()); + emit hidden(); + } + else + { + //restore widget size from the config + int size = 0; + if (m_position == DDockWindow::Bottom) + { + size = config->readNumEntry("ViewWidth", m_internalLayout->sizeHint().height()); + setFixedExtentHeight(size); + } + else + { + size = config->readNumEntry("ViewWidth", m_internalLayout->sizeHint().width()); + setFixedExtentWidth(size); + } + } +} + +void DDockWindow::loadSettings() +{ +} + +void DDockWindow::saveSettings() +{ + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + int invisibleWidth = 0; + config->setGroup(group); + if (config->hasKey("ViewWidth")) + invisibleWidth = config->readNumEntry("ViewWidth"); + config->deleteEntry("ViewWidth"); + config->deleteEntry("ViewLastWidget"); + if (m_toggledButton && m_visible) + { + config->writeEntry("ViewWidth", m_position == DDockWindow::Bottom ? height() : width()); + config->writeEntry("ViewLastWidget", m_toggledButton->realTextWithoutAccel()); + } + else if (invisibleWidth != 0) + config->writeEntry("ViewWidth", invisibleWidth); +} + +QWidget *DDockWindow::currentWidget() const +{ + return m_widgetStack->visibleWidget(); +} + +void DDockWindow::addWidget(const QString &title, QWidget *widget, bool skipActivation) +{ + kdDebug(9000) << k_funcinfo << endl; + QPixmap *pm = const_cast<QPixmap*>(widget->icon()); + Ideal::Button *button; + if (pm != 0) + { + //force 16pt for now + if (pm->height() > 16) + { + QImage img = pm->convertToImage(); + img = img.smoothScale(16, 16); + pm->convertFromImage(img); + } + button = new Ideal::Button(m_bar, title, *pm); + } + else + button = new Ideal::Button(m_bar, title); + m_widgets[button] = widget; + m_buttons[widget] = button; + m_bar->addButton(button); + + m_widgetStack->addWidget(widget); + connect(button, SIGNAL(clicked()), this, SLOT(selectWidget())); + connect(button, SIGNAL(contextMenu(QPopupMenu*)), this, SLOT(contextMenu(QPopupMenu*)) ); + + if (!skipActivation) + { + //if the widget was selected last time the dock is deleted + //we need to show it + KConfig *config = kapp->config(); + QString group = QString("%1").arg(m_name); + config->setGroup(group); + if (config->readEntry("ViewLastWidget") == title) + { + kdDebug(9000) << k_funcinfo << " : activating last widget " << title << endl; + button->setOn(true); + selectWidget(button); + } + } +} + +void DDockWindow::raiseWidget(QWidget *widget) +{ + kdDebug(9000) << k_funcinfo << endl; + + if ( !widget ) return; + + Ideal::Button *button = m_buttons[widget]; + if ((button != 0) && (!button->isOn())) + { + button->setOn(true); + selectWidget(button); + } +} + +void DDockWindow::lowerWidget(QWidget * widget) +{ + kdDebug(9000) << k_funcinfo << endl; + + if ( !widget ) return; + + Ideal::Button *button = m_buttons[widget]; + if ((button != 0) && (button->isOn())) + { + button->setOn(false); + selectWidget(button); + } +} + +void DDockWindow::removeWidget(QWidget *widget) +{ + kdDebug(9000) << k_funcinfo << endl; + if (m_widgetStack->id(widget) == -1) + return; //not in dock + + bool changeVisibility = false; + if (m_widgetStack->visibleWidget() == widget) + changeVisibility = true; + + Ideal::Button *button = m_buttons[widget]; + if (button) + m_bar->removeButton(button); + m_widgets.remove(button); + m_buttons.remove(widget); + m_widgetStack->removeWidget(widget); + + if (changeVisibility) + { + m_toggledButton = 0; + setVisible(false); + } +} + +void DDockWindow::selectWidget(Ideal::Button *button) +{ + bool special = m_doNotCloseActiveWidget; + m_doNotCloseActiveWidget = false; + kdDebug(9000) << k_funcinfo << endl; + if (m_toggledButton == button) + { + if (special && m_visible && (!isActive())) + { + //special processing for keyboard navigation events + m_toggledButton->setOn(true); + m_widgets[button]->setFocus(); + } + else + { + m_widgets[button]->setFocus(); + setVisible(!m_visible); + } + return; + } + + if (m_toggledButton) + m_toggledButton->setOn(false); + m_toggledButton = button; + setVisible(true); + m_widgetStack->raiseWidget(m_widgets[button]); + m_widgets[button]->setFocus(); +} + +void DDockWindow::selectWidget() +{ + selectWidget((Ideal::Button*)sender()); +} + +void DDockWindow::hideWidget(QWidget *widget) +{ + Ideal::Button *button = m_buttons[widget]; + if (button != 0) + { + button->setOn(false); + button->hide(); + } + widget->hide(); + if (button == m_toggledButton) + setVisible(false); +} + +void DDockWindow::showWidget(QWidget *widget) +{ + Ideal::Button *button = m_buttons[widget]; + if (button != 0) + button->show(); +// widget->show(); +} + +void DDockWindow::setMovingEnabled(bool) +{ + //some operations on KMainWindow cause moving to be enabled + //but we always don't want DDockWindow instances to be movable + QDockWindow::setMovingEnabled(false); +} + +void DDockWindow::selectLastWidget() +{ + m_doNotCloseActiveWidget = true; + if (m_toggledButton) + m_toggledButton->animateClick(); + else if (Ideal::Button *button = m_bar->firstButton()) + button->animateClick(); +} + +bool DDockWindow::isActive() +{ + if (m_toggledButton) + { + QWidget *w = qApp->focusWidget(); + if (!w) + return false; + QWidget *toolWidget = m_widgets[m_toggledButton]; + if (toolWidget == w) + return true; + else + { + do { + w = (QWidget*)w->parent(); + if (w && (w == toolWidget)) return true; + } while (w); + } + } + return false; +} + +void DDockWindow::selectNextWidget() +{ + if (!m_toggledButton) + return; + Ideal::Button *b = m_bar->nextTo(m_toggledButton); + if (b) + b->animateClick(); +} + +void DDockWindow::selectPrevWidget() +{ + if (!m_toggledButton) + return; + Ideal::Button *b = m_bar->prevTo(m_toggledButton); + if (b) + b->animateClick(); +} + +void DDockWindow::contextMenu(QPopupMenu * menu) +{ + m_lastContextMenuButton = static_cast<Ideal::Button*>( const_cast<QObject*>( sender() ) ); + + menu->insertSeparator(); + + if ( position() != DDockWindow::Left ) + m_moveToDockLeft->plug( menu ); + if ( position()!= DDockWindow::Right ) + m_moveToDockRight->plug( menu ); + if ( position() != DDockWindow::Bottom ) + m_moveToDockBottom->plug( menu ); +} + +void DDockWindow::moveToDockLeft() +{ + moveToDock( DDockWindow::Left ); +} + +void DDockWindow::moveToDockRight() +{ + moveToDock( DDockWindow::Right ); +} + +void DDockWindow::moveToDockBottom() +{ + moveToDock( DDockWindow::Bottom ); +} + +void DDockWindow::moveToDock(DDockWindow::Position position ) +{ + if ( m_widgets.contains( m_lastContextMenuButton ) ) + { + mainWindow()->moveWidget( position, m_widgets[ m_lastContextMenuButton ], m_lastContextMenuButton->realTextWithoutAccel() ); + } +} + +#include "ddockwindow.moc" diff --git a/src/newui/ddockwindow.h b/src/newui/ddockwindow.h new file mode 100644 index 00000000..ece0db8c --- /dev/null +++ b/src/newui/ddockwindow.h @@ -0,0 +1,114 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DDOCKWINDOW_H +#define DDOCKWINDOW_H + +#include <qdockwindow.h> +#include <qvaluelist.h> + +class QBoxLayout; +class QToolButton; +class QWidgetStack; +class QPopupMenu; + +class KComboBox; +class KAction; + +class DMainWindow; + +namespace Ideal { + class Button; + class ButtonBar; +} + +class DDockWindow : public QDockWindow { + Q_OBJECT +public: + enum Position { Bottom, Left, Right }; + + DDockWindow(DMainWindow *parent, Position position); + virtual ~DDockWindow(); + + virtual void setVisible(bool v); + bool visible() const { return m_visible; } + Position position() const { return m_position; } + + virtual void addWidget(const QString &title, QWidget *widget, bool skipActivation = false); + virtual void raiseWidget(QWidget *widget); + virtual void lowerWidget(QWidget *widget); + /**Removes the widget from dock. Does not delete it.*/ + virtual void removeWidget(QWidget *widget); + + virtual void hideWidget(QWidget *widget); + virtual void showWidget(QWidget *widget); + + virtual QWidget *currentWidget() const; + + virtual void setMovingEnabled(bool b); + + virtual void saveSettings(); + + DMainWindow *mainWindow() const { return m_mainWindow; } + + virtual void selectLastWidget(); + virtual void selectNextWidget(); + virtual void selectPrevWidget(); + + bool isActive(); + +signals: + void hidden(); + +private slots: + void selectWidget(); + void selectWidget(Ideal::Button *button); + void contextMenu(QPopupMenu*); + void moveToDockLeft(); + void moveToDockRight(); + void moveToDockBottom(); + void moveToDock(DDockWindow::Position); + +protected: + virtual void loadSettings(); + + Ideal::ButtonBar *m_bar; + QWidgetStack *m_widgetStack; + + QMap<Ideal::Button*, QWidget*> m_widgets; + QMap<QWidget*, Ideal::Button*> m_buttons; + +private: + Position m_position; + bool m_visible; + QString m_name; + DMainWindow *m_mainWindow; + bool m_doNotCloseActiveWidget; + + Ideal::Button *m_toggledButton; + Ideal::Button *m_lastContextMenuButton; + QBoxLayout *m_internalLayout; + + + KAction * m_moveToDockLeft; + KAction * m_moveToDockRight; + KAction * m_moveToDockBottom; +}; + +#endif diff --git a/src/newui/dmainwindow.cpp b/src/newui/dmainwindow.cpp new file mode 100644 index 00000000..27ffcf73 --- /dev/null +++ b/src/newui/dmainwindow.cpp @@ -0,0 +1,309 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "dmainwindow.h" + +#include <kdebug.h> +#include <kapplication.h> +#include <kconfig.h> +#include <kiconloader.h> + +#include <qtoolbutton.h> + +#include "dtabwidget.h" +#include "docksplitter.h" + +DMainWindow::DMainWindow(QWidget *parent, const char *name) + :KParts::MainWindow(parent, name), m_firstRemoved(false), m_currentWidget(0) +{ + loadSettings(); + createToolWindows(); + m_central = new Ideal::DockSplitter(Qt::Horizontal, this); + m_activeTabWidget = createTab(); + m_central->addDock(0, 0, m_activeTabWidget); + setCentralWidget(m_central); +} + +void DMainWindow::loadSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("UI"); + m_openTabAfterCurrent = config->readBoolEntry("OpenNewTabAfterCurrent", true); + m_showIconsOnTabs = config->readBoolEntry("ShowTabIcons", false); +} + +void DMainWindow::saveSettings() +{ + m_leftDock->saveSettings(); + m_rightDock->saveSettings(); + m_bottomDock->saveSettings(); +} + +DMainWindow::~DMainWindow() +{ +/* for (QValueList<QWidget*>::iterator it = m_widgets.begin(); it != m_widgets.end(); ++it) + removeWidget(*it);*/ +} + +DDockWindow *DMainWindow::toolWindow(DDockWindow::Position position) const +{ + switch (position) { + case DDockWindow::Bottom: return m_bottomDock; + case DDockWindow::Left: return m_leftDock; + case DDockWindow::Right: return m_rightDock; + } + return 0; +} + +void DMainWindow::createToolWindows() +{ + m_bottomDock = new DDockWindow(this, DDockWindow::Bottom); + moveDockWindow(m_bottomDock, Qt::DockBottom); + m_leftDock = new DDockWindow(this, DDockWindow::Left); + moveDockWindow(m_leftDock, Qt::DockLeft); + m_rightDock = new DDockWindow(this, DDockWindow::Right); + moveDockWindow(m_rightDock, Qt::DockRight); +} + +void DMainWindow::addWidget(QWidget *widget, const QString &title) +{ +// invalidateActiveTabWidget(); + if (m_firstRemoved && m_activeTabWidget == m_tabs.first()) + { + m_central->addDock(0, 0, m_activeTabWidget); + m_firstRemoved = false; + } + + addWidget(m_activeTabWidget, widget, title); +} + +void DMainWindow::addWidget(DTabWidget *tab, QWidget *widget, const QString &title) +{ + static QPixmap emptyPixmap; + + int idx = -1; + if (m_openTabAfterCurrent && (tab->count() > 0)) + idx = tab->currentPageIndex() + 1; + if (m_showIconsOnTabs) + { + const QPixmap *pixmap = widget->icon(); + const QIconSet &icons = (pixmap && (pixmap->size().height() <= 16)) ? *(pixmap) : SmallIcon("kdevelop"); + tab->insertTab(widget, icons, title, idx); + } + else + tab->insertTab(widget, emptyPixmap, title, idx); + m_widgets.append(widget); + m_widgetTabs[widget] = tab; + widget->installEventFilter(this); + tab->showPage(widget); +} + +void DMainWindow::removeWidget(QWidget *widget) +{ + if (!m_widgets.contains(widget)) + return; //not a widget in main window + + if (m_widgetTabs.contains(widget)) + { + DTabWidget *tab = m_widgetTabs[widget]; + if (tab->indexOf(widget) >= 0) + { + tab->removePage(widget); + widget->reparent(0,QPoint(0,0),false); + if (tab->count() == 0) + { + if (tab->closeButton()) + tab->closeButton()->hide(); + //remove and delete tabwidget if it is not the first one + if (tab != m_tabs.first()) + { + QPair<uint, uint> idx = m_central->indexOf(tab); + m_tabs.remove(tab); + m_activeTabWidget = m_tabs.first(); + m_central->removeDock(idx.first, idx.second, true); + } + //only temporarily remove the first tabwidget + else + { + m_central->removeDock(0, 0, false); + m_firstRemoved = true; + } + //focus smth in m_activeTabWidget + if (m_activeTabWidget) + { + if (m_activeTabWidget->currentPage()) + { + m_activeTabWidget->currentPage()->setFocus(); + } + } + } + } + } + + m_widgets.remove(widget); + m_widgetTabs.remove(widget); + if (m_activeTabWidget && m_activeTabWidget->currentPage()) + { + //a hack to please multibuffer and actually switch the active part + QFocusEvent ev(QEvent::FocusIn); + QApplication::sendEvent(m_activeTabWidget->currentPage(), &ev); + } +} + +DTabWidget *DMainWindow::splitHorizontal() +{ + m_activeTabWidget = createTab(); + m_central->addDock(m_central->numRows(), 0, m_activeTabWidget); + return m_activeTabWidget; +} + +DTabWidget *DMainWindow::splitVertical() +{ +// invalidateActiveTabWidget(); + int row = m_central->indexOf(m_activeTabWidget).first; + m_activeTabWidget = createTab(); + m_central->addDock(row, m_central->numCols(row), m_activeTabWidget); + return m_activeTabWidget; +} + +void DMainWindow::invalidateActiveTabWidget() +{ +/* QWidget *focused = m_central->focusWidget(); + kdDebug(9000) << "invalidate: " << focused << endl; + if (focused == 0) + return; + if (!m_widgets.contains(focused)) + { + kdDebug(9000) << " focused is not in m_widgets" << endl; + return; + } + if (m_widgetTabs.contains(focused)) + { + kdDebug(9000) << " focused is in m_widgets and m_widgetTabs" << endl; + DTabWidget *tab = m_widgetTabs[focused]; + if (tab->indexOf(focused) >= 0) + m_activeTabWidget = tab; + kdDebug(9000) << " tab: " << tab << endl; + }*/ +} + +DTabWidget *DMainWindow::createTab() +{ + DTabWidget *tab = new DTabWidget(m_central); + m_tabs.append(tab); + if (tab->closeButton()) + connect(tab->closeButton(), SIGNAL(clicked()), this, SLOT(closeTab())); + connect(tab, SIGNAL(closeRequest(QWidget*)), this, SLOT(closeTab(QWidget*))); + connect(tab, SIGNAL(contextMenu(QWidget*,const QPoint &)), + this, SLOT(tabContext(QWidget*,const QPoint &))); + return tab; +} + +bool DMainWindow::eventFilter(QObject *obj, QEvent *ev) +{ + QWidget *w = (QWidget*)obj; + if (!m_widgets.contains(w)) + return KParts::MainWindow::eventFilter(obj, ev); + + if ((m_currentWidget != w) && (ev->type() == QEvent::FocusIn)) + { + m_currentWidget = w; + emit widgetChanged(w); + } + else if (ev->type() == QEvent::IconChange) + { + if (m_widgetTabs.contains(w)) + { + DTabWidget *tab = m_widgetTabs[w]; + tab->setTabIconSet(w, w->icon() ? (*(w->icon())) : QPixmap()); + } + } + else if (ev->type() == QEvent::CaptionChange) + { + kdDebug(9000) << "caption change" << endl; + DTabWidget *tab = m_widgetTabs[w]; + tab->changeTab(w, w->caption()); + } + + return KParts::MainWindow::eventFilter(obj, ev); +} + +void DMainWindow::closeTab() +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::tabContext(QWidget *, const QPoint &) +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::closeTab(QWidget *) +{ + //nothing to do here, should be reimplemented +} + +void DMainWindow::moveWidget(DDockWindow::Position position, QWidget * view, const QString & title) +{ + if (m_docks.contains(view)) + { + toolWindow(m_docks[view])->removeWidget(view); + + toolWindow(position)->addWidget( title, view, true ); + m_docks[view] = position; + } +} + +void DMainWindow::addDockWidget(DDockWindow::Position position, QWidget *view, const QString &title) +{ + toolWindow(position)->addWidget(title, view); + m_docks[view] = position; + connect(view, SIGNAL(destroyed()), this, SLOT(widgetDestroyed())); +} + +void DMainWindow::removeDockWidget(QWidget *view) +{ + toolWindow(m_docks[view])->removeWidget(view); + m_docks.remove(view); +} + +bool DMainWindow::hasDockWidget(QWidget *view) +{ + return m_docks.contains(view); +} + +DDockWindow::Position DMainWindow::dockWidgetPosition(QWidget *view) +{ + return m_docks[view]; +} + +void DMainWindow::widgetDestroyed() +{ + QWidget *w = static_cast<QWidget*>(const_cast<QObject*>(sender())); + + if (m_docks.contains(w)) + { + kdError() << "Widget destroyed before being removed from UI!" << endl; + m_docks.remove(w); + } +} + +#include "dmainwindow.moc" + +// kate: space-indent on; indent-width 4; tab-width 4; replace-tabs on diff --git a/src/newui/dmainwindow.h b/src/newui/dmainwindow.h new file mode 100644 index 00000000..326d0c02 --- /dev/null +++ b/src/newui/dmainwindow.h @@ -0,0 +1,113 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DMAINWINDOW_H +#define DMAINWINDOW_H + +#include <kxmlguiclient.h> +#include <kparts/mainwindow.h> + +#include "ddockwindow.h" + +class DTabWidget; +namespace Ideal { + class DockSplitter; +} + +/**Main window which provides simplified IDEA mode.*/ +class DMainWindow: public KParts::MainWindow { + Q_OBJECT +public: + DMainWindow(QWidget *parent = 0, const char *name = 0); + virtual ~DMainWindow(); + + /**@return The tool window in given @p position.*/ + DDockWindow *toolWindow(DDockWindow::Position position) const; + + /**Adds a tabbed widget into the active (focused) tab widget. + If @p widget is null then only tab is created.*/ + virtual void addWidget(QWidget *widget, const QString &title); + virtual void addWidget(DTabWidget *tab, QWidget *widget, const QString &title); + /**Removes widget. Does not delete it.*/ + virtual void removeWidget(QWidget *widget); + /**Moves a widget from an existing dockposition to a new position**/ + virtual void moveWidget(DDockWindow::Position newPosition, QWidget *widget, const QString & title); + + /**Adds a dock widget into given position.*/ + virtual void addDockWidget(DDockWindow::Position position, QWidget *view, const QString &title); + /**Removes a dock widget.*/ + virtual void removeDockWidget(QWidget *view); + + virtual void saveSettings(); + + bool hasDockWidget(QWidget *view); + DDockWindow::Position dockWidgetPosition(QWidget *view); + +public slots: + DTabWidget *splitHorizontal(); + DTabWidget *splitVertical(); + +protected slots: + /**This does nothing. Reimplement in subclass to close the tab + when corner close button is pressed.*/ + virtual void closeTab(); + /**This does nothing. Reimplement in subclass to close the tab + when hover close button is pressed.*/ + virtual void closeTab(QWidget*); + /**This does nothing. Reimplement in subclass to show tab context menu.*/ + virtual void tabContext(QWidget*,const QPoint &); + + void widgetDestroyed(); + +signals: + void widgetChanged(QWidget *); + +protected: + bool eventFilter(QObject *obj, QEvent *ev); + + virtual void loadSettings(); + + virtual void createToolWindows(); + virtual DTabWidget *createTab(); + + DDockWindow *m_leftDock; + DDockWindow *m_rightDock; + DDockWindow *m_bottomDock; + + QMap<QWidget*, DDockWindow::Position> m_docks; + + Ideal::DockSplitter *m_central; + DTabWidget *m_activeTabWidget; + + QValueList<DTabWidget*> m_tabs; + + bool m_openTabAfterCurrent; + bool m_showIconsOnTabs; + bool m_firstRemoved; + + QValueList<QWidget*> m_widgets; + QMap<QWidget*, DTabWidget*> m_widgetTabs; + QWidget *m_currentWidget; + +private slots: + void invalidateActiveTabWidget(); + +}; + +#endif diff --git a/src/newui/docksplitter.cpp b/src/newui/docksplitter.cpp new file mode 100644 index 00000000..46212f6c --- /dev/null +++ b/src/newui/docksplitter.cpp @@ -0,0 +1,175 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "docksplitter.h" + +#include <kdebug.h> + +namespace Ideal { + +DockSplitter::DockSplitter(Orientation orientation, QWidget *parent, const char *name) + :QSplitter(parent, name), m_orientation(orientation) +{ + switch (m_orientation) + { + case Horizontal: + setOrientation(Vertical); + break; + case Vertical: + setOrientation(Horizontal); + break; + } + setOpaqueResize(true); + appendSplitter(); +} + +DockSplitter::~DockSplitter() +{ +} + +void DockSplitter::addDock(uint row, uint col, QWidget *dock) +{ + if (m_docks.count() <= row) + for (uint i = m_docks.count(); i <= row ; ++i) + m_docks.append(QValueList<QWidget*>()); + + if (m_docks[row].count() <= col) + { + for (uint i = m_docks[row].count(); i <= col ; ++i) + m_docks[row].append(0); + m_docks[row][col] = dock; + } + else if (m_docks[row][col] == 0) + m_docks[row][col] = dock; + else + m_docks[row].insert(m_docks[row].at(col), dock); + + if (m_splitters.count() <= row) + createSplitters(row); + QSplitter *splitter = m_splitters[row]; + + dock->reparent(splitter, QPoint(0,0), true); + if (col < m_docks[row].count()-1) + shiftWidgets(splitter, row, col+1); +} + +void DockSplitter::appendSplitter() +{ + switch (m_orientation) + { + case Horizontal: + m_splitters.append(new QSplitter(Horizontal, this)); + break; + case Vertical: + m_splitters.append(new QSplitter(Vertical, this)); + break; + } + m_splitters[m_splitters.size()-1]->setOpaqueResize(true); + m_splitters[m_splitters.size()-1]->show(); +} + +void DockSplitter::createSplitters(uint index) +{ + kdDebug(9000) << "DockSplitter::createSplitters index = " << index << " count = " << m_splitters.count() << endl; + for (uint i = m_splitters.count(); i <= index; ++i) + { + kdDebug(9000) << " appendSplitter..." << endl; + appendSplitter(); + } +} + +void DockSplitter::removeDock(uint row, uint col, bool alsoDelete) +{ + if ((row >= m_docks.count()) || (col >= m_docks[row].count())) + return; + + QWidget *w = m_docks[row][col]; + m_docks[row].remove(m_docks[row].at(col)); + + if (alsoDelete) + { + delete w; + w = 0; + } + else + { + w->reparent(0, QPoint(0,0), false); + w->hide(); + } + + m_splitters[row]->setMinimumSize(m_splitters[row]->minimumSizeHint()); + + if (isRowEmpty(row)) + { + m_docks.remove(m_docks.at(row)); + delete m_splitters[row]; + m_splitters[row] = 0; + m_splitters.remove(m_splitters.at(row)); + } +} + +bool DockSplitter::isRowEmpty(int row) +{ + if (m_docks[row].count() == 0) + return true; + for (uint i = 0; i < m_docks[row].count(); ++i) + if (m_docks[row][i] != 0) + return false; + return true; +} + +void DockSplitter::shiftWidgets(QSplitter *splitter, uint row, uint fromCol) +{ + kdDebug(9000) << "shiftWidgets: row=" << row << " from col=" << fromCol << endl; + kdDebug(9000) << "row size is: " << m_docks[row].count() << endl; + + for (uint i = fromCol; i < m_docks[row].count(); ++i) + { + kdDebug(9000) << "move from " << i << " to last" << endl; + if (m_docks[row][i]) + splitter->moveToLast(m_docks[row][i]); + else + kdDebug(9000) << "m_docks[" << row << "][" << i << "] is 0" << endl; + } +} + +int DockSplitter::numRows() const +{ + return m_docks.count(); +} + +int DockSplitter::numCols(int row) const +{ + if (row < numRows()) + return m_docks[row].count(); + return 0; +} + +QPair<uint, uint> DockSplitter::indexOf(QWidget *dock) +{ + for (uint i = 0; i < m_docks.count(); ++i) + for (uint j = 0; j < m_docks[i].count(); ++j) + if (dock == m_docks[i][j]) + return qMakePair(i, j); + return qMakePair(0u, 0u); +} + +} + +#include "docksplitter.moc" diff --git a/src/newui/docksplitter.h b/src/newui/docksplitter.h new file mode 100644 index 00000000..214ad529 --- /dev/null +++ b/src/newui/docksplitter.h @@ -0,0 +1,62 @@ +/*************************************************************************** + * Copyright (C) 2004 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef IDEALDOCKSPLITTER_H +#define IDEALDOCKSPLITTER_H + +#include <qsplitter.h> +#include <qvaluelist.h> + +namespace Ideal { + +class DockWidget; + +/** +@short Splitter for docks +*/ +class DockSplitter: public QSplitter { + Q_OBJECT +public: + DockSplitter(Orientation orientation, QWidget *parent = 0, const char *name = 0); + ~DockSplitter(); + + void addDock(uint row, uint col, QWidget *dock); + void removeDock(uint row, uint col, bool alsoDelete = false); + + QPair<uint, uint> indexOf(QWidget *dock); + + int numRows() const; + int numCols(int row) const; + +protected: + void appendSplitter(); + void createSplitters(uint index); + void shiftWidgets(QSplitter *splitter, uint row, uint fromCol); + + bool isRowEmpty(int row); + +private: + Orientation m_orientation; + QValueList<QSplitter*> m_splitters; + QValueList<QValueList<QWidget*> > m_docks; +}; + +} + +#endif diff --git a/src/newui/dtabwidget.cpp b/src/newui/dtabwidget.cpp new file mode 100644 index 00000000..34ac9a5a --- /dev/null +++ b/src/newui/dtabwidget.cpp @@ -0,0 +1,106 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#include "dtabwidget.h" + +#include <qtoolbutton.h> +#include <qtabbar.h> + +#include <kconfig.h> +#include <kiconloader.h> +#include <kapplication.h> + +DTabWidget::DTabWidget(QWidget *parent, const char *name) + :KTabWidget(parent, name), m_closeButton(0) +{ + setFocusPolicy(NoFocus); + setMargin(0); + + loadSettings(); + + if (!m_tabBarShown) + tabBar()->hide(); + else { + m_closeButton = new QToolButton(this); + m_closeButton->setIconSet(SmallIcon("tab_remove")); + m_closeButton->adjustSize(); + m_closeButton->hide(); + setCornerWidget(m_closeButton, TopRight); + + if (m_closeOnHover) + setHoverCloseButton(true); + + setTabReorderingEnabled(true); + } + + connect(this, SIGNAL(currentChanged(QWidget*)), this, SLOT(setFocus(QWidget*))); +// connect(this, SIGNAL(currentChanged(QWidget*)), this, SLOT(updateHistory(QWidget*))); +} + +void DTabWidget::loadSettings() +{ + KConfig *config = kapp->config(); + config->setGroup("UI"); +// m_tabBarShown = config->readBoolEntry("TabBarShown", true); + m_tabBarShown = ! config->readNumEntry("TabWidgetVisibility", 0); + m_closeOnHover = config->readBoolEntry("CloseOnHover", false); + m_closeButtonShown = config->readBoolEntry("ShowCloseTabsButton", true); + //we do not delay hover close buttons - that looks and feels ugly + setHoverCloseButtonDelayed(false); +} + +void DTabWidget::saveSettings() +{ +} + +QToolButton *DTabWidget::closeButton() const +{ + return m_closeButton; +} + +void DTabWidget::setFocus(QWidget *w) +{ + if (w) + w->setFocus(); +} + +void DTabWidget::insertTab(QWidget *child, const QString &label, int index) +{ + if (m_closeButton && m_closeButtonShown) + m_closeButton->show(); + KTabWidget::insertTab(child, label, index); + if (index != -1) tabBar()->repaint(); +} + +void DTabWidget::insertTab(QWidget *child, const QIconSet &iconset, + const QString &label, int index) +{ + if (m_closeButton && m_closeButtonShown) + m_closeButton->show(); + KTabWidget::insertTab(child, iconset, label, index); + if (index != -1) tabBar()->repaint(); +} + +/*void DTabWidget::updateHistory(QWidget *w) +{ + if (m_history.top() != w) + m_history.push(w); +}*/ + +#include "dtabwidget.moc" diff --git a/src/newui/dtabwidget.h b/src/newui/dtabwidget.h new file mode 100644 index 00000000..4f51e47b --- /dev/null +++ b/src/newui/dtabwidget.h @@ -0,0 +1,58 @@ +/*************************************************************************** + * Copyright (C) 2005 by Alexander Dymo * + * adymo@kdevelop.org * + * * + * This program 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 program 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 General Public License for more details. * + * * + * You should have received a copy of the GNU Library General Public * + * License along with this program; if not, write to the * + * Free Software Foundation, Inc., * + * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * + ***************************************************************************/ +#ifndef DTABWIDGET_H +#define DTABWIDGET_H + +#include <ktabwidget.h> + +class QToolButton; + +class DTabWidget: public KTabWidget { + Q_OBJECT +public: + DTabWidget(QWidget *parent=0, const char *name=0); + + /**@return The close button at the top right corner. + May be 0 if the configuration do not allow close buttons or the tabbar.*/ + QToolButton *closeButton() const; + + virtual void insertTab(QWidget *child, const QString &label, int index = -1 ); + virtual void insertTab(QWidget *child, const QIconSet &iconset, + const QString &label, int index = -1); + +protected: + virtual void loadSettings(); + virtual void saveSettings(); + +private slots: + void setFocus(QWidget *w); +// void updateHistory(QWidget *w); + +private: + bool m_tabBarShown; + bool m_closeOnHover; + bool m_closeButtonShown; + + QToolButton *m_closeButton; +// QValueStack<QWidget*> *m_history; + +}; + +#endif |