Fix Symbian bugs.
[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     pushButton->setFixedWidth(list->width());
73     connect(pushButton, SIGNAL(clicked()), b.receiver, b.slot);
74     QListWidgetItem *item = new QListWidgetItem();
75     item->setFlags(Qt::NoItemFlags);
76     list->insertItem(row, item);
77     list->setItemWidget(item, pushButton);
78 }
79
80 void ListWindow::setModel(QAbstractItemModel *aModel)
81 {
82     TRACE;
83     mModel = aModel;
84     populateList();
85     if (mModel) {
86         connect(mModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
87                 this, SLOT(populateList()));
88         connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
89                 this, SLOT(populateList()));
90         connect(mModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
91                 this, SLOT(populateList()));
92         connect(mModel, SIGNAL(layoutChanged()), this, SLOT(populateList()));
93     }
94 }
95
96 QAbstractItemModel *ListWindow::model() const
97 {
98     return mModel;
99 }
100
101 void ListWindow::addButton(const QString &title, QObject *receiver,
102                            const char *slot, const QString &iconName)
103 {
104     TRACE;
105
106 #ifdef Q_OS_SYMBIAN
107     Q_UNUSED(iconName);
108     addMenuAction(title, receiver, slot);
109 #else
110     Button b;
111     b.title = title;
112     b.receiver = receiver;
113     b.slot = slot;
114     b.iconName = iconName;
115     insertButton(buttons.length(), b);
116     buttons.append(b);
117 #endif
118 }
119
120 QAction *ListWindow::addMenuAction(const QString &title, QObject *receiver,
121                                    const char *slot)
122 {
123     TRACE;
124     QAction *action = 0;
125 #if defined(Q_WS_MAEMO_5)
126     action = menuBar()->addAction(title);
127     connect(action, SIGNAL(triggered()), receiver, slot);
128 #elif defined(Q_OS_SYMBIAN)
129     action = new QAction(title, this);
130     connect(action, SIGNAL(triggered()), receiver, slot);
131     action->setSoftKeyRole(QAction::PositiveSoftKey);
132     menuBar()->addAction(action);
133 #else
134     Q_UNUSED(title);
135     Q_UNUSED(receiver);
136     Q_UNUSED(slot);
137     action = new QAction(this);
138 #endif
139     action->setCheckable(true);
140     return action;
141 }
142
143 void ListWindow::onItemActivated(const QModelIndex &index)
144 {
145     TRACE;
146
147     // Work around Qt/Symbian^3 bug: Disabled list items still can be selected
148     if (!mModel) {
149         return;
150     }
151     if (!mModel->rowCount()) {
152         return;
153     }
154
155     int row = index.row() - buttons.count();
156     qDebug() << "Activated" << index.row() << ", emit activated(" << row << ")";
157     emit activated(mModel->index(row, 0));
158 }
159
160 void ListWindow::setCurrentItem(const QModelIndex &item)
161 {
162     int index = item.row();
163     list->setCurrentItem(list->item(index + buttons.count()));
164 }
165
166 QModelIndex ListWindow::currentItem() const
167 {
168     TRACE;
169     QListWidgetItem *currentItem = list->currentItem();
170     if (currentItem) {
171         int row = list->row(currentItem) - buttons.count();
172         qDebug() << "Current row is" << row;
173         return mModel->index(row, 0);
174     }
175     return QModelIndex();
176 }
177
178 #ifdef Q_WS_MAEMO_5
179
180 void ListWindow::closeEvent(QCloseEvent *event)
181 {
182     // Work around Maemo/Qt bug: Menu items are not removed on close
183     menuBar()->clear();
184     event->accept();
185     QMainWindow::closeEvent(event);
186 }
187
188 #endif // Q_WS_MAEMO_5
189
190 #ifdef Q_OS_SYMBIAN
191
192 void ListWindow::show()
193 {
194     foreach (QWidget *w, QApplication::allWidgets()) {
195         w->setContextMenuPolicy(Qt::NoContextMenu);
196     }
197     showMaximized();
198 }
199
200 #endif // Q_OS_SYMBIAN