changeset 1580:a2ff9c01889e

Merge from branch background-mode
author Chris Cannam
date Fri, 24 Jan 2020 15:11:08 +0000
parents 5f6fdd525158 (current diff) 85f04c956f03 (diff)
children 11660e0c896f 01a41a37bd26
files
diffstat 5 files changed, 177 insertions(+), 53 deletions(-) [+]
line wrap: on
line diff
--- a/layer/ColourDatabase.cpp	Wed Jan 15 13:58:33 2020 +0000
+++ b/layer/ColourDatabase.cpp	Fri Jan 24 15:11:08 2020 +0000
@@ -88,17 +88,44 @@
 }
 
 int
-ColourDatabase::getNearbyColourIndex(QColor col) const
+ColourDatabase::getNearbyColourIndex(QColor col, WithBackgroundMode mode) const
 {
-    int index = 0;
+    int index = -1;
     int closestIndex = -1;
-    int closestDistance = 0;
+    double closestDistance = 0;
 
     for (auto &c: m_colours) {
-        int distance =
-            std::abs(col.red() - c.colour.red()) +
-            std::abs(col.green() - c.colour.green()) +
-            std::abs(col.blue() - c.colour.blue());
+
+        ++index;
+
+        if (mode == WithDarkBackground && !c.darkbg) {
+#ifdef DEBUG_COLOUR_DATABASE
+            SVDEBUG << "getNearbyColourIndex: dark background requested, skipping " << c.colour.name() << endl;
+#endif
+            continue;
+        }
+        if (mode == WithLightBackground && c.darkbg) {
+#ifdef DEBUG_COLOUR_DATABASE
+            SVDEBUG << "getNearbyColourIndex: light background requested, skipping " << c.colour.name() << endl;
+#endif
+            continue;
+        }
+
+        // This distance formula is "one of the better low-cost
+        // approximations" according to
+        // https://en.wikipedia.org/w/index.php?title=Color_difference&oldid=936888327
+        
+        double r1 = col.red(), r2 = c.colour.red();
+        double g1 = col.green(), g2 = c.colour.green();
+        double b1 = col.blue(), b2 = c.colour.blue();
+
+        double rav = (r1 + r2) / 2.0;
+        double rterm = (2.0 + rav / 256.0) * (r1 - r2) * (r1 - r2);
+        double gterm = 4.0 * (g1 - g2) * (g1 - g2);
+        double bterm = (2.0 + (255 - rav) / 256.0) * (b1 - b2) * (b1 - b2);
+        
+        double distance = sqrt(rterm + gterm + bterm);
+
 #ifdef DEBUG_COLOUR_DATABASE
         SVDEBUG << "getNearbyColourIndex: comparing " << c.colour.name()
                 << " to " << col.name() << ": distance = " << distance << endl;
@@ -110,7 +137,6 @@
             SVDEBUG << "(this is the best so far)" << endl;
 #endif
         }
-        ++index;
     }
 
 #ifdef DEBUG_COLOUR_DATABASE
--- a/layer/ColourDatabase.h	Wed Jan 15 13:58:33 2020 +0000
+++ b/layer/ColourDatabase.h	Fri Jan 24 15:11:08 2020 +0000
@@ -71,13 +71,20 @@
      */
     bool haveColour(QColor c) const;
 
+    enum WithBackgroundMode {
+        WithAnyBackground,
+        WithDarkBackground,
+        WithLightBackground
+    };
+    
     /**
      * Return the index of the colour in the database that is closest
-     * to the given one, by some simplistic measure (Manhattan
-     * distance in RGB space). This always returns some valid index,
-     * unless the database is empty, in which case it returns -1.
+     * to the given one, by some simple measure. This always returns
+     * some valid index, unless the database is empty, in which case
+     * it returns -1.
      */
-    int getNearbyColourIndex(QColor c) const;
+    int getNearbyColourIndex(QColor c,
+                             WithBackgroundMode mode = WithAnyBackground) const;
 
     /**
      * Add a colour to the database, with the associated name. Return
@@ -110,9 +117,9 @@
 
     /**
      * Return a colour that contrasts with the one at index c,
-     * according to some simplistic algorithm. The returned colour is
-     * not necessarily in the database; pass it to
-     * getNearbyColourIndex if you need one that is.
+     * according to some simple algorithm. The returned colour is not
+     * necessarily in the database; pass it to getNearbyColourIndex if
+     * you need one that is.
      */
     QColor getContrastingColour(int c) const;
 
--- a/view/ViewManager.cpp	Wed Jan 15 13:58:33 2020 +0000
+++ b/view/ViewManager.cpp	Fri Jan 24 15:11:08 2020 +0000
@@ -22,8 +22,11 @@
 #include "View.h"
 #include "Overview.h"
 
+#include "system/System.h"
+
 #include <QSettings>
 #include <QApplication>
