File indexing completed on 2024-04-28 04:20:20
0001 /* 0002 Copyright (c) 2003-2007 Clarence Dang <dang@kde.org> 0003 All rights reserved. 0004 0005 Redistribution and use in source and binary forms, with or without 0006 modification, are permitted provided that the following conditions 0007 are met: 0008 0009 1. Redistributions of source code must retain the above copyright 0010 notice, this list of conditions and the following disclaimer. 0011 2. Redistributions in binary form must reproduce the above copyright 0012 notice, this list of conditions and the following disclaimer in the 0013 documentation and/or other materials provided with the distribution. 0014 0015 THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 0016 IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 0017 OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 0018 IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 0019 INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 0020 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 0021 DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 0022 THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 0023 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 0024 THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 0025 */ 0026 0027 0028 #include "kpMainWindow.h" 0029 #include "kpMainWindowPrivate.h" 0030 0031 #include "widgets/kpColorCells.h" 0032 #include "lgpl/generic/kpColorCollection.h" 0033 #include "lgpl/generic/kpUrlFormatter.h" 0034 #include "widgets/toolbars/kpColorToolBar.h" 0035 0036 #include <KActionCollection> 0037 #include <KMessageBox> 0038 #include <KSelectAction> 0039 #include <KStandardGuiItem> 0040 #include "kpLogCategories.h" 0041 0042 #include <QFileDialog> 0043 #include <QAction> 0044 #include <kwidgetsaddons_version.h> 0045 0046 //--------------------------------------------------------------------- 0047 0048 static QStringList KDEColorCollectionNames () 0049 { 0050 return kpColorCollection::installedCollections (); 0051 } 0052 0053 //--------------------------------------------------------------------- 0054 0055 // private 0056 void kpMainWindow::setupColorsMenuActions () 0057 { 0058 KActionCollection *ac = actionCollection (); 0059 0060 0061 d->actionColorsDefault = ac->addAction (QStringLiteral("colors_default")); 0062 d->actionColorsDefault->setText (i18n ("Use KolourPaint Defaults")); 0063 connect (d->actionColorsDefault, &QAction::triggered, 0064 this, &kpMainWindow::slotColorsDefault); 0065 0066 d->actionColorsKDE = ac->add <KSelectAction> (QStringLiteral("colors_kde")); 0067 d->actionColorsKDE->setText (i18nc ("@item:inmenu colors", "Use KDE's")); 0068 // TODO: Will this slot be called spuriously if there are no colors 0069 // installed? 0070 #if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) 0071 connect (d->actionColorsKDE, 0072 static_cast<void (KSelectAction::*)(QAction*)>(&KSelectAction::triggered), 0073 this, &kpMainWindow::slotColorsKDE); 0074 #else 0075 connect (d->actionColorsKDE, 0076 &KSelectAction::actionTriggered, 0077 this, &kpMainWindow::slotColorsKDE); 0078 #endif 0079 0080 for (const auto &colName : ::KDEColorCollectionNames ()) { 0081 d->actionColorsKDE->addAction (colName); 0082 } 0083 0084 d->actionColorsOpen = ac->addAction (QStringLiteral("colors_open")); 0085 d->actionColorsOpen->setText (i18nc ("@item:inmenu colors", "&Open...")); 0086 connect (d->actionColorsOpen, &QAction::triggered, this, &kpMainWindow::slotColorsOpen); 0087 0088 d->actionColorsReload = ac->addAction (QStringLiteral("colors_reload")); 0089 d->actionColorsReload->setText (i18nc ("@item:inmenu colors", "Reloa&d")); 0090 connect (d->actionColorsReload, &QAction::triggered, 0091 this, &kpMainWindow::slotColorsReload); 0092 0093 d->actionColorsSave = ac->addAction (QStringLiteral("colors_save")); 0094 d->actionColorsSave->setText (i18nc ("@item:inmenu colors", "&Save")); 0095 connect (d->actionColorsSave, &QAction::triggered, 0096 this, &kpMainWindow::slotColorsSave); 0097 0098 d->actionColorsSaveAs = ac->addAction (QStringLiteral("colors_save_as")); 0099 d->actionColorsSaveAs->setText (i18nc ("@item:inmenu colors", "Save &As...")); 0100 connect (d->actionColorsSaveAs, &QAction::triggered, 0101 this, &kpMainWindow::slotColorsSaveAs); 0102 0103 d->actionColorsAppendRow = ac->addAction (QStringLiteral("colors_append_row")); 0104 d->actionColorsAppendRow->setText (i18nc ("@item:inmenu colors", "Add Row")); 0105 connect (d->actionColorsAppendRow, &QAction::triggered, 0106 this, &kpMainWindow::slotColorsAppendRow); 0107 0108 d->actionColorsDeleteRow = ac->addAction (QStringLiteral("colors_delete_row")); 0109 d->actionColorsDeleteRow->setText (i18nc ("@item:inmenu colors", "Delete Last Row")); 0110 connect (d->actionColorsDeleteRow, &QAction::triggered, 0111 this, &kpMainWindow::slotColorsDeleteRow); 0112 0113 0114 enableColorsMenuDocumentActions (false); 0115 } 0116 0117 //--------------------------------------------------------------------- 0118 0119 // private 0120 void kpMainWindow::createColorBox () 0121 { 0122 d->colorToolBar = new kpColorToolBar (i18n ("Color Box"), this); 0123 0124 // (needed for QMainWindow::saveState()) 0125 d->colorToolBar->setObjectName ( QStringLiteral("Color Box" )); 0126 0127 connect (colorCells (), &kpColorCells::rowCountChanged, 0128 this, &kpMainWindow::slotUpdateColorsDeleteRowActionEnabled); 0129 } 0130 0131 //--------------------------------------------------------------------- 0132 0133 // private 0134 void kpMainWindow::enableColorsMenuDocumentActions (bool enable) 0135 { 0136 d->actionColorsDefault->setEnabled (enable); 0137 d->actionColorsKDE->setEnabled (enable); 0138 d->actionColorsOpen->setEnabled (enable); 0139 d->actionColorsReload->setEnabled (enable); 0140 0141 d->actionColorsSave->setEnabled (enable); 0142 d->actionColorsSaveAs->setEnabled (enable); 0143 0144 d->actionColorsAppendRow->setEnabled (enable); 0145 0146 d->colorMenuDocumentActionsEnabled = enable; 0147 0148 slotUpdateColorsDeleteRowActionEnabled (); 0149 } 0150 0151 //--------------------------------------------------------------------- 0152 0153 // private slot 0154 void kpMainWindow::slotUpdateColorsDeleteRowActionEnabled () 0155 { 0156 // Currently, this is always enabled since kpColorCells guarantees that 0157 // there will be at least one row of cells (which might all be of the 0158 // invalid color). 0159 // 0160 // But this method is left here for future extensibility. 0161 d->actionColorsDeleteRow->setEnabled ( 0162 d->colorMenuDocumentActionsEnabled && (colorCells ()->rowCount () > 0)); 0163 } 0164 0165 //--------------------------------------------------------------------- 0166 0167 0168 // Used in 2 situations: 0169 // 0170 // 1. User opens a color without using the "Use KDE's" submenu. 0171 // 2. User attempts to open a color using the "Use KDE's" submenu but the 0172 // opening fails. 0173 // 0174 // TODO: Maybe we could put the 3 actions (for different ways of opening 0175 // colors) in an exclusive group -- this might eliminate the need for 0176 // this hack. 0177 // 0178 // private 0179 void kpMainWindow::deselectActionColorsKDE () 0180 { 0181 d->actionColorsKDE->setCurrentItem (-1); 0182 } 0183 0184 //--------------------------------------------------------------------- 0185 0186 0187 // private 0188 bool kpMainWindow::queryCloseColors () 0189 { 0190 #if DEBUG_KP_MAIN_WINDOW 0191 qCDebug(kpLogMainWindow) << "kpMainWindow::queryCloseColors() colorCells.modified=" 0192 << colorCells ()->isModified (); 0193 #endif 0194 0195 toolEndShape (); 0196 0197 if (!colorCells ()->isModified ()) { 0198 return true; // ok to close 0199 } 0200 0201 int result = KMessageBox::Cancel; 0202 0203 0204 if (!colorCells ()->url ().isEmpty ()) 0205 { 0206 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0207 result = KMessageBox::warningTwoActionsCancel(this, 0208 #else 0209 result = KMessageBox::warningYesNoCancel (this, 0210 #endif 0211 i18n ("The color palette \"%1\" has been modified.\n" 0212 "Do you want to save it?", 0213 kpUrlFormatter::PrettyFilename (colorCells ()->url ())), 0214 QString ()/*caption*/, 0215 KStandardGuiItem::save (), KStandardGuiItem::discard ()); 0216 } 0217 else 0218 { 0219 const QString name = colorCells ()->colorCollection ()->name (); 0220 if (!name.isEmpty ()) 0221 { 0222 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0223 result = KMessageBox::warningTwoActionsCancel(this, 0224 #else 0225 result = KMessageBox::warningYesNoCancel (this, 0226 #endif 0227 i18n ("The KDE color palette \"%1\" has been modified.\n" 0228 "Do you want to save it to a file?", 0229 name), 0230 QString ()/*caption*/, 0231 KStandardGuiItem::save (), KStandardGuiItem::discard ()); 0232 } 0233 else 0234 { 0235 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0236 result = KMessageBox::warningTwoActionsCancel(this, 0237 #else 0238 result = KMessageBox::warningYesNoCancel (this, 0239 #endif 0240 i18n ("The default color palette has been modified.\n" 0241 "Do you want to save it to a file?"), 0242 QString ()/*caption*/, 0243 KStandardGuiItem::save (), KStandardGuiItem::discard ()); 0244 } 0245 } 0246 0247 switch (result) 0248 { 0249 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0250 case KMessageBox::ButtonCode::PrimaryAction: 0251 #else 0252 case KMessageBox::Yes: 0253 #endif 0254 return slotColorsSave (); // close only if save succeeds 0255 #if KWIDGETSADDONS_VERSION >= QT_VERSION_CHECK(5, 100, 0) 0256 case KMessageBox::ButtonCode::SecondaryAction: 0257 #else 0258 case KMessageBox::No: 0259 #endif 0260 return true; // close without saving 0261 default: 0262 return false; // don't close current doc 0263 } 0264 } 0265 0266 //--------------------------------------------------------------------- 0267 0268 0269 // private 0270 void kpMainWindow::openDefaultColors () 0271 { 0272 colorCells ()->setColorCollection ( 0273 kpColorCells::DefaultColorCollection ()); 0274 } 0275 0276 //--------------------------------------------------------------------- 0277 0278 // private slot 0279 void kpMainWindow::slotColorsDefault () 0280 { 0281 // Call just in case. 0282 toolEndShape (); 0283 0284 if (!queryCloseColors ()) { 0285 return; 0286 } 0287 0288 openDefaultColors (); 0289 0290 deselectActionColorsKDE (); 0291 } 0292 0293 //--------------------------------------------------------------------- 0294 0295 // private 0296 bool kpMainWindow::openKDEColors (const QString &name) 0297 { 0298 #if DEBUG_KP_MAIN_WINDOW 0299 qCDebug(kpLogMainWindow) << "kpMainWindow::openKDEColors(" << name << ")"; 0300 #endif 0301 0302 kpColorCollection colorCol; 0303 if (colorCol.openKDE (name, this)) 0304 { 0305 #if DEBUG_KP_MAIN_WINDOW 0306 qCDebug(kpLogMainWindow) << "opened"; 0307 #endif 0308 colorCells ()->setColorCollection (colorCol); 0309 return true; 0310 } 0311 else 0312 { 0313 #if DEBUG_KP_MAIN_WINDOW 0314 qCDebug(kpLogMainWindow) << "failed to open"; 0315 #endif 0316 return false; 0317 } 0318 } 0319 0320 //--------------------------------------------------------------------- 0321 0322 // private slot 0323 void kpMainWindow::slotColorsKDE () 0324 { 0325 // Call in case an error dialog appears. 0326 toolEndShape (); 0327 0328 const int curItem = d->actionColorsKDE->currentItem (); 0329 0330 if (!queryCloseColors ()) 0331 { 0332 deselectActionColorsKDE (); 0333 return; 0334 } 0335 0336 // queryCloseColors() calls slotColorSave(), which can call 0337 // slotColorSaveAs(), which can call deselectActionColorsKDE(). 0338 d->actionColorsKDE->setCurrentItem (curItem); 0339 0340 const QStringList colNames = ::KDEColorCollectionNames (); 0341 const int selected = d->actionColorsKDE->currentItem (); 0342 Q_ASSERT (selected >= 0 && selected < colNames.size ()); 0343 0344 if (!openKDEColors (colNames [selected])) { 0345 deselectActionColorsKDE (); 0346 } 0347 } 0348 0349 //--------------------------------------------------------------------- 0350 0351 // private 0352 bool kpMainWindow::openColors (const QUrl &url) 0353 { 0354 return colorCells ()->openColorCollection (url); 0355 } 0356 0357 //--------------------------------------------------------------------- 0358 0359 // private slot 0360 void kpMainWindow::slotColorsOpen () 0361 { 0362 // Call due to dialog. 0363 toolEndShape (); 0364 0365 QFileDialog fd(this); 0366 fd.setDirectoryUrl(colorCells ()->url()); 0367 fd.setWindowTitle(i18nc ("@title:window", "Open Color Palette")); 0368 0369 if (fd.exec ()) 0370 { 0371 if (!queryCloseColors ()) { 0372 return; 0373 } 0374 0375 QList<QUrl> selected = fd.selectedUrls(); 0376 if ( selected.count() && openColors(selected[0]) ) { 0377 deselectActionColorsKDE(); 0378 } 0379 } 0380 } 0381 0382 //--------------------------------------------------------------------- 0383 0384 // private slot 0385 void kpMainWindow::slotColorsReload () 0386 { 0387 toolEndShape (); 0388 0389 if (colorCells ()->isModified ()) 0390 { 0391 int result = KMessageBox::Cancel; 0392 0393 if (!colorCells ()->url ().isEmpty ()) 0394 { 0395 result = KMessageBox::warningContinueCancel (this, 0396 i18n ("The color palette \"%1\" has been modified.\n" 0397 "Reloading will lose all changes since you last saved it.\n" 0398 "Are you sure?", 0399 kpUrlFormatter::PrettyFilename (colorCells ()->url ())), 0400 QString ()/*caption*/, 0401 KGuiItem(i18n ("&Reload"))); 0402 } 0403 else 0404 { 0405 const QString name = colorCells ()->colorCollection ()->name (); 0406 if (!name.isEmpty ()) 0407 { 0408 result = KMessageBox::warningContinueCancel (this, 0409 i18n ("The KDE color palette \"%1\" has been modified.\n" 0410 "Reloading will lose all changes.\n" 0411 "Are you sure?", 0412 colorCells ()->colorCollection ()->name ()), 0413 QString ()/*caption*/, 0414 KGuiItem (i18n ("&Reload"))); 0415 } 0416 else 0417 { 0418 result = KMessageBox::warningContinueCancel (this, 0419 i18n ("The default color palette has been modified.\n" 0420 "Reloading will lose all changes.\n" 0421 "Are you sure?"), 0422 QString ()/*caption*/, 0423 KGuiItem (i18n ("&Reload"))); 0424 } 0425 } 0426 0427 #if DEBUG_KP_MAIN_WINDOW 0428 qCDebug(kpLogMainWindow) << "result=" << result 0429 << "vs KMessageBox::Continue" << KMessageBox::Continue; 0430 #endif 0431 if (result != KMessageBox::Continue) { 0432 return; 0433 } 0434 } 0435 0436 0437 if (!colorCells ()->url ().isEmpty ()) 0438 { 0439 openColors (colorCells ()->url ()); 0440 } 0441 else 0442 { 0443 const QString name = colorCells ()->colorCollection ()->name (); 0444 if (!name.isEmpty ()) { 0445 openKDEColors (name); 0446 } 0447 else { 0448 openDefaultColors (); 0449 } 0450 } 0451 } 0452 0453 //--------------------------------------------------------------------- 0454 0455 0456 // private slot 0457 bool kpMainWindow::slotColorsSave () 0458 { 0459 // Call due to dialog. 0460 toolEndShape (); 0461 0462 if (colorCells ()->url ().isEmpty ()) 0463 { 0464 return slotColorsSaveAs (); 0465 } 0466 0467 return colorCells ()->saveColorCollection (); 0468 } 0469 0470 //--------------------------------------------------------------------- 0471 0472 // private slot 0473 bool kpMainWindow::slotColorsSaveAs () 0474 { 0475 // Call due to dialog. 0476 toolEndShape (); 0477 0478 QFileDialog fd(this); 0479 fd.setDirectoryUrl(colorCells ()->url()); 0480 fd.setWindowTitle(i18n("Save Color Palette As")); 0481 fd.setAcceptMode(QFileDialog::AcceptSave); 0482 // Note that QFileDialog takes care of asking the user to confirm overwriting. 0483 0484 if (fd.exec ()) 0485 { 0486 QList<QUrl> selected = fd.selectedUrls(); 0487 if ( !selected.count() || !colorCells ()->saveColorCollectionAs(selected[0]) ) { 0488 return false; 0489 } 0490 0491 // We're definitely using our own color collection now. 0492 deselectActionColorsKDE (); 0493 0494 return true; 0495 } 0496 0497 return false; 0498 } 0499 0500 //--------------------------------------------------------------------- 0501 0502 // private slot 0503 void kpMainWindow::slotColorsAppendRow () 0504 { 0505 // Call just in case. 0506 toolEndShape (); 0507 0508 kpColorCells *colorCells = d->colorToolBar->colorCells (); 0509 colorCells->appendRow (); 0510 } 0511 0512 //--------------------------------------------------------------------- 0513 0514 // private slot 0515 void kpMainWindow::slotColorsDeleteRow () 0516 { 0517 // Call just in case. 0518 toolEndShape (); 0519 0520 kpColorCells *colorCells = d->colorToolBar->colorCells (); 0521 colorCells->deleteLastRow (); 0522 }