1 /****************************************************************************
3 ** Copyright (C) Qxt Foundation. Some rights reserved.
5 ** This file is part of the QxtGui module of the Qt eXTension library
7 ** This library is free software; you can redistribute it and/or modify it
8 ** under the terms of th Common Public License, version 1.0, as published by
11 ** This file is provided "AS IS", without WARRANTIES OR CONDITIONS OF ANY
12 ** KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY
13 ** WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR
14 ** FITNESS FOR A PARTICULAR PURPOSE.
16 ** You should have received a copy of the CPL along with this file.
17 ** See the LICENSE file and the cpl1.0.txt file included with the source
18 ** distribution for more information. If you did not receive a copy of the
19 ** license, contact the Qxt Foundation.
21 ** <http://libqxt.sourceforge.net> <foundation@libqxt.org>
23 ****************************************************************************/
24 #include "qxttabwidget.h"
25 #include <QContextMenuEvent>
26 #include <QApplication>
31 typedef QList<QAction*> Actions;
33 class QxtTabWidgetPrivate : public QxtPrivate<QxtTabWidget>
36 QXT_DECLARE_PUBLIC(QxtTabWidget);
38 QxtTabWidgetPrivate();
39 int tabIndexAt(const QPoint& pos) const;
41 QList<Actions> actions;
42 Qt::ContextMenuPolicy policy;
45 QxtTabWidgetPrivate::QxtTabWidgetPrivate() : policy(Qt::DefaultContextMenu)
48 int QxtTabWidgetPrivate::tabIndexAt(const QPoint& pos) const
50 const int count = qxt_p().count();
51 const QTabBar* tabBar = qxt_p().tabBar();
52 for (int i = 0; i < count; ++i)
53 if (tabBar->tabRect(i).contains(pos))
59 \class QxtTabWidget QxtTabWidget
61 \brief An extended QTabWidget.
63 QxtTabWidget provides some convenience for handling tab specific context menus.
67 QxtTabWidget* tabWidget = new QxtTabWidget();
68 tabWidget->addTab(tab0, "1");
69 tabWidget->addTab(tab1, "2");
71 QList<QAction*> actions0;
72 actions0 << new QAction("Quisque", tab0) << new QAction("Aenean", tab0);
73 QList<QAction*> actions1;
74 actions1 << new QAction("Phasellus", tab1) << new QAction("Maecenas", tab1);
76 tabWidget->setTabContextMenuPolicy(Qt::ActionsContextMenu);
77 tabWidget->addTabActions(0, actions0);
78 tabWidget->addTabActions(1, actions1);
81 \image html qxttabwidget.png "QxtTabWidget in WindowsXP style."
83 \note http://www.trolltech.com/developer/task-tracker/index_html?method=entry&id=137891
87 \fn QxtTabWidget::tabContextMenuRequested(int index, const QPoint& globalPos)
89 This signal is emitted whenever the context menu is requested over
90 tab at \a index at \a globalPos.
94 Constructs a new QxtTabWidget with \a parent.
96 QxtTabWidget::QxtTabWidget(QWidget* parent) : QTabWidget(parent)
98 QXT_INIT_PRIVATE(QxtTabWidget);
102 Destructs the tab widget.
104 QxtTabWidget::~QxtTabWidget()
108 \property QxtTabWidget::tabContextMenuPolicy
109 \brief This property holds how the tab specific context menus are handled.
111 The default value of this property is \b Qt::DefaultContextMenu,
112 which means that the tabContextMenuEvent() handler is called.
113 Other values are \b Qt::NoContextMenu, \b Qt::PreventContextMenu
114 (since Qt 4.2), \b Qt::ActionsContextMenu, and \b Qt::CustomContextMenu.
115 With \b Qt::CustomContextMenu, the signal tabContextMenuRequested() is
118 \sa tabContextMenuEvent(), tabContextMenuRequested(), tabActions()
120 Qt::ContextMenuPolicy QxtTabWidget::tabContextMenuPolicy() const
122 return qxt_d().policy;
125 void QxtTabWidget::setTabContextMenuPolicy(Qt::ContextMenuPolicy policy)
127 qxt_d().policy = policy;
131 Appends the \a action to the list of actions of the
134 \sa removeTabAction(), insertTabAction(), tabActions()
136 void QxtTabWidget::addTabAction(int index, QAction* action)
138 insertTabAction(index, 0, action);
142 This convenience function creates a new action with \a text. The function
143 adds the newly created action to the list of actions of the tab at
144 \a index, and returns it.
148 QAction* QxtTabWidget::addTabAction(int index, const QString& text)
150 return addTabAction(index, QIcon(), text, 0, 0);
154 This convenience function creates a new action with \a icon and \a text.
155 The function adds the newly created action to the list of actions of the
156 tab at \a index, and returns it.
160 QAction* QxtTabWidget::addTabAction(int index, const QIcon& icon, const QString& text)
162 return addTabAction(index, icon, text, 0, 0);
166 This convenience function creates a new action with \a text and
167 an optional \a shortcut. The action's triggered() signal is
168 connected to the \a receiver's \a member slot. The function adds
169 the newly created action to the list of actions of the tab at
170 \a index, and returns it.
172 \note In order to make it possible for the shortcut to work even
173 when the context menu is not open, the action must be added to
174 a visible widget. The corresponding tab is a good alternative.
177 QWidget* tab = createNewTab();
178 tabWidget->addTab(tab, title);
179 QAction* action = tabWidget->addTabAction(index, tr("Close"), this, SLOT(closeCurrentTab()), tr("Ctrl+W"));
183 \sa addTabAction(), QWidget::addAction()
185 QAction* QxtTabWidget::addTabAction(int index, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut)
187 return addTabAction(index, QIcon(), text, receiver, member, shortcut);
191 This convenience function creates a new action with \a icon, \a text
192 and an optional \a shortcut. The action's triggered() signal is connected
193 to the \a receiver's \a member slot. The function adds the newly created
194 action to the list of actions of the tab at \a index, and returns it.
198 QAction* QxtTabWidget::addTabAction(int index, const QIcon& icon, const QString& text, const QObject* receiver, const char* member, const QKeySequence& shortcut)
200 QAction* action = new QAction(icon, text, this);
201 addTabAction(index, action);
202 if (receiver && member)
203 connect(action, SIGNAL(triggered()), receiver, member);
204 action->setShortcut(shortcut);
209 Appends the \a actions to the list of actions of the
212 \sa removeTabAction(), addTabAction()
214 void QxtTabWidget::addTabActions(int index, QList<QAction*> actions)
216 foreach (QAction* action, actions)
218 insertTabAction(index, 0, action);
223 Clears the list of actions of the tab at \a index.
225 \note Only actions owned by the tab widget are deleted.
227 \sa removeTabAction(), addTabAction()
229 void QxtTabWidget::clearTabActions(int index)
231 Q_ASSERT(index >= 0 && index < qxt_d().actions.count());
233 while (qxt_d().actions[index].count())
235 QAction* action = qxt_d().actions[index].last();
236 removeTabAction(index, action);
237 if (action->parent() == this)
243 Inserts the \a action to the list of actions of the
244 tab at \a index, before the action \a before. It appends
245 the action if \a before is \c 0.
247 \sa removeTabAction(), addTabAction(), tabContextMenuPolicy, tabActions()
249 void QxtTabWidget::insertTabAction(int index, QAction* before, QAction* action)
251 Q_ASSERT(index >= 0 && index < qxt_d().actions.count());
255 qWarning("QxtTabWidget::insertTabAction: Attempt to insert a null action");
259 const Actions& actions = qxt_d().actions.at(index);
260 if (actions.contains(action))
261 removeTabAction(index, action);
263 int pos = actions.indexOf(before);
267 pos = actions.count();
269 qxt_d().actions[index].insert(pos, action);
271 QActionEvent e(QEvent::ActionAdded, action, before);
272 QApplication::sendEvent(this, &e);
276 Inserts the \a actions to the list of actions of the
277 tab at \a index, before the action \a before. It appends
278 the action if \a before is \c 0.
280 \sa removeAction(), QMenu, insertAction(), contextMenuPolicy
282 void QxtTabWidget::insertTabActions(int index, QAction* before, QList<QAction*> actions)
284 foreach (QAction* action, actions)
286 insertTabAction(index, before, action);
291 Removes the action \a action from the list of actions of the
294 \note The removed action is not deleted.
296 \sa insertTabAction(), tabActions(), insertTabAction()
298 void QxtTabWidget::removeTabAction(int index, QAction* action)
300 Q_ASSERT(index >= 0 && index < qxt_d().actions.count());
304 qWarning("QxtTabWidget::removeTabAction: Attempt to remove a null action");
308 if (qxt_d().actions[index].removeAll(action))
310 QActionEvent e(QEvent::ActionRemoved, action);
311 QApplication::sendEvent(this, &e);
316 Returns the (possibly empty) list of actions for the
319 \sa tabContextMenuPolicy, insertTabAction(), removeTabAction()
321 QList<QAction*> QxtTabWidget::tabActions(int index) const
323 Q_ASSERT(index >= 0 && index < qxt_d().actions.count());
324 return qxt_d().actions.at(index);
327 void QxtTabWidget::tabInserted(int index)
329 Q_ASSERT(index >= 0 && index <= qxt_d().actions.count());
330 qxt_d().actions.insert(index, Actions());
333 void QxtTabWidget::tabRemoved(int index)
335 Q_ASSERT(index >= 0 && index < qxt_d().actions.count());
336 qxt_d().actions.removeAt(index);
339 void QxtTabWidget::contextMenuEvent(QContextMenuEvent* event)
341 const QPoint& pos = event->pos();
342 if (!tabBar()->geometry().contains(pos))
343 return QTabWidget::contextMenuEvent(event);
345 const int index = qxt_d().tabIndexAt(event->pos());
346 switch (qxt_d().policy)
348 case Qt::NoContextMenu:
352 #if QT_VERSION >= 0x040200
353 case Qt::PreventContextMenu:
358 case Qt::ActionsContextMenu:
359 if (index != -1 && qxt_d().actions.at(index).count())
361 QMenu::exec(qxt_d().actions.at(index), event->globalPos());
365 case Qt::CustomContextMenu:
368 emit tabContextMenuRequested(index, event->globalPos());
372 case Qt::DefaultContextMenu:
376 tabContextMenuEvent(index, event);
383 This event handler, for event \a event, can be reimplemented in a
384 subclass to receive context menu events for the tab at \a index.
386 The handler is called when \b tabContextMenuPolicy is
387 \b Qt::DefaultContextMenu.
389 The default implementation ignores the context menu event.
391 \sa tabContextMenuPolicy, tabContextMenuRequested()
393 void QxtTabWidget::tabContextMenuEvent(int index, QContextMenuEvent* event)