/*
* Copyright (C) 2000-2001 Marc Wandschneider <mw@kiltdown.org>
*
* 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.
*
* For more information look at the file COPYRIGHT in this package
*
*/
#ifndef _KMAILLIST_H_
#define _KMAILLIST_H_
#include <sanity.h>
#include <qpixmap.h>
#include <qscrollbar.h>
#include <llist.h>
/**
* this widget is similar to a QListView, but ends up requiring a few things
* that the list view can't handle, such as pixmaps all over the place, and
* some items that have extra crap on the bottom (spanning all cells) and
* others that don't.
*
* Please note: This widget is not intended to be terribly robust and handle
* all unforseen cases -- I wrote it specifically for a given program, and
* as long as it does everything that program needs, that's cool.
*/
enum ColumnWidth {
CW_FIXED = 0,
CW_PERCENTAGE
};
enum ColumnAlignment {
CA_LEFT = 0,
CA_CENTRE,
CA_RIGHT
};
enum ColumnSorting {
CS_NONE = 0,
CS_PRIMARY_UP = 1,
CS_PRIMARY_DOWN = 2,
CS_SECONDARY = 3
};
/**
* Forward decls
*/
class KMailList;
class KMailListItem;
/**
* Pass an array of these to setColumns. If the text is set, then that is
* used for the header, otherwise a pixmap is used. If neither is set, the
* column header is left blank. The width of the column can be specified as
* either fixed or a percentage. If it's fixed, then when the control is
* resized, the column remains the same width. However, percentage width
* columns are resized as appropriate. They use a percentage of all the
* space that the fixed columns aren't using.
*/
struct KMailListHeader {
const char *text;
QPixmap *pixmap;
int width;
double pct;
ColumnWidth type;
ColumnSorting sort;
unsigned int itemData;
int (*sortfn)(int, unsigned int, KMailListItem *, KMailListItem *);
};
/**
* You pass an array of these to addRow/updateRow. It contains either the
* text or the pixmap for the given column ... The KMailList control will
* free strings, but WILL NOT CLEAN UP PIXMAPS!!!!!!
*/
struct KMailListColumn {
const char *text;
QPixmap *pixmap;
enum ColumnAlignment alignment;
};
/**
* You pass in one of these to enter a row in the control.
*/
struct KMailListItem {
struct KMailListColumn *columns; // array of these, one per column.
int ccolumns;
bool boldEntry; // should all the text be bolded?
unsigned int itemData; // whatever you want.
};
/**
* This is for events that involve items.
*/
class KMailListEvent {
public:
/**
* Returns the index of the item that triggered the event. This is a zero
* base index.
*/
int index() { return itemIndex; }
/**
* Returns the number of items that were affected by this event. This can
* be greater than one when somebody goes and multi-selects a bunch of
* objects, and then double clicks on one of them, or hits ENTER.
*/
int itemCount() { return countOfItems; }
/**
* Returns an array of items that caused the event. if itemCount() is
* greater than zero, and this is NULL, then E_OUTOFMEMORY; CALLER frees
* resulting array with localFree();
*/
KMailListItem **items();
private:
/**
* Only KMailList can create and destroy us!
*/
friend class KMailList;
KMailListEvent(int ind, int citems, KMailListItem **rgitems);
~KMailListEvent();
int itemIndex;
int countOfItems;
KMailListItem **itemValues;
};
/**
* This is the actual KMailList class ...
*/
class KMailList : public QWidget {
/**
* All MOC'able Qt Objects require this.
*/
Q_OBJECT
DEBUG_TEST_DECL;
public:
/**
* you create a new one by specifying a parent and an optional name.
*/
KMailList(QWidget *parent, const char *name = 0);
/**
* Adds the given row to the list. The first two parameters specify the
* number of columns being passed in and the data for those columns. The
* next two specify an optional item data and it's size. This is merely
* stored and nothing is done with it.
*
* The Maillist assumes control of the memory in the item (but not the
* item itself). The caller need not clean up any allocations made for
* the columns.
*/
ERRCODE addRow(KMailListItem *rowData);
/**
* returns the item data for the selected rows in the database. We don't
* have need for a more general version that returns all the item data
* just yet.
*/
ERRCODE getSelectedRows(LinkList<unsigned int> &);
/**
* Clears out the entire control, including the headers, contents,
* etc. control is left in empty state.
*/
void nukeAll();
/**
* Removes the given rows from the mail list based on their item data.
* We don't currently have a need for another version based on any
* other identifiers.
*/
ERRCODE removeRows(int count, unsigned int *itemDataArray);
/**
* Sets the column headers for this control. Duplicates of all the
* data are maintained, so you should clean up whatever you have when
* you're done with it.
*/
ERRCODE setColumnHeaders(KMailListHeader *headers, int cheaders);
/**
* Given an identifier for a row, select it.
*/
ERRCODE selectRowFromItemData(unsigned int);
/**
* Given some itemData to identify a row, go and find the row with that
* itemData, and then go and update that row with the given information.
* NOTE: this assumes that itemData is unique. I didn't design this
* control to deal with the case where the itemData isn't something
* unique-like, such as a pointer, etc ...
*
* The Maillist assumes control of the memory in the item (but not the
* item itself). The caller need not clean up any allocations made for
* the columns.
*/
ERRCODE updateRowFromItemData(unsigned int, KMailListItem *rowData);
/**
* These two methods are used to iterate over items in the mail list.
* you pass in some item Data, and the next/previous item is returned, or
* NULL if the item is no longer in the list, or at the end/beginning.
*/
KMailListItem *nextItem(unsigned int);
KMailListItem *previousItem(unsigned int);
/**
* Little selection helpers that the folders might want to use sometime
*/
void selectFirst();
void selectLast();
~KMailList();
signals:
/**
* Emitted whenever a user has changed the size or location of a header.
*/
void columnHeadersChanged(int, KMailListHeader *);
/**
* The user has hit enter or double clicked on the given items(s).
*/
void itemLaunched(KMailListEvent *);
/**
* The user has selected the given item. It currently has the focus
* selection rectangle on it.
*/
void itemSelected(KMailListEvent *);
/**
* The user has pressed a key -- if we don't use it, then we'll pass it
* on to whomever is listening.
*/
void keyPressed(QKeyEvent *);
/**
* The user has right clicked somewhere in the control.
*/
void rightButtonPressed(QMouseEvent *);
/**
* The user is about to start dragging something. fweee!
*/
void dragItemStarted();
protected:
/**
* Event routines.
*/
virtual void paintEvent(QPaintEvent *);
virtual void wheelEvent(QWheelEvent *);
virtual void resizeEvent(QResizeEvent *);
virtual void focusInEvent(QFocusEvent *);
virtual void keyPressEvent(QKeyEvent * e);
virtual void focusOutEvent(QFocusEvent *);
virtual void mouseMoveEvent(QMouseEvent *);
virtual void mousePressEvent(QMouseEvent *);
virtual void mouseReleaseEvent(QMouseEvent *);
virtual void mouseDoubleClickEvent(QMouseEvent *);
private slots:
void scrollValueChanged(int);
private:
enum KMouseMode {
MMNormal = 0,
MMColumnResize,
MMColumnDrag
};
/**
* invalidates our buffer and forces an update.
*/
void forceUpdate() {
mustUpdateBuffer = true;
this->repaint();
}
/**
* We need to keep a little extra information about the column around.
*/
struct KInternalHeader : public KMailListHeader {
int widthCache;
int stringCache;
int pressedX;
bool pressed;
};
/**
* Our internal list will be a doubly linked list of these fellows.
* This will make things a bit complicated, but more efficient than
* using an array, unfortunately.
*/
struct KInternalItem : public KMailListItem {
bool selected;
KInternalItem *next;
KInternalItem *prev;
};
/**
* Headers.
*/
KInternalHeader *headers;
int cheaders;
/**
* Rows.
*/
KInternalItem *front, *end;
int viewableRows;
int rowHeight;
int crowTop;
int crows;
int secondarySort;
int primarySort;
bool primaryUp;
/**
* Mouse control and tracking.
*/
enum KMouseMode mouseMode;
int activeColumn, resizeX;
/**
* Selection management.
*/
int focusSelect;
int shiftAnchor;
bool rememberPress;
/**
* these are for drawing and updating.
*/
bool mustUpdateBuffer;
QPixmap *_doubleBuffer;
QBrush *_backgroundBrush;
/**
* This is for handling our scrollbar.
*/
QScrollBar *scrollBar;
/**
+=---------------------------------------------------------------------=
* Private routines.
+=---------------------------------------------------------------------=
*/
/**
* signals
*/
ERRCODE internalGenerateEventInfo(KMailListItem ** &, int &);
void emitRightButtonPressed(QMouseEvent *);
void emitKeyPressed(QKeyEvent *);
void emitDragItemStarted();
void emitColumnsChanged();
void emitItemLaunched();
void emitItemSelected();
/**
* Drawing
*/
void drawHeadersInBuffer(QPainter &, QColorGroup &);
void drawRowsInBuffer(QPainter &, QColorGroup &);
void drawContentsInBuffer();
int drawableWidth();
/**
* Mouse input
*/
void rightButtonPress(QMouseEvent *);
void leftButtonPress(QMouseEvent *);
/**
* Sizing/resizing
*/
void adjustScrollBar(int newHeight = -1);
void resizeColumnHeader(int, int);
int getMinRightWidth(int);
int getFixedWidth();
int getRowHeight();
int getColumnLeft(int);
/**
* Item creation
*/
ERRCODE copyColumnInfo(KMailListColumn *, KMailListColumn **);
ERRCODE addRowInternal(KInternalItem *item);
/**
* Selection management.
*/
KInternalItem *itemAtIndex(int);
void previousElement(ButtonState);
void nextElement(ButtonState);
void columnSortingChanged();
int getSelectedCount();
/**
* keyboard input
*/
void pageDown(ButtonState);
void homeKey(ButtonState);
void pageUp(ButtonState);
void endKey(ButtonState);
/**
* Scroll Bar goo
*/
QScrollBar *getScrollBar();
void setScrollValue(int);
/**
* Clean up
*/
void clearColumnInfo(KMailListColumn *);
void cleanUpHeaders();
void cleanUpRows();
};
#endif // _KMAILLIST_H_
syntax highlighted by Code2HTML, v. 0.9.1