File indexing completed on 2024-04-28 04:33:57
0001 /******************************************************************************** 0002 * Copyright (C) 2012-2015 by Stephen Allewell * 0003 * steve.allewell@gmail.com * 0004 * * 0005 * This program is free software; you can redistribute it and/or modify * 0006 * it under the terms of the GNU General Public License as published by * 0007 * the Free Software Foundation; either version 2 of the License, or * 0008 * (at your option) any later version. * 0009 ********************************************************************************/ 0010 0011 0012 /** 0013 * @file 0014 * Implement the SymbolListWidget class 0015 */ 0016 0017 0018 /** 0019 * @page library_list_widget SymbolListWidget 0020 * This class implements an extension to the QListWidget class that provides population of the widget 0021 * with the contents of a SymbolLibrary. For each Symbol in the library a QListWidgetItem is created 0022 * with a data item representing the Symbol identifier in the library and an icon at a given size that 0023 * is generated from the Symbol path. 0024 * 0025 * The widget is intended to be used in a dialog or main window and allows selection of a symbol to be 0026 * used for some purpose in the application. 0027 * 0028 * @image html ui-main-library.png "The user interface showing the library tab" 0029 */ 0030 0031 0032 #include "SymbolListWidget.h" 0033 0034 #include <QApplication> 0035 #include <QMimeData> 0036 #include <QPainter> 0037 #include <QPalette> 0038 #include <QPen> 0039 0040 #include "Commands.h" 0041 #include "Symbol.h" 0042 #include "SymbolLibrary.h" 0043 0044 0045 /** 0046 * Constructor. 0047 */ 0048 SymbolListWidget::SymbolListWidget(QWidget *parent) 0049 : QListWidget(parent), 0050 m_library(nullptr), 0051 m_lastIndex(0) 0052 { 0053 setResizeMode(QListView::Adjust); 0054 setViewMode(QListView::IconMode); 0055 setIconSize(48); 0056 } 0057 0058 0059 /** 0060 * Set the size of the icons to be used. 0061 * The base QListWidget has the icon size and grid size set to this value. 0062 * If there are existing items in the QListWidget, they are updated with new icons. 0063 * 0064 * @param size the size in pixels 0065 */ 0066 void SymbolListWidget::setIconSize(int size) 0067 { 0068 m_size = size; 0069 QListWidget::setIconSize(QSize(m_size, m_size)); 0070 setGridSize(QSize(m_size, m_size)); 0071 updateIcons(); 0072 } 0073 0074 0075 /** 0076 * Populate the QListWidget with the QListWidgetItems for each Symbol in the SymbolLibrary. 0077 * An icon is created for each Symbol. 0078 * 0079 * @param library a pointer to the SymbolLibrary containing the Symbols 0080 */ 0081 void SymbolListWidget::loadFromLibrary(SymbolLibrary *library) 0082 { 0083 if (!library) { 0084 return; 0085 } 0086 0087 m_library = library; 0088 0089 foreach (qint16 index, library->indexes()) { 0090 addSymbol(index, library->symbol(index)); 0091 } 0092 } 0093 0094 0095 /** 0096 * Add an individual Symbol to the view. 0097 * 0098 * @param index the index of the Symbol 0099 * @param symbol a const reference to the Symbol to add 0100 */ 0101 void SymbolListWidget::addSymbol(qint16 index, const Symbol &symbol) 0102 { 0103 QListWidgetItem *item = createItem(index); 0104 item->setIcon(createIcon(symbol, m_size)); 0105 } 0106 0107 0108 /** 0109 * Remove a symbol item from the view. 0110 * 0111 * @param index the index of the item to remove 0112 */ 0113 void SymbolListWidget::removeSymbol(qint16 index) 0114 { 0115 if (m_items.contains(index)) { 0116 removeItemWidget(m_items.value(index)); 0117 delete m_items.take(index); 0118 } 0119 } 0120 0121 0122 /** 0123 * If an item for the index currently exists return it otherwise create 0124 * an item to be inserted into the QListWidget. 0125 * The item created has a data entry added representing the index. 0126 * The items are inserted so that the Symbols are sorted by their index. 0127 * 0128 * @param index an index in the SymbolLibrary 0129 * 0130 * @return a pointer to the QListWidgetItem created 0131 */ 0132 QListWidgetItem *SymbolListWidget::createItem(qint16 index) 0133 { 0134 if (m_items.contains(index)) { 0135 return m_items.value(index); 0136 } 0137 0138 QListWidgetItem *item = new QListWidgetItem; 0139 item->setData(Qt::UserRole, index); 0140 m_items.insert(index, item); 0141 int i = index; 0142 0143 while (++i < m_lastIndex) 0144 if (m_items.contains(i)) { 0145 break; 0146 } 0147 0148 if (i >= m_lastIndex) { 0149 addItem(item); 0150 m_lastIndex = index; 0151 } else { 0152 insertItem(row(m_items[i]), item); 0153 } 0154 0155 return item; 0156 } 0157 0158 0159 /** 0160 * Create a QIcon for the supplied Symbol. 0161 * 0162 * @param symbol a const reference to a Symbol 0163 * @param size a size for the icon 0164 * 0165 * @return a QIcon 0166 */ 0167 QIcon SymbolListWidget::createIcon(const Symbol &symbol, int size) 0168 { 0169 QPalette pal = QApplication::palette(); 0170 0171 QPixmap icon(size, size); 0172 icon.fill(Qt::transparent); 0173 0174 QPainter p(&icon); 0175 p.setRenderHint(QPainter::Antialiasing, true); 0176 p.scale(size, size); 0177 0178 QBrush brush = symbol.brush(); 0179 QPen pen = symbol.pen(); 0180 0181 brush.setColor(pal.color(QPalette::WindowText)); 0182 pen.setColor(pal.color(QPalette::WindowText)); 0183 0184 p.setBrush(brush); 0185 p.setPen(pen); 0186 p.drawPath(symbol.path()); 0187 p.end(); 0188 0189 return QIcon(icon); 0190 } 0191 0192 0193 /** 0194 * Provide a list of mimetypes that this widget provides when dragging from it. 0195 * 0196 * @return a QStringList containing the mimetype strings 0197 */ 0198 QStringList SymbolListWidget::mimeTypes() const 0199 { 0200 QStringList mimetypes; 0201 mimetypes.append(QStringLiteral("application/kxstitchsymbol")); 0202 return mimetypes; 0203 } 0204 0205 0206 Qt::DropActions SymbolListWidget::supportedDropActions() const 0207 { 0208 return Qt::CopyAction; 0209 } 0210 0211 0212 /** 0213 * Called when dragging items from one QListWidget to another to provide the serialised data. 0214 * 0215 * @param items a QList of pointers to the QListWidgetItems to provide data for 0216 * 0217 * @return a pointer to the QMimeData created 0218 */ 0219 QMimeData *SymbolListWidget::mimeData(const QList<QListWidgetItem *> items) const 0220 { 0221 QMimeData *mimeData = new QMimeData; 0222 0223 QByteArray data; 0224 QDataStream stream(&data, QIODevice::WriteOnly); 0225 0226 foreach (QListWidgetItem * item, items) { 0227 qint16 index = static_cast<qint16>(item->data(Qt::UserRole).toInt()); 0228 Symbol symbol = m_library->symbol(index); 0229 stream << symbol; 0230 } 0231 0232 mimeData->setData(QStringLiteral("application/kxstitchsymbol"), data); 0233 return mimeData; 0234 } 0235 0236 0237 /** 0238 * Called when QListWidgetItems are dragged from one QListWidget to another. 0239 * 0240 * @param index the position index of the dropped item 0241 * @param mimeData a pointer to the serialised data from the source 0242 * @param action the requested drop action, only copying will be implemented 0243 * 0244 * @return @c true if the action is handled, @c false otherwise 0245 */ 0246 bool SymbolListWidget::dropMimeData(int index, const QMimeData *mimeData, Qt::DropAction action) 0247 { 0248 Q_UNUSED(index); 0249 Q_UNUSED(action); 0250 0251 if (mimeData->hasFormat(QStringLiteral("application/kxstitchsymbol"))) { 0252 m_library->undoStack()->push(new DragAndDropCommand(m_library, mimeData)); 0253 return true; 0254 } 0255 0256 return false; 0257 } 0258 0259 0260 /** 0261 * Intercept the events system to discover if the theme has changed, this should invoke 0262 * an update to the icons used to display the correct colors. 0263 * 0264 * @param e a pointer to the events 0265 * 0266 * @return @c true if the event was accepted, @c false otherwise 0267 */ 0268 bool SymbolListWidget::event(QEvent *e) 0269 { 0270 bool accepted = QListWidget::event(e); 0271 0272 if (e->type() == QEvent::PaletteChange) { 0273 updateIcons(); 0274 } 0275 0276 return accepted; 0277 } 0278 0279 0280 /** 0281 * Generate the icons for all the QListWidgetItems stored in m_items. 0282 */ 0283 void SymbolListWidget::updateIcons() 0284 { 0285 QMapIterator<qint16, QListWidgetItem *> i(m_items); 0286 0287 while (i.hasNext()) { 0288 i.next(); 0289 i.value()->setIcon(createIcon(m_library->symbol(i.key()), m_size)); 0290 } 0291 }