You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
289 lines
7.5 KiB
289 lines
7.5 KiB
11 years ago
|
/***************************************************************************
|
||
|
* Copyright (C) 2004 by *
|
||
|
* Jason Kivlighn (jkivlighn@gmail.com) *
|
||
|
* Unai Garro (ugarro@users.sourceforge.net) *
|
||
|
* *
|
||
|
* This program is free software; you can redistribute it and/or modify *
|
||
|
* it under the terms of the GNU General Public License as published by *
|
||
|
* the Free Software Foundation; either version 2 of the License, or *
|
||
|
* (at your option) any later version. *
|
||
|
***************************************************************************/
|
||
|
|
||
|
#ifndef CATEGORYLISTVIEW_H
|
||
|
#define CATEGORYLISTVIEW_H
|
||
|
|
||
|
#include <qmap.h>
|
||
|
#include <qpixmap.h>
|
||
|
|
||
|
#include "dblistviewbase.h"
|
||
|
|
||
|
#include "datablocks/elementlist.h"
|
||
|
|
||
|
class KPopupMenu;
|
||
|
|
||
|
class RecipeDB;
|
||
|
class CategoryTree;
|
||
|
class CategoryCheckListView;
|
||
|
|
||
|
#define CATEGORYCHECKLISTITEM_RTTI 1005
|
||
|
#define CATEGORYLISTITEM_RTTI 1001
|
||
|
#define PSEUDOLISTITEM_RTTI 1008
|
||
|
|
||
|
/** Category listitems inherit this class to provide a common interface for accessing this information.
|
||
|
*/
|
||
|
class CategoryItemInfo
|
||
|
{
|
||
|
public:
|
||
|
CategoryItemInfo( const Element &category ) : ctyStored( category ), populated(false){}
|
||
|
bool isPopulated() const { return populated; }
|
||
|
void setPopulated( bool b ){ populated = b; }
|
||
|
|
||
|
Element element() const
|
||
|
{
|
||
|
return ctyStored;
|
||
|
}
|
||
|
|
||
|
int categoryId() const
|
||
|
{
|
||
|
return ctyStored.id;
|
||
|
}
|
||
|
QString categoryName() const
|
||
|
{
|
||
|
return ctyStored.name;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
Element ctyStored;
|
||
|
|
||
|
private:
|
||
|
bool populated;
|
||
|
};
|
||
|
|
||
|
class CategoryCheckListItem : public QCheckListItem, public CategoryItemInfo
|
||
|
{
|
||
|
public:
|
||
|
CategoryCheckListItem( CategoryCheckListView* klv, const Element &category, bool exclusive = true );
|
||
|
CategoryCheckListItem( QListViewItem* it, const Element &category, bool exclusive = true );
|
||
|
CategoryCheckListItem( CategoryCheckListView* klv, QListViewItem* it, const Element &category, bool exclusive = true );
|
||
|
|
||
|
virtual QString text( int column ) const;
|
||
|
virtual void setText( int column, const QString &text );
|
||
|
|
||
|
int rtti() const
|
||
|
{
|
||
|
return CATEGORYCHECKLISTITEM_RTTI;
|
||
|
}
|
||
|
|
||
|
protected:
|
||
|
virtual void stateChange( bool );
|
||
|
void setChildrenState( bool );
|
||
|
void setParentsState( bool );
|
||
|
|
||
|
bool locked;
|
||
|
bool exclusive;
|
||
|
|
||
|
private:
|
||
|
CategoryCheckListView *m_listview;
|
||
|
};
|
||
|
|
||
|
|
||
|
class CategoryListItem : public QListViewItem, public CategoryItemInfo
|
||
|
{
|
||
|
public:
|
||
|
CategoryListItem( QListView* klv, const Element &category );
|
||
|
CategoryListItem( QListViewItem* it, const Element &category );
|
||
|
CategoryListItem( QListView* klv, QListViewItem* it, const Element &category );
|
||
|
|
||
|
virtual QString text( int column ) const;
|
||
|
virtual void setText( int column, const QString &text );
|
||
|
|
||
|
int rtti() const
|
||
|
{
|
||
|
return CATEGORYLISTITEM_RTTI;
|
||
|
}
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
class CategoryListView : public DBListViewBase
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
CategoryListView( QWidget *parent, RecipeDB * );
|
||
|
|
||
|
void populateAll( QListViewItem *parent = 0 );
|
||
|
|
||
|
public slots:
|
||
|
void open( QListViewItem *item );
|
||
|
|
||
|
protected:
|
||
|
virtual void init();
|
||
|
|
||
|
virtual void load( int limit, int offset );
|
||
|
|
||
|
/** so that it allows dropping into
|
||
|
* subchildren that aren't expandable. The code is taken from KDE's KListView with
|
||
|
* one line commented out.
|
||
|
*/
|
||
|
void findDrop( const QPoint &pos, QListViewItem *&parent, QListViewItem *&after )
|
||
|
{
|
||
|
QPoint p ( contentsToViewport( pos ) );
|
||
|
|
||
|
// Get the position to put it in
|
||
|
QListViewItem *atpos = itemAt( p );
|
||
|
|
||
|
QListViewItem *above;
|
||
|
if ( !atpos ) // put it at the end
|
||
|
above = lastItem();
|
||
|
else {
|
||
|
// Get the closest item before us ('atpos' or the one above, if any)
|
||
|
if ( p.y() - itemRect( atpos ).topLeft().y() < ( atpos->height() / 2 ) )
|
||
|
above = atpos->itemAbove();
|
||
|
else
|
||
|
above = atpos;
|
||
|
}
|
||
|
|
||
|
if ( above ) {
|
||
|
// if above has children, I might need to drop it as the first item there
|
||
|
|
||
|
if ( above->firstChild() && above->isOpen() ) {
|
||
|
parent = above;
|
||
|
after = 0;
|
||
|
return ;
|
||
|
}
|
||
|
|
||
|
// Now, we know we want to go after "above". But as a child or as a sibling ?
|
||
|
// We have to ask the "above" item if it accepts children.
|
||
|
// ### NOTE: Here is the one line commented out so that "above" always accepts children
|
||
|
//if (above->isExpandable())
|
||
|
{
|
||
|
// The mouse is sufficiently on the right ? - doesn't matter if 'above' has visible children
|
||
|
if ( p.x() >= depthToPixels( above->depth() + 1 ) ||
|
||
|
( above->isOpen() && above->childCount() > 0 ) )
|
||
|
{
|
||
|
parent = above;
|
||
|
after = 0L;
|
||
|
return ;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
// Ok, there's one more level of complexity. We may want to become a new
|
||
|
// sibling, but of an upper-level group, rather than the "above" item
|
||
|
QListViewItem * betterAbove = above->parent();
|
||
|
QListViewItem * last = above;
|
||
|
while ( betterAbove ) {
|
||
|
// We are allowed to become a sibling of "betterAbove" only if we are
|
||
|
// after its last child
|
||
|
if ( last->nextSibling() == 0 ) {
|
||
|
if ( p.x() < depthToPixels ( betterAbove->depth() + 1 ) )
|
||
|
above = betterAbove; // store this one, but don't stop yet, there may be a better one
|
||
|
else
|
||
|
break; // not enough on the left, so stop
|
||
|
last = betterAbove;
|
||
|
betterAbove = betterAbove->parent(); // up one level
|
||
|
}
|
||
|
else
|
||
|
break; // we're among the child of betterAbove, not after the last one
|
||
|
}
|
||
|
}
|
||
|
// set as sibling
|
||
|
after = above;
|
||
|
parent = after ? after->parent() : 0L ;
|
||
|
}
|
||
|
|
||
|
protected slots:
|
||
|
virtual void removeCategory( int id ) = 0;
|
||
|
virtual void createCategory( const Element &category, int parent_id ) = 0;
|
||
|
virtual void modifyCategory( const Element &category );
|
||
|
virtual void modifyCategory( int id, int parent_id );
|
||
|
virtual void mergeCategories( int id1, int id2 );
|
||
|
|
||
|
virtual void checkCreateCategory( const Element &, int parent_id );
|
||
|
virtual void populate( QListViewItem *item );
|
||
|
|
||
|
QMap<int, QListViewItem*> items_map;
|
||
|
|
||
|
private:
|
||
|
QListViewItem *m_item_to_delete;
|
||
|
};
|
||
|
|
||
|
|
||
|
class StdCategoryListView : public CategoryListView
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
StdCategoryListView( QWidget *parent, RecipeDB *, bool editable = false );
|
||
|
~StdCategoryListView();
|
||
|
|
||
|
protected:
|
||
|
virtual void removeCategory( int id );
|
||
|
virtual void createCategory( const Element &category, int parent_id );
|
||
|
|
||
|
void setPixmap( const QPixmap &pixmap );
|
||
|
|
||
|
private slots:
|
||
|
void preparePopup();
|
||
|
void showPopup( KListView *, QListViewItem *, const QPoint & );
|
||
|
|
||
|
void createNew();
|
||
|
void remove
|
||
|
();
|
||
|
void rename();
|
||
|
void cut();
|
||
|
void paste();
|
||
|
void pasteAsSub();
|
||
|
|
||
|
void changeCategoryParent( QListViewItem *item, QListViewItem * /*afterFirst*/, QListViewItem * /*afterNow*/ );
|
||
|
|
||
|
void modCategory( QListViewItem* i );
|
||
|
void saveCategory( QListViewItem* i );
|
||
|
|
||
|
private:
|
||
|
bool checkBounds( const QString &name );
|
||
|
|
||
|
KPopupMenu *kpop;
|
||
|
QListViewItem *clipboard_item;
|
||
|
QListViewItem *clipboard_parent;
|
||
|
|
||
|
QPixmap m_folder_icon;
|
||
|
};
|
||
|
|
||
|
|
||
|
class CategoryCheckListView : public CategoryListView
|
||
|
{
|
||
|
Q_OBJECT
|
||
|
|
||
|
public:
|
||
|
CategoryCheckListView( QWidget *parent, RecipeDB *, bool exclusive=true, const ElementList &init_items_checked = ElementList() );
|
||
|
|
||
|
virtual void stateChange( CategoryCheckListItem*, bool );
|
||
|
|
||
|
ElementList selections() const{ return m_selections; }
|
||
|
|
||
|
protected:
|
||
|
virtual void removeCategory( int id );
|
||
|
virtual void createCategory( const Element &category, int parent_id );
|
||
|
|
||
|
virtual void load( int limit, int offset );
|
||
|
|
||
|
bool exclusive;
|
||
|
|
||
|
private:
|
||
|
ElementList m_selections;
|
||
|
};
|
||
|
|
||
|
|
||
|
class PseudoListItem : public QListViewItem
|
||
|
{
|
||
|
public:
|
||
|
PseudoListItem( QListView* lv ) : QListViewItem(lv){}
|
||
|
PseudoListItem( QListViewItem* it ) : QListViewItem(it){}
|
||
|
|
||
|
protected:
|
||
|
int rtti() const { return PSEUDOLISTITEM_RTTI; }
|
||
|
};
|
||
|
|
||
|
#endif //CATEGORYLISTVIEW_H
|