diff options
Diffstat (limited to 'src/frontend/mainindex/bookmarks/cbookmarkindex.cpp')
-rw-r--r-- | src/frontend/mainindex/bookmarks/cbookmarkindex.cpp | 850 |
1 files changed, 850 insertions, 0 deletions
diff --git a/src/frontend/mainindex/bookmarks/cbookmarkindex.cpp b/src/frontend/mainindex/bookmarks/cbookmarkindex.cpp new file mode 100644 index 0000000..7405fd3 --- /dev/null +++ b/src/frontend/mainindex/bookmarks/cbookmarkindex.cpp @@ -0,0 +1,850 @@ +/********* +* +* This file is part of BibleTime's source code, http://www.bibletime.info/. +* +* Copyright 1999-2008 by the BibleTime developers. +* The BibleTime source code is licensed under the GNU General Public License version 2.0. +* +**********/ + +//BibleTime includes +#include "cbookmarkindex.h" + +#include "btbookmarkitembase.h" +#include "btbookmarkitem.h" +#include "btbookmarkfolder.h" +#include "btbookmarkloader.h" + +#include "backend/managers/creferencemanager.h" +#include "backend/drivers/cswordmoduleinfo.h" + +#include "frontend/searchdialog/csearchdialog.h" +#include "backend/config/cbtconfig.h" +#include "frontend/cinfodisplay.h" + +#include "frontend/cprinter.h" +#include "frontend/cdragdrop.h" + +#include "util/cresmgr.h" +#include "util/directoryutil.h" +#include "util/ctoolclass.h" + +#include <boost/scoped_ptr.hpp> + +//Qt includes +#include <QInputDialog> +#include <QDragLeaveEvent> +#include <QDragMoveEvent> +#include <QDropEvent> +#include <QHeaderView> +#include <QTimer> +#include <QToolTip> +#include <QList> +#include <QTreeWidget> +#include <QTreeWidgetItem> +#include <QCursor> +#include <QMouseEvent> +#include <QMessageBox> +#include <QMenu> +#include <QAction> +#include <QPaintEvent> +#include <QPainter> +#include <QApplication> +#include <QDrag> + +#include <QDebug> + +CBookmarkIndex::CBookmarkIndex(QWidget *parent) + : QTreeWidget(parent), + m_magTimer(this), + m_previousEventItem(0) +{ + setMouseTracking(true); + m_magTimer.setSingleShot(true); + m_magTimer.setInterval(CBTConfig::get(CBTConfig::magDelay)); + setContextMenuPolicy(Qt::CustomContextMenu); + initView(); + initConnections(); + initTree(); +} + +CBookmarkIndex::~CBookmarkIndex() +{ + saveBookmarks(); +} + + +/** Initializes the view. */ +void CBookmarkIndex::initView() +{ + //qDebug("CBookmarkIndex::initView"); + + header()->hide(); + + setFocusPolicy(Qt::WheelFocus); + + //d'n'd related settings + setDragEnabled( true ); + setAcceptDrops( true ); + setDragDropMode(QAbstractItemView::DragDrop); + viewport()->setAcceptDrops(true); + setAutoScroll(true); + setAutoExpandDelay(800); + + setItemsExpandable(true); + setRootIsDecorated(true); + setAllColumnsShowFocus(true); + setSelectionMode(QAbstractItemView::ExtendedSelection); + + //setup the popup menu + m_popup = new QMenu(viewport()); + m_popup->setTitle(tr("Bookmarks")); + + m_actions.newFolder = newQAction(tr("New folder"), CResMgr::mainIndex::newFolder::icon, 0, this, SLOT(createNewFolder()), this); + m_actions.changeFolder = newQAction(tr("Rename folder"),CResMgr::mainIndex::changeFolder::icon, 0, this, SLOT(changeFolder()), this); + + m_actions.changeBookmark = newQAction(tr("Change bookmark description..."), CResMgr::mainIndex::changeBookmark::icon, 0, this, SLOT(changeBookmark()), this); + m_actions.importBookmarks = newQAction(tr("Import to folder..."), CResMgr::mainIndex::importBookmarks::icon, 0, this, SLOT(importBookmarks()), this); + m_actions.exportBookmarks = newQAction(tr("Export from folder..."), CResMgr::mainIndex::exportBookmarks::icon, 0, this, SLOT(exportBookmarks()), this); + m_actions.printBookmarks = newQAction(tr("Print bookmarks..."), CResMgr::mainIndex::printBookmarks::icon, 0, this, SLOT(printBookmarks()), this); + + m_actions.deleteEntries = newQAction(tr("Remove selected items..."), CResMgr::mainIndex::deleteItems::icon, 0, this, SLOT(deleteEntries()), this); + + + //fill the popup menu itself + m_popup->addAction(m_actions.newFolder); + m_popup->addAction(m_actions.changeFolder); + QAction* separator = new QAction(this); + separator->setSeparator(true); + m_popup->addAction(separator); + m_popup->addAction(m_actions.changeBookmark); + m_popup->addAction(m_actions.importBookmarks); + m_popup->addAction(m_actions.exportBookmarks); + m_popup->addAction(m_actions.printBookmarks); + separator = new QAction(this); + separator->setSeparator(true); + m_popup->addAction(separator); + m_popup->addAction(m_actions.deleteEntries); + + //qDebug("CBookmarkIndex::initView end"); +} + +/** Convenience function for creating a new QAction. +* Should be replaced with something better; it was easier to make a new function +* than to modify all QAction constructors. +*/ +QAction* CBookmarkIndex::newQAction(const QString& text, const QString& pix, const int /*shortcut*/, const QObject* receiver, const char* slot, QObject* parent) +{ + QAction* action = new QAction(util::filesystem::DirectoryUtil::getIcon(pix), text, parent); + QObject::connect(action, SIGNAL(triggered()), receiver, slot); + return action; +} + +/** Initialize the SIGNAL<->SLOT connections */ +void CBookmarkIndex::initConnections() +{ + //qDebug("CBookmarkIndex::initConnections"); + bool ok; + ok = connect(this, SIGNAL(itemActivated(QTreeWidgetItem*, int)), this, SLOT(slotExecuted(QTreeWidgetItem*))); + Q_ASSERT(ok); + ok = connect(this, SIGNAL(customContextMenuRequested(const QPoint&)), + SLOT(contextMenu(const QPoint&))); + Q_ASSERT(ok); + ok = connect(&m_magTimer, SIGNAL(timeout()), this, SLOT(magTimeout())); + Q_ASSERT(ok); + ok = connect(this, SIGNAL(itemEntered(QTreeWidgetItem*, int)), this, SLOT(slotItemEntered(QTreeWidgetItem*, int)) ); + Q_ASSERT(ok); +} + + +/** +* Hack to get single click and selection working. See slotExecuted. +*/ +void CBookmarkIndex::mouseReleaseEvent(QMouseEvent* event) +{ + //qDebug("CBookmarkIndex::mouseReleaseEvent"); + m_mouseReleaseEventModifiers = event->modifiers(); + QTreeWidget::mouseReleaseEvent(event); +} + +/** Called when an item is clicked with mouse or activated with keyboard. */ +void CBookmarkIndex::slotExecuted( QTreeWidgetItem* i ) +{ + qDebug("CBookmarkIndex::slotExecuted"); + + //HACK: checking the modifier keys from the last mouseReleaseEvent + //depends on executing order: mouseReleaseEvent first, then itemClicked signal + int modifiers = m_mouseReleaseEventModifiers; + m_mouseReleaseEventModifiers = Qt::NoModifier; + if (modifiers != Qt::NoModifier) { + return; + } + + BtBookmarkItemBase* btItem = dynamic_cast<BtBookmarkItemBase*>(i); + if (!btItem) { + return; + } + + BtBookmarkFolder* folderItem = 0; + BtBookmarkItem* bookmarkItem = 0; + if ((folderItem = dynamic_cast<BtBookmarkFolder*>(btItem))) { + i->setExpanded( !i->isExpanded() ); + } + else if (( bookmarkItem = dynamic_cast<BtBookmarkItem*>(btItem) )) { //clicked on a bookmark + if (CSwordModuleInfo* mod = bookmarkItem->module()) { + QList<CSwordModuleInfo*> modules; + modules.append(mod); + emit createReadDisplayWindow(modules, bookmarkItem->key()); + } + } +} + +/** Creates a drag mime data object for the current selection. */ +QMimeData* CBookmarkIndex::dragObject() +{ + BTMimeData::ItemList dndItems; + BTMimeData* mimeData = new BTMimeData; + + foreach( QTreeWidgetItem* widgetItem, selectedItems() ) { + if (!widgetItem) + break; + if (dynamic_cast<BtBookmarkItemBase*>(widgetItem)) { + if (BtBookmarkItem* bookmark = dynamic_cast<BtBookmarkItem*>( widgetItem )) { + //take care of bookmarks which have no valid module any more, e.g. if it was uninstalled + const QString moduleName = bookmark->module() ? bookmark->module()->name() : QString::null; + mimeData->appendBookmark(moduleName, bookmark->key(), bookmark->description()); + } + } + } + return mimeData; +} + +void CBookmarkIndex::dragEnterEvent( QDragEnterEvent* event ) +{ + //qDebug("CBookmarkIndex::dragEnterEvent"); + setState(QAbstractItemView::DraggingState); + QTreeWidget::dragEnterEvent(event); + if (event->source() == this || event->mimeData()->hasFormat("BibleTime/Bookmark")) { + event->acceptProposedAction(); + } +} + + +void CBookmarkIndex::dragMoveEvent( QDragMoveEvent* event ) +{ + //qDebug("CBookmarkIndex::dragMoveEvent"); + + // do this first, otherwise the event may be ignored + QTreeWidget::dragMoveEvent(event); + + event->acceptProposedAction(); + event->accept(); + + // do this to paint the arrow + m_dragMovementPosition = event->pos(); + viewport()->update(); + +} + +void CBookmarkIndex::dragLeaveEvent( QDragLeaveEvent* ) +{ + qDebug("CBookmarkIndex::dragLeaveEvent"); + setState(QAbstractItemView::NoState); // not dragging anymore + viewport()->update(); // clear the arrow +} + + +void CBookmarkIndex::paintEvent(QPaintEvent* event) +{ + static QPixmap pix; + static int halfPixHeight; + static bool arrowInitialized = false; + + // Initialize the static variables, including the arrow pixmap + if (!arrowInitialized) { + arrowInitialized = true; + int arrowSize = CToolClass::mWidth(this, 1); + QString fileName; + if (util::filesystem::DirectoryUtil::getIconDir().exists("pointing_arrow.svg")) { + fileName = util::filesystem::DirectoryUtil::getIconDir().filePath("pointing_arrow.svg"); + } else { + if (util::filesystem::DirectoryUtil::getIconDir().exists("pointing_arrow.png")) { + fileName = util::filesystem::DirectoryUtil::getIconDir().filePath("pointing_arrow.png"); + } else { + qWarning() << "Picture file pointing_arrow.svg or .png not found!"; + } + } + + pix = QPixmap(fileName); + pix = pix.scaled(arrowSize, arrowSize, Qt::KeepAspectRatioByExpanding); + halfPixHeight = pix.height()/2; + } + + // Do the normal painting first + QTreeWidget::paintEvent(event); + + // Paint the arrow if the drag is going on + if (QAbstractItemView::DraggingState == state()) { + bool rtol = QApplication::isRightToLeft(); + + QPainter painter(this->viewport()); + QTreeWidgetItem* item = itemAt(m_dragMovementPosition); + bool isFolder = dynamic_cast<BtBookmarkFolder*>(item); + bool isBookmark = dynamic_cast<BtBookmarkItem*>(item); + + // Find the place for the arrow + QRect rect = visualItemRect(item); + int xCoord = rtol ? rect.right() : rect.left(); + int yCoord; + if (isFolder) { + if (m_dragMovementPosition.y() > rect.bottom() - (2* rect.height()/3) ) { + yCoord = rect.bottom() - halfPixHeight; // bottom + xCoord = rtol ? (xCoord - indentation()) : (xCoord + indentation()); + } else { + yCoord = rect.top() - halfPixHeight - 1; // top + } + + } else { + if (isBookmark) { + if (m_dragMovementPosition.y() > rect.bottom() - rect.height()/2) { + yCoord = rect.bottom() - halfPixHeight; // bottom + } else { + yCoord = rect.top() - halfPixHeight - 1; // top + } + } else { + if (item) { // the extra item + yCoord = rect.top() - halfPixHeight - 1; + } else { // empty area + rect = visualItemRect(m_extraItem); + yCoord = rect.top() - halfPixHeight - 1; + xCoord = rtol ? rect.right() : rect.left(); + } + } + } + + painter.drawPixmap(xCoord, yCoord, pix); + } +} + + +void CBookmarkIndex::dropEvent( QDropEvent* event ) +{ + qDebug("CBookmarkIndex::dropEvent"); + + //setState(QAbstractItemView::NoState); + // Try to prevent annoying timed autocollapsing. Remember to disconnect before return. + QObject::connect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(expandAutoCollapsedItem(QTreeWidgetItem*))); + QTreeWidgetItem* item = itemAt(event->pos()); + QTreeWidgetItem* parentItem = 0; + int indexUnderParent = 0; + + // Find the place where the drag is dropped + if (item) { + qDebug()<<"there was item"; + + QRect rect = visualItemRect(item); + bool isFolder = dynamic_cast<BtBookmarkFolder*>(item); + bool isBookmark = dynamic_cast<BtBookmarkItem*>(item); + + if (isFolder) { // item is a folder + qDebug()<<"item was folder"; + if (event->pos().y() > rect.bottom() - (2* rect.height()/3) ) { + parentItem = item; + } else { + parentItem = item->parent(); + if (!parentItem) { + parentItem = invisibleRootItem(); + } + qDebug()<<"item:" << item << "parent:" << parentItem; + indexUnderParent = parentItem->indexOfChild(item); // before the current folder + } + } else { + if (isBookmark) { // item is a bookmark + qDebug()<<"item was bookmark"; + parentItem = item->parent(); + if (!parentItem) { + parentItem = invisibleRootItem(); + } + indexUnderParent = parentItem->indexOfChild(item); // before the current bookmark + if (event->pos().y() > rect.bottom() - rect.height()/2) { + indexUnderParent++; // after the current bookmark + } + } else { // item is the extra item + parentItem = item->parent(); + if (!parentItem) { + parentItem = invisibleRootItem(); + } + indexUnderParent = parentItem->indexOfChild(item); // before the current bookmark + } + } + + } else { // no item under event point: drop to the end + qDebug()<<"there was no item"; + parentItem = invisibleRootItem(); + indexUnderParent = parentItem->childCount()-1; + } + + + if ( event->source() == this ) { + qDebug("dropping internal drag"); + event->accept(); + + bool bookmarksOnly = true; + bool targetIncluded = false; + bool moreThanOneFolder = false; + + QList<QTreeWidgetItem*> newItems = addItemsToDropTree(parentItem, bookmarksOnly, targetIncluded, moreThanOneFolder); + + if (moreThanOneFolder) { + QToolTip::showText(QCursor::pos(), tr("Can drop only bookmarks or one folder")); + QObject::disconnect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(expandAutoCollapsedItem(QTreeWidgetItem*))); + return; + } + if (targetIncluded) { + QToolTip::showText(QCursor::pos(), tr("Can't drop folder into the folder itself or into its subfolder")); + QObject::disconnect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(expandAutoCollapsedItem(QTreeWidgetItem*))); + return; + } + // Ask whether to copy or move with a popup menu + + QMenu* dropPopupMenu = new QMenu(this); + QAction* copy = dropPopupMenu->addAction(tr("Copy")); + QAction* move = dropPopupMenu->addAction(tr("Move")); + QAction* dropAction = dropPopupMenu->exec(QCursor::pos()); + if (dropAction == copy) { + qDebug() << "copy"; + parentItem->insertChildren(indexUnderParent, newItems); + } else { + if (dropAction == move) { + qDebug() << "move"; + parentItem->insertChildren(indexUnderParent, newItems); + deleteEntries(false); + } else { + QObject::disconnect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(expandAutoCollapsedItem(QTreeWidgetItem*))); + return; // user canceled + } + } + + } else { + qDebug()<<"the source was outside this"; + createBookmarkFromDrop(event, parentItem, indexUnderParent); + } + QObject::disconnect(this, SIGNAL(itemCollapsed(QTreeWidgetItem*)), this, SLOT(expandAutoCollapsedItem(QTreeWidgetItem*))); + setState(QAbstractItemView::NoState); +} + + +void CBookmarkIndex::createBookmarkFromDrop(QDropEvent* event, QTreeWidgetItem* parentItem, int indexInParent) +{ + //qDebug("CBookmarkIndex::createBookmarkFromDrop"); + //take the bookmark data from the mime source + const BTMimeData* mdata = dynamic_cast<const BTMimeData*>(event->mimeData()); + if (mdata) { + //create the new bookmark + QString moduleName = mdata->bookmark().module(); + QString keyText = mdata->bookmark().key(); + QString description = mdata->bookmark().description(); + CSwordModuleInfo* minfo = CPointers::backend()->findModuleByName(moduleName); + + QTreeWidgetItem* newItem = new BtBookmarkItem(minfo, keyText, description); + parentItem->insertChild(indexInParent, newItem); + } +} + + +/** Load the tree from file */ +void CBookmarkIndex::initTree() { + qDebug("CBookmarkIndex::initTree"); + BtBookmarkLoader loader; + addTopLevelItems(loader.loadTree()); + + // add the invisible extra item at the end + m_extraItem = new QTreeWidgetItem(); + m_extraItem->setFlags(Qt::ItemIsDropEnabled); + addTopLevelItem(m_extraItem); +} + +void CBookmarkIndex::slotItemEntered(QTreeWidgetItem* item, int) +{ + qDebug() << "CBookmarkIndex::slotItemEntered"; + if (item == m_extraItem) { + m_extraItem->setText(0, tr("Drag references from text views to this view")); + } + else { + m_extraItem->setText(0, QString::null); + } +} + + +/** Returns the correct QAction object for the given type of action. */ +QAction* CBookmarkIndex::action( BtBookmarkItemBase::MenuAction type ) const { + switch (type) { + case BtBookmarkItemBase::NewFolder: + return m_actions.newFolder; + case BtBookmarkItemBase::ChangeFolder: + return m_actions.changeFolder; + + case BtBookmarkItemBase::ChangeBookmark: + return m_actions.changeBookmark; + case BtBookmarkItemBase::ImportBookmarks: + return m_actions.importBookmarks; + case BtBookmarkItemBase::ExportBookmarks: + return m_actions.exportBookmarks; + case BtBookmarkItemBase::PrintBookmarks: + return m_actions.printBookmarks; + + case BtBookmarkItemBase::DeleteEntries: + return m_actions.deleteEntries; + + default: + return 0; + } +} + +/** Shows the context menu at the given position. */ +void CBookmarkIndex::contextMenu(const QPoint& p) +{ + //qDebug("CBookmarkIndex::contextMenu"); + //setup menu entries depending on current selection + QTreeWidgetItem* i = itemAt(p); + QList<QTreeWidgetItem *> items = selectedItems(); + //The item which was clicked may not be selected + if (i && !items.contains(i) && i != m_extraItem) + items.append(i); + + if (items.count() == 0) { + //special handling for no selection + BtBookmarkItemBase::MenuAction actionType; + for (int index = BtBookmarkItemBase::ActionBegin; index <= BtBookmarkItemBase::ActionEnd; ++index) { + actionType = static_cast<BtBookmarkItemBase::MenuAction>(index); + if (QAction* a = action(actionType)) { + switch (index) { + //case BtBookmarkItemBase::ExportBookmarks: + //case BtBookmarkItemBase::ImportBookmarks: + case BtBookmarkItemBase::NewFolder: + //case BtBookmarkItemBase::PrintBookmarks: + a->setEnabled(true); + break; + default: + a->setEnabled(false); + } + } + } + } + else if (items.count() == 1) { + //special handling for one selected item + + BtBookmarkItemBase* item = dynamic_cast<BtBookmarkItemBase*>(items.at(0)); + BtBookmarkItemBase::MenuAction actionType; + for (int index = BtBookmarkItemBase::ActionBegin; index <= BtBookmarkItemBase::ActionEnd; ++index) { + actionType = static_cast<BtBookmarkItemBase::MenuAction>(index); + if (QAction* a = action(actionType)) + a->setEnabled( item->enableAction(actionType) ); + } + } + else { + //first disable all actions + BtBookmarkItemBase::MenuAction actionType; + for (int index = BtBookmarkItemBase::ActionBegin; index <= BtBookmarkItemBase::ActionEnd; ++index) { + actionType = static_cast<BtBookmarkItemBase::MenuAction>(index); + if (QAction* a = action(actionType)) + a->setEnabled(false); + } + //enable the menu items depending on the types of the selected items. + for (int index = BtBookmarkItemBase::ActionBegin; index <= BtBookmarkItemBase::ActionEnd; ++index) { + actionType = static_cast<BtBookmarkItemBase::MenuAction>(index); + bool enableAction = isMultiAction(actionType); + QListIterator<QTreeWidgetItem *> it(items); + while(it.hasNext()) { + BtBookmarkItemBase* i = dynamic_cast<BtBookmarkItemBase*>(it.next()); + enableAction = enableAction && i->enableAction(actionType); + } + if (enableAction) { + QAction* a = action(actionType) ; + if (i && a) + a->setEnabled(enableAction); + } + } + } + //finally, open the popup + m_popup->exec(mapToGlobal(p)); + //qDebug("CBookmarkIndex::contextMenu end"); +} + +/** Adds a new subfolder to the current item. */ +void CBookmarkIndex::createNewFolder() { + //qDebug("CBookmarkIndex::createNewFolder"); + QList<QTreeWidgetItem*> selected = selectedItems(); + if (selected.count() > 0) { + BtBookmarkFolder* i = dynamic_cast<BtBookmarkFolder*>(currentItem()); + if (i) { + i->newSubFolder(); + } + } + else { + // create a top level folder + BtBookmarkFolder* newFolder = new BtBookmarkFolder(0, QObject::tr("New folder")); + //parentFolder->addChild(newFolder); + insertTopLevelItem(topLevelItemCount()-1, newFolder); + newFolder->update(); + newFolder->rename(); + } +} + +/** Opens a dialog to change the current folder. */ +void CBookmarkIndex::changeFolder() { + BtBookmarkFolder* i = dynamic_cast<BtBookmarkFolder*>(currentItem()); + Q_ASSERT(i); + if (i) { + i->rename(); + } +} + +/** Changes the current bookmark. */ +void CBookmarkIndex::changeBookmark() { + BtBookmarkItem* i = dynamic_cast<BtBookmarkItem*>(currentItem()); + Q_ASSERT(i); + + if (i) { + i->rename(); + } +} + +/** Exports the bookmarks being in the selected folder. */ +void CBookmarkIndex::exportBookmarks() { + BtBookmarkFolder* i = dynamic_cast<BtBookmarkFolder*>(currentItem()); + Q_ASSERT(i); + + if (i) { + i->exportBookmarks(); + } +} + +/** Import bookmarks from a file and add them to the selected folder. */ +void CBookmarkIndex::importBookmarks() { + BtBookmarkFolder* i = dynamic_cast<BtBookmarkFolder*>(currentItem()); + Q_ASSERT(i); + + if (i) { + i->importBookmarks(); + } +} + +/** Prints the selected bookmarks. */ +void CBookmarkIndex::printBookmarks() { + Printing::CPrinter::KeyTree tree; + Printing::CPrinter::KeyTreeItem::Settings settings; + settings.keyRenderingFace = Printing::CPrinter::KeyTreeItem::Settings::CompleteShort; + + QList<QTreeWidgetItem*> items; + BtBookmarkFolder* bf = dynamic_cast<BtBookmarkFolder*>(currentItem()); + + if (bf) { + items = bf->getChildList(); + } + else { + items = selectedItems(); + } + + //create a tree of keytreeitems using the bookmark hierarchy. + QListIterator<QTreeWidgetItem*> it(items); + while(it.hasNext()) { + BtBookmarkItem* i = dynamic_cast<BtBookmarkItem*>(it.next()); + if (i) { + qDebug() << "printBookmarks: add to list" << i->key(); + tree.append( new Printing::CPrinter::KeyTreeItem( i->key(), i->module(), settings ) ); + } + } + + if (items.count() == 0) { + qWarning("Tried to print empty bookmark list."); + return; + } + boost::scoped_ptr<Printing::CPrinter> printer( + new Printing::CPrinter( this, CBTConfig::getDisplayOptionDefaults(), CBTConfig::getFilterOptionDefaults() ) + ); + printer->printKeyTree(tree); +} + +/** Deletes the selected entries. */ +void CBookmarkIndex::deleteEntries(bool confirm) +{ + if (confirm) { + if (!selectedItems().count()) { + BtBookmarkItemBase* f = dynamic_cast<BtBookmarkItemBase*>(currentItem()); + if (f) { + currentItem()->setSelected(true); + } else { + return; + } + } + + if (QMessageBox::question(this, tr("Delete Items"), tr("Do you really want to delete the selected items and child-items?"), QMessageBox::Yes|QMessageBox::No, QMessageBox::No ) != QMessageBox::Yes) { + return; + } + } + + while (selectedItems().size() > 0) { + delete selectedItems().at(0); // deleting all does not work because it may cause double deletion + } + +} + + +/* +Reimplementation from QAbstractItemView/QTreeWidget. Takes care of movable items. +It's easier to use this than to start drag with mouse event handlers. +The default implementation would drag items, but we don't call it. Instead we create +a BibleTime mimedata object. It can be dragged and dropped to a text view or somewhere else. +The internal drag is handled differently, it doesn't use the mimedata (see dropEvent()). +*/ +void CBookmarkIndex::startDrag(Qt::DropActions) +{ + qDebug("CBookmarkIndex::startDrag"); + + QMimeData* mData = dragObject(); // create the data which can be used in other widgets + QDrag* drag = new QDrag(this); + drag->setMimeData(mData); + drag->exec(); + + viewport()->update(); // because of the arrow +} + + + + + + +/* Returns true if more than one entry is supported by this action type. Returns false for actions which support only one entry, e.g. about module etc. */ +bool CBookmarkIndex::isMultiAction( const BtBookmarkItemBase::MenuAction type ) const { + switch (type) { + case BtBookmarkItemBase::NewFolder: + return false; + case BtBookmarkItemBase::ChangeFolder: + return false; + + case BtBookmarkItemBase::ChangeBookmark: + return false; + case BtBookmarkItemBase::ImportBookmarks: + return false; + case BtBookmarkItemBase::ExportBookmarks: + return false; + case BtBookmarkItemBase::PrintBookmarks: + return true; + + case BtBookmarkItemBase::DeleteEntries: + return true; + } + + return false; +} + +/* Saves the bookmarks to the default bookmarks file. */ +void CBookmarkIndex::saveBookmarks() { + + qDebug("CBookmarkIndex::saveBookmarks()"); + BtBookmarkLoader loader; + loader.saveTreeFromRootItem(invisibleRootItem()); + //qDebug("CBookmarkIndex::saveBookmarks end"); +} + +void CBookmarkIndex::mouseMoveEvent(QMouseEvent* event) +{ + //qDebug() << "CBookmarkIndex::mouseMoveEvent"; + + // Restart the mag timer if we have moved to another item and shift was not pressed. + QTreeWidgetItem* itemUnderPointer = itemAt(event->pos()); + if (itemUnderPointer && (itemUnderPointer != m_previousEventItem) ) { + //qDebug("CBookmarkIndex::mouseMoveEvent, moved onto another item"); + if ( !(event->modifiers() & Qt::ShiftModifier)) { + m_magTimer.start(); // see the ctor for the timer properties + } + } + m_previousEventItem = itemUnderPointer; + + // Clear the extra item text unless we are on top of it + if ( (itemUnderPointer != m_extraItem) && !m_extraItem->text(0).isNull()) { + m_extraItem->setText(0, QString::null); + } + + QTreeWidget::mouseMoveEvent(event); +} + +void CBookmarkIndex::magTimeout() +{ + //qDebug("CBookmarkIndex::magTimeout"); + + QTreeWidgetItem* itemUnderPointer = 0; + if (underMouse()) { + itemUnderPointer = itemAt(mapFromGlobal(QCursor::pos())); + } + // if the mouse pointer have been over the same item since the timer was started + if (itemUnderPointer && (m_previousEventItem == itemUnderPointer)) { + BtBookmarkItem* bitem = dynamic_cast<BtBookmarkItem*>(itemUnderPointer); + if (bitem) { + //qDebug("CBookmarkIndex::timerEvent: update the infodisplay"); + // Update the mag + if (bitem->module()) { + (CPointers::infoDisplay())->setInfo( + InfoDisplay::CInfoDisplay::CrossReference, + bitem->module()->name() + ":" + bitem->key() + ); + } else { + (CPointers::infoDisplay())->setInfo(InfoDisplay::CInfoDisplay::Text, tr("The work to which the bookmark points to is not installed.")); + } + + } + } +} + +/* +Creates a list of new items based on the current selection. +If there are only bookmarks in the selection they are all included. +If there is one folder it's included as a deep copy. +Sets bookmarksOnly=false if it finds a folder. +Sets targetIncluded=true if the target is in the list. +Sets moreThanOneFolder=true if selection includes one folder and something more. +If moreThanOneFolder or targetIncluded is detected the creation of list is stopped +and the list is incomplete. +*/ +QList<QTreeWidgetItem*> CBookmarkIndex::addItemsToDropTree( + QTreeWidgetItem* target, bool& bookmarksOnly, bool& targetIncluded, bool& moreThanOneFolder) +{ + qDebug() << "CBookmarkIndex::addItemsToDropTree"; + QList<QTreeWidgetItem*> selectedList = selectedItems(); + QList<QTreeWidgetItem*> newList; + + foreach(QTreeWidgetItem* item, selectedList) { + qDebug() << "go through all items:" << item; + if ( BtBookmarkFolder* folder = dynamic_cast<BtBookmarkFolder*>(item)) { + bookmarksOnly = false; + if (selectedList.count() > 1) { // only one item allowed if a folder is selected + qDebug() << "one folder and something else is selected"; + moreThanOneFolder = true; + break; + } + if (folder->hasDescendant(target)) { // dropping to self or descendand not allowed + qDebug() << "addItemsToDropTree: target is included"; + targetIncluded = true; + break; + } + } else { + qDebug() << "append new QTreeWidget item (should be BtBookmarkItem?)"; + newList.append(new BtBookmarkItem( *(dynamic_cast<BtBookmarkItem*>(item)) )); + } + } + if (!bookmarksOnly && selectedList.count() == 1) { + qDebug() << "exactly one folder"; + BtBookmarkFolder* folder = dynamic_cast<BtBookmarkFolder*>(selectedList.value(0)); + BtBookmarkFolder* copy = folder->deepCopy(); + newList.append(copy); + } + if (!bookmarksOnly && selectedList.count() > 1) { + // wrong amount of items + qDebug() << "one folder and something else is selected 2"; + moreThanOneFolder = true; + } + qDebug() << "return the new list" << newList; + return newList; +} + |