/*************************************************************************** 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 #include #include #include 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, TQ_SIGNAL(contextMenuRequested(TQListViewItem*, const TQPoint&, int)), TQ_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(item_); if(item->isFilterItem()) { TDEPopupMenu menu(this); menu.insertItem(SmallIconSet(TQString::fromLatin1("filter")), i18n("Modify Filter"), this, TQ_SLOT(slotModifyFilter())); menu.insertItem(SmallIconSet(TQString::fromLatin1("edit-delete")), i18n("Delete Filter"), this, TQ_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(item)->filter(); for(Data::EntryVecIt it = entries_.begin(); it != entries_.end(); ++it) { if(filter && filter->matches(it.data())) { new EntryItem(static_cast(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(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(item)->filter(); if(hasEntry && !filter->matches(static_cast(entryItem)->entry())) { delete entryItem; } else if(!hasEntry && filter->matches(entry_)) { new EntryItem(static_cast(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(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(currentItem()); if(!item || !item->isFilterItem()) { return; } Kernel::self()->modifyFilter(static_cast(item)->filter()); } void FilterView::slotDeleteFilter() { GUI::ListViewItem* item = static_cast(currentItem()); if(!item || !item->isFilterItem()) { return; } Kernel::self()->removeFilter(static_cast(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(currentItem()); if(cur && cur->isFilterItem() && static_cast(cur)->filter() == filter_) { // found it! found = cur; } else { // iterate over all filter items for(TQListViewItem* item = firstChild(); item; item = item->nextSibling()) { if(static_cast(item)->filter() == filter_) { found = static_cast(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(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(item)->entry()->collection(); if(!coll) { return; } Data::FieldPtr f = coll->fieldByName(TQString::fromLatin1("title")); if(f) { setComparison(0, ListViewComparison::create(f)); } } #include "filterview.moc"