added multi-select and drag&drop

svn path=/trunk/kdenetwork/kmail/; revision=228
wilder-work
Stefan Taferner 29 years ago
parent de25ba58df
commit 9c7b00a35f
  1. 97
      kmheaders.cpp
  2. 31
      kmheaders.h
  3. 181
      ktablistbox.cpp
  4. 53
      ktablistbox.h

@ -1,7 +1,17 @@
#include <qstrlist.h>
// $Id$
#include "kmheaders.h"
#include "mclass.h"
#include "kbusyptr.h"
#include "kmdragdata.h"
#include <drag.h>
#include <qstrlist.h>
#define MFL_DEL 'D'
#define MFL_NEW 'N'
#define MFL_UNREAD 'U'
extern KBusyPtr* kbp;
//-----------------------------------------------------------------------------
KMHeaders::KMHeaders(QWidget *parent=0, const char *name=0) : KTabListBox(parent, name)
@ -74,7 +84,7 @@ void KMHeaders::deleteMsg (int msgId)
Message* msg;
for (msg=getMsg(msgId); msg; msg=getMsg())
{
{
msg->del();
changeItem(msg->getFlag(), getMsgIndex, 0);
}
@ -94,9 +104,27 @@ void KMHeaders::undeleteMsg (int msgId)
}
//-----------------------------------------------------------------------------
void KMHeaders::toggleDeleteMsg (int msgId)
{
Message* msg;
if (!(msg=getMsg(msgId))) return;
if (msg->getFlag() != MFL_DEL) deleteMsg(msgId);
else undeleteMsg(msgId);
}
//-----------------------------------------------------------------------------
void KMHeaders::forwardMsg (int msgId)
{
static bool isBusy = FALSE;
if (isBusy) kbp->idle();
else kbp->busy();
isBusy = !isBusy;
}
@ -121,7 +149,9 @@ void KMHeaders::moveMsgToFolder (Folder* destination, int msgId)
//-----------------------------------------------------------------------------
Message* KMHeaders::getMsg (int msgId)
{
if (!folder)
int i, high;
if (!folder || msgId < -2)
{
getMsgIndex = -1;
return NULL;
@ -129,15 +159,34 @@ Message* KMHeaders::getMsg (int msgId)
if (msgId >= 0)
{
getMsgIndex = msgId;
getMsgMulti = FALSE;
return folder->getMsg(msgId+1);
}
if (msgId == -1)
{
getMsgMulti = TRUE;
getMsgIndex = currentItem();
for (i=0,high=numRows(); i<high; i++)
{
if (itemList[i].isMarked())
{
getMsgIndex = i;
break;
}
}
return (getMsgIndex>=0 ? folder->getMsg(getMsgIndex+1) : NULL);
}
if (getMsgIndex < 0) return NULL;
if (getMsgMulti) for (getMsgIndex++; getMsgIndex < numRows(); getMsgIndex++)
{
if (itemList[getMsgIndex].isMarked())
return folder->getMsg(getMsgIndex+1);
}
getMsgIndex = -1;
return NULL;
}
@ -158,10 +207,11 @@ void KMHeaders::changeItem (char c, int itemIndex, int column)
//-----------------------------------------------------------------------------
void KMHeaders::highlightMessage(int idx, int colId)
{
printf ("message %d highlighted (column %d)\n", idx, colId);
kbp->busy();
if (idx >= 0) setMsgRead(idx);
emit messageSelected(folder->getMsg(idx+1));
kbp->idle();
}
@ -193,6 +243,7 @@ void KMHeaders::updateMessageList(void)
clear();
if (!folder) return;
kbp->busy();
setAutoUpdate(FALSE);
for (i = (long)1; i <= folder->numMsg(); i++)
{
@ -209,6 +260,42 @@ void KMHeaders::updateMessageList(void)
}
setAutoUpdate(TRUE);
repaint();
kbp->idle();
}
//-----------------------------------------------------------------------------
bool KMHeaders :: prepareForDrag (int aCol, int aRow, char** data,
int* size, int* type)
{
static KmDragData dd;
int i, from, to, high;
high = numRows()-1;
for (i=0, from=-1; i<=high; i++)
{
if (itemList[i].isMarked())
{
from = i;
break;
}
}
for (i=high-1, to=-1; i>=0; i--)
{
if (itemList[i].isMarked())
{
to = i;
break;
}
}
if (from < 0 || to < 0) return FALSE;
dd.init(folder, from, to);
*data = (char*)&dd;
*size = sizeof(dd);
*type = DndRawData;
return TRUE;
}

