We sometimes implement features that needs an up-to-date core to work correctly, but not always
a protocol bump is justified (because it's just a giant PITA). So we now have Client::coreFeatures()
that returns a bitmask of such optional features, which can be checked for at runtime and used to disable
client features if a too-old core is present.
Note that with every protocol bump the feature enum in quassel.h needs to be cleaned, and runtime checks
removed. Please mark all such places with a nice FIXME so we can find them easily.
#include <stdlib.h>
QPointer<Client> Client::instanceptr = 0;
+Quassel::Features Client::_coreFeatures = 0;
/*** Initialization/destruction ***/
return instance()->_mainUi;
}
+void Client::setCoreFeatures(Quassel::Features features) {
+ _coreFeatures = features;
+}
+
bool Client::isConnected() {
return instance()->_connected;
}
void Client::setDisconnectedFromCore() {
_connected = false;
+ _coreFeatures = 0;
+
emit disconnected();
emit coreConnectionStateChanged(false);
#include "bufferinfo.h"
#include "coreconnection.h"
+#include "quassel.h"
#include "types.h"
class Message;
static inline CoreAccountModel *coreAccountModel() { return instance()->_coreAccountModel; }
static inline CoreConnection *coreConnection() { return instance()->_coreConnection; }
static inline CoreAccount currentCoreAccount() { return coreConnection()->currentAccount(); }
+ static inline Quassel::Features coreFeatures() { return _coreFeatures; }
static bool isConnected();
static bool internalCore();
void init();
static void addNetwork(Network *);
+ static void setCoreFeatures(Quassel::Features);
static inline BufferSyncer *bufferSyncer() { return instance()->_bufferSyncer; }
static QPointer<Client> instanceptr;
QHash<IdentityId, Identity *> _identities;
bool _connected;
+ static Quassel::Features _coreFeatures;
QString _debugLogBuffer;
QTextStream _debugLog;
#endif
}
+Quassel::Features Quassel::features() {
+ Features feats = 0;
+ for(int i = 1; i <= NumFeatures; i<<=1)
+ feats |= (Feature) i;
+
+ return feats;
+}
+
const QString &Quassel::coreDumpFileName() {
if(_coreDumpFileName.isEmpty()) {
QDir configDir(configDirPath());
QString organizationDomain;
};
+ //! A list of features that are optional in core and/or client, but need runtime checking
+ /** Some features require an uptodate counterpart, but don't justify a protocol break.
+ * This is what we use this enum for. Add such features to it and check at runtime on the other
+ * side for their existence.
+ *
+ * This list should be cleaned up after every protocol break, as we can assume them to be present then.
+ */
+ enum Feature {
+ SynchronizedMarkerLine = 0x0001,
+
+ NumFeatures = 0x0001
+ };
+ Q_DECLARE_FLAGS(Features, Feature);
+
+ //! The features the current version of Quassel supports (\sa Feature)
+ /** \return An ORed list of all enum values in Feature
+ */
+ static Features features();
+
virtual ~Quassel();
static void setupBuildInfo(const QString &generated);
static QString _translationDirPath;
};
+Q_DECLARE_OPERATORS_FOR_FLAGS(Quassel::Features);
+
const Quassel::BuildInfo & Quassel::buildInfo() { return _buildInfo; }
Quassel::RunMode Quassel::runMode() { return _runMode; }
void Quassel::setRunMode(Quassel::RunMode mode) { _runMode = mode; }
.arg(Quassel::buildInfo().buildDate)
.arg(updays).arg(uphours,2,10,QChar('0')).arg(upmins,2,10,QChar('0')).arg(startTime().toString(Qt::TextDate));
+ reply["CoreFeatures"] = (int)Quassel::features();
+
#ifdef HAVE_SSL
SslServer *sslServer = qobject_cast<SslServer *>(&_server);
QSslSocket *sslSocket = qobject_cast<QSslSocket *>(socket);