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.
tellico/src/gui/listview.cpp

348 lines
10 KiB

/***************************************************************************
copyright : (C) 2001-2006 by Robby Stephenson
email : robby@periapsis.org
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of version 2 of the GNU General Public License as *
* published by the Free Software Foundation; *
* *
***************************************************************************/
#include "listview.h"
#include "../controller.h"
#include "../tellico_utils.h"
#include "../tellico_debug.h"
#include <kapplication.h>
#include <tqpainter.h>
#include <tqpixmap.h>
#include <tqheader.h>
using Tellico::GUI::ListView;
using Tellico::GUI::ListViewItem;
ListView::ListView(TQWidget* parent_, const char* name_) : KListView(parent_, name_/*=0*/),
m_sortStyle(SortByText), m_isClear(true) {
setSelectionMode(TQListView::Extended);
connect(this, TQT_SIGNAL(selectionChanged()),
TQT_SLOT(slotSelectionChanged()));
connect(this, TQT_SIGNAL(doubleClicked(TQListViewItem*)),
TQT_SLOT(slotDoubleClicked(TQListViewItem*)));
#if !KDE_IS_VERSION(3,3,90)
m_shadeSortColumn = false;
// call it once to initialize
slotUpdateColors();
#endif
connect(kapp, TQT_SIGNAL(kdisplayPaletteChanged()), TQT_SLOT(slotUpdateColors()));
m_comparisons.setAutoDelete(true);
}
ListView::~ListView() {
}
void ListView::clearSelection() {
if(m_selectedItems.isEmpty()) {
// nothing to do;
return;
}
bool b = signalsBlocked();
blockSignals(true);
selectAll(false);
blockSignals(b);
emit selectionChanged();
}
void ListView::updateSelected(ListViewItem* item_, bool selected_) {
if(selected_) {
m_selectedItems.append(item_);
} else {
m_selectedItems.removeRef(item_);
}
}
bool ListView::isSelectable(ListViewItem* item_) const {
// don't allow hidden items to be selected
if(!item_->isVisible()) {
return false;
}
// selecting multiple items is ok
// only when parent is open. Be careful to check for existence of parent
if(item_->parent() && !item_->parent()->isOpen()) {
return false;
}
// just selecting a single item is always ok
if(m_selectedItems.isEmpty()) {
return true;
}
// not allowed is something other than an entry is selected and current is entry
if(m_selectedItems.getFirst()->isEntryItem() != item_->isEntryItem()) {
return false;
}
return true;
}
int ListView::firstVisibleColumn() const {
int col = 0;
while(col < columns() && columnWidth(header()->mapToSection(col)) == 0) {
++col;
}
if(col == columns()) {
return -1;
}
return header()->mapToSection(col);
}
int ListView::lastVisibleColumn() const {
int col = columns()-1;
while(col < columns() && columnWidth(header()->mapToSection(col)) == 0) {
--col;
}
if(col == columns()) {
return -1;
}
return header()->mapToSection(col);
}
void ListView::setColumnText(int column, const TQString& label) {
ListViewComparison* comp = m_comparisons.take(columnText(column));
KListView::setColumnText(column, label);
if(comp) {
m_comparisons.insert(columnText(column), comp);
}
}
void ListView::setComparison(int column, ListViewComparison* comp) {
if(comp) {
m_comparisons.replace(columnText(column), comp);
}
}
void ListView::removeComparison(int column) {
m_comparisons.remove(columnText(column));
}
void ListView::clearComparisons() {
m_comparisons.clear();
}
int ListView::compare(int col, const GUI::ListViewItem* item1, GUI::ListViewItem* item2, bool asc) {
if(col >= 0 && col < static_cast<int>(m_comparisons.count())) {
ListViewComparison* com = m_comparisons.find(columnText(col));
if(com) {
return com->compare(col, item1, item2, asc);
}
}
return 0;
}
#if !KDE_IS_VERSION(3,3,90)
void ListView::setShadeSortColumn(bool shade_) {
if(m_shadeSortColumn != shade_) {
m_shadeSortColumn = shade_;
repaint();
}
}
#endif
void ListView::slotUpdateColors() {
#if !KDE_IS_VERSION(3,3,90)
m_backColor2 = viewport()->colorGroup().base();
if(m_backColor2 == TQt::black) {
m_backColor2 = TQColor(50, 50, 50); // dark gray
} else {
int h,s,v;
m_backColor2.hsv(&h, &s, &v);
if(v > 175) {
m_backColor2 = m_backColor2.dark(105);
} else {
m_backColor2 = m_backColor2.light(120);
}
}
m_altColor2 = alternateBackground();
if(m_altColor2 == TQt::black) {
m_altColor2 = TQColor(50, 50, 50); // dark gray
} else {
int h,s,v;
m_altColor2.hsv(&h, &s, &v);
if(v > 175) {
m_altColor2 = m_altColor2.dark(105);
} else {
m_altColor2 = m_altColor2.light(120);
}
}
#endif
Tellico::updateContrastColor(viewport()->colorGroup());
repaint();
}
void ListView::slotSelectionChanged() {
if(m_selectedItems.isEmpty()) {
if(m_isClear) {
return; // nothing to do
}
m_isClear = true;
Controller::self()->slotClearSelection();
return;
}
m_isClear = false;
Data::EntryVec entries;
// now just find all the children or grandchildren that are entry items
for(GUI::ListViewItemListIt it(m_selectedItems); it.current(); ++it) {
Data::EntryVec more = it.current()->entries();
for(Data::EntryVecIt entry = more.begin(); entry != more.end(); ++entry) {
if(!entries.contains(entry)) {
entries.append(entry);
}
}
}
// Controller::self()->slotUpdateCurrent(entries); // just update current, don't change selection
Controller::self()->slotUpdateSelection(this, entries);
}
void ListView::slotDoubleClicked(TQListViewItem* item_) {
if(!item_) {
return;
}
// if it has children, just open it
// but some items delay children creation
if(static_cast<ListViewItem*>(item_)->realChildCount() > 0) {
item_->setOpen(!item_->isOpen());
}
GUI::ListViewItem* item = static_cast<GUI::ListViewItem*>(item_);
item->doubleClicked();
}
void ListView::drawContentsOffset(TQPainter* p, int ox, int oy, int cx, int cy, int cw, int ch) {
bool oldUpdatesEnabled = isUpdatesEnabled();
setUpdatesEnabled(false);
KListView::drawContentsOffset(p, ox, oy, cx, cy, cw, ch);
setUpdatesEnabled(oldUpdatesEnabled);
}
/* ****************** ListViewItem ********************* */
ListViewItem::~ListViewItem() {
// I think there's a bug in qt where the children of this item are deleted after the item itself
// as a result, there is no listView() pointer for the children, that obvious causes
// a problem with updating the selection. So we MUST call clear() here ourselves!
clear();
// be sure to remove from selected list when it's deleted
ListView* lv = listView();
if(lv) {
lv->updateSelected(this, false);
}
}
void ListViewItem::clear() {
TQListViewItem* item = firstChild();
while(item) {
delete item;
item = firstChild();
}
}
int ListViewItem::compare(TQListViewItem* item_, int col_, bool asc_) const {
int res = compareWeight(item_, col_, asc_);
if(res != 0) {
return res;
}
res = listView()->compare(col_, this, static_cast<GUI::ListViewItem*>(item_), asc_);
return res == 0 ? KListViewItem::compare(item_, col_, asc_) : res;
}
int ListViewItem::compareWeight(TQListViewItem* item_, int col_, bool asc_) const {
Q_UNUSED(col_);
// I want the sorting to be independent of sort order
GUI::ListViewItem* i = static_cast<GUI::ListViewItem*>(item_);
int res = 0;
if(m_sortWeight < i->sortWeight()) {
res = -1;
} else if(m_sortWeight > i->sortWeight()) {
res = 1;
}
if(asc_) {
res *= -1; // reverse, heavier weights will come first always
}
return res;
}
void ListViewItem::setSelected(bool s_) {
ListView* lv = listView();
if(!lv) {
return;
}
if(s_ && !lv->isSelectable(this)) {
return;
}
if(s_ != isSelected()) {
lv->updateSelected(this, s_);
KListViewItem::setSelected(s_);
}
}
TQColor ListViewItem::backgroundColor(int column_) {
#if KDE_IS_VERSION(3,3,90)
return KListViewItem::backgroundColor(column_);
#else
ListView* view = listView();
if(view->columns() > 1 && view->shadeSortColumn() && column_ == view->sortColumn()) {
return isAlternate() ? view->alternateBackground2() : view->background2();
}
return isAlternate() ? view->alternateBackground() : view->viewport()->colorGroup().base();
#endif
}
void ListViewItem::paintCell(TQPainter* p_, const TQColorGroup& cg_,
int column_, int width_, int align_) {
// taken from klistview.cpp
// I can't call KListViewItem::paintCell since KListViewItem::backgroundCOlor(int) is
// not virtual. I need to be sure to call ListViewItem::backgroundColor(int);
TQColorGroup cg = cg_;
const TQPixmap* pm = listView()->viewport()->backgroundPixmap();
if(pm && !pm->isNull()) {
cg.setBrush(TQColorGroup::Base, TQBrush(backgroundColor(column_), *pm));
TQPoint o = p_->brushOrigin();
p_->setBrushOrigin(o.x()-listView()->contentsX(), o.y()-listView()->contentsY());
} else {
cg.setColor(listView()->viewport()->backgroundMode() == TQt::FixedColor ?
TQColorGroup::Background : TQColorGroup::Base,
backgroundColor(column_));
}
// don't call KListViewItem::paintCell() since that also does alternate painting, etc...
TQListViewItem::paintCell(p_, cg, column_, width_, align_);
// borrowed from amarok, draw line to left of cell
if(!isSelected()) {
p_->setPen(TQPen(listView()->alternateBackground(), 0, TQt::SolidLine));
p_->drawLine(width_-1, 0, width_-1, height()-1);
}
}
Tellico::Data::EntryVec ListViewItem::entries() const {
Data::EntryVec entries;
for(TQListViewItem* child = firstChild(); child; child = child->nextSibling()) {
Data::EntryVec more = static_cast<GUI::ListViewItem*>(child)->entries();
for(Data::EntryVecIt entry = more.begin(); entry != more.end(); ++entry) {
if(!entries.contains(entry)) {
entries.append(entry);
}
}
}
return entries;
}
#include "listview.moc"