diff --git a/CMakeLists.txt b/CMakeLists.txt index 9757466f..c37b3243 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -81,6 +81,7 @@ set(QTERM_SRC src/propertiesdialog.cpp src/bookmarkswidget.cpp src/fontdialog.cpp + src/palettedialog.cpp src/dbusaddressable.cpp src/tab-switcher.cpp src/qterminalutils.cpp @@ -96,6 +97,7 @@ set(QTERM_MOC_SRC src/propertiesdialog.h src/bookmarkswidget.h src/fontdialog.h + src/palettedialog.h src/tab-switcher.h ) @@ -128,6 +130,7 @@ set(QTERM_UI_SRC src/forms/propertiesdialog.ui src/forms/bookmarkswidget.ui src/forms/fontdialog.ui + src/forms/palettedialog.ui ) set(QTERM_RCC_SRC diff --git a/src/forms/palettedialog.ui b/src/forms/palettedialog.ui new file mode 100644 index 00000000..44eabcc9 --- /dev/null +++ b/src/forms/palettedialog.ui @@ -0,0 +1,565 @@ + + + PaletteDialog + + + + 0 + 0 + 450 + 377 + + + + Chose your colors + + + true + + + + + + + 18 + + + + TextLabel + + + Qt::AlignmentFlag::AlignCenter + + + + + + + Drop a color + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Blue + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Dark Gray + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Light Gray + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Green + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Black + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Yellow + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Foreground + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Cyan + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Green + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Intense Background + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Intense Foreground + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Background + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Magenta + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Cyan + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Blue + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + White + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Red + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Red + + + Qt::AlignmentFlag::AlignCenter + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Bright Magenta + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + true + + + true + + + QFrame::Shape::StyledPanel + + + Yellow + + + Qt::AlignmentFlag::AlignCenter + + + 4 + + + + + + + + + + + + Color dialog + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + Qt::Orientation::Vertical + + + + 20 + 40 + + + + + + + + QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok + + + false + + + + + + + + + buttonBox + accepted() + PaletteDialog + accept() + + + 226 + 313 + + + 226 + 167 + + + + + buttonBox + rejected() + PaletteDialog + reject() + + + 226 + 313 + + + 226 + 167 + + + + + diff --git a/src/forms/propertiesdialog.ui b/src/forms/propertiesdialog.ui index 5090c3ae..3b5d38e2 100644 --- a/src/forms/propertiesdialog.ui +++ b/src/forms/propertiesdialog.ui @@ -6,14 +6,14 @@ 0 0 - 700 - 700 + 763 + 638 Terminal settings - + @@ -21,8 +21,7 @@ Appearance - - .. + @@ -38,8 +37,7 @@ Behavior - - .. + @@ -47,8 +45,7 @@ Shortcuts - - .. + @@ -56,8 +53,7 @@ Dropdown - - .. + @@ -65,8 +61,7 @@ Bookmarks - - .. + @@ -74,7 +69,7 @@ - QFrame::StyledPanel + QFrame::Shape::StyledPanel 0 @@ -99,7 +94,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true @@ -109,138 +104,60 @@ 0 0 - 441 - 659 + 460 + 667 - - - - - - 0 - - - 0 - - - 0 - - - 0 - - - - - Font - - - changeFontButton - - - - - - - Qt::Horizontal - - - - 40 - 20 - - - - - - - - QFrame::StyledPanel - - - - - - false - - - - - - - &Change... - - - - - - - - + + + - Color scheme + Cursor shape - colorSchemaCombo + keybCursorShape_comboBox - - + + - - - - Widget style - - - styleComboBox + + + + false - - - - - - - - - Scrollbar position + + + 0 + 0 + - - scrollBarPos_comboBox + + - - - - - - - - - Tabs position + + QToolButton::ToolButtonPopupMode::InstantPopup - - tabsPos_comboBox + + Qt::ToolButtonStyle::ToolButtonIconOnly - - - - - + + + + QFrame::Shape::StyledPanel + - Cursor shape + - - keybCursorShape_comboBox + + false - - - - + Toggles usage of bold font face for rendering intense colors @@ -250,64 +167,27 @@ - - - - Show terminal size on resize - - - - - - - Enable bi-directional text support - - + + - - - - Specify whether box drawing characters should be drawn by QTerminal internally or left to underlying font rendering libraries. - + + - Use box drawing characters contained in the font + Color scheme - - + + - Terminal transparency + Tabs position - termTransparencyBox - - - - - - - % - - - 0 - - - 100 - - - 0 - - - - - - - Background image: + tabsPos_comboBox - + @@ -322,13 +202,48 @@ - + - Background mode: + Background image: - + + + + &Change... + + + + + + + + 0 + + + 0 + + + 0 + + + 0 + + + + + Font + + + changeFontButton + + + + + + + @@ -357,17 +272,54 @@ - - - - Start with preset: + + + + Current Terminal - - terminalPresetComboBox + + + + + Draw a border + + + + + + + Set the current terminal on mouseover + + + + + + + Change window title based on the terminal + + + + + + + Change window icon based on the terminal + + + + + + + + + + Specify whether box drawing characters should be drawn by QTerminal internally or left to underlying font rendering libraries. + + + Use box drawing characters contained in the font - + @@ -391,7 +343,33 @@ + + + + Qt::Orientation::Vertical + + + + 20 + 0 + + + + + + + + + + Start with preset: + + + terminalPresetComboBox + + + + Terminal margin @@ -401,62 +379,179 @@ - + + + + Show terminal size on resize + + + + + + + Terminal transparency + + + termTransparencyBox + + + + + + + % + + + 0 + + + 100 + + + 0 + + + + + + + + + + Background mode: + + + + + + + Scrollbar position + + + scrollBarPos_comboBox + + + + px - - - - Current Terminal + + + + + + + Enable bi-directional text support - - - - - Draw a border - - - - - - - Set the current terminal on mouseover - - - - - - - Change window title based on the terminal - - - - - - - Change window icon based on the terminal - - - - - - - - Qt::Vertical + + + + 20 - - - 20 - 0 - + + + + Night scheme from + + + + + + + false + + + + + + + + + + false + + + to + + + Qt::AlignmentFlag::AlignCenter + + + + + + + false + + + + + + + + + + Qt::Orientation::Horizontal + + + + 40 + 20 + + + + + + + + + + Widget style - + + styleComboBox + + + + + + + + 0 + 0 + + + + + + + QToolButton::ToolButtonPopupMode::InstantPopup + + + Qt::ToolButtonStyle::ToolButtonIconOnly + + + + + + + false + + @@ -484,7 +579,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true @@ -494,8 +589,8 @@ 0 0 - 454 - 248 + 382 + 318 @@ -627,10 +722,10 @@ - Qt::Horizontal + Qt::Orientation::Horizontal - QSizePolicy::MinimumExpanding + QSizePolicy::Policy::MinimumExpanding @@ -645,7 +740,7 @@ - Qt::Vertical + Qt::Orientation::Vertical @@ -681,7 +776,7 @@ - QFrame::NoFrame + QFrame::Shape::NoFrame true @@ -691,15 +786,15 @@ 0 0 - 347 - 530 + 330 + 593 - Qt::Vertical + Qt::Orientation::Vertical @@ -891,7 +986,7 @@ <html><head/><body><p>Which behavior to emulate. Note that this does not have to match your operating system.</p><p>If you are not sure, use the <span style=" font-weight:600;">default</span> emulation.</p></body></html> - Qt::RichText + Qt::TextFormat::RichText true @@ -923,10 +1018,10 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift)true - QAbstractItemView::ScrollPerPixel + QAbstractItemView::ScrollMode::ScrollPerPixel - QAbstractItemView::ScrollPerPixel + QAbstractItemView::ScrollMode::ScrollPerPixel true @@ -982,7 +1077,7 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift) - QFormLayout::ExpandingFieldsGrow + QFormLayout::FieldGrowthPolicy::ExpandingFieldsGrow @@ -1047,7 +1142,7 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift) - Qt::Vertical + Qt::Orientation::Vertical @@ -1117,7 +1212,7 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift) - QPlainTextEdit::NoWrap + QPlainTextEdit::LineWrapMode::NoWrap @@ -1131,10 +1226,10 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift) - Qt::Horizontal + Qt::Orientation::Horizontal - QDialogButtonBox::Apply|QDialogButtonBox::Cancel|QDialogButtonBox::Ok + QDialogButtonBox::StandardButton::Apply|QDialogButtonBox::StandardButton::Cancel|QDialogButtonBox::StandardButton::Ok @@ -1222,5 +1317,85 @@ To remove/disable a Shortcut, at point 2 press only a modifier (like Shift) + + nightSchema + toggled(bool) + nightSchemaCombo + setEnabled(bool) + + + 351 + 91 + + + 446 + 120 + + + + + nightSchema + toggled(bool) + label_4 + setEnabled(bool) + + + 351 + 91 + + + 496 + 91 + + + + + nightSchema + toggled(bool) + nightSchemaStart + setEnabled(bool) + + + 351 + 91 + + + 452 + 90 + + + + + nightSchema + toggled(bool) + nightSchemaEnd + setEnabled(bool) + + + 351 + 91 + + + 540 + 90 + + + + + nightSchema + toggled(bool) + configNightSchema + setEnabled(bool) + + + 352 + 94 + + + 725 + 125 + + + diff --git a/src/palettedialog.cpp b/src/palettedialog.cpp new file mode 100644 index 00000000..6bc8db90 --- /dev/null +++ b/src/palettedialog.cpp @@ -0,0 +1,107 @@ +/*************************************************************************** + * Copyright (C) 2025 by Thomas Lübking * + * thomas.luebking@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#include +#include +#include +#include +#include + +#include "palettedialog.h" + +PaletteDialog::PaletteDialog(QWidget *parent) : QDialog(parent) +{ + setupUi(this); + QColorDialog *cd = new QColorDialog(this); + cd->hide(); + connect (colorbutton, SIGNAL(clicked()), cd, SLOT(show())); + connect (colorbutton, SIGNAL(clicked()), cd, SLOT(raise())); + QList tileLabels = tiles->findChildren(); + for (QLabel *l : tileLabels) + l->installEventFilter(this); +} + +void PaletteDialog::setColorSchemeName(QString name) +{ + nameLabel->setText(name); +} + +#define IS_BACKGROUND objectName().contains(QLatin1String("Background")) +#define IS_INTENSE objectName().contains(QLatin1String("Intense")) + +QMap PaletteDialog::colors() +{ + QMap map; + QList tileLabels = tiles->findChildren(); + for (QLabel *l : tileLabels) + map[l->objectName()] = l->palette().color(l->IS_BACKGROUND ? l->backgroundRole() : l->foregroundRole()); + return map; +} + +int PaletteDialog::setColors(QMap map) +{ + int match = 0; + for (auto i = map.cbegin(), end = map.cend(); i != end; ++i) { + if (QLabel *l = tiles->findChild(i.key())) { + setColor(l, i.value()); + ++match; + } + } + return match; +} + +void PaletteDialog::setColor(QLabel *l, QColor c) +{ + if (l->IS_BACKGROUND) { + bool intense = l->IS_INTENSE; + QList tileLabels = tiles->findChildren(); + for (QLabel *fl : tileLabels) { + if (fl->IS_INTENSE == intense) { + QPalette pal = fl->palette(); + pal.setColor(fl->backgroundRole(), c); + fl->setPalette(pal); + } + } + } else { + QPalette pal = l->palette(); + pal.setColor(l->foregroundRole(), c); + l->setPalette(pal); + if (l->objectName().contains(QLatin1String("Foreground"))) { + const QString name = QString::fromLatin1(l->IS_INTENSE ? "BackgroundIntense" : "Background"); + if (QLabel *bl = tiles->findChild(name)) // Q_ASSERT + bl->setPalette(pal); + } + } +} + +bool PaletteDialog::eventFilter(QObject *o, QEvent *e) { + if (e->type() == QEvent::DragEnter) { + QDropEvent *de = static_cast(e); + de->mimeData()->hasColor() ? de->accept() : de->ignore(); + return false; + } + if (e->type() == QEvent::Drop) { + QDropEvent *de = static_cast(e); + if (!de->mimeData()->hasColor()) + return false; + if (QLabel *l = qobject_cast(o)) + setColor(l, qvariant_cast(de->mimeData()->colorData())); + return false; + } + return false; +} diff --git a/src/palettedialog.h b/src/palettedialog.h new file mode 100644 index 00000000..bef6a529 --- /dev/null +++ b/src/palettedialog.h @@ -0,0 +1,40 @@ +/*************************************************************************** + * Copyright (C) 2025 by Thomas Lübking * + * thomas.luebking@gmail.com * + * * + * This program is free software; you can redistribute it and/or modify * + * it under the terms of the GNU General Public License as published by * + * the Free Software Foundation; either version 2 of the License, or * + * (at your option) any later version. * + * * + * This program is distributed in the hope that it will be useful, * + * but WITHOUT ANY WARRANTY; without even the implied warranty of * + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * + * GNU General Public License for more details. * + * * + * You should have received a copy of the GNU General Public License * + * along with this program. If not, see . * + ***************************************************************************/ + +#ifndef PALETTEDIALOG_H +#define PALETTEDIALOG_H + +#include +#include +#include "ui_palettedialog.h" + +class PaletteDialog : public QDialog, Ui::PaletteDialog +{ + Q_OBJECT +public: + PaletteDialog(QWidget *parent = nullptr); + void setColorSchemeName(QString name); + QMap colors(); + int setColors(QMap); +protected: + bool eventFilter(QObject *o, QEvent *e); +private: + void setColor(QLabel *l, QColor c); +}; + +#endif // PALETTEDIALOG_H \ No newline at end of file diff --git a/src/properties.cpp b/src/properties.cpp index d455d1e0..da6ee9fb 100644 --- a/src/properties.cpp +++ b/src/properties.cpp @@ -81,6 +81,9 @@ void Properties::loadSettings() QApplication::setStyle(guiStyle); colorScheme = m_settings->value(QLatin1String("colorScheme"), QLatin1String("Linux")).toString(); + nightScheme = m_settings->value(QLatin1String("nightScheme"), QLatin1String("")).toString(); + nightStart = m_settings->value(QLatin1String("nightStart"), QTime(21,0)).toTime(); + nightEnd = m_settings->value(QLatin1String("nightEnd"), QTime(7,0)).toTime(); highlightCurrentTerminal = m_settings->value(QLatin1String("highlightCurrentTerminal"), true).toBool(); focusOnMoueOver = m_settings->value(QLatin1String("focusOnMoueOver"), false).toBool(); @@ -188,6 +191,9 @@ void Properties::saveSettings() { m_settings->setValue(QLatin1String("guiStyle"), guiStyle); m_settings->setValue(QLatin1String("colorScheme"), colorScheme); + m_settings->setValue(QLatin1String("nightScheme"), nightScheme); + m_settings->setValue(QLatin1String("nightStart"), nightStart); + m_settings->setValue(QLatin1String("nightEnd"), nightEnd); m_settings->setValue(QLatin1String("highlightCurrentTerminal"), highlightCurrentTerminal); m_settings->setValue(QLatin1String("focusOnMoueOver"), focusOnMoueOver); m_settings->setValue(QLatin1String("showTerminalSizeHint"), showTerminalSizeHint); diff --git a/src/properties.h b/src/properties.h index 34cf0a92..d503f7a2 100644 --- a/src/properties.h +++ b/src/properties.h @@ -23,6 +23,7 @@ #include #include #include +#include typedef QString Session; @@ -55,6 +56,9 @@ class Properties QStringList shell; QFont font; QString colorScheme; + QString nightScheme; + QTime nightStart; + QTime nightEnd; QString guiStyle; bool highlightCurrentTerminal; bool focusOnMoueOver; diff --git a/src/propertiesdialog.cpp b/src/propertiesdialog.cpp index 49da1d27..57f78378 100644 --- a/src/propertiesdialog.cpp +++ b/src/propertiesdialog.cpp @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -28,6 +29,7 @@ #include "propertiesdialog.h" #include "properties.h" #include "fontdialog.h" +#include "palettedialog.h" #include "config.h" #include "qterminalapp.h" @@ -144,7 +146,43 @@ PropertiesDialog::PropertiesDialog(QWidget *parent) int csix = colorSchemaCombo->findText(Properties::Instance()->colorScheme); if (csix != -1) colorSchemaCombo->setCurrentIndex(csix); - + nightSchemaCombo->addItems(colorSchemes); + nightSchema->setChecked(!Properties::Instance()->nightScheme.isEmpty()); + nightSchemaStart->setTime(Properties::Instance()->nightStart); + nightSchemaEnd->setTime(Properties::Instance()->nightEnd); + if (nightSchema->isChecked()) { + csix = nightSchemaCombo->findText(Properties::Instance()->nightScheme); + if (csix != -1) + nightSchemaCombo->setCurrentIndex(csix); + } + QMenu *schemeActions = new QMenu(this); + QAction *csNewAct = schemeActions->addAction(tr("New…")); + QAction *csEditAct = schemeActions->addAction(tr("Edit…")); + QAction *csImportAct = schemeActions->addAction(tr("Import…")); + schemeActions->addSeparator(); + QAction *csDeleteAct = schemeActions->addAction(tr("Delete")); + configColorSchema->setMenu(schemeActions); + configNightSchema->setMenu(schemeActions); + connect(configColorSchema, &QToolButton::triggered, [=](QAction *act) { + if (act == csNewAct) + newColorScheme(colorSchemaCombo); + else if (act == csEditAct) + editColorScheme(colorSchemaCombo); + else if (act == csImportAct) + importColorScheme(colorSchemaCombo); + else if (act == csDeleteAct) + deleteColorScheme(colorSchemaCombo); + }); + connect(configNightSchema, &QToolButton::triggered, [=](QAction *act) { + if (act == csNewAct) + newColorScheme(nightSchemaCombo); + else if (act == csEditAct) + editColorScheme(nightSchemaCombo); + else if (act == csImportAct) + importColorScheme(nightSchemaCombo); + else if (act == csDeleteAct) + deleteColorScheme(nightSchemaCombo); + }); backgroundImageLineEdit->setText(Properties::Instance()->backgroundImage); backgroundModecomboBox->setCurrentIndex(Properties::Instance()->backgroundMode); @@ -325,6 +363,9 @@ void PropertiesDialog::accept() void PropertiesDialog::apply() { Properties::Instance()->colorScheme = colorSchemaCombo->currentText(); + Properties::Instance()->nightScheme = nightSchema->isChecked() ? nightSchemaCombo->currentText() : QString(); + Properties::Instance()->nightStart = nightSchemaStart->time(); + Properties::Instance()->nightEnd = nightSchemaEnd->time(); Properties::Instance()->font = fontSampleLabel->font();//fontComboBox->currentFont(); Properties::Instance()->guiStyle = (styleComboBox->currentText() == tr("System Default")) ? QString() : styleComboBox->currentText(); @@ -683,6 +724,163 @@ bool PropertiesDialog::eventFilter(QObject *object, QEvent *event) return QDialog::eventFilter(object, event); } +void PropertiesDialog::newColorScheme(QComboBox *target) +{ + QString newName; + bool ok = false; + while (!ok) { + newName = QInputDialog::getText(this, tr("New Colorscheme"), + tr("Enter the name of the new colorscheme"), + QLineEdit::Normal, newName, &ok); + if (!ok) + return; + if (newName.contains(QLatin1Char('.'))) { // not allowed, see comment in ::import() + ok = false; + newName.replace(QLatin1Char('.'), QLatin1Char('-')); + continue; + } + if (target->findText(newName) > -1) { + ok = false; + for (int i = 1;;++i) { + if (target->findText(newName + QString::fromLatin1("_%1").arg(i)) < 0) { + newName = newName + QString::fromLatin1("_%1").arg(i); + break; + } + } + } + } + // create and edit newName + colorSchemaCombo->addItem(newName); + nightSchemaCombo->addItem(newName); + target->setCurrentText(newName); + editColorScheme(target); +} + +void PropertiesDialog::editColorScheme(QComboBox *target) +{ + QString name = target->currentText(); + QString writable = QFileInfo(QSettings().fileName()).canonicalPath() + QLatin1String("/color-schemes/") + + name + QLatin1String(".colorscheme"); + QString readable; + QSettings *scheme = nullptr; + if (QFile::exists(writable)) { + scheme = new QSettings(writable, QSettings::IniFormat); + } else { + QStringList dirs = QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, + QCoreApplication::applicationName(), + QStandardPaths::LocateDirectory) + + QStandardPaths::locateAll( QStandardPaths::GenericDataLocation, + QLatin1String("qtermwidget6"), + QStandardPaths::LocateDirectory); + dirs.removeDuplicates(); // QStandardPaths::locateAll() produces duplicates + + for (const QString& dir : std::as_const(dirs)) { + readable = dir + QLatin1String("/color-schemes/") + name + QLatin1String(".colorscheme"); + if (QFile::exists(readable)) { + scheme = new QSettings(readable, QSettings::IniFormat); + break; + } + } + } + PaletteDialog dlg; + dlg.setColorSchemeName(name); + + QMap colors; + if (scheme) { + QStringList keys = scheme->allKeys().filter(QLatin1String("/Color")); + for (const QString &key : std::as_const(keys)) { + QStringList nac = scheme->value(key).toStringList(); + if (nac.size() < 3) { + qDebug() << "not a color" << key << scheme->value(key); + continue; + } + colors[key.section(QLatin1Char('/'),0,0)] = QColor(nac.at(0).toShort(), nac.at(1).toShort(), nac.at(2).toShort()); + } + } + dlg.setColors(colors); + + if (dlg.exec()) { + if (!readable.isEmpty()) + QFile::copy(readable, writable); + if (scheme && scheme->fileName() != writable) { + delete scheme; + scheme = nullptr; + } + if (!scheme) + scheme = new QSettings(writable, QSettings::IniFormat); + colors = dlg.colors(); + for (auto i = colors.cbegin(), end = colors.cend(); i != end; ++i) { + QColor c = i.value(); + QStringList nac; + nac << QString::number(c.red()) << QString::number(c.green()) << QString::number(c.blue()); + scheme->setValue(i.key() + QLatin1String("/Color"), nac); + } + scheme->sync(); + } + delete scheme; +} + +void PropertiesDialog::importColorScheme(QComboBox *target) +{ + Q_UNUSED(target) + const QString dir = QFileInfo(QSettings().fileName()).canonicalPath() + QLatin1String("/color-schemes/"); + QStringList imports = QFileDialog::getOpenFileNames(this, tr("Import Color Schemes"), + QString(), QString::fromLatin1("*.colorscheme")); + if (imports.isEmpty()) + return; + if (!QDir(dir).exists()) + QDir().mkpath(dir); + QStringList baddies, collies; + for (QString import : imports) { + if (!QSettings(import, QSettings::IniFormat).allKeys().contains(QString::fromLatin1("Color0/Color"))) { + baddies << import; + continue; + } + // sanitize name. QTermWidget handles them by the files basename, if the import includes + // multiple dots like "fancy.dark.colorscheme" this will cause a collision there + // so we need to make sure the imports stay unambigious and replace inner dot's with + // dashes ("·" would be nice by maybe don't rely on utf8 too much) + QString newName = QFileInfo(import).fileName(); + newName = newName.left(newName.lastIndexOf(QLatin1String(".colorscheme"), -1)) + .replace(QLatin1Char('.'), QLatin1Char('-')); + + QString dst = dir + newName + QLatin1String(".colorscheme"); + if (QFile::exists(dst)) { + collies << import; + continue; + } + QFile::copy(import, dst); + colorSchemaCombo->addItem(newName); + nightSchemaCombo->addItem(newName); + } + /// @todo QTermWidget doesn't pick up in the new items + if (!(baddies.isEmpty() && collies.isEmpty())) { + QString message; + if (!baddies.isEmpty()) + message += tr("These files don't have a Color0/Color entry - not color schemes?
  • ") + + baddies.join(QString::fromLatin1("
  • ")) + QString::fromLatin1("
