File indexing completed on 2024-05-19 04:07:52

0001 /*
0002     SPDX-FileCopyrightText: 2009 Stefan Majewsky <majewsky@gmx.net>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "collection-view.h"
0008 #include "collection.h"
0009 #include "collection-delegate.h"
0010 #include "puzzle.h"
0011 
0012 #include <QApplication>
0013 #include <QGridLayout>
0014 #include <QLineEdit>
0015 #include <QMenu>
0016 #include <QPushButton>
0017 #include <QSortFilterProxyModel>
0018 #include <QAction>
0019 #include <KLocalizedString>
0020 
0021 Palapeli::CollectionView::CollectionView(QWidget* parent)
0022     : QWidget(parent)
0023     , m_view(new QListView(this))
0024     , m_delegate(new Palapeli::CollectionDelegate(m_view))
0025     , m_proxyModel(new QSortFilterProxyModel(this))
0026 {
0027     //setup view
0028     connect(m_view, &QListView::activated, this, &CollectionView::handleActivated);
0029 
0030     // Set up for multi-column display of the Puzzle Collection, which
0031     // allows the user to see more of the collection at one time.
0032     m_view->setWrapping(true);
0033     m_view->setResizeMode(QListView::Adjust);
0034     m_view->setUniformItemSizes(true);
0035     m_view->setFlow(QListView::LeftToRight);
0036 
0037     // Avoid a resize loop (with the scrollbar appearing and disappearing)
0038     // when the number of items and display-columns hits a bad combination.
0039     m_view->setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOn);
0040 
0041     m_view->setMouseTracking(true);
0042     m_view->setSelectionMode(QAbstractItemView::ExtendedSelection);
0043     m_view->setVerticalScrollMode(QListView::ScrollPerPixel); // Smooth.
0044     //setup proxy model
0045     m_view->setModel(m_proxyModel);
0046     connect(m_view->selectionModel(), &QItemSelectionModel::selectionChanged, this, &CollectionView::handleSelectionChanged);
0047     m_proxyModel->setDynamicSortFilter(true);
0048     m_proxyModel->setSortCaseSensitivity(Qt::CaseInsensitive);
0049     m_proxyModel->setSortLocaleAware(true);
0050     m_proxyModel->setSortRole(Qt::DisplayRole);
0051     m_proxyModel->sort(0, Qt::AscendingOrder);
0052     //TODO: save sorting role between sessions
0053     //setup filter search line
0054     QLineEdit* searchLine = new QLineEdit(this);
0055     searchLine->setClearButtonEnabled(true);
0056     connect(searchLine, &QLineEdit::textChanged, this, &Palapeli::CollectionView::slotTextChanged);
0057     //setup sort button
0058     QPushButton* sortButton = new QPushButton(i18nc("@action:button that pops up sorting strategy selection menu", "Sort List..."), this);
0059     QMenu* sortMenu = new QMenu(sortButton);
0060     sortButton->setMenu(sortMenu);
0061     m_sortByTitle = sortMenu->addAction(i18nc("@action:inmenu selects sorting strategy for collection list", "By Title"));
0062     m_sortByPieceCount = sortMenu->addAction(i18nc("@action:inmenu selects sorting strategy for collection list", "By Piece Count"));
0063     m_sortByTitle->setCheckable(true);
0064     m_sortByPieceCount->setCheckable(true);
0065     m_sortByTitle->setChecked(true);
0066     m_sortByPieceCount->setChecked(false);
0067     connect(sortMenu, &QMenu::triggered, this, &CollectionView::sortMenuTriggered);
0068     //construct layout
0069     QGridLayout* layout = new QGridLayout(this);
0070     layout->addWidget(sortButton, 0, 0);
0071     layout->addWidget(searchLine, 0, 1);
0072     layout->addWidget(m_view, 1, 0, 1, 2);
0073     // Removed this because setMargin is obsolete and (0) cuts off the right
0074     // hand and bottom edges of the search and ListView widgets --- on Apple
0075     // OSX at least. The default margin is 11 pixels all round and looks OK.
0076     // layout->setContentsMargins(0, 0, 0, 0);
0077 }
0078 
0079 void Palapeli::CollectionView::slotTextChanged(const QString &str)
0080 {
0081     m_proxyModel->setFilterFixedString(str);
0082 }
0083 
0084 void Palapeli::CollectionView::setModel(QAbstractItemModel* model)
0085 {
0086     m_proxyModel->setSourceModel(model);
0087 }
0088 
0089 QModelIndexList Palapeli::CollectionView::selectedIndexes() const
0090 {
0091     return m_view->selectionModel()->selectedIndexes();
0092 }
0093 
0094 //NOTE The QAbstractItemView::activated signal honors the mouseclick selection behavior defined by the user (e.g. one-click is default on Linux, while two-click is default on Windows).
0095 void Palapeli::CollectionView::handleActivated(const QModelIndex& index)
0096 {
0097     //do not emit a play request when the Control modifier is pressed (without this rule, users with one-click activation could not ever select multiple puzzles at once)
0098     if (QApplication::keyboardModifiers() & Qt::ControlModifier)
0099         return;
0100     //change selection to indicate that the given puzzle has been chosen
0101     m_view->selectionModel()->select(index, QItemSelectionModel::ClearAndSelect);
0102     Q_EMIT playRequest(Palapeli::Collection::instance()->puzzleFromIndex(index));
0103 }
0104 
0105 void Palapeli::CollectionView::handleSelectionChanged()
0106 {
0107     const QModelIndexList indexes = m_view->selectionModel()->selectedIndexes();
0108     const bool someSelection = !indexes.isEmpty();
0109     Q_EMIT canExportChanged(someSelection);
0110     for (const QModelIndex& index : indexes)
0111         if (!index.data(Palapeli::Collection::IsDeleteableRole).toBool())
0112         {
0113             Q_EMIT canDeleteChanged(false);
0114             return;
0115         }
0116     Q_EMIT canDeleteChanged(someSelection);
0117 }
0118 
0119 void Palapeli::CollectionView::sortMenuTriggered(QAction* action)
0120 {
0121     //find out what was requested
0122     int sortRole = Qt::DisplayRole; //corresponds to action == m_sortByTitle
0123     if (action == m_sortByPieceCount)
0124         sortRole = Palapeli::Collection::PieceCountRole;
0125     //update sorting and menu
0126     m_proxyModel->setSortRole(sortRole);
0127     m_sortByTitle->setChecked(sortRole == Qt::DisplayRole);
0128     m_sortByPieceCount->setChecked(sortRole == Palapeli::Collection::PieceCountRole);
0129 }
0130 
0131 #include "moc_collection-view.cpp"