- cd build
- if [ "$QT_VERSION" = "qt4" ]; then cmake ..; fi
- if [ "$QT_VERSION" = "qt5" ]; then source /opt/qt52/bin/qt52-env.sh && cmake -DUSE_QT5=ON ..; fi
- - make
\ No newline at end of file
+ - make
+
+matrix:
+ exclude:
+ - compiler: clang
+ env: QT_VERSION=qt4
# General setup
#####################################################################
-cmake_minimum_required(VERSION 2.8.9) # You'll need at least 2.8.12 for KDE Frameworks integration
project(QuasselIRC)
# Versions
include(QuasselCompileSettings)
include(QuasselMacros)
-# Setting COMPILE_DEFINITIONS_<CONFIG> is deprecated since CMake 3.0 in favor of generator expressions.
-# These have existed since CMake 2.8.10; until we depend on that, we have to explicitly enable the old policy.
-if (CMAKE_MAJOR_VERSION GREATER 2)
- cmake_policy(SET CMP0043 OLD)
-endif()
# Options and variables that can be set on the command line
#####################################################################
endif()
+# Setup CMake
+#####################################################################
+
+if (USE_QT5 AND WITH_KDE)
+ cmake_minimum_required(VERSION 2.8.12)
+else()
+ cmake_minimum_required(VERSION 2.8.9)
+endif()
+
+# Setting COMPILE_DEFINITIONS_<CONFIG> is deprecated since CMake 3.0 in favor of generator expressions.
+# These have existed since CMake 2.8.10; until we depend on that, we have to explicitly enable the old policy.
+if (CMAKE_MAJOR_VERSION GREATER 2)
+ cmake_policy(SET CMP0043 OLD)
+endif()
+
+
# Simplify later checks
#####################################################################
add_definitions(-DHAVE_QT5)
else()
message(STATUS "Building for Qt4...")
- if (BUILD_GUI)
- set(QT_MIN_VERSION "4.6.0")
- else()
- set(QT_MIN_VERSION "4.4.0")
- endif()
+ set(QT_MIN_VERSION "4.8.0")
# Select a Qt installation here, if you don't want to use system Qt
if(QT_PATH)
endif()
if (WITH_KDE)
- find_package(KF5TextWidgets QUIET)
- set_package_properties(KF5TextWidgets PROPERTIES TYPE REQUIRED
- URL "http://inqlude.org/libraries/ktextwidgets.html"
- DESCRIPTION "framework providing an assortment of widgets for displaying and editing text"
- PURPOSE "Allows to use extra features provided by KDE Frameworks in input widgets"
+ find_package(KF5 COMPONENTS ConfigWidgets CoreAddons Notifications NotifyConfig TextWidgets XmlGui QUIET)
+ set_package_properties(KF5 PROPERTIES TYPE REQUIRED
+ URL "http://www.kde.org"
+ DESCRIPTION "KDE Frameworks"
+ PURPOSE "Required for integration into the Plasma desktop"
)
endif()
endif(BUILD_GUI)
+
if (BUILD_CORE)
find_package(Qt5Script QUIET)
set_package_properties(Qt5Script PROPERTIES TYPE REQUIRED
DESCRIPTION "the database support module for Qt5"
)
- # While QCA2 seems to support Qt5, it is not actually co-installable or distinguishable from the Qt4 version...
- # In order to avoid linking against the Qt4 version (which is probably the one installed), disable this for now
- #find_package(QCA2 QUIET)
- #set_package_properties(QCA2 PROPERTIES TYPE RECOMMENDED
- # URL "https://projects.kde.org/projects/kdesupport/qca"
- # DESCRIPTION "Qt Cryptographic Architecture"
- # PURPOSE "Required for encryption support"
- #)
+ find_package(QCA2-QT5)
+ set_package_properties(QCA2-QT5 PROPERTIES TYPE RECOMMENDED
+ URL "https://projects.kde.org/projects/kdesupport/qca"
+ DESCRIPTION "Qt Cryptographic Architecture"
+ PURPOSE "Required for encryption support"
+ )
endif(BUILD_CORE)
DESCRIPTION "contains tools for handling translation files"
PURPOSE "Required for having translations"
)
+
# Some Qt5 versions do not define a target for lconvert, so we need to find it ourselves
if (Qt5LinguistTools_FOUND)
if (NOT TARGET Qt5::lconvert AND TARGET Qt5::lrelease)
add_definitions(-U__STRICT_ANSI__)
endif()
+# Sanitize compiler flags - old versions of KDE set -ansi, which breaks -std=c++11
+if (CMAKE_COMPILER_IS_GNUCXX)
+ string(REPLACE "-ansi" "" CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS})
+endif()
+
# Setup KDE / KDE Frameworks
#####################################################################
--- /dev/null
+# - Try to find QCA2 (Qt Cryptography Architecture 2) for QT5
+# Once done this will define
+#
+# QCA2-QT5_FOUND - system has QCA2-QT5
+# QCA2-QT5_INCLUDE_DIR - the QCA2-QT5 include directory
+# QCA2-QT5_LIBRARIES - the libraries needed to use QCA2-QT5
+# QCA2-QT5_DEFINITIONS - Compiler switches required for using QCA2-QT5
+#
+# use pkg-config to get the directories and then use these values
+# in the FIND_PATH() and FIND_LIBRARY() calls
+
+# Copyright (c) 2006, Michael Larouche, <michael.larouche@kdemail.net>
+#
+# Redistribution and use is allowed according to the terms of the BSD license.
+# For details see the accompanying COPYING-CMAKE-SCRIPTS file.
+
+include(FindLibraryWithDebug)
+
+if (QCA2-QT5_INCLUDE_DIR AND QCA2-QT5_LIBRARIES)
+
+ # in cache already
+ set(QCA2-QT5_FOUND TRUE)
+
+else (QCA2-QT5_INCLUDE_DIR AND QCA2-QT5_LIBRARIES)
+
+
+ if (NOT WIN32)
+ find_package(PkgConfig)
+ pkg_check_modules(PC_QCA2-QT5 QUIET qca2-qt5)
+ set(QCA2-QT5_DEFINITIONS ${PC_QCA2-QT5_CFLAGS_OTHER})
+ endif (NOT WIN32)
+
+ find_library_with_debug(QCA2-QT5_LIBRARIES
+ WIN32_DEBUG_POSTFIX d
+ NAMES qca-qt5
+ HINTS ${PC_QCA2-QT5_LIBDIR} ${PC_QCA2-QT5_LIBRARY_DIRS}
+ )
+
+ find_path(QCA2-QT5_INCLUDE_DIR QtCrypto
+ HINTS ${PC_QCA2-QT5_INCLUDEDIR} ${PC_QCA2-QT5_INCLUDE_DIRS}
+ PATH_SUFFIXES QtCrypto)
+
+ include(FindPackageHandleStandardArgs)
+ find_package_handle_standard_args(QCA2-QT5 DEFAULT_MSG QCA2-QT5_LIBRARIES QCA2-QT5_INCLUDE_DIR)
+
+ mark_as_advanced(QCA2-QT5_INCLUDE_DIR QCA2-QT5_LIBRARIES)
+
+endif (QCA2-QT5_INCLUDE_DIR AND QCA2-QT5_LIBRARIES)
install(FILES quassel.desktop DESTINATION ${CMAKE_INSTALL_APPDIR})
endif()
- if (KDE4_FOUND)
+ if (WITH_KDE4)
install(FILES quassel.notifyrc DESTINATION ${CMAKE_INSTALL_DATADIR}/quassel)
endif()
+
+ if (WITH_KF5)
+ install(FILES quassel.notifyrc DESTINATION ${CMAKE_INSTALL_KNOTIFY5RCDIR})
+ endif()
endif()
if (EMBED_DATA)
TryExec=quassel
Exec=quassel
Categories=Qt;Network;Chat;IRCClient;
+X-DBUS-ServiceName=org.quassel-irc.quassel
TryExec=quasselclient
Exec=quasselclient
Categories=Qt;Network;Chat;IRCClient;
+X-DBUS-ServiceName=org.quassel-irc.quasselclient
opendir (SIZEDIR, "$oxygen/$sizestr") or die "Could not open dir $sizestr\n";
foreach my $cat (readdir SIZEDIR) {
next if $cat eq '.' or $cat eq '..';
- #system "mkdir -p $output/$sizestr/$cat" and die "Could not create category dir\n";
- system "mkdir -p $output/scalable/$cat" and die "Could not create category dir\n";
opendir (CATDIR, "$oxygen/$sizestr/$cat") or die "Could not open category dir\n";
foreach my $icon (readdir CATDIR) {
$icon =~ s/\.png$//;
print "Warning: Missing icon $icon\n";
}
+# Copy license etc.
+system "cp $oxygen/AUTHORS $oxygen/CONTRIBUTING $oxygen/COPYING $oxygen/index.theme $output/";
+
# Generate .qrc
my @file_list;
generate_qrc($output, $qrcfile_kde);
-# Copy license etc.
-system "cp $oxygen/AUTHORS $oxygen/CONTRIBUTING $oxygen/COPYING $oxygen/index.theme $output/";
-
print "Done.\n";
########################################################################################
}
sub push_icon_path {
- return unless /\.png$/;
+ return unless /\.png$/ or /^index.theme$/;
push @file_list, " <file>$File::Find::name</file>";
}
<RCC>
<qresource prefix="/icons">
+ <file>oxygen/index.theme</file>
<file>oxygen/22x22/actions/irc-voice.png</file>
<file>oxygen/22x22/actions/go-next.png</file>
<file>oxygen/22x22/actions/im-user.png</file>
add_definitions(-DWITH_OXYGEN)
endif()
+# For KAboutData
+if (WITH_KF5)
+ set(CLIENT_LIBRARIES ${CLIENT_LIBRARIES} KF5::CoreAddons)
+endif()
+
# Needed for showing the cli option if appropriate
if (HAVE_SYSLOG)
add_definitions(-DHAVE_SYSLOG)
clientcoreinfo.h
)
-if (KDE4_FOUND)
- include_directories(${KDE4_INCLUDES})
- add_definitions(-DHAVE_KDE ${KDE4_DEFINITIONS})
-endif()
-
if (USE_QT5)
list(APPEND qt_modules Widgets)
endif()
qt_use_modules(mod_client Network Core Gui ${qt_modules})
target_link_libraries(mod_client mod_common)
-
-if (KDE4_FOUND)
- target_link_libraries(mod_client ${KDE4_SOLID_LIBS})
-endif()
#include "quassel.h"
#include "signalproxy.h"
#include "util.h"
+#include "clientauthhandler.h"
#include <stdio.h>
#include <stdlib.h>
connect(bufferSyncer(), SIGNAL(buffersPermanentlyMerged(BufferId, BufferId)), _messageModel, SLOT(buffersPermanentlyMerged(BufferId, BufferId)));
connect(bufferSyncer(), SIGNAL(bufferMarkedAsRead(BufferId)), SIGNAL(bufferMarkedAsRead(BufferId)));
connect(networkModel(), SIGNAL(requestSetLastSeenMsg(BufferId, MsgId)), bufferSyncer(), SLOT(requestSetLastSeenMsg(BufferId, const MsgId &)));
- signalProxy()->synchronize(bufferSyncer());
+
+ SignalProxy *p = signalProxy();
+
+ if ((Client::coreFeatures() & Quassel::PasswordChange)) {
+ p->attachSignal(this, SIGNAL(clientChangePassword(QString)));
+ }
+
+ p->synchronize(bufferSyncer());
// create a new BufferViewManager
Q_ASSERT(!_bufferViewManager);
- _bufferViewManager = new ClientBufferViewManager(signalProxy(), this);
+ _bufferViewManager = new ClientBufferViewManager(p, this);
connect(_bufferViewManager, SIGNAL(initDone()), _bufferViewOverlay, SLOT(restore()));
// create AliasManager
Q_ASSERT(!_aliasManager);
_aliasManager = new ClientAliasManager(this);
connect(aliasManager(), SIGNAL(initDone()), SLOT(sendBufferedUserInput()));
- signalProxy()->synchronize(aliasManager());
+ p->synchronize(aliasManager());
// create NetworkConfig
Q_ASSERT(!_networkConfig);
_networkConfig = new NetworkConfig("GlobalNetworkConfig", this);
- signalProxy()->synchronize(networkConfig());
+ p->synchronize(networkConfig());
// create IgnoreListManager
Q_ASSERT(!_ignoreListManager);
_ignoreListManager = new ClientIgnoreListManager(this);
- signalProxy()->synchronize(ignoreListManager());
+ p->synchronize(ignoreListManager());
Q_ASSERT(!_transferManager);
_transferManager = new ClientTransferManager(this);
- signalProxy()->synchronize(transferManager());
+ p->synchronize(transferManager());
// trigger backlog request once all active bufferviews are initialized
connect(bufferViewOverlay(), SIGNAL(initDone()), this, SLOT(requestInitialBacklog()));
bufferSyncer()->requestMarkBufferAsRead(id);
}
+void Client::changePassword(QString newPassword) {
+ CoreAccount account = currentCoreAccount();
+ account.setPassword(newPassword);
+ coreAccountModel()->createOrUpdateAccount(account);
+ coreAccountModel()->save();
+ emit clientChangePassword(newPassword);
+}
+
#if QT_VERSION < 0x050000
void Client::logMessage(QtMsgType type, const char *msg)
*/
void bufferMarkedAsRead(BufferId id);
+ void clientChangePassword(QString password);
+
public slots:
void disconnectFromCore();
void markBufferAsRead(BufferId id);
+ void changePassword(QString newPassword);
+
private slots:
void setSyncedToCore();
void setDisconnectedFromCore();
_probing = true;
QDataStream stream(socket()); // stream handles the endianness for us
+ stream.setVersion(QDataStream::Qt_4_2);
quint32 magic = Protocol::magic;
#ifdef HAVE_SSL
CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettings::networkDetectionMode()
{
-#ifdef HAVE_KDE4
- NetworkDetectionMode def = UseSolid;
-#else
- NetworkDetectionMode def = UsePingTimeout;
-#endif
- return (NetworkDetectionMode)localValue("NetworkDetectionMode", def).toInt();
+ auto mode = localValue("NetworkDetectionMode", UseQNetworkConfigurationManager).toInt();
+ if (mode == 0)
+ mode = UseQNetworkConfigurationManager; // UseSolid is gone, map that to the new default
+ return static_cast<NetworkDetectionMode>(mode);
}
{
public:
enum NetworkDetectionMode {
- UseSolid,
+ UseQNetworkConfigurationManager = 1, // UseSolid is gone
UsePingTimeout,
NoActiveDetection
};
_reconnectTimer.setSingleShot(true);
connect(&_reconnectTimer, SIGNAL(timeout()), SLOT(reconnectTimeout()));
-#ifdef HAVE_KDE4
- connect(Solid::Networking::notifier(), SIGNAL(statusChanged(Solid::Networking::Status)),
- SLOT(solidNetworkStatusChanged(Solid::Networking::Status)));
-#endif
+ _qNetworkConfigurationManager = new QNetworkConfigurationManager(this);
+ connect(_qNetworkConfigurationManager, SIGNAL(onlineStateChanged(bool)), SLOT(onlineStateChanged(bool)));
CoreConnectionSettings s;
s.initAndNotify("PingTimeoutInterval", this, SLOT(pingTimeoutIntervalChanged(QVariant)), 60);
if (!_peer) {
CoreConnectionSettings s;
if (_wantReconnect && s.autoReconnect()) {
-#ifdef HAVE_KDE4
- // If using Solid, we don't want to reconnect if we're offline
- if (s.networkDetectionMode() == CoreConnectionSettings::UseSolid) {
- if (Solid::Networking::status() != Solid::Networking::Connected
- && Solid::Networking::status() != Solid::Networking::Unknown) {
+ // If using QNetworkConfigurationManager, we don't want to reconnect if we're offline
+ if (s.networkDetectionMode() == CoreConnectionSettings::UseQNetworkConfigurationManager) {
+ if (!_qNetworkConfigurationManager->isOnline()) {
return;
- }
+ }
}
-#endif /* HAVE_KDE4 */
-
reconnectToCore();
}
}
}
-#ifdef HAVE_KDE4
-
-void CoreConnection::solidNetworkStatusChanged(Solid::Networking::Status status)
+void CoreConnection::onlineStateChanged(bool isOnline)
{
CoreConnectionSettings s;
- if (s.networkDetectionMode() != CoreConnectionSettings::UseSolid)
+ if (s.networkDetectionMode() != CoreConnectionSettings::UseQNetworkConfigurationManager)
return;
- switch (status) {
- case Solid::Networking::Unknown:
- case Solid::Networking::Connected:
- //qDebug() << "Solid: Network status changed to connected or unknown";
+ if(isOnline) {
+ // qDebug() << "QNetworkConfigurationManager reports Online";
if (state() == Disconnected) {
if (_wantReconnect && s.autoReconnect()) {
reconnectToCore();
}
}
- break;
- case Solid::Networking::Disconnecting:
- case Solid::Networking::Unconnected:
+ } else {
+ // qDebug() << "QNetworkConfigurationManager reports Offline";
if (state() != Disconnected && !isLocalConnection())
disconnectFromCore(tr("Network is down"), true);
- break;
- default:
- break;
}
}
-#endif
bool CoreConnection::isEncrypted() const
{
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#ifndef CORECONNECTION_H_
-#define CORECONNECTION_H_
+#pragma once
-#include "QPointer"
-#include "QTimer"
+#include <QNetworkConfigurationManager>
+#include <QPointer>
+#include <QTimer>
#ifdef HAVE_SSL
# include <QSslSocket>
# include <QTcpSocket>
#endif
-#ifdef HAVE_KDE4
-# include <Solid/Networking>
-#endif
-
#include "coreaccount.h"
#include "remotepeer.h"
#include "types.h"
void reconnectIntervalChanged(const QVariant &interval);
void reconnectTimeout();
-#ifdef HAVE_KDE4
- void solidNetworkStatusChanged(Solid::Networking::Status status);
-#endif
+ void onlineStateChanged(bool isOnline);
private:
QPointer<ClientAuthHandler> _authHandler;
CoreAccount _account;
CoreAccountModel *accountModel() const;
+ QPointer<QNetworkConfigurationManager> _qNetworkConfigurationManager;
+
friend class CoreConfigWizard;
};
inline CoreConnection::ConnectionState CoreConnection::state() const { return _state; }
inline bool CoreConnection::isConnected() const { return state() >= Connected; }
inline CoreAccount CoreConnection::currentAccount() const { return _account; }
-
-#endif
buffersyncer.cpp
bufferviewconfig.cpp
bufferviewmanager.cpp
- cliparser.cpp
compressor.cpp
ctcpevent.cpp
event.cpp
coreinfo.h
)
+if (USE_QT5)
+ list(APPEND SOURCES qt5cliparser.cpp)
+else()
+ list(APPEND SOURCES cliparser.cpp)
+endif()
-if (QCA2_FOUND)
+if (QCA2_FOUND OR QCA2-QT5_FOUND)
set(SOURCES ${SOURCES} keyevent.cpp)
endif()
}
- inline void addOption(const QString &longName, const char shortName = 0, const QString &help = QString(), const QString &def = QString())
+ inline void addOption(const QString &longName, const char shortName = 0, const QString &help = QString(), const QString &valueName = QString(), const QString &def = QString())
{
- addArgument(longName, CliParserArg(CliParserArg::CliArgOption, shortName, help, def));
+ addArgument(longName, CliParserArg(CliParserArg::CliArgOption, shortName, help, valueName, def));
}
CliArgOption
};
- CliParserArg(const CliArgType _type = CliArgInvalid, const char _shortName = 0, const QString _help = QString(), const QString _def = QString())
- : type(_type),
- shortName(_shortName),
- help(_help),
- def(_def),
- value(QString()),
- boolValue(false) {};
+ CliParserArg(const CliArgType type = CliArgInvalid, const char shortName = 0, const QString &help = QString(), const QString &valueName = QString(), const QString def = QString())
+ : type(type)
+ , shortName(shortName)
+ , help(help)
+ , valueName(valueName)
+ , def(def)
+ {};
CliArgType type;
char shortName;
QString help;
+ QString valueName;
QString def;
QString value;
- bool boolValue;
+ bool boolValue = false;
};
virtual void addArgument(const QString &longName, const CliParserArg &arg) = 0;
}
-void CliParser::addArgument(const QString &longName_, const CliParserArg &arg)
+void CliParser::addArgument(const QString &longName, const CliParserArg &arg)
{
- QString longName = longName_;
- longName.remove(QRegExp("\\s*<.*>\\s*")); // KCmdLineArgs takes args of the form "arg <defval>"
if (argsMap.contains(longName)) qWarning() << "Warning: Multiple definition of argument" << longName;
if (arg.shortName != 0 && !lnameOfShortArg(arg.shortName).isNull())
qWarning().nospace() << "Warning: Redefining shortName '" << arg.shortName << "' for " << longName << " previously defined for " << lnameOfShortArg(arg.shortName);
}
else output.append(" ");
lnameField.append(" --").append(arg.key());
- if (arg.value().type == CliParserArg::CliArgOption) {
- lnameField.append("=[").append(arg.key().toUpper()).append("]");
+ if (arg.value().type == CliParserArg::CliArgOption && !arg.value().valueName.isEmpty()) {
+ lnameField.append("=<").append(arg.value().valueName).append(">");
}
output.append(lnameField.leftJustified(lnameFieldSize));
if (!arg.value().help.isEmpty()) {
#include <cstdlib>
+#include <QTextCodec>
+
#ifdef BUILD_CORE
# include "coreapplication.h"
#elif defined BUILD_QTUI
+# include "aboutdata.h"
# include "qtuiapplication.h"
#elif defined BUILD_MONO
+# include "aboutdata.h"
# include "monoapplication.h"
#else
#if defined HAVE_KDE4 && defined BUILD_CORE
# undef HAVE_KDE4
#endif
+// We don't want quasselcore to depend on KDE
+#if defined HAVE_KF5 && defined BUILD_CORE
+# undef HAVE_KF5
+#endif
#ifdef HAVE_KDE4
# include <KAboutData>
# include "kcmdlinewrapper.h"
+#elif defined HAVE_KF5
+# include <KCoreAddons/KAboutData>
+# include <KCoreAddons/Kdelibs4ConfigMigrator>
+# include "qt5cliparser.h"
+#elif defined HAVE_QT5
+# include "qt5cliparser.h"
+#else
+# include "cliparser.h"
#endif
#if !defined(BUILD_CORE) && defined(STATIC)
Q_IMPORT_PLUGIN(qgif)
#endif
-#include "cliparser.h"
#include "quassel.h"
int main(int argc, char **argv)
{
+#if QT_VERSION < 0x050000
+ // All our source files are in UTF-8, and Qt5 even requires that
+ QTextCodec::setCodecForCStrings(QTextCodec::codecForName("UTF-8"));
+ QTextCodec::setCodecForTr(QTextCodec::codecForName("UTF-8"));
+#endif
+
Quassel::setupBuildInfo();
QCoreApplication::setApplicationName(Quassel::buildInfo().applicationName);
+ QCoreApplication::setApplicationVersion(Quassel::buildInfo().plainVersionString);
QCoreApplication::setOrganizationName(Quassel::buildInfo().organizationName);
QCoreApplication::setOrganizationDomain(Quassel::buildInfo().organizationDomain);
# endif
#endif
+ // Migrate settings from KDE4 to KF5 if appropriate
+#ifdef HAVE_KF5
+ Kdelibs4ConfigMigrator migrator(QCoreApplication::applicationName());
+ migrator.setConfigFiles(QStringList() << "quasselrc" << "quassel.notifyrc");
+ migrator.migrate();
+#endif
+
AbstractCliParser *cliParser;
#ifdef HAVE_KDE4
// We need to init KCmdLineArgs first
- // TODO: build an AboutData compat class to replace our aboutDlg strings
KAboutData aboutData("quassel", "kdelibs4", ki18n("Quassel IRC"), Quassel::buildInfo().plainVersionString.toUtf8(),
ki18n("A modern, distributed IRC client"));
aboutData.addLicense(KAboutData::License_GPL_V2);
KCmdLineArgs::init(argc, argv, &aboutData);
cliParser = new KCmdLineWrapper();
+#elif defined HAVE_QT5
+ cliParser = new Qt5CliParser();
#else
cliParser = new CliParser();
#endif
// Initialize CLI arguments
// NOTE: We can't use tr() at this point, since app is not yet created
+ // TODO: Change this once we get rid of KDE4 and can initialize the parser after creating the app
// put shared client&core arguments here
cliParser->addSwitch("debug", 'd', "Enable debug output");
cliParser->addSwitch("help", 'h', "Display this help and exit");
cliParser->addSwitch("version", 'v', "Display version information");
#ifdef BUILD_QTUI
- cliParser->addOption("configdir <path>", 'c', "Specify the directory holding the client configuration");
+ cliParser->addOption("configdir", 'c', "Specify the directory holding the client configuration", "path");
#else
- cliParser->addOption("configdir <path>", 'c', "Specify the directory holding configuration files, the SQlite database and the SSL certificate");
+ cliParser->addOption("configdir", 'c', "Specify the directory holding configuration files, the SQlite database and the SSL certificate", "path");
#endif
- cliParser->addOption("datadir <path>", 0, "DEPRECATED - Use --configdir instead");
+ cliParser->addOption("datadir", 0, "DEPRECATED - Use --configdir instead", "path");
#ifndef BUILD_CORE
// put client-only arguments here
- cliParser->addOption("icontheme <theme>", 0, "Override the system icon theme ('oxygen' is recommended)");
- cliParser->addOption("qss <file.qss>", 0, "Load a custom application stylesheet");
+ cliParser->addOption("icontheme", 0, "Override the system icon theme ('oxygen' is recommended)", "theme");
+ cliParser->addOption("qss", 0, "Load a custom application stylesheet", "file.qss");
cliParser->addSwitch("debugbufferswitches", 0, "Enables debugging for bufferswitches");
cliParser->addSwitch("debugmodel", 0, "Enables debugging for models");
cliParser->addSwitch("hidewindow", 0, "Start the client minimized to the system tray");
#endif
#ifndef BUILD_QTUI
// put core-only arguments here
- cliParser->addOption("listen <address>[,<address[,...]]>", 0, "The address(es) quasselcore will listen on", "::,0.0.0.0");
- cliParser->addOption("port <port>", 'p', "The port quasselcore will listen at", QString("4242"));
+ cliParser->addOption("listen", 0, "The address(es) quasselcore will listen on", "<address>[,<address>[,...]]", "::,0.0.0.0");
+ cliParser->addOption("port", 'p', "The port quasselcore will listen at", "port", "4242");
cliParser->addSwitch("norestore", 'n', "Don't restore last core's state");
- cliParser->addOption("loglevel <level>", 'L', "Loglevel Debug|Info|Warning|Error", "Info");
+ cliParser->addOption("loglevel", 'L', "Loglevel Debug|Info|Warning|Error", "level", "Info");
#ifdef HAVE_SYSLOG
cliParser->addSwitch("syslog", 0, "Log to syslog");
#endif
- cliParser->addOption("logfile <path>", 'l', "Log to a file");
- cliParser->addOption("select-backend <backendidentifier>", 0, "Switch storage backend (migrating data if possible)");
+ cliParser->addOption("logfile", 'l', "Log to a file", "path");
+ cliParser->addOption("select-backend", 0, "Switch storage backend (migrating data if possible)", "backendidentifier");
cliParser->addSwitch("add-user", 0, "Starts an interactive session to add a new core user");
- cliParser->addOption("change-userpass <username>", 0, "Starts an interactive session to change the password of the user identified by username");
+ cliParser->addOption("change-userpass", 0, "Starts an interactive session to change the password of the user identified by <username>", "username");
cliParser->addSwitch("oidentd", 0, "Enable oidentd integration");
- cliParser->addOption("oidentd-conffile <file>", 0, "Set path to oidentd configuration file");
+ cliParser->addOption("oidentd-conffile", 0, "Set path to oidentd configuration file", "file");
#ifdef HAVE_SSL
cliParser->addSwitch("require-ssl", 0, "Require SSL for client connections");
#endif
}
#endif
- if (!app.init()) return EXIT_FAILURE;
+#ifdef HAVE_KF5
+ // FIXME: This should be done after loading the translation catalogue, but still in main()
+ AboutData aboutData;
+ AboutData::setQuasselPersons(&aboutData);
+ KAboutData::setApplicationData(aboutData.kAboutData());
+#endif
+
+ if (!app.init())
+ return EXIT_FAILURE;
+
return app.exec();
}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2015 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "qt5cliparser.h"
+
+#include <QCoreApplication>
+#include <QDebug>
+
+bool Qt5CliParser::init(const QStringList &arguments)
+{
+ _qCliParser.addHelpOption();
+ _qCliParser.addVersionOption();
+ _qCliParser.setApplicationDescription(QCoreApplication::translate("CliParser", "Quassel IRC is a modern, distributed IRC client."));
+
+ _qCliParser.process(arguments);
+ return true; // process() does error handling by itself
+}
+
+
+bool Qt5CliParser::isSet(const QString &longName)
+{
+
+ return _qCliParser.isSet(longName);
+}
+
+
+QString Qt5CliParser::value(const QString &longName)
+{
+ return _qCliParser.value(longName);
+}
+
+
+void Qt5CliParser::usage()
+{
+ _qCliParser.showHelp();
+}
+
+
+void Qt5CliParser::addArgument(const QString &longName, const AbstractCliParser::CliParserArg &arg)
+{
+ QStringList names(longName);
+ if (arg.shortName != 0)
+ names << QString(arg.shortName);
+
+ switch(arg.type) {
+ case CliParserArg::CliArgSwitch:
+ _qCliParser.addOption(QCommandLineOption(names, arg.help));
+ break;
+ case CliParserArg::CliArgOption:
+ _qCliParser.addOption(QCommandLineOption(names, arg.help, arg.valueName, arg.def));
+ break;
+ default:
+ qWarning() << "Warning: Unrecognized argument:" << longName;
+ }
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2015 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#pragma once
+
+#include <QCommandLineParser>
+
+#include "abstractcliparser.h"
+
+
+class Qt5CliParser : public AbstractCliParser
+{
+public:
+ bool init(const QStringList &arguments = QStringList());
+
+ QString value(const QString &longName);
+ bool isSet(const QString &longName);
+ void usage();
+
+private:
+ void addArgument(const QString &longName, const CliParserArg &arg);
+
+ QCommandLineParser _qCliParser;
+
+};
QStringList Quassel::findDataDirPaths() const
{
- QStringList dataDirNames = QString(qgetenv("XDG_DATA_DIRS")).split(':', QString::SkipEmptyParts);
+ // We don't use QStandardPaths for now, as we still need to provide fallbacks for Qt4 and
+ // want to stay consistent.
- if (!dataDirNames.isEmpty()) {
- for (int i = 0; i < dataDirNames.count(); i++)
- dataDirNames[i].append("/apps/quassel/");
- }
- else {
- // Provide a fallback
+ QStringList dataDirNames;
#ifdef Q_OS_WIN
- dataDirNames << qgetenv("APPDATA") + QCoreApplication::organizationDomain() + "/share/apps/quassel/"
- << qgetenv("APPDATA") + QCoreApplication::organizationDomain()
- << QCoreApplication::applicationDirPath();
- }
+ dataDirNames << qgetenv("APPDATA") + QCoreApplication::organizationDomain() + "/share/apps/quassel/"
+ << qgetenv("APPDATA") + QCoreApplication::organizationDomain()
+ << QCoreApplication::applicationDirPath();
#elif defined Q_OS_MAC
- dataDirNames << QDir::homePath() + "/Library/Application Support/Quassel/"
- << QCoreApplication::applicationDirPath();
- }
+ dataDirNames << QDir::homePath() + "/Library/Application Support/Quassel/"
+ << QCoreApplication::applicationDirPath();
#else
- dataDirNames.append("/usr/share/apps/quassel/");
- }
- // on UNIX, we always check our install prefix
- QString appDir = QCoreApplication::applicationDirPath();
- int binpos = appDir.lastIndexOf("/bin");
- if (binpos >= 0) {
- appDir.replace(binpos, 4, "/share");
- appDir.append("/apps/quassel/");
- if (!dataDirNames.contains(appDir))
- dataDirNames.append(appDir);
- }
+ // Linux et al
+
+ // XDG_DATA_HOME is the location for users to override system-installed files, usually in .local/share
+ // This should thus come first.
+ QString xdgDataHome = QFile::decodeName(qgetenv("XDG_DATA_HOME"));
+ if (xdgDataHome.isEmpty())
+ xdgDataHome = QDir::homePath() + QLatin1String("/.local/share");
+ dataDirNames << xdgDataHome;
+
+ // Now whatever is configured through XDG_DATA_DIRS
+ QString xdgDataDirs = QFile::decodeName(qgetenv("XDG_DATA_DIRS"));
+ if (xdgDataDirs.isEmpty())
+ dataDirNames << "/usr/local/share" << "/usr/share";
+ else
+ dataDirNames << xdgDataDirs.split(':', QString::SkipEmptyParts);
+
+ // Just in case, also check our install prefix
+ dataDirNames << QCoreApplication::applicationDirPath() + "/../share";
+
+ // Normalize and append our application name
+ for (int i = 0; i < dataDirNames.count(); i++)
+ dataDirNames[i] = QDir::cleanPath(dataDirNames.at(i)) + "/quassel/";
+
#endif
- // add resource path and workdir just in case
- dataDirNames << QCoreApplication::applicationDirPath() + "/data/"
- << ":/data/";
+ // Add resource path and workdir just in case.
+ // Workdir should have precedence
+ dataDirNames.prepend(QCoreApplication::applicationDirPath() + "/data/");
+ dataDirNames.append(":/data/");
- // append trailing '/' and check for existence
- QStringList::Iterator iter = dataDirNames.begin();
+ // Append trailing '/' and check for existence
+ auto iter = dataDirNames.begin();
while (iter != dataDirNames.end()) {
if (!iter->endsWith(QDir::separator()) && !iter->endsWith('/'))
iter->append(QDir::separator());
++iter;
}
+ dataDirNames.removeDuplicates();
+
return dataDirNames;
}
SaslAuthentication = 0x0002,
SaslExternal = 0x0004,
HideInactiveNetworks = 0x0008,
+ PasswordChange = 0x0010,
- NumFeatures = 0x0008
+ NumFeatures = 0x0010
};
Q_DECLARE_FLAGS(Features, Feature);
void RemotePeer::handle(const HeartBeatReply &heartBeatReply)
{
_heartBeatCount = 0;
-#if QT_VERSION >= 0x040700
emit lagUpdated(heartBeatReply.timestamp.msecsTo(QDateTime::currentDateTime().toUTC()) / 2);
-#else
- emit lagUpdated(heartBeatReply.timestamp.time().msecsTo(QDateTime::currentDateTime().toUTC().time()) / 2);
-#endif
}
list(APPEND LIBS ${QCA2_LIBRARIES})
endif()
+if (QCA2-QT5_FOUND)
+ add_definitions(-DHAVE_QCA2)
+ include_directories(${QCA2-QT5_INCLUDE_DIR})
+ list(APPEND SOURCES cipher.cpp)
+ list(APPEND LIBS ${QCA2-QT5_LIBRARIES})
+endif()
+
include_directories(${CMAKE_SOURCE_DIR}/src/common)
set(CORE_RCS ${CORE_RCS} ${CMAKE_CURRENT_SOURCE_DIR}/sql.qrc)
foreach(CoreAuthHandler *handler, _connectingClients) {
handler->deleteLater(); // disconnect non authed clients
}
- qDeleteAll(sessions);
+ qDeleteAll(_sessions);
qDeleteAll(_storageBackends);
}
CoreSettings s;
QVariantMap state;
QVariantList activeSessions;
- foreach(UserId user, instance()->sessions.keys()) activeSessions << QVariant::fromValue<UserId>(user);
+ foreach(UserId user, instance()->_sessions.keys())
+ activeSessions << QVariant::fromValue<UserId>(user);
state["CoreStateVersion"] = 1;
state["ActiveSessions"] = activeSessions;
s.setCoreState(state);
// qWarning() << qPrintable(tr("Cannot restore a state for an unconfigured core!"));
return;
}
- if (instance()->sessions.count()) {
+ if (instance()->_sessions.count()) {
qWarning() << qPrintable(tr("Calling restoreState() even though active sessions exist!"));
return;
}
quInfo() << "Restoring previous core state...";
foreach(QVariant v, activeSessions) {
UserId user = v.value<UserId>();
- instance()->createSession(user, true);
+ instance()->sessionForUser(user, true);
}
}
}
handler->deleteLater();
// Find or create session for validated user
- SessionThread *session;
- if (sessions.contains(uid)) {
- session = sessions[uid];
- }
- else {
- session = createSession(uid);
- if (!session) {
- qWarning() << qPrintable(tr("Could not initialize session for client:")) << qPrintable(peer->description());
- peer->close();
- peer->deleteLater();
- return;
- }
- }
+ sessionForUser(uid);
// as we are currently handling an event triggered by incoming data on this socket
// it is unsafe to directly move the socket to the client thread.
void Core::addClientHelper(RemotePeer *peer, UserId uid)
{
// Find or create session for validated user
- if (!sessions.contains(uid)) {
- qWarning() << qPrintable(tr("Could not find a session for client:")) << qPrintable(peer->description());
- peer->close();
- peer->deleteLater();
- return;
- }
-
- SessionThread *session = sessions[uid];
+ SessionThread *session = sessionForUser(uid);
session->addClient(peer);
}
clientPeer->setPeer(corePeer);
// Find or create session for validated user
- SessionThread *sessionThread;
- if (sessions.contains(uid))
- sessionThread = sessions[uid];
- else
- sessionThread = createSession(uid);
-
+ SessionThread *sessionThread = sessionForUser(uid);
sessionThread->addClient(corePeer);
}
-SessionThread *Core::createSession(UserId uid, bool restore)
+SessionThread *Core::sessionForUser(UserId uid, bool restore)
{
- if (sessions.contains(uid)) {
- qWarning() << "Calling createSession() when a session for the user already exists!";
- return 0;
- }
- SessionThread *sess = new SessionThread(uid, restore, this);
- sessions[uid] = sess;
- sess->start();
- return sess;
+ if (_sessions.contains(uid))
+ return _sessions[uid];
+
+ SessionThread *session = new SessionThread(uid, restore, this);
+ _sessions[uid] = session;
+ session->start();
+ connect(session, SIGNAL(passwordChangeRequested(UserId, QString)), _storage, SLOT(updateUser(UserId, QString)));
+ return session;
}
void socketError(QAbstractSocket::SocketError err, const QString &errorString);
void setupClientSession(RemotePeer *, UserId);
+ void changeUserPass(const QString &username);
+
private:
Core();
~Core();
void init();
static Core *instanceptr;
- SessionThread *createSession(UserId userId, bool restoreState = false);
+ SessionThread *sessionForUser(UserId userId, bool restoreState = false);
void addClientHelper(RemotePeer *peer, UserId uid);
//void processCoreSetup(QTcpSocket *socket, QVariantMap &msg);
QString setupCoreForInternalUsage();
void unregisterStorageBackend(Storage *);
bool selectBackend(const QString &backend);
void createUser();
- void changeUserPass(const QString &username);
void saveBackendSettings(const QString &backend, const QVariantMap &settings);
QVariantMap promptForSettings(const Storage *storage);
private:
QSet<CoreAuthHandler *> _connectingClients;
- QHash<UserId, SessionThread *> sessions;
+ QHash<UserId, SessionThread *> _sessions;
Storage *_storage;
QTimer _storageSyncTimer;
_quitReason = reason;
displayMsg(Message::Server, BufferInfo::StatusBuffer, "", tr("Disconnecting. (%1)").arg((!requested && !withReconnect) ? tr("Core Shutdown") : _quitReason));
- switch (socket.state()) {
- case QAbstractSocket::ConnectedState:
- userInputHandler()->issueQuit(_quitReason);
+ if (socket.state() == QAbstractSocket::UnconnectedState) {
+ socketDisconnected();
+ } else {
+ if (socket.state() == QAbstractSocket::ConnectedState) {
+ userInputHandler()->issueQuit(_quitReason);
+ } else {
+ socket.close();
+ }
if (requested || withReconnect) {
// the irc server has 10 seconds to close the socket
_socketCloseTimer.start(10000);
- break;
}
- default:
- socket.close();
- socketDisconnected();
}
}
else if (s.endsWith("\n"))
s.chop(1);
NetworkDataEvent *event = new NetworkDataEvent(EventManager::NetworkIncoming, this, s);
-#if QT_VERSION >= 0x040700
event->setTimestamp(QDateTime::currentDateTimeUtc());
-#else
- event->setTimestamp(QDateTime::currentDateTime().toUTC());
-#endif
emit newEvent(event);
}
}
disconnectFromIrc();
return;
}
-
+
emit socketOpen(identity, localAddress(), localPort(), peerAddress(), peerPort());
-
+
Server server = usedServer();
#ifdef HAVE_SSL
if (server.useSsl && !socket.isEncrypted())
return;
#endif
-#if QT_VERSION >= 0x040600
socket.setSocketOption(QAbstractSocket::KeepAliveOption, true);
-#endif
emit socketInitialized(identity, localAddress(), localPort(), peerAddress(), peerPort());
p->attachSlot(SIGNAL(createNetwork(const NetworkInfo &, const QStringList &)), this, SLOT(createNetwork(const NetworkInfo &, const QStringList &)));
p->attachSlot(SIGNAL(removeNetwork(NetworkId)), this, SLOT(removeNetwork(NetworkId)));
+ p->attachSlot(SIGNAL(clientChangePassword(QString)), this, SLOT(changePassword(QString)));
+
loadSettings();
initScriptEngine();
net->userInputHandler()->issueAway(msg, false /* no force away */);
}
}
+
+void CoreSession::changePassword(QString password)
+{
+ emit passwordChangeRequested(_user, password);
+}
//! Marks us away (or unaway) on all networks
void globalAway(const QString &msg = QString());
+ void changePassword(QString password);
+
signals:
void initialized();
void sessionState(const Protocol::SessionState &sessionState);
void networkRemoved(NetworkId);
void networkDisconnected(NetworkId);
+ void passwordChangeRequested(UserId user, QString password);
+
protected:
virtual void customEvent(QEvent *event);
QString verboseMessage = tr("sending CTCP-%1 request to %2").arg(ctcpTag).arg(nick);
if (ctcpTag == "PING") {
-#if QT_VERSION >= 0x040700
message = QString::number(QDateTime::currentMSecsSinceEpoch());
-#else
- message = QString::number(QDateTime::currentDateTime().toTime_t());
-#endif
}
// FIXME make this a proper event
}
+void CoreUserInputHandler::handlePrint(const BufferInfo &bufferInfo, const QString &msg)
+{
+ if (bufferInfo.bufferName().isEmpty() || !bufferInfo.acceptsRegularMessages())
+ return; // server buffer
+
+ QByteArray encMsg = channelEncode(bufferInfo.bufferName(), msg);
+ emit displayMsg(Message::Info, bufferInfo.type(), bufferInfo.bufferName(), msg, network()->myNick(), Message::Self);
+}
+
+
// TODO: implement queries
void CoreUserInputHandler::handleQuery(const BufferInfo &bufferInfo, const QString &msg)
{
void handleHalfop(const BufferInfo& bufferInfo, const QString &nicks);
void handlePart(const BufferInfo &bufferInfo, const QString &text);
void handlePing(const BufferInfo &bufferInfo, const QString &text);
+ void handlePrint(const BufferInfo &bufferInfo, const QString &text);
void handleQuery(const BufferInfo &bufferInfo, const QString &text);
void handleQuit(const BufferInfo &bufferInfo, const QString &text);
void handleQuote(const BufferInfo &bufferInfo, const QString &text);
if (e->ctcpType() == CtcpEvent::Query)
defaultHandler(e->ctcpCmd(), e);
else {
-#if QT_VERSION >= 0x040700
displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 milliseconds round trip time")
.arg(nickFromMask(e->prefix())).arg(QDateTime::fromMSecsSinceEpoch(e->param().toULongLong()).msecsTo(e->timestamp())));
-#else
- displayMsg(e, Message::Server, tr("Received CTCP-PING answer from %1 with %2 seconds round trip time")
- .arg(nickFromMask(e->prefix())).arg(QDateTime::fromTime_t(e->param().toInt()).secsTo(e->timestamp())));
-#endif
}
}
void SessionThread::run()
{
_session = new CoreSession(user(), _restoreState);
+ connect(_session, SIGNAL(passwordChangeRequested(UserId, QString)), SIGNAL(passwordChangeRequested(UserId, QString)));
connect(this, SIGNAL(addRemoteClient(RemotePeer*)), _session, SLOT(addClient(RemotePeer*)));
connect(this, SIGNAL(addInternalClient(InternalPeer*)), _session, SLOT(addClient(InternalPeer*)));
connect(_session, SIGNAL(sessionState(Protocol::SessionState)), Core::instance(), SIGNAL(sessionState(Protocol::SessionState)));
void addRemoteClient(RemotePeer *peer);
void addInternalClient(InternalPeer *peer);
+ void passwordChangeRequested(UserId user, QString newPassword);
+
private:
CoreSession *_session;
UserId _user;
set(LIBS )
set(QT_MODULES )
-if (KDE4_FOUND)
+if (WITH_KDE4)
add_definitions(-DHAVE_KDE ${KDE4_DEFINITIONS})
include_directories(${KDE4_INCLUDES})
list(APPEND SOURCES knotificationbackend.cpp)
list(APPEND LIBS ${KDE4_KDECORE_LIBS} ${KDE4_KDEUI_LIBRARY} ${KDE4_KNOTIFYCONFIG_LIBRARY})
endif()
+if (WITH_KF5)
+ list(APPEND SOURCES knotificationbackend.cpp)
+ list(APPEND LIBS KF5::ConfigWidgets KF5::Notifications KF5::NotifyConfig KF5::WidgetsAddons KF5::XmlGui)
+endif()
+
if (LIBSNORE_FOUND)
add_definitions(-DHAVE_LIBSNORE)
include_directories(${LIBSNORE_INCLUDE_DIRS})
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
+#include "aboutdlg.h"
+
#include <QDateTime>
#include <QIcon>
-#include "aboutdlg.h"
+#include "aboutdata.h"
#include "quassel.h"
-AboutDlg::AboutDlg(QWidget *parent) : QDialog(parent)
+AboutDlg::AboutDlg(QWidget *parent)
+ : QDialog(parent)
+ , _aboutData(new AboutData(this))
{
+ AboutData::setQuasselPersons(_aboutData);
+
ui.setupUi(this);
ui.quasselLogo->setPixmap(QIcon(":/icons/quassel-64.png").pixmap(64)); // don't let the icon theme affect our logo here
QString AboutDlg::authors() const
{
QString res;
- res = tr("Quassel IRC is mainly developed by:") +
- "<dl>"
- "<dt><b>Manuel \"Sputnick\" Nickschas</b></dt><dd><a href=\"mailto:sput@quassel-irc.org\">sput@quassel-irc.org</a><br>"
- "Project Founder, Lead Developer</dd>"
- "<dt><b>Marcus \"EgS\" Eggenberger</b></dt><dd><a href=\"mailto:egs@quassel-irc.org\">egs@quassel-irc.org</a><br>"
- "Project Motivator, Lead Developer, Mac Maintainer</dd>"
- "<dt><b>Alexander \"phon\" von Renteln</b></dt><dd><a href=\"mailto:phon@quassel-irc.org\">phon@quassel-irc.org</a><br>"
- "Developer, Windows Maintainer</dd>"
- "</dl>";
-
+ res = tr("Quassel IRC is mainly developed by:") + "<dl>";
+ for (const auto &person : _aboutData->authors()) {
+ res.append("<dt><b>" + person.prettyName() + "</b></dt><dd>");
+ if (!person.emailAddress().isEmpty())
+ res.append("<a href=\"mailto:" + person.emailAddress() + "\">" + person.emailAddress() + "</a><br>");
+ res.append("<i>" + person.task() + "</i><br></dd>");
+ }
+ res.append("</dl>");
return res;
}
QString AboutDlg::contributors() const
{
QString res;
- res = tr("We would like to thank the following contributors (in alphabetical order) and everybody we forgot to mention here:")
- + QString::fromUtf8("<br>"
- "<dl>"
- "<dt><b>Daniel \"al\" Albers</b></dt><dd>Master Of Translation, many fixes and enhancements</dd>"
- "<dt><b>Liudas Alisauskas</b></dt><dd>Lithuanian translation</dd>"
- "<dt><b>Terje \"tan\" Andersen</b></dt><dd>Norwegian translation, documentation</dd>"
- "<dt><b>Jens \"amiconn\" Arnold</b></dt><dd>Postgres migration fixes</dd>"
- "<dt><b>Adolfo Jayme Barrientos</b></dt><dd>Spanish translation</dd>"
- "<dt><b>Mattia Basaglia</b></dt><dd>Fixes</dd>"
- "<dt><b>Pete \"elbeardmorez\" Beardmore</b></dt><dd>Linewrap for input line</dd>"
- "<dt><b>Rafael \"EagleScreen\" Belmonte</b></dt><dd>Spanish translation</dd>"
- "<dt><b>Sergiu Bivol</b></dt><dd>Romanian translation</dd>"
- "<dt><b>Bruno Brigras</b></dt><dd>Crash fixes</dd>"
- "<dt><b>Florent Castelli</b></dt><dd>Sanitize topic handling</dd>"
- "<dt><b>Theo \"tampakrap\" Chatzimichos</b></dt><dd>Greek translation</dd>"
- "<dt><b>Yuri Chornoivan</b></dt><dd>Ukrainian translation</dd>"
- "<dt><b>Tomáš \"scarabeus\" Chvátal</b></dt><dd>Czech translation</dd>"
- "<dt><b>\"Condex\"</b></dt><dd>Galician translation</dd>"
- "<dt><b>Joshua \"tvakah\" Corbin</b></dt><dd>Various fixes</dd>"
- "<dt><b>\"cordata\"</b></dt><dd>Esperanto translation</dd>"
- "<dt><b>Matthias \"pennywise\" Coy</b></dt><dd>German translation</dd>"
- "<dt><b>\"derpella\"</b></dt><dd>Polish translation</dd>"
- "<dt><b>\"Dorian\"</b></dt><dd>French translation</dd>"
- "<dt><b>Luke Faraone</b></dt><dd>Doc fixes</dd>"
- "<dt><b>Chris \"stitch\" Fuenty</b></dt><dd>SASL support</dd>"
- "<dt><b>Kevin \"KRF\" Funk</b></dt><dd>German translation</dd>"
- "<dt><b>Fabiano \"elbryan\" Francesconi</b></dt><dd>Italian translation</dd>"
- "<dt><b>Leo Franchi</b></dt><dd>OSX improvements</dd>"
- "<dt><b>Sebastien Fricker</b></dt><dd>Audio backend improvements</dd>"
- "<dt><b>Alf Gaida</b></dt><dd>Language improvements</dd>"
- "<dt><b>Aurélien \"agateau\" Gâteau</b></dt><dd>Message Indicator support</dd>"
- "<dt><b>Marco \"kaffeedoktor\" Genise</b></dt><dd>Ideas, hacking, motivation</dd>"
- "<dt><b>Felix \"debfx\" Geyer</b></dt><dd>Certificate handling improvements</dd>"
- "<dt><b>Volkan Gezer</b></dt><dd>Turkish translation</dd>"
- "<dt><b>Sjors \"dazjorz\" Gielen</b></dt><dd>Fixes</dd>"
- "<dt><b>Sebastian \"seezer\" Goth</b></dt><dd>Many improvements and features</dd>"
- "<dt><b>Michael \"brot\" Groh</b></dt><dd>German translation, fixes</dd>"
- "<dt><b>\"Gryllida\"</b></dt><dd>IRC parser improvements</dd>"
- "<dt><b>H. İbrahim \"igungor\" Güngör</b></dt><dd>Turkish translation</dd>"
- "<dt><b>Jiri Grönroos</b></dt><dd>Finnish translation</dd>"
- "<dt><b>Chris \"Zren\" H</b></dt><dd>Various improvements</dd>"
- "<dt><b>Edward Hades</b></dt><dd>Russian translation</dd>"
- "<dt><b>John \"nox\" Hand</b></dt><dd>Former All-Seeing Eye logo</dd>"
- "<dt><b>Adam \"2kah\" Harwood</b></dt><dd>ChatView improvements</dd>"
- "<dt><b>Jonas \"Dante\" Heese</b></dt><dd>Project founder, various improvements</dd>"
- "<dt><b>Thomas \"Datafreak\" Hogh</b></dt><dd>Windows builder</dd>"
- "<dt><b>Johannes \"j0hu\" Huber</b></dt><dd>Many fixes and features, bug triaging</dd>"
- "<dt><b>Theofilos Intzoglou</b></dt><dd>Greek translation</dd>"
- "<dt><b>Jovan Jojkić</b></dt><dd>Serbian translation</dd>"
- "<dt><b>Allan Jude</b></dt><dd>Documentation improvements</dd>"
- "<dt><b>Michael \"ycros\" Kedzierski</b></dt><dd>Mac fixes</dd>"
- "<dt><b>Scott \"ScottK\" Kitterman<b></dt><dd>Kubuntu nightly packager, (packaging/build system) bughunter</dd>"
- "<dt><b>Paul \"Haudrauf\" Klumpp</b></dt><dd>Initial design and mainwindow layout</dd>"
- "<dt><b>Maia Kozheva</b></dt><dd>Russian translation</dd>"
- "<dt><b>Tae-Hoon Kwon</b></dt><dd>Korean translation</dd>"
- "<dt><b>\"Larso\"</b></dt><dd>Finnish translation</dd>"
- "<dt><b>Patrick \"bonsaikitten\" Lauer</b></dt><dd>Gentoo packaging</dd>"
- "<dt><b>Chris \"Fish-Face\" Le Sueur</b></dt><dd>Various fixes and improvements</dd>"
- "<dt><b>Jerome \"Adys\" Leclanche</b></dt><dd>Context menu fixes</dd>"
- "<dt><b>Hendrik \"nevcairiel\" Leppkes</b></dt><dd>Various features</dd>"
- "<dt><b>Jason Lynch</b></dt><dd>Bugfixes</dd>"
- "<dt><b>Awad \"firesock\" Mackie</b></dt><dd>ChatView improvements</dd>"
- "<dt><b>Michael \"mamarley\" Marley</b></dt><dd>Various fixes and improvements</dd>"
- "<dt><b>Martin \"m4yer\" Mayer</b></dt><dd>German translation</dd>"
- "<dt><b>Daniel \"hydrogen\" Meltzer</b></dt><dd>Various fixes and improvements</dd>"
- "<dt><b>Sebastian Meyer</b></dt><dd>Fixes</dd>"
- "<dt><b>Daniel E. Moctezuma</b></dt><dd>Japanese translation</dd>"
- "<dt><b>Chris \"kode54\" Moeller</b></dt><dd>Various fixes and improvements</dd>"
- "<dt><b>Thomas Müller</b></dt><dd>Fixes, Debian packaging</dd>"
- "<dt><b>Gábor \"ELITE_x\" Németh</b></dt><dd>Hungarian translation</dd>"
- "<dt><b>Per Nielsen</b></dt><dd>Danish translation</dd>"
- "<dt><b>J-P Nurmi</b></dt><dd>Fixes</dd>"
- "<dt><b>Marco \"Quizzlo\" Paolone</b></dt><dd>Italian translation</dd>"
- "<dt><b>Bas \"Tucos\" Pape</b></dt><dd>Many fixes and improvements, bug and patch triaging, tireless community support</dd>"
- "<dt><b>Bruno Patri</b></dt><dd>French translation</dd>"
- "<dt><b>Drew \"LinuxDolt\" Patridge</b></dt><dd>BluesTheme stylesheet</dd>"
- "<dt><b>Celeste \"seele\" Paul</b></dt><dd>Usability Queen</dd>"
- "<dt><b>Vit Pelcak</b></dt><dd>Czech translation</dd>"
- "<dt><b>Regis \"ZRegis\" Perrin</b></dt><dd>French translation</dd>"
- "<dt><b>Diego \"Flameeyes\" Pettenò</b></dt><dd>Gentoo maintainer, build system improvements</dd>"
- "<dt><b>Simon Philips</b></dt><dd>Dutch translation</dd>"
- "<dt><b>Daniel \"billie\" Pielmeier</b></dt><dd>Gentoo maintainer</dd>"
- "<dt><b>Nuno \"pinheiro\" Pinheiro</b></dt><dd>Tons of Oxygen icons including our application icon</dd>"
- "<dt><b>David Planella</b></dt><dd>Translation system fixes</dd>"
- "<dt><b>Jure \"JLP\" Repinc</b></dt><dd>Slovenian translation</dd>"
- "<dt><b>Patrick \"TheOneRing\" von Reth</b></dt><dd>MinGW support, SNORE backend, Windows packager</dd>"
- "<dt><b>Dirk \"MarcLandis\" Rettschlag</b></dt><dd>Various fixes and new features</dd>"
- "<dt><b>Miguel Revilla</b></dt><dd>Spanish translation</dd>"
- "<dt><b>Jaak Ristioja</b></dt><dd>Fixes</dd>"
- "<dt><b>David \"Bombe\" Roden</b></dt><dd>Fixes</dd>"
- "<dt><b>Henning \"honk\" Rohlfs</b></dt><dd>Various fixes</dd>"
- "<dt><b>Stella \"differentreality\" Rouzi</b></dt><dd>Greek translation</dd>"
- "<dt><b>\"salnx\"</b></dt><dd>Highlight configuration improvements</dd>"
- "<dt><b>Martin \"sandsmark\" Sandsmark</b></dt><dd>Core fixes, Quasseldroid</dd>"
- "<dt><b>David Sansome</b></dt><dd>OSX Notification Center support</dd>"
- "<dt><b>Dennis \"DevUrandom\" Schridde</b></dt><dd>D-Bus notifications</dd>"
- "<dt><b>Jussi \"jussi01\" Schultink</b></dt><dd>Tireless tester, {ku|U}buntu tester and lobbyist, liters of delicious Finnish alcohol</dd>"
- "<dt><b>Tim \"xAFFE\" Schumacher</b></dt><dd>Fixes and feedback</dd>"
- "<dt><b>\"sfionov\"</b></dt><dd>Russian translation</dd>"
- "<dt><b>Harald \"apachelogger\" Sitter</b></dt><dd>{ku|U}buntu packager, motivator, promoter</dd>"
- "<dt><b>Ramanathan Sivagurunathan</b></dt><dd>Fixes</dd>"
- "<dt><b>Stefanos Sofroniou</b></dt><dd>Greek translation</dd>"
- "<dt><b>Rüdiger \"ruediger\" Sonderfeld</b></dt><dd>Emacs keybindings</dd>"
- "<dt><b>Alexander Stein</b></dt><dd>Tray icon fix</dd>"
- "<dt><b>Daniel \"son\" Steinmetz</b></dt><dd>Early beta tester and bughunter (on Vista™!)</dd>"
- "<dt><b>Jesper Thomschütz</b></dt><dd>Various fixes</dd>"
- "<dt><b>Arthur \"roentgen\" Titeica</b></dt><dd>Romanian translation</dd>"
- "<dt><b>\"ToBeFree\"</b></dt><dd>German translation</dd>"
- "<dt><b>Edward \"Aides\" Toroshchin</b></dt><dd>Russian translation</dd>"
- "<dt><b>Adam \"adamt\" Tulinius</b></dt><dd>Early beta tester and bughunter, Danish translation</dd>"
- "<dt><b>Deniz Türkoglu</b></dt><dd>Mac fixes</dd>"
- "<dt><b>Frederik M.J. \"freqmod\" Vestre</b></dt><dd>Norwegian translation</dd>"
- "<dt><b>Atte Virtanen</b></dt><dd>Finnish translation</dd>"
- "<dt><b>Pavel \"int\" Volkovitskiy</b></dt><dd>Early beta tester and bughunter</dd>"
- "<dt><b>Roscoe van Wyk</b></dt><dd>Fixes</dd>"
- "<dt><b>Zé</b></dt><dd>Portuguese translation</dd>"
- "<dt><b>Benjamin \"zbenjamin\" Zeller</b></dt><dd>Windows build system fixes</dd>"
- "<dt><b>\"zeugma\"</b></dt><dd>Turkish translation</dd>"
- "</dl><br>"
- "...and anybody else finding and reporting bugs, giving feedback, helping others and being part of the community!");
+ res = tr("We would like to thank the following contributors (in alphabetical order) and everybody we forgot to mention here:") + "<br><dl>";
+ for (const auto &person : _aboutData->credits()) {
+ res.append("<dt><b>" + person.prettyName() + "</b></dt><dd><i>" + person.task() + "</i><br></dd>");
+ }
+ res.append("</dl>" + tr("...and anybody else finding and reporting bugs, giving feedback, helping others and being part of the community!"));
return res;
}
res = tr("Special thanks goes to:<br>"
"<dl>"
"<dt><img src=\":/pics/quassel-eye.png\"> <b>John \"nox\" Hand</b></dt>"
- "<dd>for the original Quassel icon - The All-Seeing Eye</dt>"
+ "<dd><i>for the original Quassel icon - The All-Seeing Eye</i><br></dt>"
"<dt><img src=\":/pics/oxygen.png\"> <b><a href=\"http://www.oxygen-icons.org\">The Oxygen Team</a></b></dt>"
- "<dd>for creating all the artwork you see throughout Quassel</dd>"
+ "<dd><i>for creating all the artwork you see throughout Quassel</i><br></dd>"
"<dt><img src=\":/pics/qt-logo-32.png\"> <b><a href=\"http://www.trolltech.com\">Qt Software formerly known as Trolltech</a></b></dt>"
- "<dd>for creating Qt and Qtopia, and for sponsoring development of QuasselTopia with Greenphones and more</dd>"
+ "<dd><i>for creating Qt and Qtopia, and for sponsoring development of QuasselTopia with Greenphones and more</i><br></dd>"
"<dt><a href=\"http://www.nokia.com\"><img src=\":/pics/nokia.png\"></a></b></dt>"
- "<dd>for keeping Qt alive, and for sponsoring development of Quassel Mobile with N810s</dd>"
+ "<dd><i>for sponsoring development of Quassel Mobile with N810s</i></dd>"
);
return res;
#include "ui_aboutdlg.h"
+class AboutData;
+
class AboutDlg : public QDialog
{
Q_OBJECT
QString authors() const;
QString contributors() const;
QString thanksTo() const;
+
+ AboutData *_aboutData;
};
#ifndef CHATVIEWSEARCHCONTROLLER_H
#define CHATVIEWSEARCHCONTROLLER_H
-#include <QObject>
+#include <QGraphicsItem>
#include <QHash>
#include <QPointer>
#include <QString>
// Highlight Items
-#include <QGraphicsItem>
-
class SearchHighlightItem : public QObject, public QGraphicsItem
{
Q_OBJECT
+
+// Apparently, there are broken Qt 4.8.2 mocs around that will fail without this (otherwise useless) #if... looking at you, Wheezy!
#if QT_VERSION >= 0x040600
Q_INTERFACES(QGraphicsItem)
#endif
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#include <KNotification>
-#include <KNotifyConfigWidget>
+#include "knotificationbackend.h"
+
#include <QIcon>
#include <QTextDocument>
#include <QVBoxLayout>
-#include "knotificationbackend.h"
+#ifdef HAVE_KDE4
+# include <KNotification>
+# include <KNotifyConfigWidget>
+#else
+# include <KNotifications/KNotification>
+# include <KNotifyConfig/KNotifyConfigWidget>
+#endif
#include "client.h"
#include "mainwin.h"
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#ifndef KNOTIFICATIONBACKEND_H_
-#define KNOTIFICATIONBACKEND_H_
+#pragma once
#include <QPointer>
void removeNotificationById(uint id);
void updateToolTip();
- QList<QPair<uint, QPointer<KNotification> > > _notifications;
+ QList<QPair<uint, QPointer<KNotification>>> _notifications;
};
private:
KNotifyConfigWidget *_widget;
};
-
-
-#endif
#include <QMessageBox>
#include <QStatusBar>
#include <QToolBar>
+#include <QInputDialog>
#ifdef HAVE_KDE4
-# include <KAction>
-# include <KActionCollection>
# include <KHelpMenu>
# include <KMenuBar>
# include <KShortcutsDialog>
# include <KStatusBar>
# include <KToggleFullScreenAction>
# include <KToolBar>
-# include <KWindowSystem>
+#endif
+
+#ifdef HAVE_KF5
+# include <KConfigWidgets/KStandardAction>
+# include <KXmlGui/KHelpMenu>
+# include <KXmlGui/KShortcutsDialog>
+# include <KXmlGui/KToolBar>
+# include <KWidgetsAddons/KToggleFullScreenAction>
#endif
#ifdef Q_WS_X11
#include "topicwidget.h"
#include "verticaldock.h"
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
# ifdef HAVE_PHONON
# include "phononnotificationbackend.h"
# endif
# endif
# include "systraynotificationbackend.h"
# include "taskbarnotificationbackend.h"
-#else /* HAVE_KDE4 */
+#else /* HAVE_KDE */
# include "knotificationbackend.h"
-#endif /* HAVE_KDE4 */
+#endif /* HAVE_KDE */
#ifdef HAVE_SSL
# include "sslinfodlg.h"
#include "settingspages/notificationssettingspage.h"
#include "settingspages/topicwidgetsettingspage.h"
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
# include "settingspages/shortcutssettingspage.h"
#endif
MainWin::MainWin(QWidget *parent)
-#ifdef HAVE_KDE4
- : KMainWindow(parent),
- _kHelpMenu(new KHelpMenu(this, KGlobal::mainComponent().aboutData())),
+#ifdef HAVE_KDE
+ : KMainWindow(parent), _kHelpMenu(new KHelpMenu(this)),
#else
: QMainWindow(parent),
#endif
connect(Client::coreConnection(), SIGNAL(handleSslErrors(const QSslSocket *, bool *, bool *)), SLOT(handleSslErrors(const QSslSocket *, bool *, bool *)));
#endif
+ connect(this, SIGNAL(changePassword(QString)), Client::instance(), SLOT(changePassword(QString)));
+
// Setup Dock Areas
setDockNestingEnabled(true);
setCorner(Qt::TopLeftCorner, Qt::LeftDockWidgetArea);
setupTitleSetter();
setupHotList();
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
# ifdef HAVE_PHONON
QtUi::registerNotificationBackend(new PhononNotificationBackend(this));
# endif
QtUi::registerNotificationBackend(new TaskbarNotificationBackend(this));
-#else /* HAVE_KDE4 */
+#else /* HAVE_KDE */
QtUi::registerNotificationBackend(new KNotificationBackend(this));
-#endif /* HAVE_KDE4 */
+#endif /* HAVE_KDE */
#ifdef HAVE_INDICATEQT
QtUi::registerNotificationBackend(new IndicatorNotificationBackend(this));
setDisconnectedState(); // Disable menus and stuff
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
setAutoSaveSettings();
#endif
if (lastBufId.isValid())
s.setValue("LastUsedBufferId", lastBufId.toInt());
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
saveAutoSaveSettings();
#endif
}
_normalPos = s.value("MainWinPos", pos()).toPoint();
bool maximized = s.value("MainWinMaximized", false).toBool();
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
restoreGeometry(s.value("MainWinGeometry").toByteArray());
if (maximized) {
this, SLOT(showCoreConnectionDlg())));
coll->addAction("DisconnectCore", new Action(QIcon::fromTheme("network-disconnect"), tr("&Disconnect from Core"), coll,
Client::instance(), SLOT(disconnectFromCore())));
+ coll->addAction("ChangePassword", new Action(QIcon::fromTheme("dialog-password"), tr("Change &Password..."), coll,
+ this, SLOT(showChangePasswordDialog())));
coll->addAction("CoreInfo", new Action(QIcon::fromTheme("help-about"), tr("Core &Info..."), coll,
this, SLOT(showCoreInfoDlg())));
coll->addAction("ConfigureNetworks", new Action(QIcon::fromTheme("configure"), tr("Configure &Networks..."), coll,
coll->addAction("ToggleStatusBar", new Action(tr("Show Status &Bar"), coll,
0, 0))->setCheckable(true);
-#ifdef HAVE_KDE4
- QAction *fullScreenAct = KStandardAction::fullScreen(this, SLOT(onFullScreenToggled()), this, coll);
+#ifdef HAVE_KDE
+ _fullScreenAction = KStandardAction::fullScreen(this, SLOT(onFullScreenToggled()), this, coll);
#else
- QAction *fullScreenAct = new Action(QIcon::fromTheme("view-fullscreen"), tr("&Full Screen Mode"), coll,
+ _fullScreenAction = new Action(QIcon::fromTheme("view-fullscreen"), tr("&Full Screen Mode"), coll,
this, SLOT(onFullScreenToggled()), QKeySequence(Qt::Key_F11));
- fullScreenAct->setCheckable(true);
+ _fullScreenAction->setCheckable(true);
+ coll->addAction("ToggleFullScreen", _fullScreenAction);
#endif
- coll->addAction("ToggleFullScreen", fullScreenAct);
// Settings
QAction *configureShortcutsAct = new Action(QIcon::fromTheme("configure-shortcuts"), tr("Configure &Shortcuts..."), coll,
configureShortcutsAct->setMenuRole(QAction::NoRole);
coll->addAction("ConfigureShortcuts", configureShortcutsAct);
- #ifdef Q_OS_MAC
+#ifdef Q_OS_MAC
QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll,
this, SLOT(showSettingsDlg()));
configureQuasselAct->setMenuRole(QAction::PreferencesRole);
- #else
+#else
QAction *configureQuasselAct = new Action(QIcon::fromTheme("configure"), tr("&Configure Quassel..."), coll,
this, SLOT(showSettingsDlg()), QKeySequence(Qt::Key_F7));
- #endif
+#endif
coll->addAction("ConfigureQuassel", configureQuasselAct);
// Help
_fileMenu = menuBar()->addMenu(tr("&File"));
static const QStringList coreActions = QStringList()
- << "ConnectCore" << "DisconnectCore" << "CoreInfo";
+ << "ConnectCore" << "DisconnectCore" << "ChangePassword" << "CoreInfo";
QAction *coreAction;
foreach(QString actionName, coreActions) {
_viewMenu->addAction(coll->action("LockLayout"));
_settingsMenu = menuBar()->addMenu(tr("&Settings"));
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
_settingsMenu->addAction(KStandardAction::configureNotifications(this, SLOT(showNotificationsDlg()), this));
_settingsMenu->addAction(KStandardAction::keyBindings(this, SLOT(showShortcutsDlg()), this));
#else
#endif
_settingsMenu->addAction(coll->action("ConfigureQuassel"));
+
_helpMenu = menuBar()->addMenu(tr("&Help"));
+
_helpMenu->addAction(coll->action("AboutQuassel"));
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
_helpMenu->addAction(coll->action("AboutQt"));
#else
_helpMenu->addAction(KStandardAction::aboutKDE(_kHelpMenu, SLOT(aboutKDE()), this));
}
+void MainWin::showChangePasswordDialog()
+{
+ if((Client::coreFeatures() & Quassel::PasswordChange)) {
+ bool ok;
+ QString newPassword = QInputDialog::getText(this, tr("Set Core Password"), tr("New password for your Quassel Core:"), QLineEdit::Password, QString(), &ok);
+ if (ok && !newPassword.isEmpty()) {
+ emit changePassword(newPassword);
+ }
+ }
+ else {
+ QMessageBox box(QMessageBox::Warning, tr("Feature Not Supported"),
+ tr("<b>Your Quassel Core does not support this feature</b>"),
+ QMessageBox::Ok, this);
+ box.setInformativeText(tr("You need a Quassel Core v0.12.0 or newer in order to be able to remotely change your password."));
+ box.exec();
+ }
+}
+
+
void MainWin::changeActiveBufferView(bool backwards)
{
BufferView *current = activeBufferView();
void MainWin::setupViewMenuTail()
{
_viewMenu->addSeparator();
- _viewMenu->addAction(QtUi::actionCollection("General")->action("ToggleFullScreen"));
+ _viewMenu->addAction(_fullScreenAction);
}
setUnifiedTitleAndToolBarOnMac(true);
#endif
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
_mainToolBar = new KToolBar("MainToolBar", this, Qt::TopToolBarArea, false, true, true);
#else
_mainToolBar = new QToolBar(this);
coll->action("ConnectCore")->setEnabled(false);
coll->action("DisconnectCore")->setEnabled(true);
+ coll->action("ChangePassword")->setEnabled(true);
coll->action("CoreInfo")->setEnabled(true);
foreach(QAction *action, _fileMenu->actions()) {
coll->action("ConnectCore")->setEnabled(true);
coll->action("DisconnectCore")->setEnabled(false);
coll->action("CoreInfo")->setEnabled(false);
+ coll->action("ChangePassword")->setEnabled(false);
//_viewMenu->setEnabled(false);
statusBar()->showMessage(tr("Not connected to core."));
if (_msgProcessorStatusWidget)
void MainWin::showShortcutsDlg()
{
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
KShortcutsDialog dlg(KShortcutsEditor::AllActions, KShortcutsEditor::LetterShortcutsDisallowed, this);
foreach(KActionCollection *coll, QtUi::actionCollections())
dlg.addCollection(coll, coll->property("Category").toString());
- dlg.exec();
+ dlg.configure(true);
#else
SettingsPageDlg dlg(new ShortcutsSettingsPage(QtUi::actionCollections(), this), this);
dlg.exec();
// Relying on QWidget::isFullScreen is discouraged, see the KToggleFullScreenAction docs
// Also, one should not use showFullScreen() or showNormal(), as those reset all other window flags
- QAction *action = QtUi::actionCollection("General")->action("ToggleFullScreen");
- if (!action)
- return;
-
-#ifdef HAVE_KDE4
- KToggleFullScreenAction *kAct = static_cast<KToggleFullScreenAction *>(action);
- kAct->setFullScreen(this, kAct->isChecked());
+#ifdef HAVE_KDE
+ static_cast<KToggleFullScreenAction*>(_fullScreenAction)->setFullScreen(this, _fullScreenAction->isChecked());
#else
- if (action->isChecked())
+ if (_fullScreenAction->isChecked())
setWindowState(windowState() | Qt::WindowFullScreen);
else
setWindowState(windowState() & ~Qt::WindowFullScreen);
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
***************************************************************************/
-#ifndef MAINWIN_H_
-#define MAINWIN_H_
+#pragma once
#ifdef HAVE_KDE4
# include <KMainWindow>
+#elif defined HAVE_KF5
+# include <KXmlGui/KMainWindow>
#else
# include <QMainWindow>
#endif
//!\brief The main window of Quassel's QtUi.
class MainWin
-#ifdef HAVE_KDE4
- : public KMainWindow
-{
+#ifdef HAVE_KDE
+ : public KMainWindow {
#else
-: public QMainWindow {
+ : public QMainWindow {
#endif
Q_OBJECT
void changeActiveBufferView(bool backwards);
void changeActiveBufferView(int bufferViewId);
+ void showChangePasswordDialog();
+
signals:
void connectToCore(const QVariantMap &connInfo);
void disconnectFromCore();
+ void changePassword(QString newPassword);
private:
-#ifdef HAVE_KDE4
+#ifdef HAVE_KDE
KHelpMenu *_kHelpMenu;
#endif
ChatMonitorView *_chatMonitorView;
TopicWidget *_topicWidget;
+ QAction *_fullScreenAction;
QMenu *_fileMenu, *_networksMenu, *_viewMenu, *_bufferViewsMenu, *_settingsMenu, *_helpMenu, *_helpDebugMenu;
QMenu *_toolbarMenu;
QToolBar *_mainToolBar, *_chatViewToolBar, *_nickToolBar;
friend class QtUi;
};
-
-
-#endif
#include "qtui.h"
#include "qtuisettings.h"
+
QtUiApplication::QtUiApplication(int &argc, char **argv)
#ifdef HAVE_KDE4
- : KApplication(),
+ : KApplication(), // KApplication is deprecated in KF5
#else
: QApplication(argc, argv),
#endif
#ifdef HAVE_KDE4
Q_UNUSED(argc); Q_UNUSED(argv);
- // We need to setup KDE's data dirs
+ // Setup KDE's data dirs
+ // Because we can't use KDE stuff in (the class) Quassel directly, we need to do this here...
QStringList dataDirs = KGlobal::dirs()->findDirs("data", "");
+
+ // Just in case, also check our install prefix
+ dataDirs << QCoreApplication::applicationDirPath() + "/../share/apps/";
+
+ // Normalize and append our application name
for (int i = 0; i < dataDirs.count(); i++)
- dataDirs[i].append("quassel/");
+ dataDirs[i] = QDir::cleanPath(dataDirs.at(i)) + "/quassel/";
+
+ // Add resource path and just in case.
+ // Workdir should have precedence
+ dataDirs.prepend(QCoreApplication::applicationDirPath() + "/data/");
dataDirs.append(":/data/");
+
+ // Append trailing '/' and check for existence
+ auto iter = dataDirs.begin();
+ while (iter != dataDirs.end()) {
+ if (!iter->endsWith(QDir::separator()) && !iter->endsWith('/'))
+ iter->append(QDir::separator());
+ if (!QFile::exists(*iter))
+ iter = dataDirs.erase(iter);
+ else
+ ++iter;
+ }
+
+ dataDirs.removeDuplicates();
setDataDirPaths(dataDirs);
#else /* HAVE_KDE4 */
: SettingsPage(tr("Remote Cores"), tr("Connection"), parent)
{
ui.setupUi(this);
-#ifndef HAVE_KDE4
- ui.useSolid->hide();
-#endif
initAutoWidgets();
- connect(ui.useSolid, SIGNAL(toggled(bool)), SLOT(widgetHasChanged()));
+ connect(ui.useQNetworkConfigurationManager, SIGNAL(toggled(bool)), SLOT(widgetHasChanged()));
connect(ui.usePingTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged()));
connect(ui.useNoTimeout, SIGNAL(toggled(bool)), SLOT(widgetHasChanged()));
}
void CoreConnectionSettingsPage::defaults()
{
-#ifdef HAVE_KDE4
- setRadioButtons(CoreConnectionSettings::UseSolid);
-#else
- setRadioButtons(CoreConnectionSettings::UsePingTimeout);
-#endif
+ setRadioButtons(CoreConnectionSettings::UseQNetworkConfigurationManager);
SettingsPage::defaults();
}
void CoreConnectionSettingsPage::setRadioButtons(CoreConnectionSettings::NetworkDetectionMode mode)
{
switch (mode) {
-#ifdef HAVE_KDE4
- case CoreConnectionSettings::UseSolid:
- ui.useSolid->setChecked(true);
+ case CoreConnectionSettings::UseQNetworkConfigurationManager:
+ ui.useQNetworkConfigurationManager->setChecked(true);
break;
-#endif
case CoreConnectionSettings::UsePingTimeout:
ui.usePingTimeout->setChecked(true);
break;
CoreConnectionSettings::NetworkDetectionMode CoreConnectionSettingsPage::modeFromRadioButtons() const
{
-#ifdef HAVE_KDE4
- if (ui.useSolid->isChecked())
- return CoreConnectionSettings::UseSolid;
-#endif
+ if (ui.useQNetworkConfigurationManager->isChecked())
+ return CoreConnectionSettings::UseQNetworkConfigurationManager;
if (ui.usePingTimeout->isChecked())
return CoreConnectionSettings::UsePingTimeout;
<rect>
<x>0</x>
<y>0</y>
- <width>446</width>
+ <width>476</width>
<height>465</height>
</rect>
</property>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
- <widget class="QRadioButton" name="useSolid">
+ <widget class="QRadioButton" name="useQNetworkConfigurationManager">
<property name="toolTip">
- <string>Rely on KDE's hardware layer to detect if we're online. Recommended for most KDE users</string>
+ <string>Rely on Qt's network configuration manager to detect if we're online</string>
</property>
<property name="text">
- <string>Use KDE's network status detection (via Solid)</string>
+ <string>Automatic</string>
</property>
<property name="checked">
<bool>false</bool>
<item>
<widget class="QSpinBox" name="reconnectInterval">
<property name="toolTip">
- <string>Actively ping the remote core and disconnect if we didn't get a reply after a certain time</string>
+ <string>Interval between consecutive connection attempts</string>
</property>
<property name="suffix">
<string> seconds</string>
</item>
</layout>
</widget>
+ <tabstops>
+ <tabstop>useQNetworkConfigurationManager</tabstop>
+ <tabstop>usePingTimeout</tabstop>
+ <tabstop>pingTimeout</tabstop>
+ <tabstop>useNoTimeout</tabstop>
+ <tabstop>autoReconnect</tabstop>
+ <tabstop>reconnectInterval</tabstop>
+ </tabstops>
<resources/>
<connections>
<connection>
NotificationSettings notificationSettings;
notificationSettings.setHighlightList(highlightList);
- NotificationSettings::HighlightNickType highlightNickType;
- if (ui.highlightNoNick->isChecked())
- highlightNickType = NotificationSettings::NoNick;
+ NotificationSettings::HighlightNickType highlightNickType = NotificationSettings::NoNick;
if (ui.highlightCurrentNick->isChecked())
highlightNickType = NotificationSettings::CurrentNick;
if (ui.highlightAllNicks->isChecked())
{
NotificationSettings notificationSettings;
- NotificationSettings::HighlightNickType highlightNickType;
- if (ui.highlightNoNick->isChecked())
- highlightNickType = NotificationSettings::NoNick;
+ NotificationSettings::HighlightNickType highlightNickType = NotificationSettings::NoNick;
if (ui.highlightCurrentNick->isChecked())
highlightNickType = NotificationSettings::CurrentNick;
if (ui.highlightAllNicks->isChecked())
highlightNickType = NotificationSettings::AllNicks;
- if (notificationSettings.highlightNick() != highlightNickType) return true;
- if (notificationSettings.nicksCaseSensitive() != ui.nicksCaseSensitive->isChecked()) return true;
-
- if (notificationSettings.highlightList() != highlightList) return true;
+ if (notificationSettings.highlightNick() != highlightNickType)
+ return true;
+ if (notificationSettings.nicksCaseSensitive() != ui.nicksCaseSensitive->isChecked())
+ return true;
+ if (notificationSettings.highlightList() != highlightList)
+ return true;
return false;
}
ui.setupUi(this);
ui.useSSL->setIcon(QIcon::fromTheme("document-encrypt"));
ui.host->setText(server.host);
+ ui.host->setFocus();
ui.port->setValue(server.port);
ui.password->setText(server.password);
ui.useSSL->setChecked(server.useSsl);
virtual QString iconNameForAction(QAction *action) // TODO Qt 4.7: fixme when we have converted our iconloader
{
QIcon icon(action->icon());
-#if QT_VERSION >= 0x040701
- // QIcon::name() is in the 4.7 git branch, but it is not in 4.7 TP.
- // If you get a build error here, you need to update your pre-release
- // of Qt 4.7.
return icon.isNull() ? QString() : icon.name();
-#else
- return QString();
-#endif
}
};
# Builds the uisupport module
set(SOURCES
+ aboutdata.cpp
abstractbuffercontainer.cpp
abstractitemview.cpp
action.cpp
endif()
if (WITH_KF5)
- target_link_libraries(mod_uisupport KF5::TextWidgets)
+ target_link_libraries(mod_uisupport KF5::CoreAddons KF5::TextWidgets KF5::XmlGui)
endif()
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2015 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#include "aboutdata.h"
+
+#include <QImage>
+
+#include "quassel.h"
+
+
+AboutPerson::AboutPerson(const QString &name, const QString &nick, const QString &task, const QString &emailAddress, QLocale::Language translatedLanguage)
+ : _name(name)
+ , _nick(nick)
+ , _task(task)
+ , _emailAddress(emailAddress)
+ , _language(translatedLanguage)
+{
+
+}
+
+
+QString AboutPerson::name() const
+{
+ return _name;
+}
+
+
+QString AboutPerson::nick() const
+{
+ return _nick;
+}
+
+
+QString AboutPerson::task() const
+{
+ return _task;
+}
+
+
+QString AboutPerson::emailAddress() const
+{
+ return _emailAddress;
+}
+
+
+QLocale::Language AboutPerson::translatedLanguage() const
+{
+ return _language;
+}
+
+
+QString AboutPerson::prettyName() const
+{
+ if (!name().isEmpty() && !nick().isEmpty())
+ return name() + " (" + nick() + ')';
+
+ if (name().isEmpty() && !nick().isEmpty())
+ return nick();
+
+ return name();
+}
+
+
+/**************************************************************************************************/
+
+
+AboutData::AboutData(QObject *parent)
+ : QObject(parent)
+{
+
+}
+
+
+QList<AboutPerson> AboutData::authors() const
+{
+ return _authors;
+}
+
+
+QList< AboutPerson > AboutData::credits() const
+{
+ return _credits;
+}
+
+
+AboutData &AboutData::addAuthor(const AboutPerson &author)
+{
+ _authors.append(author);
+ return *this;
+}
+
+
+AboutData &AboutData::addAuthors(std::initializer_list<AboutPerson> authors)
+{
+ _authors.append(authors);
+ return *this;
+}
+
+
+AboutData &AboutData::addCredit(const AboutPerson &credit)
+{
+ _credits.append(credit);
+ return *this;
+}
+
+
+AboutData &AboutData::addCredits(std::initializer_list<AboutPerson> credits)
+{
+ _credits.append(credits);
+ return *this;
+}
+
+#ifdef HAVE_KF5
+
+KAboutData AboutData::kAboutData() const
+{
+ KAboutData aboutData(
+ Quassel::buildInfo().applicationName,
+ tr("Quassel IRC"),
+ Quassel::buildInfo().plainVersionString
+ );
+ aboutData.addLicense(KAboutLicense::GPL_V2);
+ aboutData.addLicense(KAboutLicense::GPL_V3);
+ aboutData.setShortDescription(tr("A modern, distributed IRC client"));
+ aboutData.setProgramLogo(QVariant::fromValue(QImage(":/pics/quassel-logo.png")));
+ aboutData.setBugAddress("http://bugs.quassel-irc.org/projects/quassel-irc/issues/new");
+ aboutData.setOrganizationDomain(Quassel::buildInfo().organizationDomain.toUtf8());
+
+ for (const auto &person : authors()) {
+ aboutData.addAuthor(person.prettyName(), person.task(), person.emailAddress());
+ }
+
+ for (const auto &person : credits()) {
+ aboutData.addCredit(person.prettyName(), person.task(), person.emailAddress());
+ }
+
+ return aboutData;
+}
+
+#endif
+
+
+/**************************************************************************************************/
+
+/*
+ * NOTE: The list of contributors was retrieved from the Git history, but sometimes things fall
+ * through the cracks... especially for translations, we don't have an easy way to track
+ * contributors' names.
+ * If you find wrong data for yourself, want your nickname and/or mail addresses added or
+ * removed, or feel left out or unfairly credited, please don't hesitate to let us know! We
+ * do want to credit everyone who has contributed to Quassel development.
+ */
+
+void AboutData::setQuasselPersons(AboutData *aboutData)
+{
+ aboutData->addAuthors({
+ { "Manuel Nickschas", "Sputnick", tr("Project Founder, Lead Developer"), "sputnick@quassel-irc.org" },
+ { "Marcus Eggenberger", "EgS", tr("Project Motivator, Lead Developer"), "egs@quassel-irc.org" },
+ { "Alexander von Renteln", "phon", tr("Former Lead Developer"), "phon@quassel-irc.org" },
+ { "Daniel Albers", "al", tr("Master of Translation, many fixes and enhancements") },
+ { "Sebastian Goth", "seezer", tr("Many features, fixes and improvements") },
+ { "Bas Pape", "Tucos", tr("Many fixes and improvements, bug and patch triaging, community support") },
+ });
+
+ aboutData->addCredits({
+ { "Adam Harwood", "2kah", tr("Chatview improvements") },
+ { "Adam Tulinius", "adamt", tr("Early beta tester and bughunter, Danish translation"), "", QLocale::Danish },
+ { "Adolfo Jayme Barrientos", "", tr("Spanish translation"), "", QLocale::Spanish },
+ { "Alexander Stein", "", tr("Tray icon fix") },
+ { "Alf Gaida", "agaida", tr("Language improvements") },
+ { "Allan Jude", "", tr("Documentation improvements") },
+ { "Arthur Titeica", "roentgen", tr("Romanian translation"), "", QLocale::Romanian },
+ { "Atte Virtanen", "", tr("Finnish translation"), "", QLocale::Finnish },
+ { "Aurélien Gâteau", "agateau", tr("Message indicator support") },
+ { "Awad Mackie", "firesock", tr("Chatview improvements") },
+ { "Benjamin Zeller", "zbenjamin", tr("Windows build system fixes") },
+ { "Bruno Brigras", "", tr("Crash fixes") },
+ { "Bruno Patri", "", tr("French translation"), "", QLocale::French },
+ { "Celeste Paul", "seele", tr("Usability review") },
+ { "Chris Fuenty", "stitch", tr("SASL support") },
+ { "Chris H", "Zren", tr("Various improvements") },
+ { "Chris Le Sueur", "Fish-Face", tr("Various fixes and improvements") },
+ { "Chris Moeller", "kode54", tr("Various fixes and improvements") },
+ { "", "Condex", tr("Galician translation"), "", QLocale::Galician },
+ { "", "cordata", tr("Esperanto translation"), "", QLocale::Esperanto },
+ { "Daniel E. Moctezuma", "", tr("Japanese translation"), "", QLocale::Japanese },
+ { "Daniel Meltzer", "hydrogen", tr("Various fixes and improvements") },
+ { "Daniel Pielmeier", "billie", tr("Gentoo maintainer") },
+ { "Daniel Steinmetz", "son", tr("Early beta tester and bughunter (on Vista™!)") },
+ { "David Planella", "", tr("Translation system fixes") },
+ { "David Sansome", "", tr("OSX Notification Center support") },
+ { "David Roden", "Bombe", tr("Fixes") },
+ { "Deniz Türkoglu", "", tr("Mac fixes") },
+ { "Dennis Schridde", "devurandom", tr("D-Bus notifications") },
+ { "", "derpella", tr("Polish translation"), "", QLocale::Polish },
+ { "Diego Pettenò", "Flameeyes", tr("Build system improvements") },
+ { "Dirk Rettschlag", "MarcLandis", tr("Formatting support and other input line improvements, many other fixes") },
+ { "", "Dorian", tr("French translation"), "", QLocale::French },
+ { "Drew Patridge", "LinuxDolt", tr("BluesTheme stylesheet") },
+ { "Edward Hades", "", tr("Russian translation"), "", QLocale::Russian },
+ { "Fabiano Francesconi", "elbryan", tr("Italian translation"), "", QLocale::Italian },
+ { "Felix Geyer", "debfx", tr("Certificate handling improvements") },
+ { "Florent Castelli", "", tr("Sanitize topic handling") },
+ { "Frederik M.J. Vestre", "freqmod", tr("Norwegian translation"), "", QLocale::Norwegian },
+ { "Gábor Németh", "ELITE_x", tr("Hungarian translation"), "", QLocale::Hungarian },
+ { "Gryllida A", "gry", tr("IRC parser improvements") },
+ { "H. İbrahim Güngör", "igungor", tr("Turkish translation"), "", QLocale::Turkish },
+ { "Harald Fernengel", "harryF", tr("Initial Qt5 support") },
+ { "Harald Sitter", "apachelogger", tr("{Ku|U}buntu packager, motivator, promoter") },
+ { "Hendrik Leppkes", "nevcairiel", tr("Various features") },
+ { "Henning Rohlfs", "honk", tr("Various fixes") },
+ { "J-P Nurmi", "", tr("Various fixes") },
+ { "Jaak Ristioja", "", tr("Bugfixes") },
+ { "Jason Lynch", "", tr("Bugfixes") },
+ { "Jens Arnold", "amiconn", tr("Postgres migration fixes") },
+ { "Jerome Leclanche", "Adys", tr("Context menu fixes") },
+ { "Jesper Thomschütz", "", tr("Various fixes") },
+ { "Jiri Grönroos", "", tr("Finnish translation"), "", QLocale::Finnish },
+ { "Johannes Huber", "johu", tr("Many fixes and improvements, bug triaging") },
+ { "John Hand", "nox", tr("Original \"All-Seeing Eye\" logo") },
+ { "Jonas Heese", "Dante", tr("Project founder, various improvements") },
+ { "Joshua T Corbin", "tvakah", tr("Various fixes") },
+ { "Jovan Jojkić", "", tr("Serbian translation"), "", QLocale::Serbian },
+ { "Jure Repinc", "JLP", tr("Slovenian translation"), "", QLocale::Slovenian },
+ { "Jussi Schultink", "jussi01", tr("Tireless tester, {Ku|U}buntu tester and lobbyist, liters of delicious Finnish alcohol") },
+ { "K. Ernest Lee", "iFire", tr("Qt5 porting help, Travis CI setup") },
+ { "Kevin Funk", "KRF", tr("German translation"), "", QLocale::German },
+ { "", "Larso", tr("Finnish translation"), "", QLocale::Finnish },
+ { "Lasse Liehu", "", tr("Finnish translation"), "", QLocale::Finnish },
+ { "Leo Franchi", "", tr("OSX improvements") },
+ { "Liudas Alisauskas", "", tr("Lithuanian translation"), "", QLocale::Lithuanian },
+ { "Luke Faraone", "", tr("Documentation fixes") },
+ { "Maia Kozheva", "", tr("Russian translation"), "", QLocale::Russian },
+ { "Marco Genise", "kaffeedoktor", tr("Ideas, hacking, initial motivation") },
+ { "Marco Paolone", "Quizzlo", tr("Italian translation"), "", QLocale::Italian },
+ { "Martin Mayer", "m4yer", tr("German translation"), "", QLocale::German },
+ { "Martin Sandsmark", "sandsmark", tr("Core and other fixes, QuasselDroid") },
+ { "Matthias Coy", "pennywise", tr("German translation"), "", QLocale::German },
+ { "Mattia Basaglia", "", tr("Fixes") },
+ { "Michael Groh", "brot", tr("German translation, fixes"), "", QLocale::German },
+ { "Michael Kedzierski", "ycros", tr("Mac fixes") },
+ { "Michael Marley", "mamarley", tr("Many fixes and improvements; Ubuntu live packages") },
+ { "Miguel Revilla", "", tr("Spanish translation"), "", QLocale::Spanish },
+ { "Nuno Pinheiro", "", tr("Tons of Oxygen icons including the Quassel logo") },
+ { "Patrick Lauer", "bonsaikitten", tr("Gentoo maintainer") },
+ { "Patrick von Reth", "TheOneRing", tr("MinGW support, SNORE backend, Windows packaging") },
+ { "Paul Klumpp", "Haudrauf", tr("Initial design and main window layout") },
+ { "Pavel Volkovitskiy", "int", tr("Early beta tester and bughunter") },
+ { "Per Nielsen", "", tr("Danish translation"), "", QLocale::Danish },
+ { "Pete Beardmore", "elbeardmorez", tr("Linewrap for input line") },
+ { "Ramanathan Sivagurunathan", "", tr("Bugfixes") },
+ { "Regis Perrin", "ZRegis", tr("French translation"), "", QLocale::French },
+ { "Rolf Eike Beer", "", tr("Build system fixes") },
+ { "Roscoe van Wyk", "", tr("Bugfixes") },
+ { "Rüdiger Sonderfeld", "ruediger", tr("Emacs keybindings") },
+ { "", "salnx", tr("Highlight configuration improvements") },
+ { "Scott Kitterman", "ScottK", tr("Kubuntu packager, (packaging/build system) bughunter") },
+ { "Sebastian Meyer", "", tr("Bugfixes") },
+ { "Sebastien Fricker", "", tr("Audio backend improvements") },
+ { "", "sfionov", tr("Russian translation"), "", QLocale::Russian },
+ { "Simon Philips", "", tr("Dutch translation"), "", QLocale::Dutch },
+ { "Sjors Gielen", "dazjorz", tr("Bugfixes") },
+ { "Stefanos Sofroniou", "", tr("Greek translation"), "", QLocale::Greek },
+ { "Stella Rouzi", "differentreality", tr("Greek translation"), "", QLocale::Greek },
+ { "Rafael Belmonte", "EagleScreen", tr("Spanish translation"), "", QLocale::Spanish },
+ { "Sergiu Bivol", "", tr("Romanian translation"), "", QLocale::Romanian },
+ { "Tae-Hoon Kwon", "", tr("Korean translation"), "", QLocale::Korean },
+ { "Terje Andersen", "tan", tr("Norwegian translation, documentation") },
+ { "Theo Chatzimichos", "tampakrap", tr("Greek translation"), "", QLocale::Greek },
+ { "Theofilos Intzoglou", "", tr("Greek translation"), "", QLocale::Greek },
+ { "Thomas Hogh", "Datafreak", tr("Former Windows builder") },
+ { "Thomas Müller", "", tr("Fixes, Debian packaging") },
+ { "Tim Schumacher", "xAFFE", tr("Fixes and feedback") },
+ { "", "ToBeFree", tr("German translation"), "", QLocale::German },
+ { "Tomáš Chvátal", "scarabeus", tr("Czech translation"), "", QLocale::Czech },
+ { "Vit Pelcak", "", tr("Czech translation"), "", QLocale::Czech },
+ { "Volkan Gezer", "", tr("Turkish translation"), "", QLocale::Turkish },
+ { "Yaohan Chen", "hagabaka", tr("Network detection improvements") },
+ { "Yuri Chornoivan", "", tr("Ukrainian translation"), "", QLocale::Ukrainian },
+ { "Zé", "", tr("Portuguese translation"), "", QLocale::Portuguese },
+ { "", "zeugma", tr("Turkish translation"), "", QLocale::Turkish }
+ });
+}
--- /dev/null
+/***************************************************************************
+ * Copyright (C) 2005-2015 by the Quassel Project *
+ * devel@quassel-irc.org *
+ * *
+ * This program is free software; you can redistribute it and/or modify *
+ * it under the terms of the GNU General Public License as published by *
+ * the Free Software Foundation; either version 2 of the License, or *
+ * (at your option) version 3. *
+ * *
+ * This program is distributed in the hope that it will be useful, *
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of *
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
+ * GNU General Public License for more details. *
+ * *
+ * You should have received a copy of the GNU General Public License *
+ * along with this program; if not, write to the *
+ * Free Software Foundation, Inc., *
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. *
+ ***************************************************************************/
+
+#pragma once
+
+#include <QLocale>
+
+#ifdef HAVE_KF5
+# include <KCoreAddons/KAboutData>
+#endif
+
+
+/**
+ * Represents a contributor or author for Quassel.
+ *
+ * This is used to show a list of contributors in the About Quassel dialog.
+ */
+class AboutPerson
+{
+public:
+ /**
+ * Constructor.
+ *
+ * @param[in] name The person's name (in the form "Firstname Surname")
+ * @param[in] nick The person's nickname, if applicable
+ * @param[in] task Things the person does or has done for the project
+ * @param[in] emailAddress The person's email address, if applicable
+ * @param[in] translatedLanguage The language the person helped translate (only applicable for translators)
+ */
+ AboutPerson(const QString &name, const QString &nick, const QString &task, const QString &emailAddress = QString(), QLocale::Language translatedLanguage = QLocale::C);
+
+ /**
+ * Gets the person's name.
+ *
+ * @returns The person's name
+ */
+ QString name() const;
+
+ /**
+ * Gets the person's nick.
+ *
+ * @returns The person's nick
+ */
+ QString nick() const;
+
+ /**
+ * Gets the person's task.
+ *
+ * @returns The person's task
+ */
+ QString task() const;
+
+ /**
+ * Gets the person's e-mail address.
+ *
+ * @returns The person's e-mail address
+ */
+ QString emailAddress() const;
+
+ /**
+ * Gets the language this person helped translate.
+ *
+ * @returns The language this person helped translate
+ */
+ QLocale::Language translatedLanguage() const;
+
+ /**
+ * Gets the person's formatted name and nick.
+ *
+ * @returns The person's name and nick formatted for combined output
+ */
+ QString prettyName() const;
+
+private:
+ QString _name; ///< The person's name
+ QString _nick; ///< The person's nick
+ QString _task; ///< The person's task
+ QString _emailAddress; ///< The person's email address
+ QLocale::Language _language; ///< The language the person helps translate
+};
+
+
+/**
+ * Holds a list of authors, contributors and translators.
+ *
+ * This class is meant to hold the list of people who contributed to Quassel, used for displaying
+ * the About Quassel dialog. Additionally, this class can provide a KAboutData object to be shown
+ * if KDE integration is enabled.
+ */
+class AboutData : public QObject
+{
+ Q_OBJECT
+public:
+ /**
+ * Default constructor.
+ *
+ * @param[in] parent The parent object, if applicable
+ */
+ AboutData(QObject *parent = nullptr);
+
+ /**
+ * Adds an author to the list of contributors.
+ *
+ * Authors are people who contributed a significant amount of code to Quassel.
+ *
+ * @param[in] author The author to add
+ * @returns A reference to this AboutData instance
+ */
+ AboutData &addAuthor(const AboutPerson &author);
+
+ /**
+ * Adds a list of authors to the list of contributors.
+ *
+ * This method allows the use of a brace initializer in order to easily add a long list of
+ * people.
+ *
+ * @param[in] authors A list of authors to add
+ * @returns A reference to this AboutData instance
+ */
+ AboutData &addAuthors(std::initializer_list<AboutPerson> authors);
+
+ /**
+ * Adds a contributor.
+ *
+ * @param[in] author The contributor to add
+ * @returns A reference to this AboutData instance
+ */
+ AboutData &addCredit(const AboutPerson &credit);
+
+ /**
+ * Adds a list of contributors.
+ *
+ * This method allows the use of brace initializers in order to easily add a long list of
+ * people.
+ *
+ * @param[in] authors A list of contributors to add
+ * @returns A reference to this AboutData instance
+ */
+ AboutData &addCredits(std::initializer_list<AboutPerson> credits);
+
+ /**
+ * Gets the list of authors stored in this AboutData instance.
+ *
+ * @returns A list of authors
+ */
+ QList<AboutPerson> authors() const;
+
+ /**
+ * Gets the list of non-author contributors stored in this AboutData instance.
+ *
+ * @returns A list of contributors
+ */
+ QList<AboutPerson> credits() const;
+
+#ifdef HAVE_KF5
+ /**
+ * Creates a KAboutData instance based on the contents of this AboutData instance.
+ *
+ * @returns A KAboutData instance holding the list of contributors as well as any additional
+ * data required for KAboutDialog and friends
+ */
+ KAboutData kAboutData() const;
+#endif
+
+ /**
+ * Fills the given AboutData instance with data relevant for Quassel itself.
+ *
+ * This method adds a (hardcoded) list of contributors to the given AboutData instance.
+ *
+ * @param[in,out] aboutData An existing AboutData instance to add Quassel's contributors to
+ */
+ static void setQuasselPersons(AboutData *aboutData);
+
+private:
+ QList<AboutPerson> _authors; ///< The list of authors
+ QList<AboutPerson> _credits; ///< The list of other contributors
+};
* Parts of this implementation are based on KDE's KActionCollection. *
***************************************************************************/
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
#include <QAction>
#include <QDebug>
}
-#endif /* HAVE_KDE4 */
+#endif /* HAVE_KDE */
* This is a subset of the API of KDE's KActionCollection. *
***************************************************************************/
-#ifndef ACTIONCOLLECTION_H_
-#define ACTIONCOLLECTION_H_
+#pragma once
-#ifndef HAVE_KDE4
+#ifndef HAVE_KDE
#include <QDebug>
#include <QList>
int ActionCollection::count() const { return actions().count(); }
bool ActionCollection::isEmpty() const { return actions().count(); }
-#else /* HAVE_KDE4 */
-
-#include <KActionCollection>
+#else /* HAVE_KDE */
+# ifdef HAVE_KDE4
+# include <KActionCollection>
+# else
+# include <KXmlGui/KActionCollection>
+# endif
class ActionCollection : public KActionCollection
{
explicit ActionCollection(QObject *parent) : KActionCollection(parent) {};
};
-
-#endif
-
-#endif
+#endif /* HAVE_KDE */
registerAction(BufferRemove, tr("Delete Chat(s)..."));
registerAction(BufferSwitchTo, tr("Go to Chat"));
+ registerAction(HideJoinPartQuit, tr("Joins/Parts/Quits"));
registerAction(HideJoin, tr("Joins"), true);
registerAction(HidePart, tr("Parts"), true);
registerAction(HideQuit, tr("Quits"), true);
registerAction(ShowIgnoreList, tr("Show Ignore List"));
QMenu *hideEventsMenu = new QMenu();
+ hideEventsMenu->addAction(action(HideJoinPartQuit));
+ hideEventsMenu->addSeparator();
hideEventsMenu->addAction(action(HideJoin));
hideEventsMenu->addAction(action(HidePart));
hideEventsMenu->addAction(action(HideQuit));
row++;
}
- Q_ASSERT(topLeftItem && bottomRightItem); // there should be one range left.
- sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem)));
+ if (topLeftItem && bottomRightItem) { // there should be one range left.
+ sourceSelection << QItemSelectionRange(mapToSource(createIndex(topLeftItem->pos(), left, topLeftItem)), mapToSource(createIndex(bottomRightItem->pos(), right, bottomRightItem)));
+ }
}
return sourceSelection;
}
+// NOTE: Window activation stuff seems to work just fine in Plasma 5 without requiring X11 hacks.
+// TODO: Evaluate cleaning all this up once we can get rid of Qt4/KDE4
+
// Code taken from KStatusNotifierItem for handling minimize/restore
bool GraphicalUi::checkMainWidgetVisibility(bool perform)
}
-void KCmdLineWrapper::addArgument(const QString &longName, const CliParserArg &arg)
+void KCmdLineWrapper::addArgument(const QString &longName_, const CliParserArg &arg)
{
+ QString longName = longName_;
+ if (arg.type == CliParserArg::CliArgOption && !arg.valueName.isEmpty())
+ longName += " <" + arg.valueName + ">";
+
if (arg.shortName != 0) {
- _cmdLineOptions.add(QByteArray().append(arg.shortName));
+ _cmdLineOptions.add(QByteArray(1, arg.shortName));
}
+
_cmdLineOptions.add(longName.toUtf8(), ki18n(arg.help.toUtf8()), arg.def.toUtf8());
}
cursor.clearSelection();
}
- if (color) {
- color = false;
+
+ if (color)
mircText.append('\x03');
- }
- if (underline) {
- underline = false;
+
+ if (underline)
mircText.append('\x1f');
- }
- if (italic) {
- italic = false;
+
+ if (italic)
mircText.append('\x1d');
- }
- if (bold) {
- bold = false;
+
+ if (bold)
mircText.append('\x02');
- }
return mircText;
}
{
Q_UNUSED(action)
+ if (type == HideJoinPartQuit) {
+ bool anyChecked = NetworkModelController::action(HideJoin)->isChecked();
+ anyChecked |= NetworkModelController::action(HidePart)->isChecked();
+ anyChecked |= NetworkModelController::action(HideQuit)->isChecked();
+
+ // If any are checked, uncheck them all.
+ // If none are checked, check them all.
+ bool newCheckedState = !anyChecked;
+ NetworkModelController::action(HideJoin)->setChecked(newCheckedState);
+ NetworkModelController::action(HidePart)->setChecked(newCheckedState);
+ NetworkModelController::action(HideQuit)->setChecked(newCheckedState);
+ }
+
int filter = 0;
if (NetworkModelController::action(HideJoin)->isChecked())
filter |= Message::Join | Message::NetsplitJoin;
filter |= Message::Topic;
switch (type) {
+ case HideJoinPartQuit:
case HideJoin:
case HidePart:
case HideQuit:
HideMode = 0x0500,
HideDayChange = 0x0600,
HideTopic = 0x0700,
+ HideJoinPartQuit = 0xd00,
HideUseDefaults = 0xe00,
HideApplyToAll = 0xf00,
QString styleSheet;
styleSheet += loadStyleSheet("file:///" + Quassel::findDataFilePath("stylesheets/default.qss"));
styleSheet += loadStyleSheet("file:///" + Quassel::configDirPath() + "settings.qss");
- if (s.value("UseCustomStyleSheet", false).toBool())
- styleSheet += loadStyleSheet("file:///" + s.value("CustomStyleSheetPath").toString(), true);
+ if (s.value("UseCustomStyleSheet", false).toBool()) {
+ QString customSheetPath(s.value("CustomStyleSheetPath").toString());
+ QString customSheet = loadStyleSheet("file:///" + customSheetPath, true);
+ if (customSheet.isEmpty()) {
+ // MIGRATION: changed default install path for data from /usr/share/apps to /usr/share
+ if (customSheetPath.startsWith("/usr/share/apps/quassel")) {
+ customSheetPath.replace(QRegExp("^/usr/share/apps"), "/usr/share");
+ customSheet = loadStyleSheet("file:///" + customSheetPath, true);
+ if (!customSheet.isEmpty()) {
+ s.setValue("CustomStyleSheetPath", customSheetPath);
+ qDebug() << "Custom stylesheet path migrated to" << customSheetPath;
+ }
+ }
+ }
+ styleSheet += customSheet;
+ }
styleSheet += loadStyleSheet("file:///" + Quassel::optionValue("qss"), true);
if (!styleSheet.isEmpty()) {