@ -16,6 +16,12 @@ public:
virtual void setFolder(Folder *);
Folder* currentFolder(void) { return folder; }
virtual void changeItem (char c, int itemIndex, int column);
// Change part of the contents of a line
// The following methods process the message in the folder with
// the given msgId, or if no msgId is given all selected
// messages are processed.
virtual void setMsgUnread(int msgId=-1);
virtual void setMsgRead(int msgId=-1);
virtual void deleteMsg(int msgId=-1);
@ -24,31 +30,36 @@ public:
virtual void replyToMsg(int msgId=-1);
virtual void replyAllToMsg(int msgId=-1);
virtual void moveMsgToFolder(Folder* destination, int msgId=-1);
// These methods process the message in the folder with the
// given msgId, or if no msgId is given the (all) selected
// message(s) is (are) processed.
virtual void toggleDeleteMsg(int msgId=-1);
// Delete/undelete message(s) depending on the flag of
// the first selected message.
virtual void changeItem (char c, int itemIndex, int column);
// Change part of the contents of a line
Message* getMsg (int msgId=-2);
// Returns message with given id or current message if no
// id is given. First call with msgId==-1 returns first
// selected message, subsequent calls with no argument
// return the following selected messages.
int indexOfGetMsg (void) const { return getMsgIndex; }
// Returns index of message returned by last getMsg() call
signals:
virtual void messageSelected(Message *);
protected slots:
void selectMessage(int msgId, int colId);
void highlightMessage(int msgId, int colId);
protected:
Message* getMsg (int msgId=-2);
// Returns message with given id or current message if no
// id is given. First call with msgId==-1 returns first
// selected message, subsequent calls with no argument
// return the following selected messages.
virtual bool prepareForDrag (int col, int row, char** data, int* size,
int* type);
private:
virtual void updateMessageList(void);
Folder *folder;
int getMsgIndex;
bool getMsgMulti;
};
#endif

