File indexing completed on 2025-03-16 13:13:04
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(0), 0051 m_lastIndex(0) 0052 { 0053 setResizeMode(QListView::Adjust); 0054 setViewMode(QListView::IconMode); 0055 setIconSize(48); 0056 } 0057 0058 0059 /** 0060 * Destructor. 0061 */ 0062 SymbolListWidget::~SymbolListWidget() 0063 { 0064 } 0065 0066 0067 /** 0068 * Set the size of the icons to be used. 0069 * The base QListWidget has the icon size and grid size set to this value. 0070 * If there are existing items in the QListWidget, they are updated with new icons. 0071 * 0072 * @param size the size in pixels 0073 */ 0074 void SymbolListWidget::setIconSize(int size) 0075 { 0076 m_size = size; 0077 QListWidget::setIconSize(QSize(m_size, m_size)); 0078 setGridSize(QSize(m_size, m_size)); 0079 updateIcons(); 0080 } 0081 0082 0083 /** 0084 * Populate the QListWidget with the QListWidgetItems for each Symbol in the SymbolLibrary. 0085 * An icon is created for each Symbol. 0086 * 0087 * @param library a pointer to the SymbolLibrary containing the Symbols 0088 */ 0089 void SymbolListWidget::loadFromLibrary(SymbolLibrary *library) 0090 { 0091 if (!library) { 0092 return; 0093 } 0094 0095 m_library = library; 0096 0097 foreach (qint16 index, library->indexes()) { 0098 addSymbol(index, library->symbol(index)); 0099 } 0100 } 0101 0102 0103 /** 0104 * Add an individual Symbol to the view. 0105 * 0106 * @param index the index of the Symbol 0107 * @param symbol a const reference to the Symbol to add 0108 */ 0109 void SymbolListWidget::addSymbol(qint16 index, const Symbol &symbol) 0110 { 0111 QListWidgetItem *item = createItem(index); 0112 item->setIcon(createIcon(symbol, m_size)); 0113 } 0114 0115 0116 /** 0117 * Remove a symbol item from the view. 0118 * 0119 * @param index the index of the item to remove 0120 */ 0121 void SymbolListWidget::removeSymbol(qint16 index) 0122 { 0123 if (m_items.contains(index)) { 0124 removeItemWidget(m_items.value(index)); 0125 delete m_items.take(index); 0126 } 0127 } 0128 0129 0130 /** 0131 * If an item for the index currently exists return it otherwise create 0132 * an item to be inserted into the QListWidget. 0133 * The item created has a data entry added representing the index. 0134 * The items are inserted so that the Symbols are sorted by their index. 0135 * 0136 * @param index an index in the SymbolLibrary 0137 * 0138 * @return a pointer to the QListWidgetItem created 0139 */ 0140 QListWidgetItem *SymbolListWidget::createItem(qint16 index) 0141 { 0142 if (m_items.contains(index)) { 0143 return m_items.value(index); 0144 } 0145 0146 QListWidgetItem *item = new QListWidgetItem; 0147 item->setData(Qt::UserRole, index); 0148 m_items.insert(index, item); 0149 int i = index; 0150 0151 while (++i < m_lastIndex) 0152 if (m_items.contains(i)) { 0153 break; 0154 } 0155 0156 if (i >= m_lastIndex) { 0157 addItem(item); 0158 m_lastIndex = index; 0159 } else { 0160 insertItem(row(m_items[i]), item); 0161 } 0162 0163 return item; 0164 } 0165 0166 0167 /** 0168 * Create a QIcon for the supplied Symbol. 0169 * 0170 * @param symbol a const reference to a Symbol 0171 * @param size a size for the icon 0172 * 0173 * @return a QIcon 0174 */ 0175 QIcon SymbolListWidget::createIcon(const Symbol &symbol, int size) 0176 { 0177 QPalette pal = QApplication::palette(); 0178 0179 QPixmap icon(size, size); 0180 icon.fill(Qt::transparent); 0181 0182 QPainter p(&icon); 0183 p.setRenderHint(QPainter::Antialiasing, true); 0184 p.scale(size, size); 0185 0186 QBrush brush = symbol.brush(); 0187 QPen pen = symbol.pen(); 0188 0189 brush.setColor(pal.color(QPalette::WindowText)); 0190 pen.setColor(pal.color(QPalette::WindowText)); 0191 0192 p.setBrush(brush); 0193 p.setPen(pen); 0194 p.drawPath(symbol.path()); 0195 p.end(); 0196 0197 return QIcon(icon); 0198 } 0199 0200 0201 /** 0202 * Provide a list of mimetypes that this widget provides when dragging from it. 0203 * 0204 * @return a QStringList containing the mimetype strings 0205 */ 0206 QStringList SymbolListWidget::mimeTypes() const 0207 { 0208 QStringList mimetypes; 0209 mimetypes.append("application/kxstitchsymbol"); 0210 return mimetypes; 0211 } 0212 0213 0214 Qt::DropActions SymbolListWidget::supportedDropActions() const 0215 { 0216 return Qt::CopyAction; 0217 } 0218 0219 0220 /** 0221 * Called when dragging items from one QListWidget to another to provide the serialised data. 0222 * 0223 * @param items a QList of pointers to the QListWidgetItems to provide data for 0224 * 0225 * @return a pointer to the QMimeData created 0226 */ 0227 QMimeData *SymbolListWidget::mimeData(const QList<QListWidgetItem *> items) const 0228 { 0229 QMimeData *mimeData = new QMimeData; 0230 0231 QByteArray data; 0232 QDataStream stream(&data, QIODevice::WriteOnly); 0233 0234 foreach (QListWidgetItem * item, items) { 0235 qint16 index = static_cast<qint16>(item->data(Qt::UserRole).toInt()); 0236 Symbol symbol = m_library->symbol(index); 0237 stream << symbol; 0238 } 0239 0240 mimeData->setData("application/kxstitchsymbol", data); 0241 return mimeData; 0242 } 0243 0244 0245 /** 0246 * Called when QListWidgetItems are dragged from one QListWidget to another. 0247 * 0248 * @param index the position index of the dropped item 0249 * @param mimeData a pointer to the serialised data from the source 0250 * @param action the requested drop action, only copying will be implemented 0251 * 0252 * @return @c true if the action is handled, @c false otherwise 0253 */ 0254 bool SymbolListWidget::dropMimeData(int index, const QMimeData *mimeData, Qt::DropAction action) 0255 { 0256 Q_UNUSED(index); 0257 Q_UNUSED(action); 0258 0259 if (mimeData->hasFormat("application/kxstitchsymbol")) { 0260 m_library->undoStack()->push(new DragAndDropCommand(m_library, mimeData)); 0261 return true; 0262 } 0263 0264 return false; 0265 } 0266 0267 0268 /** 0269 * Intercept the events system to discover if the theme has changed, this should invoke 0270 * an update to the icons used to display the correct colors. 0271 * 0272 * @param e a pointer to the events 0273 * 0274 * @return @c true if the event was accepted, @c false otherwise 0275 */ 0276 bool SymbolListWidget::event(QEvent *e) 0277 { 0278 bool accepted = QListWidget::event(e); 0279 0280 if (e->type() == QEvent::PaletteChange) { 0281 updateIcons(); 0282 } 0283 0284 return accepted; 0285 } 0286 0287 0288 /** 0289 * Generate the icons for all the QListWidgetItems stored in m_items. 0290 */ 0291 void SymbolListWidget::updateIcons() 0292 { 0293 QMapIterator<qint16, QListWidgetItem *> i(m_items); 0294 0295 while (i.hasNext()) { 0296 i.next(); 0297 i.value()->setIcon(createIcon(m_library->symbol(i.key()), m_size)); 0298 } 0299 }