~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to src/widgets/psitabwidget.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2008-04-14 18:57:30 UTC
  • mfrom: (2.1.9 hardy)
  • Revision ID: james.westby@ubuntu.com-20080414185730-528re3zp0m2hdlhi
Tags: 0.11-8
* added CONFIG -= link_prl to .pro files and removed dependencies
  which are made unnecessary by this change
* Fix segfault when closing last chat tab with qt4.4
  (This is from upstream svn, rev. 1101) (Closes: Bug#476122)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * psitabwidget.cpp - Customised QTabWidget for Psi
 
3
 * Copyright (C) 2006  Kevin Smith
 
4
 *
 
5
 * This program is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU General Public License
 
7
 * as published by the Free Software Foundation; either version 2
 
8
 * of the License, or (at your option) any later version.
 
9
 *
 
10
 * This program is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
13
 * GNU General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU General Public License
 
16
 * along with this library; if not, write to the Free Software
 
17
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
18
 *
 
19
 */
 
20
 
 
21
#include "psitabwidget.h"
 
22
#include "psitabbar.h"
 
23
#include <QWidget>
 
24
#include <QVBoxLayout>
 
25
#include <QHBoxLayout>
 
26
#include <QToolButton>
 
27
#include <QStackedLayout>
 
28
#include <QStyle>
 
29
#include <QApplication>
 
30
#include <QMenu>
 
31
#include <QDebug>
 
32
 
 
33
/**
 
34
 * Constructor
 
35
 */
 
36
PsiTabWidget::PsiTabWidget(QWidget *parent) : QWidget(parent)
 
37
        //: QTabWidget(parent)
 
38
{
 
39
        tabsPosition_ = QTabWidget::East; // impossible => uninitialised state
 
40
        tabBar_ = new PsiTabBar(this);
 
41
        tabBar_->setUsesScrollButtons(true);
 
42
        layout_ = new QVBoxLayout(this);
 
43
        layout_->setMargin(0);
 
44
        layout_->setSpacing(0);
 
45
        barLayout_ = new QHBoxLayout(layout_);
 
46
        barLayout_->setMargin(0);
 
47
        barLayout_->setSpacing(0);
 
48
        barLayout_->addWidget(tabBar_, 2);
 
49
        barLayout_->setAlignment(Qt::AlignLeft);
 
50
 
 
51
        int buttonwidth = qMax(tabBar_->style()->pixelMetric(QStyle::PM_TabBarScrollButtonWidth, 0, tabBar_),
 
52
                    QApplication::globalStrut().width());
 
53
 
 
54
        downButton_ = new QToolButton(this);
 
55
        downButton_->setMinimumSize(3,3);
 
56
        downButton_->setFixedWidth(buttonwidth);
 
57
        downButton_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
 
58
        menu_ = new QMenu(this);
 
59
        downButton_->setMenu(menu_);
 
60
        connect(menu_, SIGNAL(aboutToShow()), SLOT(menu_aboutToShow()));
 
61
        connect(menu_, SIGNAL(triggered(QAction*)), SLOT(menu_triggered(QAction*)));
 
62
        barLayout_->add(downButton_);
 
63
 
 
64
        closeButton_ = new QToolButton(this);
 
65
        closeButton_->setMinimumSize(3,3);
 
66
        closeButton_->setFixedWidth(buttonwidth);
 
67
        closeButton_->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Minimum);
 
68
        barLayout_->add(closeButton_);
 
69
        closeButton_->setText("x");
 
70
        downButton_->setArrowType(Qt::DownArrow);
 
71
        downButton_->setPopupMode(QToolButton::InstantPopup);
 
72
        stacked_ = new QStackedLayout(layout_);
 
73
        
 
74
        setTabPosition(QTabWidget::Top);
 
75
 
 
76
        connect( tabBar_, SIGNAL(mouseDoubleClickTab(int)), SLOT(mouseDoubleClickTab(int)));
 
77
        connect( tabBar_, SIGNAL( currentChanged(int)), SLOT(tab_currentChanged(int)));
 
78
        connect( tabBar_, SIGNAL( contextMenu(QContextMenuEvent*,int)), SLOT( tab_contextMenu(QContextMenuEvent*,int)));
 
79
        connect( closeButton_, SIGNAL(clicked()), SIGNAL(closeButtonClicked()));
 
80
}
 