@ -7,11 +7,13 @@
#include <qpixmap.h>
#include <qapp.h>
#include <qdrawutl.h>
#include <kapp.h>
#define INIT_MAX_ITEMS 16
#include "ktablistbox.moc"
//=============================================================================
//
// C L A S S KTabListBoxItem
@ -21,6 +23,7 @@ KTabListBoxItem :: KTabListBoxItem (int aColumns)
{
columns = aColumns;
txt = new QString[columns];
mark = -2;
}
@ -37,6 +40,12 @@ void KTabListBoxItem :: setForeground (const QColor& fg)
}
void KTabListBoxItem :: setMarked (int m)
{
mark = m;
}
KTabListBoxItem& KTabListBoxItem :: operator= (const KTabListBoxItem& from)
{
int i;
@ -132,8 +141,15 @@ KTabListBox :: KTabListBox (QWidget *parent, const char *name, int columns,
KTabListBoxInherited (parent, name, f), lbox(this)
{
const QFontMetrics* fm = &fontMetrics();
QString f;
initMetaObject();
f = kapp->kdedir();
f.detach();
f += "/lib/pics/khtmlw_dnd.xpm";
dndDefaultPixmap.load(f.data());
maxItems = 0;
current = -1;
colList = NULL;
@ -144,7 +160,6 @@ KTabListBox :: KTabListBox (QWidget *parent, const char *name, int columns,
if (columns > 0) lbox.setNumCols(columns);
lbox.setGeometry(0, labelHeight, width(), height()-labelHeight);
}
@ -205,22 +220,54 @@ void KTabListBox :: setCurrentItem (int idx, int colId)
if (idx>=numRows()) return;
unmarkAll();
if (idx != current)
{
i = current;
current = idx;
updateItem(i);
updateItem(i,FALSE);
}
if (current >= 0)
{
updateItem(current);
markItem(idx);
emit highlighted(current, colId);
}
}
//-----------------------------------------------------------------------------
void KTabListBox :: markItem (int idx, int colId)
{
if (itemList[idx].marked()==colId) return;
itemList[idx].setMarked(colId);
updateItem(idx,FALSE);
}
//-----------------------------------------------------------------------------
void KTabListBox :: unmarkItem (int idx)
{
int mark;
mark = itemList[idx].marked();
itemList[idx].setMarked(-2);
if (mark>=-1) updateItem(idx);
}
//-----------------------------------------------------------------------------
void KTabListBox :: unmarkAll (void)
{
int i;
for (i=numRows()-1; i>=0; i--)
unmarkItem(i);
}
//-----------------------------------------------------------------------------
void KTabListBox :: insertItem (const char* aStr, int row)
{
@ -328,7 +375,13 @@ void KTabListBox :: updateItem (int row, bool erase)
//-----------------------------------------------------------------------------
void KTabListBox :: clear (void)
{
int i;
for (i=numRows()-1; i>=0; i--)
itemList[i].setMarked(-2);
setNumRows(0);
lbox.setTopLeftCell(0,0);
current = -1;
}
@ -365,12 +418,6 @@ void KTabListBox :: resizeList (int newNumItems)
}
//-----------------------------------------------------------------------------
void KTabListBox :: mouseDoubleClickEvent (QMouseEvent*)
{
}
//-----------------------------------------------------------------------------
void KTabListBox :: resizeEvent (QResizeEvent* e)
{
@ -421,15 +468,26 @@ void KTabListBox :: paintEvent (QPaintEvent* e)
//-----------------------------------------------------------------------------
void KTabListBox :: mousePressEvent (QMouseEvent* e)
bool KTabListBox :: startDrag (int aCol, int aRow, const QPoint& p)
{
printf ("+%d+%d\n", e->pos().x(), e->pos().y());
int dx = -(dndDefaultPixmap.width() >> 1);
int dy = -(dndDefaultPixmap.height() >> 1);
KDNDIcon* icon = new KDNDIcon(dndDefaultPixmap, p.x()+dx, p.y()+dy);
int size, type;
char* data;
if (!prepareForDrag(aCol,aRow, &data, &size, &type)) return FALSE;
KTabListBoxInherited::startDrag(icon, data, size, type, dx, dy);
return TRUE;
}
//-----------------------------------------------------------------------------
void KTabListBox :: mouseReleaseEvent (QMouseEvent*)
bool KTabListBox :: prepareForDrag (int aCol, int aRow, char** data,
int* size, int* type)
{
return FALSE;
}
@ -443,6 +501,7 @@ void KTabListBox :: horSbValue (int val)
//-----------------------------------------------------------------------------
void KTabListBox :: horSbSlidingDone ()
{
printf ("sliding done\n");
}
@ -453,6 +512,13 @@ void KTabListBox :: horSbSlidingDone ()
// C L A S S KTabListBoxTable
//
//=============================================================================
QPoint KTabListBoxTable::dragStartPos;
int KTabListBoxTable::dragCol = -1;
int KTabListBoxTable::dragRow = -1;
int KTabListBoxTable::selIdx = -1;
KTabListBoxTable :: KTabListBoxTable (KTabListBox *parent):
KTabListBoxTableInherited (parent)
{
@ -460,6 +526,8 @@ KTabListBoxTable :: KTabListBoxTable (KTabListBox *parent):
initMetaObject();
dragging = FALSE;
setTableFlags (Tbl_autoVScrollBar|Tbl_autoHScrollBar|Tbl_smoothVScrolling|
Tbl_clipCellPainting);
@ -495,16 +563,19 @@ void KTabListBoxTable :: paintCell (QPainter* p, int row, int col)
QColor bg;
QColorGroup g = colorGroup();
KTabListBox* owner = (KTabListBox*)parentWidget();
KTabListBoxItem* item = owner->getItem(row);
if (!item) return;
if (owner->current == row)
if (item->marked()==-1)
{
bg = g.background();
p->fillRect (0, 0, cellWidth(col), cellHeight(row), bg);
}
p->setPen (owner->itemList[row].foreground());
p->setPen (item->foreground());
p->setBackgroundColor (g.base());
owner->colList[col].paintCell (p, owner->itemList[row].text(col));
owner->colList[col].paintCell (p, item->text(col));
}
@ -530,17 +601,93 @@ void KTabListBoxTable :: mouseDoubleClickEvent (QMouseEvent* e)
}
//-----------------------------------------------------------------------------
void KTabListBoxTable :: doItemSelection (QMouseEvent* e, int idx)
{
KTabListBox* owner = (KTabListBox*)parentWidget();
int i, di;
owner->unmarkAll();
if ((e->state()&ShiftButton)!=0 && owner->currentItem()>=0)
{
i = owner->currentItem();
di = (i>idx ? -1 : 1);
while (1)
{
owner->markItem(i);
if (i == idx) break;
i += di;
}
}
else owner->setCurrentItem(idx);
}
//-----------------------------------------------------------------------------
void KTabListBoxTable :: mousePressEvent (QMouseEvent* e)
{
KTabListBox* owner = (KTabListBox*)parentWidget();
owner->setCurrentItem (findRow(e->pos().y()), findCol(e->pos().x()));
int idx;
// arm for possible dragging
dragStartPos = e->pos();
dragCol = findCol(e->pos().x());
dragRow = findRow(e->pos().y());
// handle item highlighting
idx = findRow(e->pos().y());
if (idx >= 0 && owner->getItem(idx)->marked() < -1)
{
doItemSelection(e, idx);
selIdx = idx;
}
else selIdx = -1;
}
//-----------------------------------------------------------------------------
void KTabListBoxTable :: mouseReleaseEvent (QMouseEvent* e)
{
KTabListBox* owner = (KTabListBox*)parentWidget();
int idx;
if (dragging)
{
owner->mouseReleaseEvent(e);
dragRow = dragCol = -1;
dragging = FALSE;
}
else
{
idx = findRow(e->pos().y());
if (idx >= 0 && selIdx < 0)
doItemSelection(e, idx);
}
}
//-----------------------------------------------------------------------------
void KTabListBoxTable :: mouseReleaseEvent (QMouseEvent*)
void KTabListBoxTable :: mouseMoveEvent (QMouseEvent* e)
{
KTabListBox* owner = (KTabListBox*)parentWidget();
if (dragging)
{
owner->mouseMoveEvent(e);
return;
}
if ((e->state() & (RightButton|LeftButton|MidButton)) != 0)
{
if (dragRow >= 0 && dragCol >= 0 &&
(abs(e->pos().x()-dragStartPos.x()) >= 5 ||
abs(e->pos().y()-dragStartPos.y()) >= 5))
{
// we have a liftoff !
dragging = owner->startDrag(dragCol, dragRow, mapToGlobal(e->pos()));
return;
}
}
}

@ -9,12 +9,13 @@
#include <qtablevw.h>
#include <qcolor.h>
#include <qpixmap.h>
#include <drag.h>
#define MAX_SEP_CHARS 16
class KTabListBoxColumn;
class KTabListBoxItem;
class KTabListBoxTable;
class KTabListBoxItem;
class KTabListBox;
typedef QDict<QPixmap> KTabListBoxDict;
@ -31,20 +32,27 @@ public:
virtual ~KTabListBoxTable();
protected:
virtual void mouseDoubleClickEvent (QMouseEvent *);
virtual void mousePressEvent (QMouseEvent *);
virtual void mouseReleaseEvent (QMouseEvent *);
virtual void mouseDoubleClickEvent (QMouseEvent*);
virtual void mousePressEvent (QMouseEvent*);
virtual void mouseReleaseEvent (QMouseEvent*);
virtual void mouseMoveEvent (QMouseEvent*);
virtual void doItemSelection (QMouseEvent*, int idx);
virtual void paintCell (QPainter*, int row, int col);
virtual int cellWidth (int col);
void reconnectSBSignals (void);
static QPoint dragStartPos;
static int dragCol, dragRow;
static int selIdx;
bool dragging;
};
//--------------------------------------------------
#define KTabListBoxInherited QWidget
class KTabListBox : public QWidget
#define KTabListBoxInherited KDNDWidget
class KTabListBox : public KDNDWidget
{
Q_OBJECT;
friend KTabListBoxTable;
@ -82,6 +90,11 @@ public:
// set the current (selected) column. colId is the value that
// is transfered with the selected() signal that is emited.
virtual void unmarkAll (void);
// unmark all items
virtual void markItem (int idx, int colId=-1);
virtual void unmarkItem (int idx);
int findItem (int yPos) const { return (lbox.findRow(yPos)); }
int topItem (void) const { return (lbox.topCell()); }
@ -111,6 +124,12 @@ public:
void repaint (void) { QWidget::repaint(); lbox.repaint(); }
bool startDrag(int col, int row, const QPoint& mousePos);
// Indicates that a drag has started with given item.
// Returns TRUE if we are dragging, FALSE if drag-start failed.
QPixmap& dndPixmap(void) { return dndDefaultPixmap; }
signals:
void highlighted (int Index, int column);
// emited when the current item changes (either via setCurrentItem()
@ -128,15 +147,18 @@ protected:
void updateItem (int idx, bool clear = TRUE);
bool needsUpdate (int id) { return (lbox.autoUpdate() && itemVisible(id)); }
KTabListBoxItem* getItem (int idx);
virtual void resizeEvent (QResizeEvent*);
virtual void paintEvent (QPaintEvent*);
virtual void resizeList (int newNumItems=-1);
// Resize item array. Per default enlarge it to double size
virtual void mouseDoubleClickEvent (QMouseEvent *);
virtual void mousePressEvent (QMouseEvent *);
virtual void mouseReleaseEvent (QMouseEvent *);
virtual bool prepareForDrag (int col, int row, char** data, int* size,
int* type);
// Called to set drag data, size, and type. If this method
// returns FALSE then no drag occurs.
KTabListBoxColumn* colList;
KTabListBoxItem* itemList;
@ -146,6 +168,7 @@ protected:
KTabListBoxDict pixDict;
KTabListBoxTable lbox;
int labelHeight;
QPixmap dndDefaultPixmap;
private: // Disabled copy constructor and operator=
KTabListBox (const KTabListBox &) {}
@ -167,10 +190,15 @@ public:
KTabListBoxItem& operator= (const KTabListBoxItem&);
int marked (void) const { return mark; }
bool isMarked (void) const { return (mark >= -1); }
virtual void setMarked (int mark);
private:
QString* txt;
int columns;
QColor fgColor;
int mark;
friend class KTabListBox;
};
@ -201,4 +229,11 @@ protected:
KTabListBox* parent;
};
inline KTabListBoxItem* KTabListBox :: getItem (int idx)
{
return ((idx>=0 && idx<maxItems) ? &itemList[idx] : (KTabListBoxItem*)NULL);
}
#endif /*KTabListBox_h*/

Loading…
Cancel
Save