Move all the things (YES. Move them.)

Also, implemented some basic modlist logic, to be wired up.
This commit is contained in:
Petr Mrázek
2013-08-17 13:40:51 +02:00
parent 77e8066542
commit 253067c782
184 changed files with 414 additions and 345 deletions

View File

@ -0,0 +1,175 @@
/*
* This file is part of the KDE project
* Copyright (C) 2007 Rafael Fernández López <ereslibre@kde.org>
* Copyright (C) 2007 John Tapsell <tapsell@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KCATEGORIZEDSORTFILTERPROXYMODEL_H
#define KCATEGORIZEDSORTFILTERPROXYMODEL_H
#include <QSortFilterProxyModel>
#include <groupview_config.h>
class QItemSelection;
/**
* This class lets you categorize a view. It is meant to be used along with
* KCategorizedView class.
*
* In general terms all you need to do is to reimplement subSortLessThan() and
* compareCategories() methods. In order to make categorization work, you need
* to also call setCategorizedModel() class to enable it, since the categorization
* is disabled by default.
*
* @see KCategorizedView
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
class LIBGROUPVIEW_EXPORT KCategorizedSortFilterProxyModel
: public QSortFilterProxyModel
{
public:
enum AdditionalRoles
{
// Note: use printf "0x%08X\n" $(($RANDOM*$RANDOM))
// to define additional roles.
CategoryDisplayRole = 0x17CE990A, ///< This role is used for asking the category to a given index
CategorySortRole = 0x27857E60 ///< This role is used for sorting categories. You can return a
///< string or a long long value. Strings will be sorted alphabetically
///< while long long will be sorted by their value. Please note that this
///< value won't be shown on the view, is only for sorting purposes. What will
///< be shown as "Category" on the view will be asked with the role
///< CategoryDisplayRole.
};
KCategorizedSortFilterProxyModel ( QObject *parent = 0 );
virtual ~KCategorizedSortFilterProxyModel();
/**
* Overridden from QSortFilterProxyModel. Sorts the source model using
* @p column for the given @p order.
*/
virtual void sort ( int column, Qt::SortOrder order = Qt::AscendingOrder );
/**
* @return whether the model is categorized or not. Disabled by default.
*/
bool isCategorizedModel() const;
/**
* Enables or disables the categorization feature.
*
* @param categorizedModel whether to enable or disable the categorization feature.
*/
void setCategorizedModel ( bool categorizedModel );
/**
* @return the column being used for sorting.
*/
int sortColumn() const;
/**
* @return the sort order being used for sorting.
*/
Qt::SortOrder sortOrder() const;
/**
* Set if the sorting using CategorySortRole will use a natural comparison
* in the case that strings were returned. If enabled, QString::localeAwareCompare
* will be used for sorting.
*
* @param sortCategoriesByNaturalComparison whether to sort using a natural comparison or not.
*/
void setSortCategoriesByNaturalComparison ( bool sortCategoriesByNaturalComparison );
/**
* @return whether it is being used a natural comparison for sorting. Enabled by default.
*/
bool sortCategoriesByNaturalComparison() const;
protected:
/**
* Overridden from QSortFilterProxyModel. If you are subclassing
* KCategorizedSortFilterProxyModel, you will probably not need to reimplement this
* method.
*
* It calls compareCategories() to sort by category. If the both items are in the
* same category (i.e. compareCategories returns 0), then subSortLessThan is called.
*
* @return Returns true if the item @p left is less than the item @p right when sorting.
*
* @warning You usually won't need to reimplement this method when subclassing
* from KCategorizedSortFilterProxyModel.
*/
virtual bool lessThan ( const QModelIndex &left, const QModelIndex &right ) const;
/**
* This method has a similar purpose as lessThan() has on QSortFilterProxyModel.
* It is used for sorting items that are in the same category.
*
* @return Returns true if the item @p left is less than the item @p right when sorting.
*/
virtual bool subSortLessThan ( const QModelIndex &left, const QModelIndex &right ) const;
/**
* This method compares the category of the @p left index with the category
* of the @p right index.
*
* Internally and if not reimplemented, this method will ask for @p left and
* @p right models for role CategorySortRole. In order to correctly sort
* categories, the data() metod of the model should return a qlonglong (or numeric) value, or
* a QString object. QString objects will be sorted with QString::localeAwareCompare if
* sortCategoriesByNaturalComparison() is true.
*
* @note Please have present that:
* QString(QChar(QChar::ObjectReplacementCharacter)) >
* QString(QChar(QChar::ReplacementCharacter)) >
* [ all possible strings ] >
* QString();
*
* This means that QString() will be sorted the first one, while
* QString(QChar(QChar::ObjectReplacementCharacter)) and
* QString(QChar(QChar::ReplacementCharacter)) will be sorted in last
* position.
*
* @warning Please note that data() method of the model should return always
* information of the same type. If you return a QString for an index,
* you should return always QStrings for all indexes for role CategorySortRole
* in order to correctly sort categories. You can't mix by returning
* a QString for one index, and a qlonglong for other.
*
* @note If you need a more complex layout, you will have to reimplement this
* method.
*
* @return A negative value if the category of @p left should be placed before the
* category of @p right. 0 if @p left and @p right are on the same category, and
* a positive value if the category of @p left should be placed after the
* category of @p right.
*/
virtual int compareCategories ( const QModelIndex &left, const QModelIndex &right ) const;
private:
class Private;
Private *const d;
};
#endif // KCATEGORIZEDSORTFILTERPROXYMODEL_H

