Fix buttons in lists on Maemo.
[dorian] / widgets / listwindow.cpp
1 #include <QtGui>
2 #include <QListWidget>
3 #include <QAbstractItemModel>
4
5 #include "listwindow.h"
6 #include "trace.h"
7 #include "platform.h"
8
9 #ifdef Q_OS_SYMBIAN
10 #include "flickcharm.h"
11 #endif
12
13 ListWindow::ListWindow(const QString &noItems_, QWidget *parent):
14         QMainWindow(parent), mModel(0), noItems(noItems_)
15 {
16 #if defined(Q_WS_MAEMO_5)
17     setAttribute(Qt::WA_Maemo5StackedWindow, true);
18 #endif
19     setAttribute(Qt::WA_DeleteOnClose);
20
21     list = new QListWidget(this);
22     list->setSelectionMode(QAbstractItemView::SingleSelection);
23 #if defined(Q_OS_SYMBIAN)
24     list->setFixedWidth(QApplication::desktop()->availableGeometry().width());
25     list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
26 #endif
27     populateList();
28     setCentralWidget(list);
29
30 #ifdef Q_OS_SYMBIAN
31     charm = new FlickCharm(this);
32     // charm->activateOn(list);
33     QAction *closeAction = new QAction(parent? tr("Back"): tr("Exit"), this);
34     closeAction->setSoftKeyRole(QAction::NegativeSoftKey);
35     connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
36     QMainWindow::addAction(closeAction);
37 #endif // Q_OS_SYMBIAN
38
39     connect(list, SIGNAL(activated(const QModelIndex &)),
40             this, SLOT(onItemActivated(const QModelIndex &)));
41 }
42
43 void ListWindow::populateList()
44 {
45     TRACE;
46
47     list->clear();
48     list->setIconSize(QSize(48, 48)); // FIXME
49     list->setUniformItemSizes(true);
50     if (mModel && mModel->rowCount()) {
51         for (int i = 0; i < mModel->rowCount(); i++) {
52             QModelIndex index = mModel->index(i, 0);
53             QString text = mModel->data(index, Qt::DisplayRole).toString();
54             QVariant imageData = mModel->data(index, Qt::DecorationRole);
55             QIcon icon(QPixmap::fromImage(imageData.value<QImage>()));
56             (void)new QListWidgetItem(icon, text, list);
57         }
58     } else {
59         QListWidgetItem *item = new QListWidgetItem(noItems);
60         item->setFlags(Qt::NoItemFlags);
61         list->addItem(item);
62     }
63     for (int i = 0; i < buttons.count(); i++) {
64         insertButton(i, buttons[i]);
65     }
66 }
67
68 void ListWindow::insertButton(int row, const Button &b)
69 {
70     QPushButton *pushButton = new QPushButton(
71         QIcon(Platform::instance()->icon(b.iconName)), b.title, this);
72 #ifdef Q_OS_SYMBIAN
73     pushButton->setFixedWidth(list->width());
74 #endif
75     connect(pushButton, SIGNAL(clicked()), b.receiver, b.slot);
76     QListWidgetItem *item = new QListWidgetItem();
77     item->setFlags(Qt::NoItemFlags);
78     list->insertItem(row, item);
79     list->setItemWidget(item, pushButton);
80 }
81
82 void ListWindow::setModel(QAbstractItemModel *aModel)
83 {
84     TRACE;
85     mModel = aModel;
86     populateList();
87     if (mModel) {
88         connect(mModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
89                 this, SLOT(populateList()));
90         connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
91                 this, SLOT(populateList()));
92         connect(mModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
93                 this, SLOT(populateList()));
94         connect(mModel, SIGNAL(layoutChanged()), this, SLOT(populateList()));
95     }
96 }
97
98 QAbstractItemModel *ListWindow::model() const
99 {
100     return mModel;
101 }
102
103 void ListWindow::addButton(const QString &title, QObject *receiver,
104                            const char *slot, const QString &iconName)
105 {
106     TRACE;
107
108 #ifdef Q_OS_SYMBIAN
109     Q_UNUSED(iconName);
110     addMenuAction(title, receiver, slot);
111 #else
112     Button b;
113     b.title = title;
114     b.receiver = receiver;
115     b.slot = slot;
116     b.iconName = iconName;
117     insertButton(buttons.length(), b);
118     buttons.append(b);
119 #endif
120 }
121
122 QAction *ListWindow::addMenuAction(const QString &title, QObject *receiver,
123                                    const char *slot)
124 {
125     TRACE;
126     QAction *action = 0;
127 #if defined(Q_WS_MAEMO_5)
128     action = menuBar()->addAction(title);
129     connect(action, SIGNAL(triggered()), receiver, slot);
130 #elif defined(Q_OS_SYMBIAN)
131     action = new QAction(title, this);
132     connect(action, SIGNAL(triggered()), receiver, slot);
133     action->setSoftKeyRole(QAction::PositiveSoftKey);
134     menuBar()->addAction(action);
135 #else
136     Q_UNUSED(title);
137     Q_UNUSED(receiver);
138     Q_UNUSED(slot);
139     action = new QAction(this);
140 #endif
141     action->setCheckable(true);
142     return action;
143 }
144
145 void ListWindow::onItemActivated(const QModelIndex &index)
146 {
147     TRACE;
148
149     // Work around Qt/Symbian^3 bug: Disabled list items still can be selected
150     if (!mModel) {
151         return;
152     }
153     if (!mModel->rowCount()) {
154         return;
155     }
156
157     int row = index.row() - buttons.count();
158     qDebug() << "Activated" << index.row() << ", emit activated(" << row << ")";
159     emit activated(mModel->index(row, 0));
160 }
161
162 void ListWindow::setCurrentItem(const QModelIndex &item)
163 {
164     int index = item.row();
165     list->setCurrentItem(list->item(index + buttons.count()));
166 }
167
168 QModelIndex ListWindow::currentItem() const
169 {
170     TRACE;
171     QListWidgetItem *currentItem = list->currentItem();
172     if (currentItem) {
173         int row = list->row(currentItem) - buttons.count();
174         qDebug() << "Current row is" << row;
175         return mModel->index(row, 0);
176     }
177     return QModelIndex();
178 }
179
180 #ifdef Q_WS_MAEMO_5
181
182 void ListWindow::closeEvent(QCloseEvent *event)
183 {
184     // Work around Maemo/Qt bug: Menu items are not removed on close
185     menuBar()->clear();
186     event->accept();
187     QMainWindow::closeEvent(event);
188 }
189
190 #endif // Q_WS_MAEMO_5
191
192 #ifdef Q_OS_SYMBIAN
193
194 void ListWindow::show()
195 {
196     foreach (QWidget *w, QApplication::allWidgets()) {
197         w->setContextMenuPolicy(Qt::NoContextMenu);
198     }
199     showMaximized();
200 }
201
202 #endif // Q_OS_SYMBIAN