KDE Core/Platform 11/Eliminating Duplication With Qt
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.
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 choice of Decimal Degrees or Radians, Qt only in Decimal Degrees
- 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
- Marble can set/get lat/lon/alt in a single call, Qt can not
- Marble provides normalize methods, Qt does not
- Marble provides precision parm for toString(), Qt does not
- Marble provides fromString() method, Qt does not
- Qt provides some Great Circle calculations which use their pi and radius, Marble does these elsewhere
- Qt provides isValid(), Marble 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 accepted)
- Add convenience set/get methods for lat/lon/alt in a single call
- Add api to return as degrees or radians
- Add precision to toString()
- Add separate lat/lon/alt to toString()
- Add fromString()
Nice to have, but can be in wrapper?:
- Quaternion
- Detail level
- Normalize
- isPole()
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();
};
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;
};
GeoAddress
A very simple implementation, no validation or intelligence, simply a container.
- Uses US names for division levels (States, etc) instead of more generic names.
- Country Code is ISO Alpha3 rather than more common ISO Alpha2 as used in QLocale
- No validation/cross-check between Country Code and Country Name, QLocale could provide the name for the code instead but would limit to only valid ISO countries.
- Could hold ISO Subdivision Code?
- Is shared
- Is not Qt Meta Type
Overall could live with it as is, but any enhancements would be nice. Do somemore research on other common address containers for comparison.
class Q_LOCATION_EXPORT QGeoAddress
{
public:
QGeoAddress();
QGeoAddress(const QGeoAddress &other);
~QGeoAddress();
QGeoAddress &operator=(const QGeoAddress &other);
bool operator==(const QGeoAddress &other) const;
bool operator!=(const QGeoAddress &other) const {
return !(other == *this);
}
QString country() const;
void setCountry(const QString &country);
QString countryCode() const;
void setCountryCode(const QString &countryCode);
QString state() const;
void setState(const QString &state);
QString county() const;
void setCounty(const QString &county);
QString city() const;
void setCity(const QString &city);
QString district() const;
void setDistrict(const QString &district);
QString street() const;
void setStreet(const QString &street);
QString postcode() const;
void setPostcode(const QString &postcode);
bool isEmpty() const;
void clear();
private:
QSharedDataPointer<QGeoAddressPrivate> d;
};
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.