File indexing completed on 2024-04-21 04:32:12
0001 /* 0002 * Copyright (C) 2010-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 #include "PaletteManagerDlg.h" 0012 0013 #include <QBitmap> 0014 #include <QDesktopWidget> 0015 #include <QPainter> 0016 #include <QScreen> 0017 #include <QWidget> 0018 0019 #include <KCharSelect> 0020 #include <KHelpClient> 0021 #include <KLocalizedString> 0022 #include <KMessageBox> 0023 0024 #include "CalibrateFlossDlg.h" 0025 #include "Commands.h" 0026 #include "Floss.h" 0027 #include "FlossScheme.h" 0028 #include "MainWindow.h" 0029 #include "NewFlossDlg.h" 0030 #include "SchemeManager.h" 0031 #include "SymbolLibrary.h" 0032 #include "SymbolManager.h" 0033 #include "SymbolSelectorDlg.h" 0034 #include "configuration.h" 0035 0036 const uchar pickColorCursorMask[] = { 0037 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x18, 0x00, 0038 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0039 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0040 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0041 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0x00, 0xff, 0xff, 0xff, 0042 }; 0043 0044 PaletteManagerDlg::PaletteManagerDlg(QWidget *parent, Document *document) 0045 : QDialog(parent) 0046 , m_document(document) 0047 , m_dialogPalette(m_document->pattern()->palette()) 0048 , m_flossUsage(document->pattern()->stitches().flossUsage()) 0049 , m_scheme(SchemeManager::scheme(m_dialogPalette.schemeName())) 0050 , m_symbolSelectorDlg(nullptr) 0051 { 0052 setWindowTitle(i18n("Palette Manager")); 0053 ui.setupUi(this); 0054 0055 ui.SymbolLibrary->insertItems(0, SymbolManager::libraries()); 0056 ui.SymbolLibrary->setCurrentItem(m_dialogPalette.symbolLibrary()); 0057 0058 fillLists(); 0059 } 0060 0061 PaletteManagerDlg::~PaletteManagerDlg() 0062 { 0063 delete m_symbolSelectorDlg; 0064 } 0065 0066 const DocumentPalette &PaletteManagerDlg::palette() const 0067 { 0068 return m_dialogPalette; 0069 } 0070 0071 void PaletteManagerDlg::hideEvent(QHideEvent *event) 0072 { 0073 KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("DialogSizes")).writeEntry(QStringLiteral("PaletteManagerDlg"), size()); 0074 0075 QDialog::hideEvent(event); 0076 } 0077 0078 void PaletteManagerDlg::showEvent(QShowEvent *event) 0079 { 0080 QDialog::showEvent(event); 0081 0082 if (KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("DialogSizes")).hasKey(QStringLiteral("PaletteManagerDlg"))) { 0083 resize(KConfigGroup(KSharedConfig::openConfig(), QStringLiteral("DialogSizes")).readEntry(QStringLiteral("PaletteManagerDlg"), QSize())); 0084 } 0085 } 0086 0087 void PaletteManagerDlg::on_ColorList_currentRowChanged(int currentRow) 0088 { 0089 ui.AddFloss->setEnabled((currentRow != -1) && symbolsAvailable()); 0090 } 0091 0092 int mapStyleToIndex(Qt::PenStyle style) 0093 { 0094 int index = 0; 0095 0096 if (style == Qt::DashLine) { 0097 index = 1; 0098 } 0099 0100 if (style == Qt::DotLine) { 0101 index = 2; 0102 } 0103 0104 if (style == Qt::DashDotLine) { 0105 index = 3; 0106 } 0107 0108 if (style == Qt::DashDotDotLine) { 0109 index = 4; 0110 } 0111 0112 return index; 0113 } 0114 0115 void PaletteManagerDlg::on_CurrentList_currentRowChanged(int currentRow) 0116 { 0117 if (currentRow != -1) { 0118 int i = paletteIndex(ui.CurrentList->currentItem()->data(Qt::UserRole).toString()); 0119 const DocumentFloss *floss = m_dialogPalette.flosses().value(i); 0120 ui.StitchStrands->setCurrentIndex(floss->stitchStrands() - 1); 0121 ui.BackstitchStrands->setCurrentIndex(floss->backstitchStrands() - 1); 0122 Symbol symbol = SymbolManager::library(m_dialogPalette.symbolLibrary())->symbol(m_dialogPalette.flosses().value(i)->stitchSymbol()); 0123 ui.StitchSymbol->setIcon(SymbolListWidget::createIcon(symbol, 22)); 0124 ui.BackstitchSymbol->setCurrentIndex(mapStyleToIndex(floss->backstitchSymbol())); 0125 ui.StitchStrands->setEnabled(true); 0126 ui.BackstitchStrands->setEnabled(true); 0127 ui.StitchSymbol->setEnabled(true); 0128 ui.BackstitchSymbol->setEnabled(true); 0129 ui.ClearUnused->setEnabled(true); 0130 0131 if (m_flossUsage.contains(i) && m_flossUsage[i].totalStitches() != 0) { 0132 ui.RemoveFloss->setEnabled(false); 0133 } else { 0134 ui.RemoveFloss->setEnabled(true); 0135 } 0136 } else { 0137 ui.RemoveFloss->setEnabled(false); 0138 ui.StitchStrands->setEnabled(false); 0139 ui.BackstitchStrands->setEnabled(false); 0140 ui.StitchSymbol->setEnabled(false); 0141 ui.BackstitchSymbol->setEnabled(false); 0142 ui.ClearUnused->setEnabled(false); 0143 } 0144 0145 if (symbolsAvailable()) { 0146 ui.AddFloss->setEnabled(ui.ColorList->currentRow() != -1); 0147 ui.AddFloss->setToolTip(QString()); 0148 } else { 0149 ui.AddFloss->setEnabled(false); 0150 ui.AddFloss->setToolTip(QString(i18n("There are no more symbols available."))); 0151 } 0152 } 0153 0154 void PaletteManagerDlg::on_AddFloss_clicked(bool) 0155 { 0156 QListWidgetItem *listWidgetItem = ui.ColorList->takeItem(ui.ColorList->currentRow()); 0157 m_dialogPalette.add(listWidgetItem->data(Qt::DecorationRole).value<QColor>()); 0158 insertListWidgetItem(ui.CurrentList, listWidgetItem); 0159 ui.CurrentList->scrollToItem(listWidgetItem, QAbstractItemView::PositionAtCenter); 0160 ui.CurrentList->setCurrentItem(listWidgetItem); 0161 } 0162 0163 void PaletteManagerDlg::on_RemoveFloss_clicked(bool) 0164 { 0165 QListWidgetItem *listWidgetItem = ui.CurrentList->takeItem(ui.CurrentList->currentRow()); 0166 int i = paletteIndex(listWidgetItem->data(Qt::UserRole).toString()); 0167 m_dialogPalette.remove(i); 0168 0169 insertListWidgetItem(ui.ColorList, listWidgetItem); 0170 ui.ColorList->scrollToItem(listWidgetItem, QAbstractItemView::PositionAtCenter); 0171 ui.ColorList->setCurrentItem(listWidgetItem); 0172 } 0173 0174 void PaletteManagerDlg::on_StitchStrands_activated(int index) 0175 { 0176 m_dialogPalette.floss(paletteIndex(ui.CurrentList->currentItem()->data(Qt::UserRole).toString()))->setStitchStrands(index + 1); 0177 } 0178 0179 void PaletteManagerDlg::on_BackstitchStrands_activated(int index) 0180 { 0181 m_dialogPalette.floss(paletteIndex(ui.CurrentList->currentItem()->data(Qt::UserRole).toString()))->setBackstitchStrands(index + 1); 0182 } 0183 0184 void PaletteManagerDlg::on_SymbolLibrary_activated(const QString &library) 0185 { 0186 m_dialogPalette.setSymbolLibrary(library); 0187 0188 if (library != m_dialogPalette.symbolLibrary()) { 0189 // Can't change the library because there aren't enough symbols available 0190 // Show a warning and reset the current library in the selection 0191 KMessageBox::information(this, QString(i18n("The selected symbol library does not have enough symbols for the flosses in the palette."))); 0192 ui.SymbolLibrary->setCurrentItem(m_dialogPalette.symbolLibrary()); 0193 } else if (m_symbolSelectorDlg) { 0194 delete m_symbolSelectorDlg; 0195 m_symbolSelectorDlg = new SymbolSelectorDlg(this, library); 0196 } 0197 0198 on_CurrentList_currentRowChanged(ui.CurrentList->currentRow()); 0199 } 0200 0201 void PaletteManagerDlg::on_StitchSymbol_clicked(bool) 0202 { 0203 int i = paletteIndex(ui.CurrentList->currentItem()->data(Qt::UserRole).toString()); 0204 0205 if (m_symbolSelectorDlg == nullptr) { 0206 m_symbolSelectorDlg = new SymbolSelectorDlg(this, m_dialogPalette.symbolLibrary()); 0207 } 0208 0209 m_symbolSelectorDlg->setSelectedSymbol(m_dialogPalette.flosses().value(i)->stitchSymbol(), m_dialogPalette.usedSymbols()); 0210 0211 if (m_symbolSelectorDlg->exec() == QDialog::Accepted) { 0212 m_dialogPalette.floss(i)->setStitchSymbol(m_symbolSelectorDlg->selectedSymbol()); 0213 ui.StitchSymbol->setIcon( 0214 SymbolListWidget::createIcon(SymbolManager::library(m_dialogPalette.symbolLibrary())->symbol(m_dialogPalette.flosses().value(i)->stitchSymbol()), 0215 22)); 0216 } 0217 } 0218 0219 void PaletteManagerDlg::on_BackstitchSymbol_activated(int index) 0220 { 0221 Qt::PenStyle style = Qt::SolidLine; 0222 0223 if (index == 1) { 0224 style = Qt::DashLine; 0225 } else if (index == 2) { 0226 style = Qt::DotLine; 0227 } else if (index == 3) { 0228 style = Qt::DashDotLine; 0229 } else if (index == 4) { 0230 style = Qt::DashDotDotLine; 0231 } 0232 0233 m_dialogPalette.floss(paletteIndex(ui.CurrentList->currentItem()->data(Qt::UserRole).toString()))->setBackstitchSymbol(style); 0234 } 0235 0236 void PaletteManagerDlg::on_NewFloss_clicked(bool) 0237 { 0238 QPointer<NewFlossDlg> newFlossDlg = new NewFlossDlg(this, m_scheme); 0239 0240 if (newFlossDlg->exec()) { 0241 Floss *floss = newFlossDlg->floss(); 0242 0243 if (floss) { 0244 QListWidgetItem *listWidgetItem = new QListWidgetItem; 0245 listWidgetItem->setText(QString::fromLatin1("%1 %2").arg(floss->name(), floss->description())); 0246 listWidgetItem->setData(Qt::DecorationRole, QColor(floss->color())); 0247 listWidgetItem->setData(Qt::UserRole, QString(floss->name())); 0248 0249 if (contains(floss->name())) { 0250 insertListWidgetItem(ui.CurrentList, listWidgetItem); 0251 0252 if (m_flossUsage.contains(paletteIndex(floss->name())) && m_flossUsage[paletteIndex(floss->name())].totalStitches()) { 0253 listWidgetItem->setForeground(QBrush(Qt::gray)); 0254 } 0255 } else { 0256 insertListWidgetItem(ui.ColorList, listWidgetItem); 0257 } 0258 } 0259 } 0260 0261 delete newFlossDlg; 0262 } 0263 0264 void PaletteManagerDlg::on_ClearUnused_clicked(bool) 0265 { 0266 for (int row = 0; row < ui.CurrentList->count();) { 0267 ui.CurrentList->setCurrentRow(row); 0268 QListWidgetItem *listWidgetItem = ui.CurrentList->currentItem(); 0269 int i = paletteIndex(listWidgetItem->data(Qt::UserRole).toString()); 0270 0271 if (!m_flossUsage.contains(i) || m_flossUsage[i].totalStitches() == 0) { 0272 on_RemoveFloss_clicked(true); 0273 } else { 0274 row++; 0275 } 0276 } 0277 } 0278 0279 void PaletteManagerDlg::on_Calibrate_clicked(bool) 0280 { 0281 QPointer<CalibrateFlossDlg> calibrateFlossDlg = new CalibrateFlossDlg(this, m_dialogPalette.schemeName()); 0282 0283 if (calibrateFlossDlg->exec() == QDialog::Accepted) { 0284 fillLists(); 0285 } 0286 } 0287 0288 void PaletteManagerDlg::on_PickColor_clicked() 0289 { 0290 setMouseTracking(true); 0291 setCursor(Qt::CrossCursor); 0292 grabMouse(); 0293 } 0294 0295 void PaletteManagerDlg::mouseMoveEvent(QMouseEvent *event) 0296 { 0297 QPoint hotSpot = event->globalPos(); 0298 QColor color(QGuiApplication::primaryScreen()->grabWindow(0, hotSpot.x(), hotSpot.y(), 1, 1).toImage().pixel(0, 0)); 0299 QPixmap pixmap(32, 32); 0300 pixmap.fill(color); 0301 0302 QPainter painter(&pixmap); 0303 painter.setRenderHint(QPainter::Antialiasing, false); 0304 painter.drawLine(3, 0, 3, 7); 0305 painter.drawLine(4, 0, 4, 7); 0306 painter.drawLine(0, 3, 7, 3); 0307 painter.drawLine(0, 4, 7, 4); 0308 painter.drawRect(8, 8, 23, 23); 0309 painter.end(); 0310 0311 pixmap.setMask(QBitmap().fromData(QSize(32, 32), pickColorCursorMask, QImage::Format_Mono)); 0312 setCursor(QCursor(pixmap, 4, 4)); 0313 } 0314 0315 void PaletteManagerDlg::mouseReleaseEvent(QMouseEvent *event) 0316 { 0317 releaseMouse(); 0318 setCursor(Qt::ArrowCursor); 0319 setMouseTracking(false); 0320 0321 QColor color(QGuiApplication::primaryScreen()->grabWindow(0).toImage().pixel(event->globalPos())); 0322 Floss *floss = m_scheme->convert(color); 0323 0324 QList<QListWidgetItem *> foundItems = ui.CurrentList->findItems(floss->name(), Qt::MatchStartsWith); 0325 0326 if (foundItems.count()) { 0327 ui.CurrentList->setCurrentItem(foundItems.at(0)); 0328 ui.CurrentList->setFocus(); 0329 } else { 0330 foundItems = ui.ColorList->findItems(floss->name(), Qt::MatchStartsWith); 0331 0332 if (foundItems.count()) { 0333 ui.ColorList->setCurrentItem(foundItems.at(0)); 0334 ui.ColorList->setFocus(); 0335 } 0336 } 0337 } 0338 0339 void PaletteManagerDlg::on_DialogButtonBox_accepted() 0340 { 0341 accept(); 0342 } 0343 0344 void PaletteManagerDlg::on_DialogButtonBox_rejected() 0345 { 0346 reject(); 0347 } 0348 0349 void PaletteManagerDlg::on_DialogButtonBox_helpRequested() 0350 { 0351 KHelpClient::invokeHelp(QStringLiteral("PaletteManagerDialog"), QStringLiteral("kxstitch")); 0352 } 0353 0354 void PaletteManagerDlg::fillLists() 0355 { 0356 ui.ColorList->clear(); 0357 ui.CurrentList->clear(); 0358 ui.CurrentScheme->setText(m_scheme->schemeName()); 0359 0360 foreach (const Floss *floss, m_scheme->flosses()) { 0361 QListWidgetItem *listWidgetItem = new QListWidgetItem; 0362 listWidgetItem->setText(QString::fromLatin1("%1 %2").arg(floss->name(), floss->description())); 0363 listWidgetItem->setData(Qt::DecorationRole, QColor(floss->color())); 0364 listWidgetItem->setData(Qt::UserRole, QString(floss->name())); 0365 0366 if (contains(floss->name())) { 0367 insertListWidgetItem(ui.CurrentList, listWidgetItem); 0368 0369 if (m_flossUsage.contains(paletteIndex(floss->name())) && m_flossUsage[paletteIndex(floss->name())].totalStitches()) { 0370 listWidgetItem->setForeground(QBrush(Qt::gray)); 0371 } 0372 } else { 0373 insertListWidgetItem(ui.ColorList, listWidgetItem); 0374 } 0375 } 0376 0377 /* The following should have worked, but setting the currentRow to -1 doesn't emit 0378 the signal and consequently doesn't call the slot 0379 0380 ui.CurrentList->setCurrentRow(ui.CurrentList->count()?0:-1); 0381 ui.ColorList->setCurrentRow(ui.ColorList->count()?0:-1); 0382 */ 0383 0384 if (ui.CurrentList->count()) { 0385 ui.CurrentList->setCurrentRow(0); 0386 } else { 0387 on_CurrentList_currentRowChanged(-1); 0388 } 0389 0390 if (ui.ColorList->count()) { 0391 ui.ColorList->setCurrentRow(0); 0392 } else { 0393 on_ColorList_currentRowChanged(-1); 0394 } 0395 } 0396 0397 void PaletteManagerDlg::insertListWidgetItem(QListWidget *listWidget, QListWidgetItem *listWidgetItem) 0398 { 0399 int rows = listWidget->count(); 0400 0401 for (int row = 0; row < rows; row++) { 0402 if (listWidgetItem->data(Qt::UserRole).toInt() < listWidget->item(row)->data(Qt::UserRole).toInt()) { 0403 do { 0404 QListWidgetItem *oldListWidgetItem = listWidget->item(row); 0405 listWidget->insertItem(row, listWidgetItem); 0406 listWidgetItem = oldListWidgetItem; 0407 } while (++row < rows); 0408 } 0409 } 0410 0411 listWidget->addItem(listWidgetItem); 0412 } 0413 0414 bool PaletteManagerDlg::contains(const QString &flossName) const 0415 { 0416 for (QMap<int, DocumentFloss *>::const_iterator i = m_dialogPalette.flosses().constBegin(); i != m_dialogPalette.flosses().constEnd(); ++i) { 0417 if (flossName == i.value()->flossName()) { 0418 return true; 0419 } 0420 } 0421 0422 return false; 0423 } 0424 0425 int PaletteManagerDlg::paletteIndex(const QString &flossName) const 0426 { 0427 for (QMap<int, DocumentFloss *>::const_iterator i = m_dialogPalette.flosses().constBegin(); i != m_dialogPalette.flosses().constEnd(); ++i) { 0428 if (flossName == i.value()->flossName()) { 0429 return i.key(); 0430 } 0431 } 0432 0433 return -1; 0434 } 0435 0436 bool PaletteManagerDlg::symbolsAvailable() const 0437 { 0438 return (SymbolManager::library(m_dialogPalette.symbolLibrary())->indexes().count() > m_dialogPalette.flosses().count()); 0439 } 0440 0441 #include "moc_PaletteManagerDlg.cpp"