File indexing completed on 2024-07-14 07:17:15

0001 /*
0002     SPDX-FileCopyrightText: 2004 Jason Harris <jharris@30doradus.org>
0003 
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "opscolors.h"
0008 
0009 #include "colorscheme.h"
0010 #include "config-kstars.h"
0011 #include "kspaths.h"
0012 #include "kstars.h"
0013 #include "ksnotification.h"
0014 #include "kstarsdata.h"
0015 #include "skymap.h"
0016 #include "thememanager.h"
0017 #ifdef HAVE_CFITSIO
0018 #include "fitsviewer/fitsviewer.h"
0019 #include "fitsviewer/fitsview.h"
0020 #endif
0021 #include "skyobjects/starobject.h"
0022 
0023 #include <KActionCollection>
0024 #include <KLocalizedString>
0025 #include <KMessageBox>
0026 
0027 #include <QColorDialog>
0028 #include <QComboBox>
0029 #include <QDoubleSpinBox>
0030 #include <QFile>
0031 #include <QInputDialog>
0032 #include <QPixmap>
0033 #include <QPushButton>
0034 #include <QStandardPaths>
0035 #include <QTextStream>
0036 
0037 static int ItemColorData = Qt::UserRole + 1;
0038 
0039 OpsColors::OpsColors() : QFrame(KStars::Instance())
0040 {
0041     setupUi(this);
0042 
0043     //Populate list of Application Themes
0044     KSTheme::Manager::instance()->populateThemeQListWidget(themesWidget);
0045     connect(themesWidget, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(slotChangeTheme(QListWidgetItem*)));
0046 
0047     //Populate list of adjustable colors
0048     for (unsigned int i = 0; i < KStarsData::Instance()->colorScheme()->numberOfColors(); ++i)
0049     {
0050         QPixmap col(30, 20);
0051         QColor itemColor(KStarsData::Instance()->colorScheme()->colorAt(i));
0052         col.fill(itemColor);
0053         QListWidgetItem *item = new QListWidgetItem(KStarsData::Instance()->colorScheme()->nameAt(i), ColorPalette);
0054         item->setData(Qt::DecorationRole, col);
0055         item->setData(ItemColorData, itemColor);
0056     }
0057 
0058     PresetBox->addItem(i18nc("use default color scheme", "Default Colors"));
0059     PresetBox->addItem(i18nc("use 'star chart' color scheme", "Star Chart"));
0060     PresetBox->addItem(i18nc("use 'night vision' color scheme", "Night Vision"));
0061     PresetBox->addItem(i18nc("use 'moonless night' color scheme", "Moonless Night"));
0062 
0063     PresetFileList.append("classic.colors");
0064     PresetFileList.append("chart.colors");
0065     PresetFileList.append("night.colors");
0066     PresetFileList.append("moonless-night.colors");
0067 
0068     QFile file;
0069     QString line, schemeName, filename;
0070     file.setFileName(KSPaths::locate(QStandardPaths::AppLocalDataLocation, "colors.dat"));
0071     if (file.exists() && file.open(QIODevice::ReadOnly))
0072     {
0073         QTextStream stream(&file);
0074 
0075         while (!stream.atEnd())
0076         {
0077             line       = stream.readLine();
0078             schemeName = line.left(line.indexOf(':'));
0079             filename   = line.mid(line.indexOf(':') + 1, line.length());
0080             PresetBox->addItem(schemeName);
0081             PresetFileList.append(filename);
0082         }
0083         file.close();
0084     }
0085 
0086     kcfg_StarColorIntensity->setValue(KStarsData::Instance()->colorScheme()->starColorIntensity());
0087     kcfg_StarColorMode->addItem(i18nc("use realistic star colors", "Real Colors"));
0088     kcfg_StarColorMode->addItem(i18nc("show stars as red circles", "Solid Red"));
0089     kcfg_StarColorMode->addItem(i18nc("show stars as black circles", "Solid Black"));
0090     kcfg_StarColorMode->addItem(i18nc("show stars as white circles", "Solid White"));
0091     kcfg_StarColorMode->addItem(i18nc("show stars as colored circles", "Solid Colors"));
0092     kcfg_StarColorMode->setCurrentIndex(KStarsData::Instance()->colorScheme()->starColorMode());
0093 
0094     if (KStarsData::Instance()->colorScheme()->starColorMode() != 0) //mode is not "Real Colors"
0095         kcfg_StarColorIntensity->setEnabled(false);
0096     else
0097         kcfg_StarColorIntensity->setEnabled(true);
0098 
0099     connect(ColorPalette, SIGNAL(itemClicked(QListWidgetItem*)), this, SLOT(newColor(QListWidgetItem*)));
0100     connect(kcfg_StarColorIntensity, SIGNAL(valueChanged(int)), this, SLOT(slotStarColorIntensity(int)));
0101     connect(kcfg_StarColorMode, SIGNAL(activated(int)), this, SLOT(slotStarColorMode(int)));
0102     connect(PresetBox, SIGNAL(currentRowChanged(int)), this, SLOT(slotPreset(int)));
0103     connect(AddPreset, SIGNAL(clicked()), this, SLOT(slotAddPreset()));
0104     connect(RemovePreset, SIGNAL(clicked()), this, SLOT(slotRemovePreset()));
0105     connect(SavePreset, SIGNAL(clicked()), this, SLOT(slotSavePreset()));
0106 
0107     RemovePreset->setEnabled(false);
0108     SavePreset->setEnabled(false);
0109 }
0110 
0111 void OpsColors::slotChangeTheme(QListWidgetItem *item)
0112 {
0113     KSTheme::Manager::instance()->setCurrentTheme(item->text());
0114 }
0115 
0116 void OpsColors::newColor(QListWidgetItem *item)
0117 {
0118     if (!item)
0119         return;
0120 
0121     QPixmap pixmap(30, 20);
0122     QColor NewColor;
0123 
0124     int index = ColorPalette->row(item);
0125     if (index < 0 || index >= ColorPalette->count())
0126         return;
0127     QColor col = item->data(ItemColorData).value<QColor>();
0128     NewColor   = QColorDialog::getColor(col);
0129 
0130     //NewColor will only be valid if the above if statement was found to be true during one of the for loop iterations
0131     if (NewColor.isValid())
0132     {
0133         pixmap.fill(NewColor);
0134         item->setData(Qt::DecorationRole, pixmap);
0135         item->setData(ItemColorData, NewColor);
0136         KStarsData::Instance()->colorScheme()->setColor(KStarsData::Instance()->colorScheme()->keyAt(index),
0137                 NewColor.name());
0138     }
0139 
0140     if (PresetBox->currentRow() > 3)
0141         SavePreset->setEnabled(true);
0142 
0143     KStars::Instance()->map()->forceUpdate();
0144 
0145 #ifdef HAVE_CFITSIO
0146     QList<FITSViewer *> viewers = KStars::Instance()->findChildren<FITSViewer *>();
0147     for (auto &viewer : viewers)
0148     {
0149         QSharedPointer<FITSView> currentView;
0150         if (viewer->getCurrentView(currentView))
0151             currentView->updateFrame();
0152     }
0153 #endif
0154 }
0155 
0156 void OpsColors::slotPreset(int index)
0157 {
0158     QString sPreset = PresetFileList.at(index);
0159     setColors(sPreset);
0160 }
0161 
0162 bool OpsColors::setColors(const QString &filename)
0163 {
0164     QPixmap temp(30, 20);
0165 
0166     //check if colorscheme is removable...
0167     QFile test;
0168     //try filename in local user KDE directory tree.
0169     test.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(filename));
0170     if (test.exists())
0171     {
0172         RemovePreset->setEnabled(true);
0173         SavePreset->setEnabled(true);
0174     }
0175     else
0176     {
0177         RemovePreset->setEnabled(false);
0178         SavePreset->setEnabled(false);
0179     }
0180     test.close();
0181 
0182     QString actionName = QString("cs_" + filename.left(filename.indexOf(".colors"))).toUtf8();
0183     QAction *a         = KStars::Instance()->actionCollection()->action(actionName);
0184     if (a)
0185         a->setChecked(true);
0186     qApp->processEvents();
0187 
0188     kcfg_StarColorMode->setCurrentIndex(KStarsData::Instance()->colorScheme()->starColorMode());
0189     kcfg_StarColorIntensity->setValue(KStarsData::Instance()->colorScheme()->starColorIntensity());
0190 
0191     for (unsigned int i = 0; i < KStarsData::Instance()->colorScheme()->numberOfColors(); ++i)
0192     {
0193         QColor itemColor(KStarsData::Instance()->colorScheme()->colorAt(i));
0194         temp.fill(itemColor);
0195         ColorPalette->item(i)->setData(Qt::DecorationRole, temp);
0196         ColorPalette->item(i)->setData(ItemColorData, itemColor);
0197     }
0198 
0199     KStars::Instance()->map()->forceUpdate();
0200 #ifdef HAVE_CFITSIO
0201     QList<FITSViewer *> viewers = KStars::Instance()->findChildren<FITSViewer *>();
0202     for (auto &viewer : viewers)
0203     {
0204         QSharedPointer<FITSView> currentView;
0205         if (viewer->getCurrentView(currentView))
0206             currentView->updateFrame();
0207     }
0208 #endif
0209 
0210     return true;
0211 }
0212 
0213 void OpsColors::slotAddPreset()
0214 {
0215     bool okPressed = false;
0216     QString schemename =
0217         QInputDialog::getText(nullptr, i18n("New Color Scheme"), i18n("Enter a name for the new color scheme:"),
0218                               QLineEdit::Normal, QString(), &okPressed);
0219 
0220     if (okPressed && !schemename.isEmpty())
0221     {
0222         if (KStarsData::Instance()->colorScheme()->save(schemename))
0223         {
0224             QListWidgetItem *item = new QListWidgetItem(schemename, PresetBox);
0225             QString fname         = KStarsData::Instance()->colorScheme()->fileName();
0226             PresetFileList.append(fname);
0227             QString actionName = QString("cs_" + fname.left(fname.indexOf(".colors"))).toUtf8();
0228             KStars::Instance()->addColorMenuItem(schemename, actionName);
0229 
0230             QAction *a = KStars::Instance()->actionCollection()->action(actionName);
0231             if (a)
0232                 a->setChecked(true);
0233             PresetBox->setCurrentItem(item);
0234         }
0235     }
0236 }
0237 
0238 void OpsColors::slotSavePreset()
0239 {
0240     QString schemename = PresetBox->currentItem()->text();
0241     KStarsData::Instance()->colorScheme()->save(schemename);
0242     SavePreset->setEnabled(false);
0243 }
0244 
0245 void OpsColors::slotRemovePreset()
0246 {
0247     QListWidgetItem *current = PresetBox->currentItem();
0248     if (!current)
0249         return;
0250     QString name     = current->text();
0251     QString filename = PresetFileList[PresetBox->currentRow()];
0252     QFile cdatFile;
0253     //determine filename in local user KDE directory tree.
0254     cdatFile.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath("colors.dat"));
0255 
0256     //Remove action from color-schemes menu
0257     KStars::Instance()->removeColorMenuItem(QString("cs_" + filename.left(filename.indexOf(".colors"))).toUtf8());
0258 
0259     if (!cdatFile.exists() || !cdatFile.open(QIODevice::ReadWrite))
0260     {
0261         QString message = i18n("Local color scheme index file could not be opened.\nScheme cannot be removed.");
0262         KSNotification::sorry(message, i18n("Could Not Open File"));
0263     }
0264     else
0265     {
0266         //Remove entry from the ListBox and from the QStringList holding filenames.
0267         //There seems to be no way to set no item selected, so select
0268         // the first item.
0269         PresetBox->setCurrentRow(0);
0270         PresetFileList.removeOne(filename);
0271         delete current;
0272         RemovePreset->setEnabled(false);
0273 
0274         //Read the contents of colors.dat into a QStringList, except for the entry to be removed.
0275         QTextStream stream(&cdatFile);
0276         QStringList slist;
0277         bool removed = false;
0278 
0279         while (!stream.atEnd())
0280         {
0281             QString line = stream.readLine();
0282             if (line.left(line.indexOf(':')) != name)
0283                 slist.append(line);
0284             else
0285                 removed = true;
0286         }
0287 
0288         if (removed) //Entry was removed; delete the corresponding .colors file.
0289         {
0290             QFile colorFile;
0291             //determine filename in local user KDE directory tree.
0292             colorFile.setFileName(QDir(KSPaths::writableLocation(QStandardPaths::AppLocalDataLocation)).filePath(filename));
0293             if (!colorFile.remove())
0294             {
0295                 QString message = i18n("Could not delete the file: %1", colorFile.fileName());
0296                 KSNotification::sorry(message, i18n("Error Deleting File"));
0297             }
0298 
0299             //remove the old colors.dat file, and rebuild it with the modified string list.
0300             cdatFile.remove();
0301             cdatFile.open(QIODevice::ReadWrite);
0302             QTextStream stream2(&cdatFile);
0303             for (int i = 0; i < slist.count(); ++i)
0304                 stream << slist[i] << '\n';
0305         }
0306         else
0307         {
0308             QString message = i18n("Could not find an entry named %1 in colors.dat.", name);
0309             KSNotification::sorry(message, i18n("Scheme Not Found"));
0310         }
0311         cdatFile.close();
0312     }
0313 }
0314 
0315 void OpsColors::slotStarColorMode(int i)
0316 {
0317     KStarsData::Instance()->colorScheme()->setStarColorMode(i);
0318 
0319     if (KStarsData::Instance()->colorScheme()->starColorMode() != 0) //mode is not "Real Colors"
0320         kcfg_StarColorIntensity->setEnabled(false);
0321     else
0322         kcfg_StarColorIntensity->setEnabled(true);
0323 }
0324 
0325 void OpsColors::slotStarColorIntensity(int i)
0326 {
0327     KStarsData::Instance()->colorScheme()->setStarColorIntensity(i);
0328 }