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/filterview.cpp

267 lines
8.2 KiB

/***************************************************************************
copyright : (C) 2005-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 "filterview.h"
#include "controller.h"
#include "entry.h"
#include "collection.h"
#include "document.h"
#include "entryitem.h"
#include "tellico_kernel.h"
#include "listviewcomparison.h"
#include "../tellico_debug.h"
#include <tdelocale.h>
#include <tdepopupmenu.h>
#include <kiconloader.h>
#include <tqheader.h>
using Tellico::FilterView;
FilterView::FilterView(TQWidget* parent_, const char* name_) : GUI::ListView(parent_, name_), m_notSortedYet(true) {
addColumn(i18n("Filter"));
header()->setStretchEnabled(true, 0);
setResizeMode(TQListView::NoColumn);
setRootIsDecorated(true);
setShowSortIndicator(true);
setTreeStepSize(15);
setFullWidth(true);
connect(this, TQT_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)),
TQT_SLOT(contextMenuRequested(TQListViewItem*, const TQPoint&, int)));
}
bool FilterView::isSelectable(GUI::ListViewItem* item_) const {
if(!GUI::ListView::isSelectable(item_)) {
return false;
}
// because the popup menu has modify and delete, only
// allow one filter item to get selected
if(item_->isFilterItem()) {
return selectedItems().isEmpty();
}
return true;
}
void FilterView::contextMenuRequested(TQListViewItem* item_, const TQPoint& point_, int) {
if(!item_) {
return;
}
GUI::ListViewItem* item = static_cast<GUI::ListViewItem*>(item_);
if(item->isFilterItem()) {
TDEPopupMenu menu(this);
menu.insertItem(SmallIconSet(TQString::fromLatin1("filter")),
i18n("Modify Filter"), this, TQT_SLOT(slotModifyFilter()));
menu.insertItem(SmallIconSet(TQString::fromLatin1("edit-delete")),
i18n("Delete Filter"), this, TQT_SLOT(slotDeleteFilter()));
menu.exec(point_);
}
}
// this gets called when header() is clicked, so cycle through
void FilterView::setSorting(int col_, bool asc_) {
if(asc_ && !m_notSortedYet) {
if(sortStyle() == ListView::SortByText) {
setSortStyle(ListView::SortByCount);
} else {
setSortStyle(ListView::SortByText);
}
}
if(sortStyle() == ListView::SortByText) {
setColumnText(0, i18n("Filter"));
} else {
setColumnText(0, i18n("Filter (Sort by Count)"));
}
m_notSortedYet = false;
ListView::setSorting(col_, asc_);
}
void FilterView::addCollection(Data::CollPtr coll_) {
FilterVec filters = coll_->filters();
for(FilterVec::Iterator it = filters.begin(); it != filters.end(); ++it) {
addFilter(it);
}
Data::FieldPtr f = coll_->fieldByName(TQString::fromLatin1("title"));
if(f) {
setComparison(0, ListViewComparison::create(f));
}
}
void FilterView::addEntries(Data::EntryVec entries_) {
for(TQListViewItem* item = firstChild(); item; item = item->nextSibling()) {
Filter::Ptr filter = static_cast<FilterItem*>(item)->filter();
for(Data::EntryVecIt it = entries_.begin(); it != entries_.end(); ++it) {
if(filter && filter->matches(it.data())) {
new EntryItem(static_cast<FilterItem*>(item), it);
}
}
}
}
void FilterView::modifyEntries(Data::EntryVec entries_) {
for(Data::EntryVecIt it = entries_.begin(); it != entries_.end(); ++it) {
modifyEntry(it);
}
}
void FilterView::modifyEntry(Data::EntryPtr entry_) {
for(TQListViewItem* item = firstChild(); item; item = item->nextSibling()) {
bool hasEntry = false;
TQListViewItem* entryItem = 0;
// iterate over all children and find item with matching entry pointers
for(TQListViewItem* i = item->firstChild(); i; i = i->nextSibling()) {
if(static_cast<EntryItem*>(i)->entry() == entry_) {
i->setText(0, entry_->title());
// only one item per filter will match
hasEntry = true;
entryItem = i;
break;
}
}
// now, if the entry was there but no longer matches, delete it
// if the entry was not there but does match, add it
Filter::Ptr filter = static_cast<FilterItem*>(item)->filter();
if(hasEntry && !filter->matches(static_cast<EntryItem*>(entryItem)->entry())) {
delete entryItem;
} else if(!hasEntry && filter->matches(entry_)) {
new EntryItem(static_cast<FilterItem*>(item), entry_);
}
}
}
void FilterView::removeEntries(Data::EntryVec entries_) {
// the group modified signal gets handles separately, this is just for filters
for(TQListViewItem* item = firstChild(); item; item = item->nextSibling()) {
// iterate over all children and delete items with matching entry pointers
TQListViewItem* c1 = item->firstChild();
while(c1) {
if(entries_.contains(static_cast<EntryItem*>(c1)->entry())) {
TQListViewItem* c2 = c1;
c1 = c1->nextSibling();
delete c2;
} else {
c1 = c1->nextSibling();
}
}
}
}
void FilterView::addField(Data::CollPtr, Data::FieldPtr) {
resetComparisons();
}
void FilterView::modifyField(Data::CollPtr, Data::FieldPtr, Data::FieldPtr) {
resetComparisons();
}
void FilterView::removeField(Data::CollPtr, Data::FieldPtr) {
resetComparisons();
}
void FilterView::addFilter(FilterPtr filter_) {
FilterItem* filterItem = new FilterItem(this, filter_);
Data::EntryVec entries = Data::Document::self()->filteredEntries(filter_);
for(Data::EntryVecIt it = entries.begin(); it != entries.end(); ++it) {
new EntryItem(filterItem, it); // text gets set in constructor
}
}
void FilterView::slotModifyFilter() {
GUI::ListViewItem* item = static_cast<GUI::ListViewItem*>(currentItem());
if(!item || !item->isFilterItem()) {
return;
}
Kernel::self()->modifyFilter(static_cast<FilterItem*>(item)->filter());
}
void FilterView::slotDeleteFilter() {
GUI::ListViewItem* item = static_cast<GUI::ListViewItem*>(currentItem());
if(!item || !item->isFilterItem()) {
return;
}
Kernel::self()->removeFilter(static_cast<FilterItem*>(item)->filter());
}
void FilterView::removeFilter(FilterPtr filter_) {
// paranoia
if(!filter_) {
return;
}
// find the item for this filter
// cheating a bit, it's probably the current one
GUI::ListViewItem* found = 0;
GUI::ListViewItem* cur = static_cast<GUI::ListViewItem*>(currentItem());
if(cur && cur->isFilterItem() && static_cast<FilterItem*>(cur)->filter() == filter_) {
// found it!
found = cur;
} else {
// iterate over all filter items
for(TQListViewItem* item = firstChild(); item; item = item->nextSibling()) {
if(static_cast<FilterItem*>(item)->filter() == filter_) {
found = static_cast<FilterItem*>(item);
break;
}
}
}
// not found
if(!found) {
myDebug() << "GroupView::modifyFilter() - not found" << endl;
return;
}
delete found;
}
void FilterView::slotSelectionChanged() {
GUI::ListView::slotSelectionChanged();
GUI::ListViewItem* item = selectedItems().getFirst();
if(item && item->isFilterItem()) {
Controller::self()->slotUpdateFilter(static_cast<FilterItem*>(item)->filter());
}
}
void FilterView::resetComparisons() {
// this is only allowed when the view is not empty, so we can grab a collection ptr
if(childCount() == 0) {
return;
}
TQListViewItem* item = firstChild();
while(item && item->childCount() == 0) {
item = item->nextSibling();
}
if(!item) {
return;
}
item = item->firstChild();
Data::CollPtr coll = static_cast<EntryItem*>(item)->entry()->collection();
if(!coll) {
return;
}
Data::FieldPtr f = coll->fieldByName(TQString::fromLatin1("title"));
if(f) {
setComparison(0, ListViewComparison::create(f));
}
}
#include "filterview.moc"