File indexing completed on 2024-04-28 05:08:19

0001 /***************************************************************************
0002     Copyright (C) 2002-2009 Robby Stephenson <robby@periapsis.org>
0003  ***************************************************************************/
0004 
0005 /***************************************************************************
0006  *                                                                         *
0007  *   This program is free software; you can redistribute it and/or         *
0008  *   modify it under the terms of the GNU General Public License as        *
0009  *   published by the Free Software Foundation; either version 2 of        *
0010  *   the License or (at your option) version 3 or any later version        *
0011  *   accepted by the membership of KDE e.V. (or its successor approved     *
0012  *   by the membership of KDE e.V.), which shall act as a proxy            *
0013  *   defined in Section 14 of version 3 of the license.                    *
0014  *                                                                         *
0015  *   This program is distributed in the hope that it will be useful,       *
0016  *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
0017  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
0018  *   GNU General Public License for more details.                          *
0019  *                                                                         *
0020  *   You should have received a copy of the GNU General Public License     *
0021  *   along with this program.  If not, see <http://www.gnu.org/licenses/>. *
0022  *                                                                         *
0023  ***************************************************************************/
0024 
0025 #include "entryiconview.h"
0026 #include "collection.h"
0027 #include "controller.h"
0028 #include "entry.h"
0029 #include "field.h"
0030 #include "document.h"
0031 #include "models/models.h" // for EntryPtrRole
0032 #include "tellico_kernel.h"
0033 
0034 #include <KLocalizedString>
0035 
0036 #include <QMenu>
0037 #include <QIcon>
0038 #include <QContextMenuEvent>
0039 #include <QDesktopServices>
0040 
0041 namespace {
0042   static const int ENTRY_ICON_SIZE_PAD = 2;
0043   static const int DEFAULT_ENTRY_ICON_SIZE = 96; // same as in tellico_config.kcfg
0044 }
0045 
0046 using Tellico::EntryIconView;
0047 
0048 EntryIconView::EntryIconView(QWidget* parent_)
0049     : QListView(parent_), m_maxAllowedIconWidth(DEFAULT_ENTRY_ICON_SIZE) {
0050   setViewMode(QListView::IconMode);
0051   setMovement(QListView::Static);
0052   setDragEnabled(false);
0053   setSelectionMode(QAbstractItemView::ExtendedSelection);
0054   setResizeMode(QListView::Adjust);
0055   setWordWrap(true);
0056   setSpacing(ENTRY_ICON_SIZE_PAD);
0057   setLayoutMode(QListView::Batched);
0058 
0059   connect(this, &EntryIconView::doubleClicked, this, &EntryIconView::slotDoubleClicked);
0060 
0061   setWhatsThis(i18n("<qt>The <i>Icon View</i> shows each entry in the collection or group using "
0062                     "an icon, which may be an image in the entry.</qt>"));
0063 }
0064 
0065 EntryIconView::~EntryIconView() {
0066 }
0067 
0068 void EntryIconView::setModel(QAbstractItemModel* model_) {
0069   QListView::setModel(model_);
0070   if(!model_) {
0071     return;
0072   }
0073   connect(model_, &QAbstractItemModel::columnsInserted, this, &EntryIconView::updateModelColumn);
0074 }
0075 
0076 void EntryIconView::setMaxAllowedIconWidth(int width_) {
0077   m_maxAllowedIconWidth = qMax(16, width_);
0078   QSize iconSize(m_maxAllowedIconWidth, m_maxAllowedIconWidth);
0079   setIconSize(iconSize);
0080 
0081   QSize gridSize(m_maxAllowedIconWidth + 2*ENTRY_ICON_SIZE_PAD,
0082                  m_maxAllowedIconWidth + 3*(fontMetrics().lineSpacing() + ENTRY_ICON_SIZE_PAD));
0083   setGridSize(gridSize);
0084 }
0085 
0086 void EntryIconView::slotDoubleClicked(const QModelIndex& index_) {
0087   Data::EntryPtr entry = index_.data(EntryPtrRole).value<Data::EntryPtr>();
0088   if(entry) {
0089     Controller::self()->editEntry(entry);
0090   }
0091 }
0092 
0093 void EntryIconView::contextMenuEvent(QContextMenuEvent* ev_) {
0094   QMenu menu(this);
0095 
0096   // only insert entry items if one is selected
0097   QModelIndex index = indexAt(ev_->pos());
0098   if(index.isValid()) {
0099     Controller::self()->plugEntryActions(&menu);
0100 
0101     // add a menu item to open each URL field
0102     Data::EntryPtr entry = index.data(EntryPtrRole).value<Data::EntryPtr>();
0103     Data::FieldList urlFields;
0104     foreach(Data::FieldPtr field, Data::Document::self()->collection()->fields()) {
0105       if(field->type() == Data::Field::URL) {
0106         urlFields += field;
0107       }
0108     }
0109     foreach(Data::FieldPtr urlField, urlFields) {
0110       QAction* act = menu.addAction(QIcon::fromTheme(QStringLiteral("bookmarks")),
0111                                     i18nc("Open URL", "Open %1", urlField->title()));
0112       const QString value = entry->field(urlField);
0113       act->setData(value);
0114       act->setWhatsThis(value);
0115       act->setEnabled(!value.isEmpty());
0116       menu.addAction(act);
0117     }
0118     if(!urlFields.isEmpty()) {
0119       connect(&menu, &QMenu::triggered, this, &EntryIconView::slotOpenUrlMenuActivated);
0120     }
0121 
0122     menu.addSeparator();
0123   }
0124 
0125   QMenu* sortMenu = Controller::self()->plugSortActions(&menu);
0126   connect(sortMenu, &QMenu::triggered, this, &EntryIconView::slotSortMenuActivated);
0127 
0128   menu.exec(ev_->globalPos());
0129 }
0130 
0131 void EntryIconView::slotSortMenuActivated(QAction* action_) {
0132   Data::FieldPtr field = action_->data().value<Data::FieldPtr>();
0133   Q_ASSERT(field);
0134   if(!field) {
0135     return;
0136   }
0137   // EntryIconModel is a proxy to EntryModel which uses the field list as the full set of columns
0138   // find which columns matches the field and sort on that column
0139   for(int i = 0; i < model()->columnCount(); ++i) {
0140     if(model()->headerData(i, Qt::Horizontal, FieldPtrRole).value<Data::FieldPtr>() == field) {
0141       model()->sort(i);
0142       break;
0143     }
0144   }
0145 }
0146 
0147 void EntryIconView::slotOpenUrlMenuActivated(QAction* action_/*=0*/) {
0148   if(!action_) {
0149     return;
0150   }
0151   const QString link = action_->data().toString();
0152   if(!link.isEmpty()) {
0153     QDesktopServices::openUrl(Kernel::self()->URL().resolved(QUrl::fromUserInput(link)));
0154   }
0155 }
0156 
0157 void EntryIconView::updateModelColumn() {
0158   //default model column is 0
0159   int modelColumn = 0;
0160   // iterate over model columns, find the one whose name is "title"
0161   for(int ncol = 0; ncol < model()->columnCount(); ++ncol) {
0162     Data::FieldPtr field = model()->headerData(ncol, Qt::Horizontal, FieldPtrRole).value<Data::FieldPtr>();
0163     if(field && field->name() == QLatin1String("title")) {
0164       modelColumn = ncol;
0165       break;
0166     }
0167   }
0168   setModelColumn(modelColumn);
0169 }