81
 
 
82
void PsiTabWidget::setCloseIcon(const QIcon& icon) {
 
83
        closeButton_->setIcon(icon);
 
84
        closeButton_->setText("");
 
85
}
 
86
 
 
87
/**
 
88
 * Destructor
 
89
 */
 
90
PsiTabWidget::~PsiTabWidget()
 
91
{
 
92
        
 
93
}
 
94
 
 
95
/**
 
96
 * Set the color of text on a tab.
 
97
 * \param tab Widget for the tab to change.
 
98
 * \param color Color to set text.
 
99
 */
 
100
void PsiTabWidget::setTabTextColor( QWidget* tab, const QColor& color)
 
101
{
 
102
        for (int i=0; i < count(); i++) {
 
103
                if ( widget(i) == tab ) {
 
104
                        tabBar_->setTabTextColor(i,color);
 
105
                }
 
106
        }
 
107
}
 
108
 
 
109
/**
 
110
 * Returns the specified widget.
 
111
 * \param index Widget to return.
 
112
 * \return Specified widget. 
 
113
 */
 
114
QWidget* PsiTabWidget::widget(int index)
 
115
{
 
116
        return widgets_[index];
 
117
}
 
118
 
 
119
void PsiTabWidget::mouseDoubleClickTab( int tab )
 
120
{
 
121
        emit mouseDoubleClickTab(widget(tab));
 
122
}
 
123
 
 
124
/**
 
125
 * Number of tabs/widgets
 
126
 */
 
127
int PsiTabWidget::count()
 
