KDE Core/Platform 11/Eliminating Duplication With Qt

From KDE Community Wiki

Team Members

Olivier, Volker,John, Helios, Ishmail.

Post-it Notes

  • Merge, Augment, Kill
  • Small changes in Qt to improve KDE contributions
  • How can we get mindset change in KDE towards Qt
  • Bigger things like Printing, QDateTime, maintainerships
  • Fixing QUrl so that KUrl is not necessary
  • Replacing QSettings with KConfig DConf? Kiosk?
  • KAction - Add default shortcut to QAction, global shortcuts
  • KLocale - Move to Qt
  • tr / i18n - gettext, script, KLocalizedString - move to Qt

Notes

Kconfig / QSettings / DConf - No-one felt qualified to discuss this, needs a separate break-out group

  • A Good Thing (TM), let's do it
  • Freeze kdelibs4, but not too hard may need changes or can backport some KDE5 stuff
  • Must start now to get what we need into Qt5 or will miss the chance
  • Not everything needs to be in Qt 5.0, but do need to be structured so we can cleanly add new features in 5.1, 5.2
  • Much depends on success of OpenGov
  • All contributions from KDE must be seen as for better of Qt not just KDE, we need to be pragmatic
  • If get in early with quality contributions can establish position of trust and authority
  • Start small with some test cases to prove process, gain trust:
    • KUrl/QUrl - Very simple case with minimal change required
    • KLineEdit/QLineEdit(?) - More involved case
    • QDateTime - Test for working with Qt Brisbane to develop common requirements
    • Printing - Big test case for major changes + maintainership
  • Review progress at Desktop Summit, if good progress then commit to full process
  • Need class-by-class review:
    • Work with dependencies team, need common notes somewhere
    • Will need expert advice on each class, we can't know every reason for duplication
    • Find if a Qt equivalent (not always obvious!)
    • Determine why KDE version exists
    • Determine if Qt version is already good enough (may have improved since K class created)
    • Determine if we really still need any extra features
    • Need to consider features, quality, performance
    • Reach a conclusion:
      • Keep K class entirely
      • Keep K class but move some features to Qt
      • Remove K class, use Q class completely
      • Remove K class, use Q class with new K helper class
  • Licence:
    • Need review by eV lawyers to reassure contributors they don't lose rights, are fully informed of consequences, start asap as may take time
    • Create list of known contributors who have/will agree to Qt license so we can reuse their code if appropriate (will still need explicit agreement per contribution?)
    • Need to be very careful don't copy code of those who oppose code donations
  • Automated tools for convert?

Specific classes/modules

Some obvious stuff from off top of our collective head:

  • QtLocation: Move QGeoCoordinate and poss QGeoAddress from QtLocation to QtCore as fundamental data type
  • KUrl / QUrl
  • KIcon / QIcon
  • KDateTime / QDateTime
  • KLocale / QLocale
  • KAction / QAction
  • KSSL*
  • KCodec
  • KlineEdit / QlineEdit
  • KComboBox / QComboBox
  • KCompleter
  • ...


Some random other notes:

  • QDate/QTime don't have a qHash?

Geolocation

Qt5 Proposal: Move QGeoCoordinate and maybe QGeoAddress from QtLocation to QtCore as fundamental data types.

Discussed with Torstan / Marble guys and they are in favour. Torstan may be at QCS so can add input there.

  • Basic structure is fine
  • Extra to/from string methods would be very good to add, probably acceptable to Qt
  • Marble stores matrix/quaternion for performance, not sure how acceptable to Qt

QGeoAddress has no equivalent in Marble, may be useful as is other fundamental type in Geolocation, is a clean stand-alone implementation if not very sophisticated.

GeoCoordinate

Key differences:

  • Marble stores in qreal Radians, Qt in double Decimal Degrees
  • Marble always in 3d defaults altitude to 0m, Qt allows 2d or 3d
  • Marble stores int Detail level
  • Marble caches Quaternion/Matrix for performance
  • Marble defines M_PI to 41 decimal places, Qt to 20
  • Marble defines Earth radius as 6378.000, Qt as 6371.0072
  • Marble returns coords in Decimal Degrees or Radians
  • Marble is shared (has ref counter), Qt is not
  • Marble is able to be subclassed (has virtuals), Qt is not
  • Marble is a Qt Meta Type, Qt is not
  • Qt provides some Great Circle calculations which use their pi and radius, Marble does these elsewhere
  • Marble provides normalize methods, Qt does not
  • Marble provides precision parm for toString(), Qt does not
  • Marble provides fromString() method, Qt does not

Suggested changes:

  • Move to QtCore
  • Make Q Meta Type
  • Make shared
  • Make able to subclass (i.e. allow Marble to derive and store Quaternion if not acceptable)
  • Add convenience set/get methods for all 3 components at same time
  • Add api to return as degrees or radians
  • Add precision to toString()
  • Add separate component to toString(), i.e. just lat, lon or alt
  • Add fromString()

Nice to have, but can be in wrapper?:

  • Quaternion
  • Detail level
  • Normalize
  • isPole()

Marble API (simplified):

