Fix Symbian bugs.
[dorian] / widgets / listwindow.cpp
index 1ebd5c8..3443024 100644 (file)
 #include <QtGui>
+#include <QListWidget>
+#include <QAbstractItemModel>
 
 #include "listwindow.h"
 #include "trace.h"
-#include "listview.h"
 #include "platform.h"
 
 #ifdef Q_OS_SYMBIAN
 #include "flickcharm.h"
 #endif
 
-ListWindow::ListWindow(QWidget *parent): QMainWindow(parent), list(0)
+ListWindow::ListWindow(const QString &noItems_, QWidget *parent):
+        QMainWindow(parent), mModel(0), noItems(noItems_)
 {
 #if defined(Q_WS_MAEMO_5)
     setAttribute(Qt::WA_Maemo5StackedWindow, true);
-    popup = new QMenu(this);
-
-    QScrollArea *scroller = new QScrollArea(this);
-    setCentralWidget(scroller);
-    scroller->setProperty("FingerScrollable", true);
-    // scroller->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    // scroller->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
-    scroller->setFrameStyle(QFrame::NoFrame);
-    scroller->show();
-
-    QWidget *content = new QWidget(scroller);
-    contentLayout = new QVBoxLayout(content);
-    contentLayout->setMargin(0);
-    content->setLayout(contentLayout);
-    content->show();
-
-    scroller->setWidget(content);
-    scroller->setWidgetResizable(true);
-#else
-    QFrame *frame = new QFrame(this);
-    setCentralWidget(frame);
-    contentLayout = new QHBoxLayout();
-    frame->setLayout(contentLayout);
-    buttonBox = new QDialogButtonBox(Qt::Vertical, this);
-    contentLayout->addWidget(buttonBox);
-#endif // Q_WS_MAEMO_5
+#endif
+    setAttribute(Qt::WA_DeleteOnClose);
+
+    list = new QListWidget(this);
+    list->setSelectionMode(QAbstractItemView::SingleSelection);
+#if defined(Q_OS_SYMBIAN)
+    list->setFixedWidth(QApplication::desktop()->availableGeometry().width());
+    list->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
+#endif
+    populateList();
+    setCentralWidget(list);
 
 #ifdef Q_OS_SYMBIAN
-    charm = 0;
+    charm = new FlickCharm(this);
+    // charm->activateOn(list);
     QAction *closeAction = new QAction(parent? tr("Back"): tr("Exit"), this);
     closeAction->setSoftKeyRole(QAction::NegativeSoftKey);
     connect(closeAction, SIGNAL(triggered()), this, SLOT(close()));
     QMainWindow::addAction(closeAction);
 #endif // Q_OS_SYMBIAN
 
-#ifdef Q_WS_MAC
-    addAction(tr("Close"), this, SLOT(close()), QString(),
-              QDialogButtonBox::RejectRole);
-#endif // Q_WS_MAC
+    connect(list, SIGNAL(activated(const QModelIndex &)),
+            this, SLOT(onItemActivated(const QModelIndex &)));
 }
 