128
{
 
129
        return tabBar_->count();
 
130
 
131
 
 
132
/**
 
133
 * Returns the widget of the current page
 
134
 */
 
135
QWidget* PsiTabWidget::currentPage()
 
136
{
 
137
        return widgets_[currentPageIndex()];
 
138
}
 
139
 
 
140
void PsiTabWidget::tab_currentChanged( int tab )
 
141
{
 
142
        // qt 4.4 sends -1 i case of an empty QTabbar, ignore that case.
 
143
        if (tab == -1) return;
 
144
        setCurrentPage(tab);
 
145
        emit currentChanged(currentPage());
 
146
}
 
147
 
 
148
 
 
149
/**
 
150
 * Returns the index of the current page
 
151
 */
 
152
int PsiTabWidget::currentPageIndex()
 
153
{
 
154
        return tabBar_->currentIndex();
 
155
}
 
156
 
 
157
/**
 
158
 * Add the Widget to the tab stack.
 
159
 */
 
160
void PsiTabWidget::addTab(QWidget* widget, QString name) 
 
161
{
 
162
        Q_ASSERT(widget);
 
163
        if (widgets_.contains(widget)) {
 
164
                return;
 
165
        }
 
166
        widgets_.append(widget);
 
167
        stacked_->addWidget(widget);
 
168
        tabBar_->addTab(name);
 
169
        showPage(currentPage());
 
170
 
171
 
 
172
/**
 
173
 * Selects the page for the specified widget.
 
174
 */
 
175
void PsiTabWidget::showPage(QWidget* widget) {
 
176
        for (int i=0; i < count(); i++) {
 
177
                if (widgets_[i] == widget) {
 
178
                        showPageDirectly(widget);
 
179
                        tabBar_->setCurrentIndex(i);
 
180
                }
 
181
        }
 
182
        
 
183
 
184
 
 
185
/**
 
186
 * Selects the page for the specified widget (internal helper).
 
187
 */
 
188
void PsiTabWidget::showPageDirectly(QWidget* widget) {
 
189
        // FIXME move this back into showPage? should this be in the public interface?
 
190
        for (int i=0; i < count(); i++) {
 
191
                if (widgets_[i] == widget) {
 
192
                        stacked_->setCurrentWidget(widget);
 
193
                        // currentChanged is handled by tabBar_
 
194
                        return;
 
195
                }
 
196
        }
 
197
}
 
198
 
 
199
/**
 
200
 * Removes the page for the specified widget.
 
201
 */
 
202
void PsiTabWidget::removePage(QWidget* widget) {
 
203
        for (int i=0; i < count(); i++) {
 
204
                if (widgets_[i] == widget) {
 
205
                        stacked_->removeWidget(widget);
 
206
                        widgets_.remove(i);
 
207
                        tabBar_->removeTab(i);
 
208
                        // tabBar_ emits current changed if needed
 
209
                }
 
210
        }
 
211
}
 
212
 
 
213
/**
 
214
 * Finds the index of the widget (or -1 if missing).
 
215
 */
 
216
int PsiTabWidget::getIndex(QWidget* widget) {
 
217
        for (int i = 0; i < count(); i++) {
 
218
                if (widgets_[i] == widget) {
 
219
                        return i;
 
220
                }
 
221
        }
 
222
        return -1;
 
223
 
224
 
 
225
/**
 
226
 * Set the text of the tab.
 
227
 */
 
228
void PsiTabWidget::setTabLabel(QWidget* widget, const QString& label) {
 
229
        int index = getIndex(widget);
 
230
        if (index == -1) {
 
231
                return;
 
232
        }
 
233
        tabBar_->setTabText(index, label);
 
234
 
235
 
 
236
void PsiTabWidget::setCurrentPage(int index) {
 
237
        Q_ASSERT(index >=0 && index < count());
 
238
        showPage(widgets_[index]);
 
239
}
 
240
 
 
241
void PsiTabWidget::removeCurrentPage() {
 
242
        removePage(currentPage());
 
243
}
 
244
 
 
245
void PsiTabWidget::setTabPosition(QTabWidget::TabPosition pos)
 
246
{
 
247
        if (tabsPosition_ == pos) return;
 
248
 
 
249
        tabsPosition_ = pos;
 
250
        tabBar_->setShape(tabsPosition_ == QTabWidget::Top ? QTabBar::RoundedNorth : QTabBar::RoundedSouth);
 
251
 
 
252
        layout_->removeItem(barLayout_);
 
253
        layout_->removeItem(stacked_);
 
254
 
 
255
        // addLayout sets parent and complains if it's already set
 
256
        barLayout_->setParent(0);
 
257
        stacked_->setParent(0);
 
258
        if (tabsPosition_ == QTabWidget::Top) {
 
259
                layout_->addLayout(barLayout_);
 
260
                layout_->addLayout(stacked_);
 
261
        } else {
 
262
                layout_->addLayout(stacked_);
 
263
                layout_->addLayout(barLayout_);
 
264
        }
 
265
}
 
266
 
 
267
void PsiTabWidget::menu_aboutToShow()
 
268
{
 
269
        menu_->clear();
 
270
        bool vis = false;
 
271
        for (int i=0; i < tabBar_->count(); i++) {
 
272
                QRect r = tabBar_->tabRect(i);
 
273
                bool newvis = tabBar_->rect().contains(r);
 
274
                if (newvis != vis) {
 
275
                        menu_->addSeparator ();
 
276
                        vis = newvis;
 
277
                }
 
278
                menu_->addAction(tabBar_->tabText(i))->setData(i+1);
 
279
        }
 
280
        emit aboutToShowMenu(menu_);
 
281
}
 
282
 
 
283
void PsiTabWidget::menu_triggered(QAction *act)
 
284
{
 
285
        int idx = act->data().toInt();
 
286
        if (idx <= 0 || idx > tabBar_->count()) {
 
287
                // out of range
 
288
                // emit signal? 
 
289
        } else {
 
290
                setCurrentPage(idx-1);
 
291
        }
 
292
}
 
293
 
 
294
 
 
295
void PsiTabWidget::tab_contextMenu( QContextMenuEvent * event, int tab)
 
296
{
 
297
        emit tabContextMenu(tab, tabBar_->mapToGlobal(event->pos()), event);
 
298
}
 
299
 
 
300
 
 
301
 
 
302
QWidget* PsiTabWidget::page(int index) {
 
303
        Q_ASSERT(index >=0 && index < count());
 
304
        return widgets_[index];
 
305
}