View File

@ -0,0 +1,332 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KCATEGORIZEDVIEW_H
#define KCATEGORIZEDVIEW_H
#include <QListView>
#include <groupview_config.h>
class KCategoryDrawer;
/**
* @short Item view for listing items in a categorized fashion optionally
*
* KCategorizedView basically has the same functionality as QListView, only that it also lets you
* layout items in a way that they are categorized visually.
*
* For it to work you will need to set a KCategorizedSortFilterProxyModel and a KCategoryDrawer
* with methods setModel() and setCategoryDrawer() respectively. Also, the model will need to be
* flagged as categorized with KCategorizedSortFilterProxyModel::setCategorizedModel(true).
*
* The way it works (if categorization enabled):
*
* - When sorting, it does more things than QListView does. It will ask the model for the
* special role CategorySortRole (@see KCategorizedSortFilterProxyModel). This can return
* a QString or an int in order to tell the view the order of categories. In this sense, for
* instance, if we are sorting by name ascending, "A" would be before than "B". If we are
* sorting by size ascending, 512 bytes would be before 1024 bytes. This way categories are
* also sorted.
*
* - When the view has to paint, it will ask the model with the role CategoryDisplayRole
* (@see KCategorizedSortFilterProxyModel). It will for instance return "F" for "foo.pdf" if
* we are sorting by name ascending, or "Small" if a certain item has 100 bytes, for example.
*
* For drawing categories, KCategoryDrawer will be used. You can inherit this class to do your own
* drawing.
*
* @note All examples cited before talk about filesystems and such, but have present that this
* is a completely generic class, and it can be used for whatever your purpose is. For
* instance when talking about animals, you can separate them by "Mammal" and "Oviparous". In
* this very case, for example, the CategorySortRole and the CategoryDisplayRole could be the
* same ("Mammal" and "Oviparous").
*
* @note There is a really performance boost if CategorySortRole returns an int instead of a QString.
* Have present that this role is asked (n * log n) times when sorting and compared. Comparing
* ints is always faster than comparing strings, whithout mattering how fast the string
* comparison is. Consider thinking of a way of returning ints instead of QStrings if your
* model can contain a high number of items.
*
* @warning Note that for really drawing items in blocks you will need some things to be done:
* - The model set to this view has to be (or inherit if you want to do special stuff
* in it) KCategorizedSortFilterProxyModel.
* - This model needs to be set setCategorizedModel to true.
* - Set a category drawer by calling setCategoryDrawer.
*
* @see KCategorizedSortFilterProxyModel, KCategoryDrawer
*
* @author Rafael Fernández López <ereslibre@kde.org>
*/
class LIBGROUPVIEW_EXPORT KCategorizedView
: public QListView
{
Q_OBJECT
Q_PROPERTY ( int categorySpacing READ categorySpacing WRITE setCategorySpacing )
Q_PROPERTY ( bool alternatingBlockColors READ alternatingBlockColors WRITE setAlternatingBlockColors )
Q_PROPERTY ( bool collapsibleBlocks READ collapsibleBlocks WRITE setCollapsibleBlocks )
public:
KCategorizedView ( QWidget *parent = 0 );
~KCategorizedView();
/**
* Reimplemented from QAbstractItemView.
*/
virtual void setModel ( QAbstractItemModel *model );
/**
* Calls to setGridSizeOwn().
*/
void setGridSize ( const QSize &size );
/**
* @warning note that setGridSize is not virtual in the base class (QListView), so if you are
* calling to this method, make sure you have a KCategorizedView pointer around. This
* means that something like:
* @code
* QListView *lv = new KCategorizedView();
* lv->setGridSize(mySize);
* @endcode
*
* will not call to the expected setGridSize method. Instead do something like this:
*
* @code
* QListView *lv;
* ...
* KCategorizedView *cv = qobject_cast<KCategorizedView*>(lv);
* if (cv) {
* cv->setGridSizeOwn(mySize);
* } else {
* lv->setGridSize(mySize);
* }
* @endcode
*
* @note this method will call to QListView::setGridSize among other operations.
*
* @since 4.4
*/
void setGridSizeOwn ( const QSize &size );
/**
* Reimplemented from QAbstractItemView.
*/
virtual QRect visualRect ( const QModelIndex &index ) const;
/**
* Returns the current category drawer.
*/
KCategoryDrawer *categoryDrawer() const;
/**
* The category drawer that will be used for drawing categories.
*/
void setCategoryDrawer ( KCategoryDrawer *categoryDrawer );
/**
* @return Category spacing. The spacing between categories.
*
* @since 4.4
*/
int categorySpacing() const;
/**
* Stablishes the category spacing. This is the spacing between categories.
*
* @since 4.4
*/
void setCategorySpacing ( int categorySpacing );
/**
* @return Whether blocks should be drawn with alternating colors.
*
* @since 4.4
*/
bool alternatingBlockColors() const;
/**
* Sets whether blocks should be drawn with alternating colors.
*
* @since 4.4
*/
void setAlternatingBlockColors ( bool enable );
/**
* @return Whether blocks can be collapsed or not.
*
* @since 4.4
*/
bool collapsibleBlocks() const;
/**
* Sets whether blocks can be collapsed or not.
*
* @since 4.4
*/
void setCollapsibleBlocks ( bool enable );
/**
* @return Block of indexes that are into @p category.
*
* @since 4.5
*/
QModelIndexList block ( const QString &category );
/**
* @return Block of indexes that are represented by @p representative.
*
* @since 4.5
*/
QModelIndexList block ( const QModelIndex &representative );
/**
* Reimplemented from QAbstractItemView.
*/
virtual QModelIndex indexAt ( const QPoint &point ) const;
/**
* Reimplemented from QAbstractItemView.
*/
virtual void reset();
/**
* Signify that all item delegates size hints return the same fixed size
*/
void setUniformItemWidths(bool enable);
/**
* Do all item delegate size hints return the same fixed size?
*/
bool uniformItemWidths() const;
protected:
/**
* Reimplemented from QWidget.
*/
virtual void paintEvent ( QPaintEvent *event );
/**
* Reimplemented from QWidget.
*/
virtual void resizeEvent ( QResizeEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void setSelection ( const QRect &rect,
QItemSelectionModel::SelectionFlags flags );
/**
* Reimplemented from QWidget.
*/
virtual void mouseMoveEvent ( QMouseEvent *event );
/**
* Reimplemented from QWidget.
*/
virtual void mousePressEvent ( QMouseEvent *event );
/**
* Reimplemented from QWidget.
*/
virtual void mouseReleaseEvent ( QMouseEvent *event );
/**
* Reimplemented from QWidget.
*/
virtual void leaveEvent ( QEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void startDrag ( Qt::DropActions supportedActions );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragMoveEvent ( QDragMoveEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragEnterEvent ( QDragEnterEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dragLeaveEvent ( QDragLeaveEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dropEvent ( QDropEvent *event );
/**
* Reimplemented from QAbstractItemView.
*/
virtual QModelIndex moveCursor ( CursorAction cursorAction,
Qt::KeyboardModifiers modifiers );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void rowsAboutToBeRemoved ( const QModelIndex &parent,
int start,
int end );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void updateGeometries();
/**
* Reimplemented from QAbstractItemView.
*/
virtual void currentChanged ( const QModelIndex &current,
const QModelIndex &previous );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void dataChanged ( const QModelIndex &topLeft,
const QModelIndex &bottomRight );
/**
* Reimplemented from QAbstractItemView.
*/
virtual void rowsInserted ( const QModelIndex &parent,
int start,
int end );
protected Q_SLOTS:
/**
* @internal
* Reposition items as needed.
*/
virtual void slotLayoutChanged();
virtual void slotCollapseOrExpandClicked ( QModelIndex );
private:
class Private;
Private *const d;
};
#endif // KCATEGORIZEDVIEW_H

View File

@ -0,0 +1,179 @@
/**
* This file is part of the KDE project
* Copyright (C) 2007, 2009 Rafael Fernández López <ereslibre@kde.org>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public License
* along with this library; see the file COPYING.LIB. If not, write to
* the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
* Boston, MA 02110-1301, USA.
*/
#ifndef KCATEGORYDRAWER_H
#define KCATEGORYDRAWER_H
#include <groupview_config.h>
#include <QtCore/QObject>
#include <QtGui/QMouseEvent>
class QPainter;
class QModelIndex;
class QStyleOption;
class KCategorizedView;
/**
* @since 4.5
*/
class LIBGROUPVIEW_EXPORT KCategoryDrawer
: public QObject
{
friend class KCategorizedView;
Q_OBJECT
public:
KCategoryDrawer ( KCategorizedView *view );
virtual ~KCategoryDrawer();
/**
* @return The view this category drawer is associated with.
*/
KCategorizedView *view() const;
/**
* This method purpose is to draw a category represented by the given
* @param index with the given @param sortRole sorting role
*
* @note This method will be called one time per category, always with the
* first element in that category
*/
virtual void drawCategory ( const QModelIndex &index,
int sortRole,
const QStyleOption &option,
QPainter *painter ) const;
/**
* @return The category height for the category representated by index @p index with
* style options @p option.
*/
virtual int categoryHeight ( const QModelIndex &index, const QStyleOption &option ) const;
//TODO KDE5: make virtual as leftMargin
/**
* @note 0 by default
*
* @since 4.4
*/
int leftMargin() const;
/**
* @note call to this method on the KCategoryDrawer constructor to set the left margin
*
* @since 4.4
*/
void setLeftMargin ( int leftMargin );
//TODO KDE5: make virtual as rightMargin
/**
* @note 0 by default
*
* @since 4.4
*/
int rightMargin() const;
/**
* @note call to this method on the KCategoryDrawer constructor to set the right margin
*
* @since 4.4
*/
void setRightMargin ( int rightMargin );
KCategoryDrawer &operator= ( const KCategoryDrawer &cd );
protected:
/**
* Method called when the mouse button has been pressed.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonPressed ( const QModelIndex &index, const QRect &blockRect, QMouseEvent *event );
/**
* Method called when the mouse button has been released.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonReleased ( const QModelIndex &index, const QRect &blockRect, QMouseEvent *event );
/**
* Method called when the mouse has been moved.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*/
virtual void mouseMoved ( const QModelIndex &index, const QRect &blockRect, QMouseEvent *event );
/**
* Method called when the mouse button has been double clicked.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
* @param event The mouse event.
*
* @warning You explicitly have to determine whether the event has been accepted or not. You
* have to call event->accept() or event->ignore() at all possible case branches in
* your code.
*/
virtual void mouseButtonDoubleClicked ( const QModelIndex &index, const QRect &blockRect, QMouseEvent *event );
/**
* Method called when the mouse button has left this block.
*
* @param index The representative index of the block of items.
* @param blockRect The rect occupied by the block of items.
*/
virtual void mouseLeft ( const QModelIndex &index, const QRect &blockRect );
private:
class Private;
Private *const d;
Q_SIGNALS:
/**
* This signal becomes emitted when collapse or expand has been clicked.
*/
void collapseOrExpandClicked ( const QModelIndex &index );
/**
* Emit this signal on your subclass implementation to notify that something happened. Usually
* this will be triggered when you have received an event, and its position matched some "hot spot".
*
* You give this action the integer you want, and having connected this signal to your code,
* the connected slot can perform the needed changes (view, model, selection model, delegate...)
*/
void actionRequested ( int action, const QModelIndex &index );
};
#endif // KCATEGORYDRAWER_H

View File

@ -0,0 +1,27 @@
/* Copyright 2013 MultiMC Contributors
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
//#ifndef LIBINSTANCE_CONFIG_H
//#define LIBINSTANCE_CONFIG_H
#include <QtCore/QtGlobal>
#ifdef LIBGROUPVIEW_LIBRARY
# define LIBGROUPVIEW_EXPORT Q_DECL_EXPORT
#else
# define LIBGROUPVIEW_EXPORT Q_DECL_IMPORT
#endif
//#endif // LIBINSTANCE_CONFIG_H