class GEODATA_EXPORT GeoDataCoordinates {

public:
   enum Unit{
       Radian,
       Degree
   };
   enum Notation{
       Decimal,
       DMS
   };
   GeoDataCoordinates();
   GeoDataCoordinates( qreal lon, qreal lat, qreal alt = 0,
                       GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian,
                       int detail = 0 );
   GeoDataCoordinates( const GeoDataCoordinates& other );
   virtual ~GeoDataCoordinates();
   GeoDataCoordinates& operator=( const GeoDataCoordinates &other );
   bool operator==( const GeoDataCoordinates& ) const;
   void set( qreal lon, qreal lat, qreal alt = 0,
             GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
   void geoCoordinates( qreal& lon, qreal& lat,
                        GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
   void setLongitude( qreal lon,
             GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
   qreal longitude( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian )
                                                               const;
   void setLatitude( qreal lat,
             GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian );
   qreal latitude( GeoDataCoordinates::Unit unit = GeoDataCoordinates::Radian ) const;
   void setAltitude( const qreal altitude );
   qreal altitude() const;
   void setDetail( const int det );
   int detail() const;
   const Quaternion &quaternion() const;
   bool isPole( Pole = AnyPole ) const;
   static void setDefaultNotation( GeoDataCoordinates::Notation notation );
   static GeoDataCoordinates::Notation defaultNotation();
   static qreal normalizeLon( qreal lon,
                              GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
   static qreal normalizeLat( qreal lat,
                              GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
   static void normalizeLonLat( qreal &lon, qreal &lat,
                                GeoDataCoordinates::Unit = GeoDataCoordinates::Radian );
   static GeoDataCoordinates fromString( const QString &string, bool& successful );
   QString toString() const;
   QString toString( GeoDataCoordinates::Notation notation, int precision = -1 ) const;
   static QString lonToString( qreal lon, GeoDataCoordinates::Notation notation,
                                          GeoDataCoordinates::Unit unit = Radian,
                                          int precision = -1,
                                          char format = 'f' );
   QString lonToString() const;
   static QString latToString( qreal lat, GeoDataCoordinates::Notation notation,
                                          GeoDataCoordinates::Unit unit = Radian,
                                          int precision = -1,
   QString latToString() const;


   virtual void pack( QDataStream& stream ) const;
   virtual void unpack( QDataStream& stream );
   virtual void detach();

};

Qt 5 Code (simplified):

class Q_LOCATION_EXPORT QGeoCoordinate { public:

   enum CoordinateType {
       InvalidCoordinate,
       Coordinate2D,
       Coordinate3D
   };
   enum CoordinateFormat {
       Degrees,
       DegreesWithHemisphere,
       DegreesMinutes,
       DegreesMinutesWithHemisphere,
       DegreesMinutesSeconds,
       DegreesMinutesSecondsWithHemisphere
   };
   QGeoCoordinate();
   QGeoCoordinate(double latitude, double longitude);
   QGeoCoordinate(double latitude, double longitude, double altitude);
   QGeoCoordinate(const QGeoCoordinate &other);
   ~QGeoCoordinate();
   QGeoCoordinate &operator=(const QGeoCoordinate &other);
   bool operator==(const QGeoCoordinate &other) const;
   inline bool operator!=(const QGeoCoordinate &other) const {
       return !operator==(other);
   }
   bool isValid() const;
   CoordinateType type() const;
   void setLatitude(double latitude);
   double latitude() const;
   void setLongitude(double longitude);
   double longitude() const;
   void setAltitude(double altitude);
   double altitude() const;
   qreal distanceTo(const QGeoCoordinate &other) const;
   qreal azimuthTo(const QGeoCoordinate &other) const;
   QGeoCoordinate atDistanceAndAzimuth(qreal distance, qreal azimuth, qreal distanceUp = 0.0) const;
   QString toString(CoordinateFormat format = DegreesMinutesSecondsWithHemisphere) const;

};

Locale

What's wrong with KLocale:

  • Gtk/Qt apps running under kde-workspace don't use KDE locale
  • KDE apps running under other platforms/workspaces do not use host locale
  • Class merges settings, formatters, parsers and translations in one giant blob
  • Unnecessary dependency for Qt-Addon libraries

What's great about KLocale:

  • Users can change settings
  • Apps can change settings
  • Superior settings, date/time, etc support

What's wrong with QLocale:

  • Not all settings are supported
  • Apps and users unable to change settings

What's good with QLocale:

  • Uses host settings on all platforms
  • Low-level common class so good for Qt Addons

The Plan:

  • Add all KDE settings that already exist in CLDR to QLocale
  • Use QLocale to replace KLocale's role as settings container
    • Gives correct Windows, Mac, Gnome, Meego settings
  • KDE Workspace to set locale envvar on login if KDE locale different to system locale
    • Gives correct locale Gtk/Qt apps
  • KCM to load settings from QLocale, write out as both POSIX and CLDR format files only if user chooses different settings
    • locale envvar then set to absolute path to users POSIX file so all Gtk apps get right settings
    • QLocale loads CLDR file so KDE/Qt apps get right settings
  • Apps use parser/formatter classes/api's to alter settings for one-off calls rather than changing the locale itself, or create a whole new locale object.

Big Questions:

  • Date/Time formats: Keep POSIX formats (need own formatter/parser that translates Unicode format) or switch to Unicode format (not SC, QDateTime may not support all our features)
  • How will QLocale load custom CLDR? Fallback to custom POSIX but lacks some features.

Date/Time

Printing