-void ListWindow::addList(ListView *listView)
+void ListWindow::populateList()
 {
     TRACE;
-    list = listView;
-#if defined(Q_WS_MAEMO_5)
-    // FIXME: list->installEventFilter(this);
-    list->setProperty("FingerScrollable", false);
-    int height = list->sizeHintForRow(0) * list->model()->rowCount();
-    qDebug() << "Minimum height" << height;
-    list->setMinimumHeight(height);
-    contentLayout->addWidget(list);
-    connect(list->model(),
-            SIGNAL(rowsInserted(const QModelIndex &, int, int)),
-            this, SLOT(onModelChanged()));
-    connect(list->model(),
-            SIGNAL(rowsRemoved(const QModelIndex &, int, int)),
-            this, SLOT(onModelChanged()));
-#else
-    contentLayout->insertWidget(0, list);
-#endif // Q_WS_MAEMO5
 
-#ifdef Q_OS_SYMBIAN
-    if (!charm) {
-        charm = new FlickCharm(this);
+    list->clear();
+    list->setIconSize(QSize(48, 48)); // FIXME
+    list->setUniformItemSizes(true);
+    if (mModel && mModel->rowCount()) {
+        for (int i = 0; i < mModel->rowCount(); i++) {
+            QModelIndex index = mModel->index(i, 0);
+            QString text = mModel->data(index, Qt::DisplayRole).toString();
+            QVariant imageData = mModel->data(index, Qt::DecorationRole);
+            QIcon icon(QPixmap::fromImage(imageData.value<QImage>()));
+            (void)new QListWidgetItem(icon, text, list);
+        }
+    } else {
+        QListWidgetItem *item = new QListWidgetItem(noItems);
+        item->setFlags(Qt::NoItemFlags);
+        list->addItem(item);
     }
-    // FIXME: Charms need more work...: charm->activateOn(list);
-#endif // Q_OS_SYMBIAN
+    for (int i = 0; i < buttons.count(); i++) {
+        insertButton(i, buttons[i]);
+    }
+}
 
-    connect(list->selectionModel(),
-      SIGNAL(selectionChanged(const QItemSelection &, const QItemSelection &)),
-      this,
-      SLOT(onSelectionChanged(const QItemSelection &, const QItemSelection &)));
+void ListWindow::insertButton(int row, const Button &b)
+{
+    QPushButton *pushButton = new QPushButton(
+        QIcon(Platform::instance()->icon(b.iconName)), b.title, this);
+    pushButton->setFixedWidth(list->width());
+    connect(pushButton, SIGNAL(clicked()), b.receiver, b.slot);
+    QListWidgetItem *item = new QListWidgetItem();
+    item->setFlags(Qt::NoItemFlags);
+    list->insertItem(row, item);
+    list->setItemWidget(item, pushButton);
 }
 
-void ListWindow::addAction(const QString &title, QObject *receiver,
-                           const char *slot, const QString &iconName,
-                           QDialogButtonBox::ButtonRole role)
+void ListWindow::setModel(QAbstractItemModel *aModel)
 {
     TRACE;
-#ifdef Q_WS_MAEMO_5
-    Q_UNUSED(role);
-    QPushButton *button = new QPushButton(QIcon(Platform::instance()->
-                                                icon(iconName)), title, this);
-    contentLayout->addWidget(button);
-    connect(button, SIGNAL(clicked()), receiver, slot);
-#elif defined(Q_OS_SYMBIAN)
-    Q_UNUSED(role);
-    Q_UNUSED(iconName);
-    QAction *action = new QAction(title, this);
-    connect(action, SIGNAL(triggered()), receiver, slot);
-    action->setSoftKeyRole(QAction::PositiveSoftKey);
-    menuBar()->addAction(action);
-#else
-    Q_UNUSED(iconName);
-    QPushButton *button = buttonBox->addButton(title, role);
-    connect(button, SIGNAL(clicked()), receiver, slot);
-#endif // Q_WS_MAEMO_5
+    mModel = aModel;
+    populateList();
+    if (mModel) {
+        connect(mModel, SIGNAL(dataChanged(QModelIndex, QModelIndex)),
+                this, SLOT(populateList()));
+        connect(mModel, SIGNAL(rowsRemoved(QModelIndex, int, int)),
+                this, SLOT(populateList()));
+        connect(mModel, SIGNAL(rowsInserted(QModelIndex, int, int)),
+                this, SLOT(populateList()));
+        connect(mModel, SIGNAL(layoutChanged()), this, SLOT(populateList()));
+    }
 }
 
-void ListWindow::addItemAction(const QString &title, QObject *receiver,
-                               const char *slot)
+QAbstractItemModel *ListWindow::model() const
+{
+    return mModel;
+}
+
+void ListWindow::addButton(const QString &title, QObject *receiver,
+                           const char *slot, const QString &iconName)
 {
     TRACE;
-#ifdef Q_WS_MAEMO_5
-    popup->addAction(title, receiver, slot);
-#elif defined Q_OS_SYMBIAN
-    QAction *action = new QAction(title, this);
-    connect(action, SIGNAL(triggered()), receiver, slot);
-    action->setSoftKeyRole(QAction::PositiveSoftKey);
-    menuBar()->addAction(action);
-    // FIXME: Add action to the list of item specific actions
+
+#ifdef Q_OS_SYMBIAN
+    Q_UNUSED(iconName);
+    addMenuAction(title, receiver, slot);
 #else
-    QPushButton *button =
-            buttonBox->addButton(title, QDialogButtonBox::ActionRole);
-    connect(button, SIGNAL(clicked()), receiver, slot);
-    itemButtons.append(button);
-    activateItemButtons();
-#endif // Q_WS_MAEMO_5
+    Button b;
+    b.title = title;
+    b.receiver = receiver;
+    b.slot = slot;
+    b.iconName = iconName;
+    insertButton(buttons.length(), b);
+    buttons.append(b);
+#endif
 }
 
 QAction *ListWindow::addMenuAction(const QString &title, QObject *receiver,
@@ -157,66 +140,49 @@ QAction *ListWindow::addMenuAction(const QString &title, QObject *receiver,
     return action;
 }
 
-#ifdef Q_WS_MAEMO_5
-
-void ListWindow::closeEvent(QCloseEvent *event)
+void ListWindow::onItemActivated(const QModelIndex &index)
 {
-    // Work around Maemo/Qt but: Menu items are not removed on close
-    menuBar()->clear();
-    event->accept();
-}
+    TRACE;
 
-#endif // Q_WS_MAEMO_5
+    // Work around Qt/Symbian^3 bug: Disabled list items still can be selected
+    if (!mModel) {
+        return;
+    }
+    if (!mModel->rowCount()) {
+        return;
+    }
 
-void ListWindow::onSelectionChanged(const QItemSelection &selected,
-                                    const QItemSelection &deselected)
-{
-    Q_UNUSED(selected);
-    Q_UNUSED(deselected);
-#ifndef Q_WS_MAEMO_5
-    activateItemButtons();
-#endif
+    int row = index.row() - buttons.count();
+    qDebug() << "Activated" << index.row() << ", emit activated(" << row << ")";
+    emit activated(mModel->index(row, 0));
 }
 
-#ifndef Q_WS_MAEMO_5
-
-void ListWindow::activateItemButtons()
+void ListWindow::setCurrentItem(const QModelIndex &item)
 {
-    bool enable = false;
-    if (list) {
-        enable = list->selectionModel()->hasSelection();
-    }
-    foreach (QPushButton *button, itemButtons) {
-        button->setEnabled(enable);
-    }
+    int index = item.row();
+    list->setCurrentItem(list->item(index + buttons.count()));
 }
 
-#endif // ! Q_WS_MAEMO_5
-
-#ifdef Q_WS_MAEMO_5
-
-bool ListWindow::eventFilter(QObject *obj, QEvent *event)
+QModelIndex ListWindow::currentItem() const
 {
-    if (event->type() == QEvent::ContextMenu) {
-        qDebug() << "ListWindow::eventFiler: Received QEvent::ContextMenu";
-        if (popup->actions().size()) {
-            QMouseEvent *mouseEvent = static_cast<QMouseEvent*> (event);
-            QPoint pos = mouseEvent->globalPos();
-            pos.setX(pos.x() - 150);
-            if (pos.x() < 0) {
-                pos.setX(0);
-            }
-            popup->exec(pos);
-        }
-        return true;
-    } else {
-        return QObject::eventFilter(obj, event);
+    TRACE;
+    QListWidgetItem *currentItem = list->currentItem();
+    if (currentItem) {
+        int row = list->row(currentItem) - buttons.count();
+        qDebug() << "Current row is" << row;
+        return mModel->index(row, 0);
     }
+    return QModelIndex();
 }
 
-void ListWindow::onModelChanged()
+#ifdef Q_WS_MAEMO_5
+
+void ListWindow::closeEvent(QCloseEvent *event)
 {
-    list->setMinimumHeight(list->contentsHeight());
+    // Work around Maemo/Qt bug: Menu items are not removed on close
+    menuBar()->clear();
+    event->accept();
+    QMainWindow::closeEvent(event);
 }
 
 #endif // Q_WS_MAEMO_5