+#include <QStyleFactory>
 
 #include <iostream>
 
@@ -72,20 +75,11 @@
     settings.endGroup();
 
     if (getGlobalDarkBackground()) {
-/*
-        cerr << "dark palette:" << endl;
-        cerr << "window = " << QApplication::palette().color(QPalette::Window).name() << endl;
-        cerr << "windowtext = " << QApplication::palette().color(QPalette::WindowText).name() << endl;
-        cerr << "base = " << QApplication::palette().color(QPalette::Base).name() << endl;
-        cerr << "alternatebase = " << QApplication::palette().color(QPalette::AlternateBase).name() << endl;
-        cerr << "text = " << QApplication::palette().color(QPalette::Text).name() << endl;
-        cerr << "button = " << QApplication::palette().color(QPalette::Button).name() << endl;
-        cerr << "buttontext = " << QApplication::palette().color(QPalette::ButtonText).name() << endl;
-        cerr << "brighttext = " << QApplication::palette().color(QPalette::BrightText).name() << endl;
-        cerr << "light = " << QApplication::palette().color(QPalette::Light).name() << endl;
-        cerr << "dark = " << QApplication::palette().color(QPalette::Dark).name() << endl;
-        cerr << "mid = " << QApplication::palette().color(QPalette::Mid).name() << endl;
-*/
+        // i.e. widgets are already dark; create a light palette in
+        // case we are asked to switch to it, but don't create a dark
+        // one because it will be assigned from the actual application
+        // palette if we switch
+        
         m_lightPalette = QPalette(QColor("#000000"),  // WindowText
                                   QColor("#dddfe4"),  // Button
                                   QColor("#ffffff"),  // Light
@@ -95,32 +89,48 @@
                                   QColor("#ffffff"),  // BrightText
                                   QColor("#ffffff"),  // Base
                                   QColor("#efefef")); // Window
-                                  
+
+        m_lightPalette.setColor(QPalette::Highlight, Qt::darkBlue);
+        if (!OSReportsDarkThemeActive()) {
+            int r, g, b;
+            if (OSQueryAccentColour(r, g, b)) {
+                m_lightPalette.setColor(QPalette::Highlight, QColor(r, g, b));
+            }
+        }
 
     } else {
-/*
-        cerr << "light palette:" << endl;
-        cerr << "window = " << QApplication::palette().color(QPalette::Window).name() << endl;
-        cerr << "windowtext = " << QApplication::palette().color(QPalette::WindowText).name() << endl;
-        cerr << "base = " << QApplication::palette().color(QPalette::Base).name() << endl;
-        cerr << "alternatebase = " << QApplication::palette().color(QPalette::AlternateBase).name() << endl;
-        cerr << "text = " << QApplication::palette().color(QPalette::Text).name() << endl;
-        cerr << "button = " << QApplication::palette().color(QPalette::Button).name() << endl;
-        cerr << "buttontext = " << QApplication::palette().color(QPalette::ButtonText).name() << endl;
-        cerr << "brighttext = " << QApplication::palette().color(QPalette::BrightText).name() << endl;
-        cerr << "light = " << QApplication::palette().color(QPalette::Light).name() << endl;
-        cerr << "dark = " << QApplication::palette().color(QPalette::Dark).name() << endl;
-        cerr << "mid = " << QApplication::palette().color(QPalette::Mid).name() << endl;
-*/
-        m_darkPalette = QPalette(QColor("#ffffff"),  // WindowText
+        // i.e. widgets are currently light; create a dark palette in
+        // case we are asked to switch to it, but don't create a light
+        // one because it will be assigned from the actual application
+        // palette if we switch
+        
+        m_darkPalette = QPalette(QColor("#f0f0f0"),  // WindowText
                                  QColor("#3e3e3e"),  // Button
                                  QColor("#808080"),  // Light
                                  QColor("#1e1e1e"),  // Dark
                                  QColor("#404040"),  // Mid
-                                 QColor("#ffffff"),  // Text
+                                 QColor("#f0f0f0"),  // Text
                                  QColor("#ffffff"),  // BrightText
                                  QColor("#000000"),  // Base
                                  QColor("#202020")); // Window
+
+        m_darkPalette.setColor(QPalette::Highlight, QColor(25, 130, 220));
+        if (OSReportsDarkThemeActive()) {
+            int r, g, b;
+            if (OSQueryAccentColour(r, g, b)) {
+                m_darkPalette.setColor(QPalette::Highlight, QColor(r, g, b));
+            }
+        }
+        
+        m_darkPalette.setColor(QPalette::Link, QColor(50, 175, 255));
+        m_darkPalette.setColor(QPalette::LinkVisited, QColor(50, 175, 255));
+        
+        m_darkPalette.setColor(QPalette::Disabled, QPalette::WindowText,
+                               QColor("#808080"));
+        m_darkPalette.setColor(QPalette::Disabled, QPalette::Text,
+                               QColor("#808080"));
+        m_darkPalette.setColor(QPalette::Disabled, QPalette::Shadow,
+                               QColor("#000000"));
     }
 }
 