"); + if (!collies.isEmpty()) + message += tr("These schemes already exist
  • ") + + collies.join(QString::fromLatin1("
  • ")) + QString::fromLatin1("
"); + QMessageBox::warning(this, tr("Some files could not be imported"), message); + } +} + +void PropertiesDialog::deleteColorScheme(QComboBox *target) +{ + const QString name = target->currentText(); + QString path = QFileInfo(QSettings().fileName()).canonicalPath() + QLatin1String("/color-schemes/") + + name + QLatin1String(".colorscheme"); + if (QFile::exists(path)) { + QFile::remove(path); + colorSchemaCombo->removeItem(colorSchemaCombo->findText(name)); + nightSchemaCombo->removeItem(nightSchemaCombo->findText(name)); + return; + } + QMessageBox::warning(this, tr("%1 could not be removed").arg(target->currentText()), + tr("%1 is not a personal scheme and could not be removed").arg(target->currentText())); +} + /* void PropertiesDialog::setupShortcuts() { diff --git a/src/propertiesdialog.h b/src/propertiesdialog.h index 4ebbd263..50961545 100644 --- a/src/propertiesdialog.h +++ b/src/propertiesdialog.h @@ -76,6 +76,11 @@ class PropertiesDialog : public QDialog, Ui::PropertiesDialog KeySequenceEdit *dropShortCutEdit; QPushButton *exampleBookmarksButton; + void newColorScheme(QComboBox *target); + void editColorScheme(QComboBox *target); + void importColorScheme(QComboBox *target); + void deleteColorScheme(QComboBox *target); + private slots: void apply(); void accept() override;