refs #319, added column formatters

* Specialized formatters (e.g. for bool, for PQs etc.) allow specialized look and feel for each column
* Fixed isValidComFrequency used for formatters
* Changed models to use formatters
* Outdated propertyByIndexAsString methods removed
* During the above tasks: fixed override keyword in some places
* Column tooltips
* refs #323, wrong column name fix
This commit is contained in:
Klaus Basan
2014-08-31 15:31:19 +02:00
parent c54fa0fd43
commit 9567d1aedf
21 changed files with 893 additions and 303 deletions

View File

@@ -24,16 +24,16 @@ namespace BlackGui
*/
CAircraftListModel::CAircraftListModel(QObject *parent) : CListModelBase("ViewAircraftList", parent)
{
this->m_columns.addColumn(CColumn("callsign", CAircraft::IndexCallsign));
this->m_columns.addColumn(CColumn("pilotrealname", { CAircraft::IndexPilot, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("distance", CAircraft::IndexDistance, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("frequency", { CAircraft::IndexCom1System, CComSystem::IndexActiveFrequency }, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("model", { CAircraft::IndexIcao, CAircraftIcao::IndexAsString}));
this->m_columns.addColumn(CColumn("transponder", { CAircraft::IndexTransponder, CTransponder::IndexTransponderCodeAndModeFormatted }));
this->m_columns.addColumn(CColumn("latitude", { CAircraft::IndexSituation, CAircraftSituation::IndexLatitude }, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("longitude", { CAircraft::IndexSituation, CAircraftSituation::IndexLongitude }, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("altitude", { CAircraft::IndexSituation, CAircraftSituation::IndexAltitude }, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("groundspeed", { CAircraft::IndexSituation, CAircraftSituation::IndexGroundspeed }, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn::standardValueObject("callsign", CAircraft::IndexCallsign));
this->m_columns.addColumn(CColumn::standardString("pilotrealname", { CAircraft::IndexPilot, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("distance", CAircraft::IndexDistance, new CAirspaceDistanceFormatter()));
this->m_columns.addColumn(CColumn("frequency", { CAircraft::IndexCom1System, CComSystem::IndexActiveFrequency }, new CComFrequencyFormatter()));
this->m_columns.addColumn(CColumn::standardString("icao", { CAircraft::IndexIcao, CAircraftIcao::IndexAsString}));
this->m_columns.addColumn(CColumn::standardString("transponder", { CAircraft::IndexTransponder, CTransponder::IndexTransponderCodeAndModeFormatted }));
this->m_columns.addColumn(CColumn("latitude", { CAircraft::IndexSituation, CAircraftSituation::IndexLatitude }, new CLatLonFormatter()));
this->m_columns.addColumn(CColumn("longitude", { CAircraft::IndexSituation, CAircraftSituation::IndexLongitude }, new CLatLonFormatter()));
this->m_columns.addColumn(CColumn::standardValueObject("altitude", { CAircraft::IndexSituation, CAircraftSituation::IndexAltitude }, CDefaultFormatter::alignRightVCenter()));
this->m_columns.addColumn(CColumn("gs", { CAircraft::IndexSituation, CAircraftSituation::IndexGroundspeed }, new CAircraftSpeedFormatter()));
// default sort order
this->setSortColumnByPropertyIndex(CAircraft::IndexDistance);
@@ -49,7 +49,7 @@ namespace BlackGui
(void)QT_TRANSLATE_NOOP("ViewAircraftList", "height");
(void)QT_TRANSLATE_NOOP("ViewAircraftList", "transponder");
(void)QT_TRANSLATE_NOOP("ViewAircraftList", "groundspeed");
(void)QT_TRANSLATE_NOOP("ViewAircraftList", "model");
(void)QT_TRANSLATE_NOOP("ViewAircraftList", "icao");
}
}
}

View File

@@ -14,6 +14,7 @@
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Geo;
using namespace BlackMisc::PhysicalQuantities;
namespace BlackGui
{
@@ -25,13 +26,13 @@ namespace BlackGui
CAirportListModel::CAirportListModel(QObject *parent) :
CListModelBase<BlackMisc::Aviation::CAirport, BlackMisc::Aviation::CAirportList>("ViewAirportList", parent)
{
this->m_columns.addColumn(CColumn("ICAO", CAirport::IndexIcao));
this->m_columns.addColumn(CColumn("distance", CAirport::IndexDistance, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("bearing", CAirport::IndexBearing, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("name", CAirport::IndexDescriptiveName));
this->m_columns.addColumn(CColumn("elevation", CAirport::IndexElevation, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("latitude", CCoordinateGeodetic::IndexLatitude, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("longitude", CCoordinateGeodetic::IndexLongitude, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn::standardValueObject("ICAO", CAirport::IndexIcao));
this->m_columns.addColumn(CColumn("distance", CAirport::IndexDistance, new CAirspaceDistanceFormatter()));
this->m_columns.addColumn(CColumn("bearing", CAirport::IndexBearing, new CAngleDegreeFormatter()));
this->m_columns.addColumn(CColumn::standardString("name", CAirport::IndexDescriptiveName));
this->m_columns.addColumn(CColumn("elevation", CAirport::IndexElevation, new CPhysiqalQuantiyFormatter<CLengthUnit, CLength>(CLengthUnit::ft(), 0)));
this->m_columns.addColumn(CColumn("latitude", CAirport::IndexLatitude, new CLatLonFormatter()));
this->m_columns.addColumn(CColumn("longitude", CAirport::IndexLatitude, new CLatLonFormatter()));
// default sort order
this->setSortColumnByPropertyIndex(CAirport::IndexDistance);

View File

@@ -12,6 +12,7 @@
#include "blackmisc/nwuser.h"
#include "blackmisc/blackmiscfreefunctions.h"
using namespace BlackMisc::PhysicalQuantities;
using namespace BlackMisc::Audio;
using namespace BlackMisc::Aviation;
using namespace BlackMisc::Network;
@@ -27,6 +28,7 @@ namespace BlackGui
CListModelBase("ViewAtcList", parent), m_stationMode(NotSet)
{
this->setStationMode(stationMode);
// force strings for translation in resource files
(void)QT_TRANSLATE_NOOP("ViewAtcList", "callsign");
(void)QT_TRANSLATE_NOOP("ViewAtcList", "distance");
@@ -47,14 +49,16 @@ namespace BlackGui
{
case NotSet:
case StationsOnline:
this->m_columns.addColumn(CColumn("callsign", { CAtcStation::IndexCallsign, CCallsign::IndexCallsignStringAsSet }));
this->m_columns.addColumn(CColumn(CAtcStation::IndexPixmap, true));
this->m_columns.addColumn(CColumn("distance", CAtcStation::IndexDistance, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("frequency", CAtcStation::IndexFrequency, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("controllername", { CAtcStation::IndexController, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("bookedfrom", CAtcStation::IndexBookedFrom));
this->m_columns.addColumn(CColumn("bookeduntil", CAtcStation::IndexBookedUntil));
this->m_columns.addColumn(CColumn("voiceroomurl", { CAtcStation::IndexVoiceRoom, CVoiceRoom::IndexUrl }));
this->m_columns.addColumn(CColumn::standardString("callsign", { CAtcStation::IndexCallsign, CCallsign::IndexCallsignStringAsSet }));
this->m_columns.addColumn(CColumn("type", CAtcStation::IndexIcon));
this->m_columns.addColumn(CColumn("distance", CAtcStation::IndexDistance, new CAirspaceDistanceFormatter()));
this->m_columns.addColumn(CColumn("frequency", CAtcStation::IndexFrequency, new CComFrequencyFormatter()));
this->m_columns.addColumn(CColumn::standardString("controllername", { CAtcStation::IndexController, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("bookedfrom", CAtcStation::IndexBookedFrom,
new CDateTimeFormatter(CDateTimeFormatter::formatHm())));
this->m_columns.addColumn(CColumn("bookeduntil", CAtcStation::IndexBookedUntil,
new CDateTimeFormatter(CDateTimeFormatter::formatHm())));
this->m_columns.addColumn(CColumn::standardString("voiceroomurl", { CAtcStation::IndexVoiceRoom, CVoiceRoom::IndexUrl }));
// default sort order
this->setSortColumnByPropertyIndex(CAtcStation::IndexDistance);
@@ -62,13 +66,15 @@ namespace BlackGui
break;
case StationsBooked:
this->m_columns.addColumn(CColumn("callsign", { CAtcStation::IndexCallsign, CCallsign::IndexCallsignStringAsSet}));
this->m_columns.addColumn(CColumn(CAtcStation::IndexPixmap, true));
this->m_columns.addColumn(CColumn("controllername", {CAtcStation::IndexController, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("bookedfrom", CAtcStation::IndexBookedFrom));
this->m_columns.addColumn(CColumn("bookeduntil", CAtcStation::IndexBookedUntil));
this->m_columns.addColumn(CColumn("frequency", CAtcStation::IndexFrequency, Qt::AlignRight | Qt::AlignVCenter));
this->m_columns.addColumn(CColumn("online", CAtcStation::IndexIsOnline));
this->m_columns.addColumn(CColumn::standardString("callsign", { CAtcStation::IndexCallsign, CCallsign::IndexCallsignStringAsSet }));
this->m_columns.addColumn(CColumn(CAtcStation::IndexIcon));
this->m_columns.addColumn(CColumn("", CAtcStation::IndexIsOnline, new CBoolLedFormatter("online", "offline")));
this->m_columns.addColumn(CColumn::standardString("controllername", { CAtcStation::IndexController, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("bookedfrom", CAtcStation::IndexBookedFrom,
new CDateTimeFormatter(CDateTimeFormatter::formatYmdhm())));
this->m_columns.addColumn(CColumn("bookeduntil", CAtcStation::IndexBookedUntil,
new CDateTimeFormatter(CDateTimeFormatter::formatYmdhm())));
this->m_columns.addColumn(CColumn("frequency", CAtcStation::IndexFrequency, new CComFrequencyFormatter()));
// default sort order
this->setSortColumnByPropertyIndex(CAtcStation::IndexBookedFrom);

View File

@@ -43,6 +43,9 @@ namespace BlackGui
//! Set station mode
void setStationMode(AtcStationMode stationMode);
//! Station mode
AtcStationMode getStationMode() const { return this->m_stationMode; }
public slots:
//! Used to quickly update single station (better response for the user)
void changedAtcStationConnectionStatus(const BlackMisc::Aviation::CAtcStation &station, bool added);

View File

@@ -9,7 +9,7 @@
#include "clientlistmodel.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/icon.h"
#include "blackmisc/icons.h"
#include <QMetaProperty>
#include <QBrush>
@@ -26,14 +26,15 @@ namespace BlackGui
CClientListModel::CClientListModel(QObject *parent) :
CListModelBase<BlackMisc::Network::CClient, BlackMisc::Network::CClientList>("ViewClientList", parent)
{
this->m_columns.addColumn(CColumn(CClient::IndexPixmap, true));
this->m_columns.addColumn(CColumn("callsign", CClient::IndexCallsign));
this->m_columns.addColumn(CColumn("realname", { CClient::IndexUser, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn(CClient::IndexVoiceCapabilitiesPixmap, true));
this->m_columns.addColumn(CColumn("capabilities", CClient::IndexCapabilitiesString));
this->m_columns.addColumn(CColumn("model", {CClient::IndexModel, CAircraftModel::IndexModelString}));
this->m_columns.addColumn(CColumn("queried?", {CClient::IndexModel, CAircraftModel::IndexIsQueriedModelString}));
this->m_columns.addColumn(CColumn("server", CClient::IndexServer));
this->m_columns.addColumn(CColumn("client", CClient::IndexIcon));
this->m_columns.addColumn(CColumn::standardValueObject("callsign", CClient::IndexCallsign));
this->m_columns.addColumn(CColumn::standardString("realname", { CClient::IndexUser, CUser::IndexRealName }));
this->m_columns.addColumn(CColumn("capabilities", CClient::IndexVoiceCapabilitiesIcon));
this->m_columns.addColumn(CColumn::standardString("capabilities", CClient::IndexCapabilitiesString));
this->m_columns.addColumn(CColumn::standardString("model", {CClient::IndexModel, CAircraftModel::IndexModelString}));
this->m_columns.addColumn(CColumn("q.?", "queried", {CClient::IndexModel, CAircraftModel::IndexIsQueriedModelString},
new CBoolIconFormatter(CIcons::StandardIconTick, CIcons::StandardIconCross, "queried", "not queried")));
this->m_columns.addColumn(CColumn::standardString("server", CClient::IndexServer));
// force strings for translation in resource files
// force strings for translation in resource files

View File

@@ -0,0 +1,302 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "columnformatters.h"
#include "blackmisc/geolatitude.h"
#include "blackmisc/variant.h"
#include "blackmisc/iconlist.h"
#include "blackmisc/icons.h"
using namespace BlackMisc;
namespace BlackGui
{
namespace Models
{
QVariant CDefaultFormatter::displayRole(const QVariant &dataQVariant) const
{
// seems to be absurd, but calls the correct methods on CValueObjects
// so QVariant -> QString -> QVariant is correct
if (static_cast<QMetaType::Type>(dataQVariant.type()) == QMetaType::QString) return dataQVariant; // shortcut
return BlackMisc::qVariantToString(dataQVariant, m_useI18n);
}
QVariant CDefaultFormatter::decorationRole(const QVariant &dataQVariant) const
{
// direct return if type is already correct
if (static_cast<QMetaType::Type>(dataQVariant.type()) == QMetaType::QPixmap)
{
return dataQVariant;
}
else if (static_cast<QMetaType::Type>(dataQVariant.type()) == QMetaType::QIcon)
{
return dataQVariant;
}
// convert to pixmap
if (static_cast<QMetaType::Type>(dataQVariant.type()) == QMetaType::QImage)
{
QImage img = dataQVariant.value<QImage>();
return QPixmap::fromImage(img);
}
// Our CIcon class
if (dataQVariant.canConvert<BlackMisc::CIcon>())
{
BlackMisc::CIcon i = dataQVariant.value<BlackMisc::CIcon>();
return i.toPixmap();
}
// nope
return QPixmap();
}
QVariant CDefaultFormatter::alignmentRole() const
{
if (!this->hasAlignment())
{
return QVariant(alignDefault()); // default
}
else
{
return QVariant(m_alignment);
}
}
QVariant CDefaultFormatter::data(int role, const QVariant &inputData) const
{
Qt::ItemDataRole roleEnum = static_cast<Qt::ItemDataRole>(role);
// always supported
if (roleEnum == Qt::TextAlignmentRole) return { alignmentRole() };
// checked
if (this->m_supportedRoles.isEmpty()) return QVariant();
if (!this->m_supportedRoles.contains(role)) return QVariant();
switch (roleEnum)
{
case Qt::DisplayRole:
// formatted to string
return displayRole(inputData);
case Qt::ToolTipRole:
// formatted to string
return tooltipRole(inputData);
case Qt::DecorationRole:
// formatted as pixmap, icon, or color
return decorationRole(inputData);
default:
break;
}
return QVariant();
}
QVariant CPixmapFormatter::displayRole(const QVariant &dataQVariant) const
{
Q_UNUSED(dataQVariant);
Q_ASSERT_X(false, "CPixmapFormatter", "this role should be disabled with pixmaps");
return QVariant();
}
QVariant CPixmapFormatter::tooltipRole(const QVariant &dataQVariant) const
{
if (dataQVariant.isNull()) return "";
if (dataQVariant.canConvert<BlackMisc::CIcon>())
{
BlackMisc::CIcon icon = dataQVariant.value<BlackMisc::CIcon>();
return icon.getDescriptiveText();
}
return "";
}
QVariant CValueObjectFormatter::displayRole(const QVariant &valueObject) const
{
if (valueObject.isNull()) return QVariant();
const BlackMisc::CValueObject *cvo = BlackMisc::CValueObject::fromQVariant(valueObject);
Q_ASSERT(cvo);
if (!cvo) return QVariant();
return QVariant(cvo->toQString(m_useI18n));
}
QVariant CValueObjectFormatter::decorationRole(const QVariant &valueObject) const
{
if (valueObject.isNull()) return "";
const BlackMisc::CValueObject *cvo = BlackMisc::CValueObject::fromQVariant(valueObject);
Q_ASSERT(cvo);
if (!cvo) return QPixmap();
return QVariant(cvo->toPixmap());
}
QVariant CDateTimeFormatter::displayRole(const QVariant &dateTime) const
{
if (dateTime.isNull()) return "";
if (dateTime.type() == QMetaType::QDateTime)
{
QDateTime dt = dateTime.value<QDateTime>();
return dt.toString(m_formatString);
}
else if (dateTime.type() == QMetaType::QDate)
{
QDate d = dateTime.value<QDate>();
return d.toString(m_formatString);
}
else if (dateTime.type() == QMetaType::QTime)
{
QTime t = dateTime.value<QTime>();
return t.toString(m_formatString);
}
else
{
Q_ASSERT_X(false, "formatQVariant", "No QDate, QTime or QDateTime");
return "";
}
}
QVariant CAirspaceDistanceFormatter::displayRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<BlackMisc::PhysicalQuantities::CLength>())
{
// special treatment for some cases
BlackMisc::PhysicalQuantities::CLength l = dataQVariant.value<BlackMisc::PhysicalQuantities::CLength>();
if (!l.isNull() && (l.isPositiveWithEpsilonConsidered() || l.isZeroEpsilonConsidered()))
{
return CPhysiqalQuantiyFormatter::displayRole(dataQVariant);
}
else
{
return "";
}
}
else
{
Q_ASSERT_X(false, "CAirspaceDistanceFormatter::formatQVariant", "No CLength class");
return "";
}
}
QVariant CComFrequencyFormatter::displayRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<BlackMisc::PhysicalQuantities::CFrequency>())
{
// speical treatment for some cases
BlackMisc::PhysicalQuantities::CFrequency f = dataQVariant.value<BlackMisc::PhysicalQuantities::CFrequency>();
if (BlackMisc::Aviation::CComSystem::isValidComFrequency(f))
{
return CPhysiqalQuantiyFormatter::displayRole(dataQVariant);
}
else
{
return "";
}
}
else
{
Q_ASSERT_X(false, "CAviationComFrequencyFormatter::formatQVariant", "No CFrequency class");
return "";
}
}
QVariant CAircraftSpeedFormatter::displayRole(const QVariant &dataQVariant) const
{
// special treatment for some cases
BlackMisc::PhysicalQuantities::CSpeed s = dataQVariant.value<BlackMisc::PhysicalQuantities::CSpeed>();
if (!s.isNull() && (s.isPositiveWithEpsilonConsidered() || s.isZeroEpsilonConsidered()))
{
return CPhysiqalQuantiyFormatter::displayRole(dataQVariant);
}
else
{
return "";
}
}
QVariant CStringFormatter::displayRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<QString>()) { return dataQVariant; }
Q_ASSERT_X(false, "CStringFormatter", "no string value");
return QVariant();
}
QVariant CBoolTextFormatter::displayRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<bool>())
{
bool v = dataQVariant.toBool();
return v ? QVariant(m_trueName) : QVariant(m_falseName);
}
Q_ASSERT_X(false, "CBoolTextFormatter", "no boolean value");
return QVariant();
}
CBoolLedFormatter::CBoolLedFormatter(int alignment) : CBoolLedFormatter("on", "off", alignment)
{ }
CBoolLedFormatter::CBoolLedFormatter(const QString &onName, const QString &offName, int alignment) :
CBoolTextFormatter(alignment, onName, offName, roleDecorationAndToolTip())
{
CLedWidget *led = ledDefault();
led->setOn(true);
this->m_pixmapOnLed = led->asPixmap();
led->setOn(false);
this->m_pixmapOffLed = led->asPixmap();
delete led;
}
QVariant CBoolLedFormatter::displayRole(const QVariant &dataQVariant) const
{
Q_UNUSED(dataQVariant);
Q_ASSERT_X(false, "CBoolLedFormatter", "this role should be disabled with led boolean");
return QVariant();
}
QVariant CBoolLedFormatter::decorationRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<bool>())
{
bool v = dataQVariant.toBool();
return v ? m_pixmapOnLed : m_pixmapOffLed;
}
Q_ASSERT_X(false, "CBoolLedFormatter", "no boolean value");
return QVariant();
}
CBoolIconFormatter::CBoolIconFormatter(int alignment) :
CBoolIconFormatter(CIcons::StandardIconTick, CIcons::StandardIconEmpty16, "on", "off", alignment)
{ }
CBoolIconFormatter::CBoolIconFormatter(CIcons::IconIndex onIcon, CIcons::IconIndex offIcon, const QString &onName, const QString &offName, int alignment) :
CBoolIconFormatter(CIconList::iconForIndex(onIcon), CIconList::iconForIndex(offIcon), onName, offName, alignment)
{ }
CBoolIconFormatter::CBoolIconFormatter(const CIcon &onIcon, const CIcon &offIcon, const QString &onName, const QString &offName, int alignment) :
CBoolTextFormatter(alignment, onName, offName, roleDecorationAndToolTip()), m_iconOn(onIcon), m_iconOff(offIcon)
{
this->m_iconOn.setDescriptiveText(onName);
this->m_iconOff.setDescriptiveText(offName);
}
QVariant CBoolIconFormatter::displayRole(const QVariant &dataQVariant) const
{
Q_UNUSED(dataQVariant);
Q_ASSERT_X(false, "CBoolIconFormatter", "this role should be disabled with icon boolean");
return QVariant();
}
QVariant CBoolIconFormatter::decorationRole(const QVariant &dataQVariant) const
{
if (dataQVariant.canConvert<bool>())
{
bool v = dataQVariant.toBool();
return v ? m_iconOn.toPixmap() : m_iconOff.toPixmap();
}
Q_ASSERT_X(false, "CBoolIconFormatter", "no boolean value");
return QVariant();
}
}
}

View File

@@ -0,0 +1,327 @@
/* Copyright (C) 2013
* swift project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKGUI_COLUMNFORMATTERS_H
#define BLACKGUI_COLUMNFORMATTERS_H
#include "blackgui/led.h"
#include "blackmisc/pqallquantities.h"
#include "blackmisc/aviocomsystem.h"
#include "blackmisc/blackmiscfreefunctions.h"
#include "blackmisc/icon.h"
#include <QDateTime>
#include <QDate>
#include <QTime>
namespace BlackGui
{
namespace Models
{
//! Column formatter default implementation, also serving as interface
class CDefaultFormatter
{
public:
//! Constructor
CDefaultFormatter(int alignment = alignDefault(), bool i18n = true, const QList<int> &supportedRoles = { Qt::DisplayRole }) :
m_supportedRoles(supportedRoles), m_alignment(alignment), m_useI18n(i18n) {}
//! Virtual destructor
virtual ~CDefaultFormatter() {}
//! Value provided as QVariant, formatter converts to QString.
//! Used with Qt::DisplayRole displaying a text.
virtual QVariant displayRole(const QVariant &dataQVariant) const;
//! Value provided as QVariant, formatter converts to QString.
//! Used with Qt::ToolTipRole displaying a text.
virtual QVariant tooltipRole(const QVariant &value) const
{
return displayRole(value);
}
//! Value provided as QVariant, formatted as icon (Qt docu: "The data to be rendered as a decoration in the form of an icon").
//! Used with Qt::DecorationRole displaying an icon, method returns pixmap, icon, or color (see docu)
virtual QVariant decorationRole(const QVariant &dataQVariant) const;
//! Qt::Alignment (as QVariant)
virtual QVariant alignmentRole() const;
//! Alignment available?
virtual bool hasAlignment() const { return m_alignment >= 0; }
//! Receives QVariant of column data, and returns QVariant wrapping string, pixmap, or other values depending on role
virtual QVariant data(int role, const QVariant &inputData) const;
//! Default value
static int alignDefault() { return alignLeftVCenter(); }
//! Align left/vertically centered
static int alignLeftVCenter() { return Qt::AlignVCenter | Qt::AlignLeft; }
//! Align centered
static int alignCentered() { return Qt::AlignVCenter | Qt::AlignHCenter; }
//! Align right/vertically centered
static int alignRightVCenter() { return Qt::AlignVCenter | Qt::AlignRight; }
//! Display on role
static const QList<int> &roleDisplay() { static const QList<int> r({ Qt::DisplayRole}); return r; }
//! Display on role
static const QList<int> &roleDecorationAndToolTip() { static const QList<int> r({ Qt::DecorationRole, Qt::ToolTipRole}); return r; }
protected:
QList<int> m_supportedRoles = QList<int>({ Qt::DisplayRole}); //!< supports decoration role
int m_alignment = -1; //!< alignment horizontal/vertically / Qt::Alignment
bool m_useI18n = true; //!< i18n?
};
//! Pixmap formatter
class CPixmapFormatter : public CDefaultFormatter
{
public:
//! Constructor
CPixmapFormatter(int alignment = alignDefault(), const QList<int> &supportedRoles = roleDecorationAndToolTip()) : CDefaultFormatter(alignment, false, supportedRoles) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
//! \copydoc CDefaultFormatter::tooltipRole
virtual QVariant tooltipRole(const QVariant &dataQVariant) const override;
};
//! String formatter, if known the variant already contains the appropriate string
class CStringFormatter : public CDefaultFormatter
{
public:
//! Constructor
CStringFormatter(int alignment = alignDefault()) : CDefaultFormatter(alignment, false, roleDisplay()) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
};
//! Bool value, format as text
class CBoolTextFormatter : public CDefaultFormatter
{
public:
//! Constructor
CBoolTextFormatter(int alignment = alignDefault(), const QString &trueName = "true", const QString &falseName = "false", const QList<int> &supportedRoles = roleDisplay()) :
CDefaultFormatter(alignment, false, supportedRoles), m_trueName(trueName), m_falseName(falseName) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
protected:
QString m_trueName = "true"; //!< displayed when true
QString m_falseName = "false"; //!< displayed when false
};
//! Format as bool LED value
class CBoolLedFormatter : public CBoolTextFormatter
{
public:
//! Constructor
CBoolLedFormatter(int alignment = alignDefault());
//! Constructor
CBoolLedFormatter(const QString &onName, const QString &offName, int alignment = alignDefault());
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
//! Display the LED
virtual QVariant decorationRole(const QVariant &dataQVariant) const override;
//! \copydoc CDefaultFormatter::tooltipRole
virtual QVariant tooltipRole(const QVariant &dataQVariant) const override
{
return CBoolTextFormatter::displayRole(dataQVariant);
}
//! Default LED
static BlackGui::CLedWidget *ledDefault()
{
return new BlackGui::CLedWidget(false, BlackGui::CLedWidget::Yellow, BlackGui::CLedWidget::Black, BlackGui::CLedWidget::Rounded);
}
protected:
QPixmap m_pixmapOnLed; //!< Pixmap used when on
QPixmap m_pixmapOffLed; //!< Pixmap used when off
};
//! Format as bool pixmap
class CBoolIconFormatter : public CBoolTextFormatter
{
public:
//! Constructor
CBoolIconFormatter(int alignment = alignDefault());
//! Constructor
CBoolIconFormatter(const BlackMisc::CIcon &onIcon, const BlackMisc::CIcon &offIcon, const QString &onName, const QString &offName, int alignment = alignDefault());
//! Constructor
CBoolIconFormatter(BlackMisc::CIcons::IconIndex onIcon, BlackMisc::CIcons::IconIndex offIcon, const QString &onName, const QString &offName, int alignment = alignDefault());
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
//! Display the icon
virtual QVariant decorationRole(const QVariant &dataQVariant) const override;
//! \copydoc CDefaultFormatter::tooltipRole
virtual QVariant tooltipRole(const QVariant &dataQVariant) const override
{
return CBoolTextFormatter::displayRole(dataQVariant);
}
protected:
BlackMisc::CIcon m_iconOn; //!< Used when on
BlackMisc::CIcon m_iconOff; //!< Used when off
};
//! Default formatter when column contains CValueObject
class CValueObjectFormatter : public CDefaultFormatter
{
public:
//! Constructor
CValueObjectFormatter(int alignment = alignDefault(), bool i18n = true, QList<int> supportedRoles = {Qt::DisplayRole}) : CDefaultFormatter(alignment, i18n, supportedRoles) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &valueObject) const override;
//! \copydoc CDefaultFormatter::asPixmap
virtual QVariant decorationRole(const QVariant &valueObject) const;
};
//! Formatter when column contains QDateTime, QDate or QTime
class CDateTimeFormatter : public CDefaultFormatter
{
public:
//! Constructor
CDateTimeFormatter(const QString formatString = formatYmd(), int alignment = alignDefault(), bool i18n = true) :
CDefaultFormatter(alignment, i18n, { Qt::DisplayRole }), m_formatString(formatString) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dateTime) const override;
//! Year month day
static const QString &formatYmd() { static const QString f = "yyyy-MM-dd"; return f; }
//! Year month day hour minute
static const QString &formatYmdhm() { static const QString f = "yyyy-MM-dd HH:mm"; return f; }
//! Hour minute
static const QString &formatHm() { static const QString f = "HH:mm"; return f; }
//! Hour minute second
static const QString &formatHms() { static const QString f = "HH:mm:ss"; return f; }
private:
QString m_formatString = "yyyy-MM-dd HH:mm"; //!< how the value is displayed
};
//! Formatter for physical quantities
template<class MU, class PQ> class CPhysiqalQuantiyFormatter : public CValueObjectFormatter
{
public:
//! Constructor
CPhysiqalQuantiyFormatter(MU unit = MU::defaultUnit(), int digits = 2, int alignment = alignRightVCenter(), bool withUnit = true, bool i18n = true, QList<int> supportedRoles = { Qt::DisplayRole }) : CValueObjectFormatter(alignment, i18n, supportedRoles), m_unit(unit), m_digits(digits), m_withUnit(withUnit) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &physicalQuantity) const override
{
if (physicalQuantity.canConvert<PQ>())
{
PQ pq = physicalQuantity.value<PQ>();
if (!m_unit.isNull())
{
pq.switchUnit(m_unit);
}
return pq.valueRoundedWithUnit(m_digits, m_useI18n);
}
else
{
Q_ASSERT_X(false, "CPhysiqalQuantiyFormatter::displayRole", "No CPhysicalQuantity class");
return "";
}
}
//! Set unit
virtual void setUnit(const MU &unit) { m_unit = unit; }
//! Enable unit display
virtual void enableUnit(bool enable) { m_withUnit = enable; }
//! Digits
virtual void setDigits(int digits) { m_digits = digits; }
protected:
MU m_unit; //!< unit
int m_digits = 2; //!< digits
bool m_withUnit = true; //!< format with unit?
};
//! COM frequencies
class CComFrequencyFormatter : public CPhysiqalQuantiyFormatter<BlackMisc::PhysicalQuantities::CFrequencyUnit, BlackMisc::PhysicalQuantities::CFrequency>
{
public:
//! Constructor
CComFrequencyFormatter(int alignment = alignRightVCenter(), bool withUnit = true, bool i18n = true) : CPhysiqalQuantiyFormatter(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz(), 3, alignment, withUnit, i18n) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
};
//! Angle in degrees
class CAngleDegreeFormatter : public CPhysiqalQuantiyFormatter<BlackMisc::PhysicalQuantities::CAngleUnit, BlackMisc::PhysicalQuantities::CAngle>
{
public:
//! Constructor
CAngleDegreeFormatter(int alignment = alignRightVCenter(), bool withUnit = true, bool i18n = true) : CPhysiqalQuantiyFormatter(BlackMisc::PhysicalQuantities::CAngleUnit::deg(), 0, alignment, withUnit, i18n) {}
};
//! Latitude or Longitude formatter
class CLatLonFormatter : public CValueObjectFormatter
{
public:
//! Constructor
CLatLonFormatter(int alignment = alignRightVCenter()) : CValueObjectFormatter(alignment) {}
};
//! Airspace distance
class CAirspaceDistanceFormatter : public CPhysiqalQuantiyFormatter<BlackMisc::PhysicalQuantities::CLengthUnit, BlackMisc::PhysicalQuantities::CLength>
{
public:
//! Constructor
CAirspaceDistanceFormatter(int alignment = alignRightVCenter(), bool withUnit = true, bool i18n = true) : CPhysiqalQuantiyFormatter(BlackMisc::PhysicalQuantities::CLengthUnit::NM(), 1, alignment, withUnit, i18n) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
};
//! Airspace distance
class CAircraftSpeedFormatter : public CPhysiqalQuantiyFormatter<BlackMisc::PhysicalQuantities::CSpeedUnit, BlackMisc::PhysicalQuantities::CSpeed>
{
public:
//! Constructor
CAircraftSpeedFormatter(int alignment = alignRightVCenter(), bool withUnit = true, bool i18n = true) : CPhysiqalQuantiyFormatter(BlackMisc::PhysicalQuantities::CSpeedUnit::kts(), 0, alignment, withUnit, i18n) {}
//! \copydoc CDefaultFormatter::displayRole
virtual QVariant displayRole(const QVariant &dataQVariant) const override;
};
} // namespace
} // namespace
#endif // guard

View File

@@ -1,5 +1,5 @@
/* Copyright (C) 2013
* Swift Project Community / Contributors
* swift Project Community / Contributors
*
* This file is part of swift Project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
@@ -8,26 +8,24 @@
*/
#include "columns.h"
#include <QModelIndex>
#include <QCoreApplication>
namespace BlackGui
{
namespace Models
{
CColumn::CColumn(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment, bool editable) :
m_columnName(headerName), m_alignment(alignment), m_propertyIndex(propertyIndex),
m_editable(editable), m_icon(false)
CColumn::CColumn(const QString &headerName, const QString &toolTip, const BlackMisc::CPropertyIndex &propertyIndex, CDefaultFormatter *formatter, bool editable) :
m_columnName(headerName), m_columnToolTip(toolTip), m_formatter(formatter ? formatter : new CDefaultFormatter()), m_propertyIndex(propertyIndex),
m_editable(editable)
{}
CColumn::CColumn(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, bool editable) :
m_columnName(headerName), m_alignment(-1), m_propertyIndex(propertyIndex),
m_editable(editable), m_icon(false)
CColumn::CColumn(const BlackMisc::CPropertyIndex &propertyIndex) :
m_formatter(new CPixmapFormatter()), m_propertyIndex(propertyIndex), m_editable(false)
{}
CColumn::CColumn(const BlackMisc::CPropertyIndex &propertyIndex, bool isIcon) :
m_alignment(-1), m_propertyIndex(propertyIndex),
m_editable(false), m_icon(isIcon)
CColumn::CColumn(const QString &toolTip, const BlackMisc::CPropertyIndex &propertyIndex) :
m_columnToolTip(toolTip), m_formatter(new CPixmapFormatter()), m_propertyIndex(propertyIndex), m_editable(false)
{}
const char *CColumn::getTranslationContextChar() const
@@ -40,10 +38,9 @@ namespace BlackGui
return this->m_columnName.toUtf8().constData();
}
QVariant CColumn::aligmentAsQVariant() const
const char *CColumn::getColumnToolTipChar() const
{
if (this->hasAlignment()) return QVariant(this->m_alignment);
return QVariant(Qt::AlignVCenter | Qt::AlignLeft); // default
return this->m_columnToolTip.toUtf8().constData();
}
QString CColumn::getColumnName(bool i18n) const
@@ -52,18 +49,30 @@ namespace BlackGui
return QCoreApplication::translate(this->getTranslationContextChar(), this->getColumnNameChar());
}
/*
* Header
*/
QString CColumn::getColumnToolTip(bool i18n) const
{
if (!i18n || this->m_columnToolTip.isEmpty()) return this->m_columnToolTip;
return QCoreApplication::translate(this->getTranslationContextChar(), this->getColumnToolTipChar());
}
CColumn CColumn::standardValueObject(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment)
{
return CColumn(headerName, propertyIndex, new CValueObjectFormatter(alignment));
}
CColumn CColumn::standardString(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment)
{
return CColumn(headerName, propertyIndex, new CStringFormatter(alignment));
}
// --------------- columns ----------------------------------------------
CColumns::CColumns(const QString &translationContext, QObject *parent) :
QObject(parent), m_translationContext(translationContext)
{
// void
}
/*
* Add column
*/
void CColumns::addColumn(CColumn column)
{
Q_ASSERT(!this->m_translationContext.isEmpty());
@@ -71,36 +80,24 @@ namespace BlackGui
this->m_columns.push_back(column);
}
/*
* Property index to name
*/
QString CColumns::propertyIndexToColumnName(const BlackMisc::CPropertyIndex &propertyIndex, bool i18n) const
{
int column = this->propertyIndexToColumn(propertyIndex);
return this->m_columns.at(column).getColumnName(i18n);
}
/*
* Index to name
*/
QString CColumns::columnToName(int column, bool i18n) const
{
Q_ASSERT(column >= 0 && column < this->m_columns.size());
Q_ASSERT(isValidColumn(column));
return this->m_columns.at(column).getColumnName(i18n);
}
/*
* Get property index
*/
BlackMisc::CPropertyIndex CColumns::columnToPropertyIndex(int column) const
{
Q_ASSERT(column >= 0 && column < this->m_columns.size());
Q_ASSERT(isValidColumn(column));
return this->m_columns.at(column).getPropertyIndex();
}
/*
* Property index to column
*/
int CColumns::propertyIndexToColumn(const BlackMisc::CPropertyIndex &propertyIndex) const
{
for (int i = 0; i < this->m_columns.size(); i++)
@@ -113,9 +110,6 @@ namespace BlackGui
return -1;
}
/*
* Name to property index
*/
int CColumns::nameToPropertyIndex(const QString &name) const
{
for (int i = 0; i < this->m_columns.size(); i++)
@@ -126,53 +120,29 @@ namespace BlackGui
return -1;
}
/*
* Size
*/
int CColumns::size() const
{
return this->m_columns.size();
}
/*
* Alignment?
*/
bool CColumns::hasAlignment(const QModelIndex &index) const
{
if (index.column() < 0 || index.column() >= this->m_columns.size()) return false;
if (!isValidColumn(index)) return false;
return this->m_columns.at(index.column()).hasAlignment();
}
/*
* Editable?
*/
bool CColumns::isEditable(const QModelIndex &index) const
{
if (index.column() < 0 || index.column() >= this->m_columns.size()) return false;
if (!isValidColumn(index)) return false;
return this->m_columns.at(index.column()).isEditable();
}
/*
* Is icon?
*/
bool CColumns::isIcon(const QModelIndex &index) const
const CDefaultFormatter *CColumns::getFormatter(const QModelIndex &index) const
{
if (index.column() < 0 || index.column() >= this->m_columns.size()) return false;
return this->m_columns.at(index.column()).isIcon();
if (!isValidColumn(index)) return nullptr;
return this->m_columns.at(index.column()).getFormatter();
}
/*
* Aligment as QVariant
*/
QVariant CColumns::aligmentAsQVariant(const QModelIndex &index) const
{
if (index.column() < 0 || index.column() >= this->m_columns.size()) return QVariant();
return this->m_columns.at(index.column()).aligmentAsQVariant();
}
/*
* Context
*/
const char *CColumns::getTranslationContextChar() const
{
return this->m_translationContext.toUtf8().constData();

View File

@@ -15,8 +15,11 @@
#include "blackmisc/valueobject.h" // for qHash overload, include before Qt stuff due GCC issue
#include "blackmisc/collection.h"
#include "blackmisc/propertyindex.h"
#include "columnformatters.h"
#include <QModelIndex>
#include <QObject>
#include <QHash>
#include <QScopedPointer>
namespace BlackGui
{
@@ -26,64 +29,63 @@ namespace BlackGui
class CColumn
{
public:
/*!
* Constructor
* \param headerName
* \param propertyIndex as in CValueObject::propertyByIndex
* \param alignment Qt::Alignment
* \param editable
*/
CColumn(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment = -1, bool editable = false);
//! Constructor
CColumn(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, CDefaultFormatter *formatter, bool editable = false) :
CColumn(headerName, "", propertyIndex, formatter, editable)
{ }
/*!
* Constructor
* \param headerName
* \param propertyIndex as in CValueObject::propertyByIndex
* \param editable
*/
CColumn(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, bool editable);
//! Constructor
CColumn(const QString &headerName, const QString &toolTip, const BlackMisc::CPropertyIndex &propertyIndex, CDefaultFormatter *formatter, bool editable = false);
/*!
* Constructor column is icon
* \remarks only make sense with isIcon as true
* \param propertyIndex as in CValueObject::propertyByIndex
* \param isIcon icon, should be used with true only
*/
CColumn(const BlackMisc::CPropertyIndex &propertyIndex, bool isIcon);
//! Constructor, icon with tool tip
CColumn(const QString &toolTip, const BlackMisc::CPropertyIndex &propertyIndex);
//! Constructor used for icons
CColumn(const BlackMisc::CPropertyIndex &propertyIndex);
//! Alignment for this column?
bool hasAlignment() const { return this->m_alignment >= 0; }
bool hasAlignment() const { return (!this->m_formatter.isNull() && this->m_formatter->hasAlignment()); }
//! Editable?
bool isEditable() const { return this->m_editable; }
//! Icon?
bool isIcon() const { return this->m_icon; }
//! Formatter
void setFormatter(CDefaultFormatter *formatter) { Q_ASSERT(formatter); m_formatter.reset(formatter); }
//! Formatter
const CDefaultFormatter *getFormatter() const { return this->m_formatter.data(); }
//! Aligment as QVariant
QVariant aligmentAsQVariant() const;
QVariant getAlignment() const;
//! Column name
QString getColumnName(bool i18n = false) const;
//! Column tooltip
QString getColumnToolTip(bool i18n = false) const;
//! Property index
const BlackMisc::CPropertyIndex &getPropertyIndex() const { return this->m_propertyIndex;}
//! Translation context
void setTranslationContext(const QString &translationContext)
{
this->m_translationContext = translationContext;
}
void setTranslationContext(const QString &translationContext) { this->m_translationContext = translationContext; }
//! Get a standard value object formatted column
static CColumn standardValueObject(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment = CDefaultFormatter::alignDefault());
//! Get a standard string object formatted column
static CColumn standardString(const QString &headerName, const BlackMisc::CPropertyIndex &propertyIndex, int alignment = CDefaultFormatter::alignDefault());
private:
QString m_translationContext;
QString m_columnName;
int m_alignment;
QString m_columnToolTip;
QSharedPointer<CDefaultFormatter> m_formatter;
BlackMisc::CPropertyIndex m_propertyIndex;
bool m_editable;
bool m_icon;
const char *getTranslationContextChar() const;
const char *getColumnNameChar() const;
const char *getColumnToolTipChar() const;
};
/*!
@@ -129,11 +131,26 @@ namespace BlackGui
//! Is this column editable?
bool isEditable(const QModelIndex &index) const;
//! Is icon?
bool isIcon(const QModelIndex &index) const;
//! Valid column?
bool isValidColumn(const QModelIndex &index) const
{
return (index.column() >= 0 && index.column() < this->m_columns.size());
}
//! Valid column?
bool isValidColumn(int column) const
{
return column >= 0 && column < this->m_columns.size();
}
//! Aligment as QVariant
QVariant aligmentAsQVariant(const QModelIndex &index) const;
QVariant getAlignment(const QModelIndex &index) const;
//! Translation context
const QString &getTranslationContext() const { return m_translationContext; }
//! Formatter
const CDefaultFormatter *getFormatter(const QModelIndex &index) const;
//! Column at position
const CColumn &at(int columnNumber) const { return this->m_columns.at(columnNumber); }

View File

@@ -28,10 +28,11 @@ namespace BlackGui
CKeyboardKeyListModel::CKeyboardKeyListModel(QObject *parent) :
CListModelBase<CSettingKeyboardHotkey, CSettingKeyboardHotkeyList>("ViewKeyboardKeyList", parent)
{
this->m_columns.addColumn(CColumn("key", CSettingKeyboardHotkey::IndexKeyAsStringRepresentation, true));
this->m_columns.addColumn(CColumn("modifier 1", CSettingKeyboardHotkey::IndexModifier1AsString, true));
this->m_columns.addColumn(CColumn("modifier 2", CSettingKeyboardHotkey::IndexModifier2AsString, true));
this->m_columns.addColumn(CColumn("function", CSettingKeyboardHotkey::IndexFunctionAsString));
const bool editable = true;
this->m_columns.addColumn(CColumn("key", CSettingKeyboardHotkey::IndexKeyAsStringRepresentation, new CStringFormatter(), editable));
this->m_columns.addColumn(CColumn("modifier 1", CSettingKeyboardHotkey::IndexModifier1AsString, new CStringFormatter(), editable));
this->m_columns.addColumn(CColumn("modifier 2", CSettingKeyboardHotkey::IndexModifier2AsString, new CStringFormatter(), editable));
this->m_columns.addColumn(CColumn::standardString("function", CSettingKeyboardHotkey::IndexFunctionAsString));
this->setSortColumnByPropertyIndex(CSettingKeyboardHotkey::IndexFunctionAsString);
this->m_sortOrder = Qt::AscendingOrder;

View File

@@ -57,11 +57,20 @@ namespace BlackGui
template <typename ObjectType, typename ContainerType> QVariant
CListModelBase<ObjectType, ContainerType>::headerData(int section, Qt::Orientation orientation, int role) const
{
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
if (orientation == Qt::Horizontal)
{
if (section < 0 || section >= this->m_columns.size()) return QVariant();
QString header = this->m_columns.at(section).getColumnName(false);
return QVariant(header);
if (role == Qt::DisplayRole)
{
if (section < 0 || section >= this->m_columns.size()) { return QVariant(); }
QString header = this->m_columns.at(section).getColumnName(false);
return QVariant(header);
}
else if (role == Qt::ToolTipRole)
{
if (section < 0 || section >= this->m_columns.size()) { return QVariant(); }
QString header = this->m_columns.at(section).getColumnToolTip(false);
return header.isEmpty() ? QVariant() : QVariant(header);
}
}
return QVariant();
}
@@ -72,33 +81,16 @@ namespace BlackGui
template <typename ObjectType, typename ContainerType>
QVariant CListModelBase<ObjectType, ContainerType>::data(const QModelIndex &index, int role) const
{
// checks
if (index.row() < 0 || index.row() >= this->m_container.size() ||
index.column() < 0 || index.column() >= this->columnCount(index))
{
return QVariant();
}
// check / init
if (!this->isValidIndex(index)) { return QVariant(); }
const CDefaultFormatter *formatter = this->m_columns.getFormatter(index);
Q_ASSERT(formatter);
if (!formatter) { return QVariant(); }
if (role == Qt::DisplayRole)
{
if (this->m_columns.isIcon(index)) return QVariant();
ObjectType obj = this->m_container[index.row()];
BlackMisc::CPropertyIndex propertyIndex = this->columnToPropertyIndex(index.column());
QString propertyString = obj.propertyByIndexAsString(propertyIndex, true);
return QVariant::fromValue(propertyString);
}
else if (role == Qt::DecorationRole)
{
if (!this->m_columns.isIcon(index)) return QVariant();
ObjectType obj = this->m_container[index.row()];
BlackMisc::CPropertyIndex propertyIndex = this->columnToPropertyIndex(index.column());
return obj.propertyByIndex(propertyIndex);
}
else if (role == Qt::TextAlignmentRole)
{
return this->m_columns.aligmentAsQVariant(index);
}
return QVariant();
//! Formatted data
ObjectType obj = this->m_container[index.row()];
BlackMisc::CPropertyIndex propertyIndex = this->columnToPropertyIndex(index.column());
return formatter->data(role, obj.propertyByIndex(propertyIndex));
}
/*
@@ -107,15 +99,11 @@ namespace BlackGui
template <typename ObjectType, typename ContainerType>
int CListModelBase<ObjectType, ContainerType>::update(const ContainerType &container)
{
ContainerType copyList = (container.size() > 1 && this->hasValidSortColumn() ?
this->sortListByColumn(container, this->getSortColumn(), this->m_sortOrder) :
container);
qDebug() << "update" << this->objectName() << "size" << container.size();
this->beginResetModel();
this->m_container.clear();
foreach(ObjectType object, copyList)
{
this->m_container.push_back(object);
}
this->m_container = (container.size() > 1 && this->hasValidSortColumn() ?
this->sortListByColumn(container, this->getSortColumn(), this->m_sortOrder) :
container);
this->endResetModel();
return this->m_container.size();
}
@@ -202,6 +190,7 @@ namespace BlackGui
BlackMisc::CPropertyIndex propertyIndex = this->m_columns.columnToPropertyIndex(column);
Q_ASSERT(!propertyIndex.isEmpty());
if (propertyIndex.isEmpty()) return list; // at release build do nothing
qDebug() << "sort" << this->objectName() << "column" << column << propertyIndex.toQString();
// sort the values
return list.sorted

View File

@@ -27,32 +27,6 @@ namespace BlackGui
template <typename ObjectType, typename ContainerType> class CListModelBase : public QAbstractListModel
{
protected:
ContainerType m_container; //!< used container
CColumns m_columns; //!< columns metadata
int m_sortedColumn; //!< current sort column
Qt::SortOrder m_sortOrder; //!< sort order (asc/desc)
/*!
* Constructor
* \param translationContext I18N context
* \param parent
*/
CListModelBase(const QString &translationContext, QObject *parent = nullptr)
: QAbstractListModel(parent), m_columns(translationContext), m_sortedColumn(-1), m_sortOrder(Qt::AscendingOrder)
{
// void
}
/*!
* Sort list by given order
* \param list used list
* \param column column inder
* \param order sort order (asccending / descending)
* \return
*/
ContainerType sortListByColumn(const ContainerType &list, int column, Qt::SortOrder order);
public:
//! Destructor
@@ -73,12 +47,17 @@ namespace BlackGui
return this->columnToPropertyIndex(index.column());
}
//! Set sort column
virtual void setSortColumn(int column)
//! Valid index (in range)
virtual bool isValidIndex(const QModelIndex &index) const
{
this->m_sortedColumn = column;
if (!index.isValid()) return false;
return (index.row() >= 0 && index.row() < this->m_container.size() &&
index.column() >= 0 && index.column() < this->columnCount(index));
}
//! Set sort column
virtual void setSortColumn(int column) { this->m_sortedColumn = column; }
/*!
* Set column for sorting
* \param propertyIndex index of column to be sorted by
@@ -89,28 +68,19 @@ namespace BlackGui
}
//! Get sort column property index
virtual int getSortColumn() const
{
return this->m_sortedColumn;
}
virtual int getSortColumn() const { return this->m_sortedColumn; }
//! Has valid sort column?
virtual bool hasValidSortColumn() const
{
return this->m_sortedColumn >=0 && this->m_sortedColumn < this->m_columns.size();
return this->m_sortedColumn >= 0 && this->m_sortedColumn < this->m_columns.size();
}
//! Get sort order
virtual Qt::SortOrder getSortOrder() const
{
return this->m_sortOrder;
}
virtual Qt::SortOrder getSortOrder() const { return this->m_sortOrder; }
//! Used container data
virtual const ContainerType &getContainer() const
{
return this->m_container;
}
virtual const ContainerType &getContainer() const { return this->m_container; }
//! \copydoc QAbstractListModel::data()
virtual QVariant data(const QModelIndex &index, int role) const override;
@@ -122,6 +92,7 @@ namespace BlackGui
Qt::ItemFlags flags(const QModelIndex &index) const override;
//! Update by new container
//! \remarks a sorting is performed if a valid sort column is set
virtual int update(const ContainerType &container);
//! Update single element
@@ -138,7 +109,7 @@ namespace BlackGui
{
if (index.row() < 0 || index.row() >= this->m_container.size())
{
const static ObjectType def;
const static ObjectType def; // default object
return def;
}
else
@@ -148,7 +119,7 @@ namespace BlackGui
}
//! \copydoc QAbstractListModel::sort()
virtual void sort(int column, Qt::SortOrder order);
virtual void sort(int column, Qt::SortOrder order) override;
//! Similar to ContainerType::push_back
virtual void push_back(const ObjectType &object);
@@ -161,6 +132,40 @@ namespace BlackGui
//! Clear the list
virtual void clear();
//! Translation context
virtual const QString &getTranslationContext() const
{
return m_columns.getTranslationContext();
}
protected:
ContainerType m_container; //!< used container
CColumns m_columns; //!< columns metadata
int m_sortedColumn; //!< current sort column
Qt::SortOrder m_sortOrder; //!< sort order (asc/desc)
/*!
* Constructor
* \param translationContext I18N context
* \param parent
*/
CListModelBase(const QString &translationContext, QObject *parent = nullptr)
: QAbstractListModel(parent), m_columns(translationContext), m_sortedColumn(-1), m_sortOrder(Qt::AscendingOrder)
{
// non unique default name, set translation context as default
this->setObjectName(translationContext);
}
/*!
* Sort container by given column / order. This is used by sort().
* \param list used list
* \param column column inder
* \param order sort order (ascending / descending)
* \return
*/
ContainerType sortListByColumn(const ContainerType &list, int column, Qt::SortOrder order);
};
}
}

View File

@@ -30,10 +30,10 @@ namespace BlackGui
this->m_columns.clear();
if (withIcon)
{
this->m_columns.addColumn(CColumn(CNameVariantPair::IndexPixmap, true));
this->m_columns.addColumn(CColumn(CNameVariantPair::IndexPixmap));
}
this->m_columns.addColumn(CColumn("name", CNameVariantPair::IndexName));
this->m_columns.addColumn(CColumn("value", CNameVariantPair::IndexVariant));
this->m_columns.addColumn(CColumn::standardString("name", CNameVariantPair::IndexName));
this->m_columns.addColumn(CColumn("value", CNameVariantPair::IndexVariant, new CDefaultFormatter()));
// default sort order
this->setSortColumnByPropertyIndex(CNameVariantPair::IndexName);

View File

@@ -21,12 +21,12 @@ namespace BlackGui
CServerListModel::CServerListModel(QObject *parent) :
CListModelBase("ViewServerList", parent)
{
this->m_columns.addColumn(CColumn("name", CServer::IndexName));
this->m_columns.addColumn(CColumn("description", CServer::IndexDescription));
this->m_columns.addColumn(CColumn("address", CServer::IndexAddress));
this->m_columns.addColumn(CColumn("port", CServer::IndexPort));
this->m_columns.addColumn(CColumn("realname", { CServer::IndexUser, CUser::IndexRealName}));
this->m_columns.addColumn(CColumn("userid", { CServer::IndexUser, CUser::IndexId}));
this->m_columns.addColumn(CColumn::standardString("name", CServer::IndexName));
this->m_columns.addColumn(CColumn::standardString("description", CServer::IndexDescription));
this->m_columns.addColumn(CColumn::standardString("address", CServer::IndexAddress));
this->m_columns.addColumn(CColumn::standardString("port", CServer::IndexPort));
this->m_columns.addColumn(CColumn::standardString("realname", { CServer::IndexUser, CUser::IndexRealName}));
this->m_columns.addColumn(CColumn::standardString("userid", { CServer::IndexUser, CUser::IndexId}));
// force strings for translation in resource files
(void)QT_TRANSLATE_NOOP("ViewServerList", "name");
@@ -61,5 +61,5 @@ namespace BlackGui
return CListModelBase::data(index, role);
}
}
}
}
} // class
} // namespace

View File

@@ -54,8 +54,7 @@ namespace BlackGui
}
//! \copydoc CListModelBase::data
virtual QVariant data(const QModelIndex &index, int role) const;
virtual QVariant data(const QModelIndex &index, int role) const override;
};
}
}

View File

@@ -26,10 +26,10 @@ namespace BlackGui
CStatusMessageListModel::CStatusMessageListModel(QObject *parent) :
CListModelBase<BlackMisc::CStatusMessage, BlackMisc::CStatusMessageList>("ViewStatusMessageList", parent)
{
this->m_columns.addColumn(CColumn("time", CStatusMessage::IndexTimestamp));
this->m_columns.addColumn(CColumn("", CStatusMessage::IndexSeverity, Qt::AlignCenter));
this->m_columns.addColumn(CColumn("message", CStatusMessage::IndexMessage));
this->m_columns.addColumn(CColumn("type", CStatusMessage::IndexTypeAsString));
this->m_columns.addColumn(CColumn("time", CStatusMessage::IndexTimestamp, new CDateTimeFormatter(CDateTimeFormatter::formatHms())));
this->m_columns.addColumn(CColumn("severity", CStatusMessage::IndexSeverity));
this->m_columns.addColumn(CColumn::standardString("message", CStatusMessage::IndexMessage));
this->m_columns.addColumn(CColumn::standardString("type", CStatusMessage::IndexTypeAsString));
this->m_sortedColumn = CStatusMessage::IndexTimestamp;
this->m_sortOrder = Qt::DescendingOrder;

View File

@@ -36,7 +36,7 @@ namespace BlackGui
virtual ~CStatusMessageListModel() {}
//! \copydoc CListModelBase::data
QVariant data(const QModelIndex &modelIndex, int role = Qt::DisplayRole) const;
QVariant data(const QModelIndex &modelIndex, int role = Qt::DisplayRole) const override;
};
}
}

View File

@@ -25,6 +25,7 @@ namespace BlackGui
CListModelBase<BlackMisc::Network::CUser, BlackMisc::Network::CUserList>("ViewUserList", parent), m_userMode(NotSet)
{
this->setUserMode(userMode);
// force strings for translation in resource files
(void)QT_TRANSLATE_NOOP("ViewUserList", "callsign");
(void)QT_TRANSLATE_NOOP("ViewUserList", "realname");
@@ -44,17 +45,24 @@ namespace BlackGui
{
case NotSet:
case UserDetailed:
this->m_columns.addColumn(CColumn(CUser::IndexPixmap, true));
this->m_columns.addColumn(CColumn("realname", CUser::IndexRealName));
this->m_columns.addColumn(CColumn("callsign", CUser::IndexCallsign));
this->m_columns.addColumn(CColumn("userid", CUser::IndexId));
// this->m_columns.addColumn(CUser::IndexEmail, "email");
this->m_columns.addColumn(CColumn(CUser::IndexIcon));
this->m_columns.addColumn(CColumn::standardString("realname", CUser::IndexRealName));
this->m_columns.addColumn(CColumn::standardValueObject("callsign", CUser::IndexCallsign));
this->m_columns.addColumn(CColumn::standardString("userid", CUser::IndexId));
// default sort order
this->setSortColumnByPropertyIndex(CUser::IndexRealName);
this->m_sortOrder = Qt::AscendingOrder;
break;
case UserShort:
this->m_columns.addColumn(CColumn(CUser::IndexPixmap, true));
this->m_columns.addColumn(CColumn("realname", CUser::IndexRealName));
this->m_columns.addColumn(CColumn("callsign", CUser::IndexCallsign));
this->m_columns.addColumn(CColumn(CUser::IndexIcon));
this->m_columns.addColumn(CColumn::standardString("realname", CUser::IndexRealName));
this->m_columns.addColumn(CColumn::standardValueObject("callsign", CUser::IndexCallsign));
// default sort order
this->setSortColumnByPropertyIndex(CUser::IndexCallsign);
this->m_sortOrder = Qt::AscendingOrder;
break;
default:

View File

@@ -351,10 +351,7 @@ namespace BlackMisc
case IndexVoiceRoom:
return QVariant(this->m_voiceRoom.propertyByIndex(index.copyFrontRemoved()));
default:
if (ICoordinateGeodetic::canHandleIndex(index))
{
return ICoordinateGeodetic::propertyByIndex(index);
}
if (ICoordinateGeodetic::canHandleIndex(index)) { return ICoordinateGeodetic::propertyByIndex(index); }
return CValueObject::propertyByIndex(index);
}
}
@@ -424,49 +421,8 @@ namespace BlackMisc
bool CAtcStation::isA(int metaTypeId) const
{
if (metaTypeId == qMetaTypeId<CAtcStation>()) { return true; }
return this->CValueObject::isA(metaTypeId);
}
/*
* Property as string by index
*/
QString CAtcStation::propertyByIndexAsString(const BlackMisc::CPropertyIndex &index, bool i18n) const
{
QVariant qv = this->propertyByIndex(index);
ColumnIndex i = index.frontCasted<ColumnIndex>();
// special treatment
// this is required as it is possible an ATC station is not containing all
// properties
switch (i)
{
case IndexFrequency:
if (!CComSystem::isValidCivilAviationFrequency(qv.value<CFrequency>()))
return "";
else
return qv.value<CFrequency>().valueRoundedWithUnit(3, i18n);
break;
case IndexDistance:
{
CLength distance = qv.value<CLength>();
if (distance.isNegativeWithEpsilonConsidered()) return "";
return distance.toQString(i18n);
}
case IndexBookedFrom:
case IndexBookedUntil:
{
QDateTime dt = qv.value<QDateTime>();
if (dt.isNull() || !dt.isValid()) return "";
return dt.toString("yyyy-MM-dd HH:mm");
break;
}
default:
break;
}
return BlackMisc::qVariantToString(qv, i18n);
}
} // namespace
} // namespace

View File

@@ -278,9 +278,6 @@ namespace BlackMisc
//! \copydoc CValueObject::setPropertyByIndex(variant, index)
virtual void setPropertyByIndex(const QVariant &variant, const CPropertyIndex &index) override;
//! \copydoc CValueObject::propertyByIndexAsString()
virtual QString propertyByIndexAsString(const BlackMisc::CPropertyIndex &index, bool i18n = false) const override;
//! \copydoc CValueObject::toJson
virtual QJsonObject toJson() const override;

View File

@@ -130,6 +130,7 @@ namespace BlackMisc
//! Valid civil aviation frequency?
static bool isValidCivilAviationFrequency(const BlackMisc::PhysicalQuantities::CFrequency &f)
{
if (f.isNull()) return false;
double fr = f.valueRounded(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz(), 3);
return fr >= 118.0 && fr <= 136.975;
}
@@ -137,10 +138,17 @@ namespace BlackMisc
//! Valid military aviation frequency?
static bool isValidMilitaryFrequency(const BlackMisc::PhysicalQuantities::CFrequency &f)
{
if (f.isNull()) return false;
double fr = f.valueRounded(BlackMisc::PhysicalQuantities::CFrequencyUnit::MHz(), 3);
return fr >= 220.0 && fr <= 399.95;
}
//! Valid COM frequency (either civil or military)
static bool isValidComFrequency(const BlackMisc::PhysicalQuantities::CFrequency &f)
{
return isValidCivilAviationFrequency(f) || isValidMilitaryFrequency(f);
}
/*!
* Round to channel spacing, set MHz as unit
* \see ChannelSpacing