@@ -792,13 +802,44 @@
         m_lightPalette = QApplication::palette();
     }
 
-#ifndef Q_OS_MAC
+#ifdef Q_OS_MAC
+    return;
+#endif
+    
     if (dark) {
+
+#ifdef Q_OS_WIN32
+        // The Windows Vista style doesn't use the palette for many of
+        // its controls. They can be styled with stylesheets, but that
+        // takes a lot of fiddly and fragile custom bits. Easier and
+        // more reliable to switch to a non-Vista style which does use
+        // the palette.
+
+        QStyle *plainWindowsStyle = QStyleFactory::create("windows");
+        if (!plainWindowsStyle) {
+            SVCERR << "Failed to load plain Windows style" << endl;
+        } else {
+            qApp->setStyle(plainWindowsStyle);
+        }
+#endif
+
         QApplication::setPalette(m_darkPalette);
+        
     } else {
+
+#ifdef Q_OS_WIN32
+        // Switch back to Vista style
+        
+        QStyle *fancyWindowsStyle = QStyleFactory::create("windowsvista");
+        if (!fancyWindowsStyle) {
+            SVCERR << "Failed to load fancy Windows style" << endl;
+        } else {
+            qApp->setStyle(fancyWindowsStyle);
+        }
+#endif
+        
         QApplication::setPalette(m_lightPalette);
     }
-#endif
 }
 
 bool
--- a/widgets/ColourComboBox.cpp	Wed Jan 15 13:58:33 2020 +0000
+++ b/widgets/ColourComboBox.cpp	Fri Jan 24 15:11:08 2020 +0000
@@ -38,15 +38,29 @@
     connect(this, SIGNAL(activated(int)), this, SLOT(comboActivated(int)));
     connect(ColourDatabase::getInstance(), SIGNAL(colourDatabaseChanged()),
             this, SLOT(rebuild()));
-
-    if (count() < 20 && count() > maxVisibleItems()) {
-        setMaxVisibleItems(count());
-    }
 }
 
 void
-ColourComboBox::comboActivated(int index)
+ColourComboBox::includeUnsetEntry(QString entry)
 {
+    m_unsetEntry = entry;
+    
+    rebuild();
+
+    blockSignals(true);
+    int ix = currentIndex();
+    setCurrentIndex(ix + 1);
+    blockSignals(false);
+}
+
+void
+ColourComboBox::comboActivated(int comboIndex)
+{
+    int index = comboIndex;
+    if (m_unsetEntry != "") {
+        index = comboIndex - 1; // so index is the colour index
+    }
+    
     if (!m_withAddNewColourEntry ||
         index < int(ColourDatabase::getInstance()->getColourCount())) {
         emit colourChanged(index);
@@ -81,6 +95,10 @@
     
     clear();
 
+    if (m_unsetEntry != "") {
+        addItem(m_unsetEntry);
+    }
+    
     int size = (QFontMetrics(QFont()).height() * 2) / 3;
     if (size < 12) size = 12;
     
@@ -95,6 +113,12 @@
     }
 
     setCurrentIndex(ix);
+
+    if (count() < 18) {
+        setMaxVisibleItems(count());
+    } else {
+        setMaxVisibleItems(10);
+    }
     
     blockSignals(false);
 }
--- a/widgets/ColourComboBox.h	Wed Jan 15 13:58:33 2020 +0000
+++ b/widgets/ColourComboBox.h	Fri Jan 24 15:11:08 2020 +0000
@@ -29,7 +29,32 @@
 public:
     ColourComboBox(bool withAddNewColourEntry, QWidget *parent = 0);
 
+    /**
+     * Add an entry at the top of the combo for "no colour selected",
+     * with the given label.
+     */
+    void includeUnsetEntry(QString label);
+
+    /**
+     * Get the current colour index. This is the same as
+     * QComboBox::currentIndex() if there is no unset entry, or 1 less
+     * than it if includeUnsetEntry() has been used. So if there is an
+     * unset entry, and it is selected, this returns -1.
+     */
+    int getCurrentColourIndex() const {
+        int index = currentIndex();
+        if (m_unsetEntry == "") {
+            return index;
+        } else {
+            return index - 1;
+        }
+    }
+
 signals:
+    /**
+     * Emitted when the current index is changed. The argument is the
+     * value returned by getCurrentColourIndex()
+     */
     void colourChanged(int colourIndex);
 
 private slots:
@@ -38,6 +63,7 @@
     
 private:
     bool m_withAddNewColourEntry;
+    QString m_unsetEntry;
 };
 
 #endif