Compare commits
14 Commits
Author | SHA1 | Date | |
---|---|---|---|
321f0b03c8 | |||
d4cec645b5 | |||
a04693e39d | |||
3cce057545 | |||
9a44ae1fa5 | |||
85ff6c25ba | |||
3cc7db8eff | |||
|
ff9a591d6d | ||
8e3f10caff | |||
8bfe88929f | |||
9927bdc38b | |||
|
8083859541 | ||
|
030c374139 | ||
|
2c61b82924 |
@ -1,5 +1,13 @@
|
|||||||
# Changelog
|
# Changelog
|
||||||
|
|
||||||
|
## Squawk 0.2.4 (UNRELEASED)
|
||||||
|
### Bug fixes
|
||||||
|
- messages to the mucs get sent once again
|
||||||
|
|
||||||
|
### Improvements
|
||||||
|
- it's possible to build against Qt 6 now
|
||||||
|
- got rid of deprecated SimpleCrypt library
|
||||||
|
|
||||||
## Squawk 0.2.3 (February 04, 2024)
|
## Squawk 0.2.3 (February 04, 2024)
|
||||||
### Bug fixes
|
### Bug fixes
|
||||||
- "Add contact" and "Join conference" menu are enabled once again (pavavno)!
|
- "Add contact" and "Join conference" menu are enabled once again (pavavno)!
|
||||||
|
@ -1,12 +1,12 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.16)
|
||||||
project(squawk VERSION 0.2.3 LANGUAGES CXX)
|
project(squawk VERSION 0.2.4 LANGUAGES CXX)
|
||||||
|
|
||||||
cmake_policy(SET CMP0076 NEW)
|
cmake_policy(SET CMP0076 NEW)
|
||||||
cmake_policy(SET CMP0077 NEW)
|
cmake_policy(SET CMP0077 NEW)
|
||||||
cmake_policy(SET CMP0079 NEW)
|
cmake_policy(SET CMP0079 NEW)
|
||||||
|
cmake_policy(SET CMP0167 NEW)
|
||||||
set(CMAKE_CXX_STANDARD 17)
|
set(CMAKE_CXX_STANDARD 17)
|
||||||
|
|
||||||
set(QT_VERSION_MAJOR 5)
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
set(CMAKE_AUTOMOC ON)
|
||||||
set(CMAKE_AUTOUIC ON)
|
set(CMAKE_AUTOUIC ON)
|
||||||
set(CMAKE_AUTORCC ON)
|
set(CMAKE_AUTORCC ON)
|
||||||
@ -33,7 +33,7 @@ option(SYSTEM_LMDBAL "Use system lmdbal lib" ON)
|
|||||||
option(WITH_KWALLET "Build KWallet support module" ON)
|
option(WITH_KWALLET "Build KWallet support module" ON)
|
||||||
option(WITH_KIO "Build KIO support module" ON)
|
option(WITH_KIO "Build KIO support module" ON)
|
||||||
option(WITH_KCONFIG "Build KConfig support module" ON)
|
option(WITH_KCONFIG "Build KConfig support module" ON)
|
||||||
option(WITH_OMEMO "Build OMEMO support module" OFF) #it should be off by default untill I sourt the problems out
|
option(WITH_OMEMO "Build OMEMO support module" OFF) #it should be off by default untill I sort the problems out
|
||||||
|
|
||||||
# Dependencies
|
# Dependencies
|
||||||
## Qt
|
## Qt
|
||||||
@ -67,9 +67,9 @@ endif ()
|
|||||||
|
|
||||||
## KIO
|
## KIO
|
||||||
if (WITH_KIO)
|
if (WITH_KIO)
|
||||||
find_package(KF5KIO CONFIG)
|
find_package(KF${QT_VERSION_MAJOR}KIO CONFIG)
|
||||||
|
|
||||||
if (NOT KF5KIO_FOUND)
|
if (NOT KF${QT_VERSION_MAJOR}KIO_FOUND)
|
||||||
set(WITH_KIO OFF)
|
set(WITH_KIO OFF)
|
||||||
message("KIO package wasn't found, KIO support modules wouldn't be built")
|
message("KIO package wasn't found, KIO support modules wouldn't be built")
|
||||||
else ()
|
else ()
|
||||||
@ -80,9 +80,9 @@ endif ()
|
|||||||
|
|
||||||
## KWallet
|
## KWallet
|
||||||
if (WITH_KWALLET)
|
if (WITH_KWALLET)
|
||||||
find_package(KF5Wallet CONFIG)
|
find_package(KF${QT_VERSION_MAJOR}Wallet CONFIG)
|
||||||
|
|
||||||
if (NOT KF5Wallet_FOUND)
|
if (NOT KF${QT_VERSION_MAJOR}Wallet_FOUND)
|
||||||
set(WITH_KWALLET OFF)
|
set(WITH_KWALLET OFF)
|
||||||
message("KWallet package wasn't found, KWallet support module wouldn't be built")
|
message("KWallet package wasn't found, KWallet support module wouldn't be built")
|
||||||
else ()
|
else ()
|
||||||
@ -93,13 +93,13 @@ endif ()
|
|||||||
|
|
||||||
## KConfig
|
## KConfig
|
||||||
if (WITH_KCONFIG)
|
if (WITH_KCONFIG)
|
||||||
find_package(KF5Config CONFIG)
|
find_package(KF${QT_VERSION_MAJOR}Config CONFIG)
|
||||||
if (NOT KF5Config_FOUND)
|
if (NOT KF${QT_VERSION_MAJOR}Config_FOUND)
|
||||||
set(WITH_KCONFIG OFF)
|
set(WITH_KCONFIG OFF)
|
||||||
message("KConfig package wasn't found, KConfig support modules wouldn't be built")
|
message("KConfig package wasn't found, KConfig support modules wouldn't be built")
|
||||||
else()
|
else()
|
||||||
find_package(KF5ConfigWidgets CONFIG)
|
find_package(KF${QT_VERSION_MAJOR}ConfigWidgets CONFIG)
|
||||||
if (NOT KF5ConfigWidgets_FOUND)
|
if (NOT KF${QT_VERSION_MAJOR}ConfigWidgets_FOUND)
|
||||||
set(WITH_KCONFIG OFF)
|
set(WITH_KCONFIG OFF)
|
||||||
message("KConfigWidgets package wasn't found, KConfigWidgets support modules wouldn't be built")
|
message("KConfigWidgets package wasn't found, KConfigWidgets support modules wouldn't be built")
|
||||||
else()
|
else()
|
||||||
@ -113,12 +113,12 @@ endif()
|
|||||||
## QXmpp
|
## QXmpp
|
||||||
if (SYSTEM_QXMPP)
|
if (SYSTEM_QXMPP)
|
||||||
if (WITH_OMEMO)
|
if (WITH_OMEMO)
|
||||||
find_package(QXmpp CONFIG COMPONENTS Omemo)
|
find_package(QXmppQt${QT_VERSION_MAJOR} CONFIG COMPONENTS Omemo)
|
||||||
else ()
|
else ()
|
||||||
find_package(QXmpp CONFIG)
|
find_package(QXmppQt${QT_VERSION_MAJOR} CONFIG)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (NOT QXmpp_FOUND)
|
if (NOT QXmppQt${QT_VERSION_MAJOR}_FOUND)
|
||||||
set(SYSTEM_QXMPP OFF)
|
set(SYSTEM_QXMPP OFF)
|
||||||
message("QXmpp package wasn't found, trying to build with bundled QXmpp")
|
message("QXmpp package wasn't found, trying to build with bundled QXmpp")
|
||||||
else ()
|
else ()
|
||||||
@ -150,8 +150,8 @@ endif ()
|
|||||||
|
|
||||||
## LMDBAL
|
## LMDBAL
|
||||||
if (SYSTEM_LMDBAL)
|
if (SYSTEM_LMDBAL)
|
||||||
find_package(lmdbal)
|
find_package(lmdbalqt${QT_VERSION_MAJOR})
|
||||||
if (NOT lmdbal_FOUND)
|
if (NOT lmdbalqt${QT_VERSION_MAJOR}_FOUND)
|
||||||
set(SYSTEM_LMDBAL OFF)
|
set(SYSTEM_LMDBAL OFF)
|
||||||
message("LMDBAL package wasn't found, trying to build with bundled LMDBAL")
|
message("LMDBAL package wasn't found, trying to build with bundled LMDBAL")
|
||||||
else ()
|
else ()
|
||||||
@ -161,9 +161,11 @@ else()
|
|||||||
message("Building with bundled LMDBAL")
|
message("Building with bundled LMDBAL")
|
||||||
set(BUILD_STATIC ON)
|
set(BUILD_STATIC ON)
|
||||||
add_subdirectory(external/lmdbal)
|
add_subdirectory(external/lmdbal)
|
||||||
add_library(LMDBAL::LMDBAL ALIAS LMDBAL)
|
add_library(LMDBALQT${QT_VERSION_MAJOR}::LMDBALQT${QT_VERSION_MAJOR} ALIAS LMDBAL)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
find_package(OpenSSL REQUIRED)
|
||||||
|
|
||||||
## Linking
|
## Linking
|
||||||
target_link_libraries(squawk
|
target_link_libraries(squawk
|
||||||
PRIVATE
|
PRIVATE
|
||||||
@ -173,9 +175,9 @@ target_link_libraries(squawk
|
|||||||
Qt${QT_VERSION_MAJOR}::Network
|
Qt${QT_VERSION_MAJOR}::Network
|
||||||
Qt${QT_VERSION_MAJOR}::Gui
|
Qt${QT_VERSION_MAJOR}::Gui
|
||||||
Qt${QT_VERSION_MAJOR}::Xml
|
Qt${QT_VERSION_MAJOR}::Xml
|
||||||
LMDBAL::LMDBAL
|
LMDBALQT${QT_VERSION_MAJOR}::LMDBALQT${QT_VERSION_MAJOR}
|
||||||
|
OpenSSL::Crypto
|
||||||
QXmpp::QXmpp
|
QXmpp::QXmpp
|
||||||
simpleCrypt
|
|
||||||
)
|
)
|
||||||
|
|
||||||
if (WITH_OMEMO)
|
if (WITH_OMEMO)
|
||||||
@ -211,9 +213,13 @@ if(CMAKE_COMPILER_IS_GNUCXX)
|
|||||||
target_compile_options(squawk PRIVATE ${COMPILE_OPTIONS})
|
target_compile_options(squawk PRIVATE ${COMPILE_OPTIONS})
|
||||||
endif(CMAKE_COMPILER_IS_GNUCXX)
|
endif(CMAKE_COMPILER_IS_GNUCXX)
|
||||||
|
|
||||||
|
# I am not really sure about this solution
|
||||||
|
# This should enable plugins to be found in path like /usr/lib/squawk instead of just /usr/lib
|
||||||
|
set(PLUGIN_PATH "${CMAKE_INSTALL_PREFIX}/${CMAKE_INSTALL_LIBDIR}/squawk")
|
||||||
|
add_compile_definitions(PLUGIN_PATH="${PLUGIN_PATH}")
|
||||||
|
|
||||||
add_subdirectory(main)
|
add_subdirectory(main)
|
||||||
add_subdirectory(core)
|
add_subdirectory(core)
|
||||||
add_subdirectory(external/simpleCrypt)
|
|
||||||
add_subdirectory(packaging)
|
add_subdirectory(packaging)
|
||||||
add_subdirectory(plugins)
|
add_subdirectory(plugins)
|
||||||
add_subdirectory(resources)
|
add_subdirectory(resources)
|
||||||
|
@ -4,12 +4,12 @@
|
|||||||
[![AUR version](https://img.shields.io/aur/version/squawk?style=flat-square)](https://aur.archlinux.org/packages/squawk/)
|
[![AUR version](https://img.shields.io/aur/version/squawk?style=flat-square)](https://aur.archlinux.org/packages/squawk/)
|
||||||
[![Liberapay patrons](https://img.shields.io/liberapay/patrons/macaw.me?logo=liberapay&style=flat-square)](https://liberapay.com/macaw.me)
|
[![Liberapay patrons](https://img.shields.io/liberapay/patrons/macaw.me?logo=liberapay&style=flat-square)](https://liberapay.com/macaw.me)
|
||||||
|
|
||||||
![Squawk screenshot](https://macaw.me/images/squawk/0.2.2.png)
|
![Squawk screenshot](https://macaw.me/projects/squawk/0.2.2.png)
|
||||||
|
|
||||||
### Prerequisites
|
### Prerequisites
|
||||||
|
|
||||||
- QT 5.12 *(lower versions might work but it wasn't tested)*
|
- QT 5 or 6
|
||||||
- CMake 3.4 or higher
|
- CMake 3.10 or higher
|
||||||
- qxmpp 1.1.0 or higher
|
- qxmpp 1.1.0 or higher
|
||||||
- LMDBAL (my own [library](https://git.macaw.me/blue/lmdbal) for lmdb)
|
- LMDBAL (my own [library](https://git.macaw.me/blue/lmdbal) for lmdb)
|
||||||
- KDE Frameworks: kwallet (optional)
|
- KDE Frameworks: kwallet (optional)
|
||||||
@ -108,6 +108,7 @@ Here is the list of keys you can pass to configuration phase of `cmake ..`:
|
|||||||
- `WITH_KIO` - `True` builds the `KIO` capability module if `KIO` is installed and if not goes to `False`. `False` disables `KIO` support (default is `True`)
|
- `WITH_KIO` - `True` builds the `KIO` capability module if `KIO` is installed and if not goes to `False`. `False` disables `KIO` support (default is `True`)
|
||||||
- `WITH_KCONFIG` - `True` builds the `KConfig` and `KConfigWidgets` capability module if such packages are installed and if not goes to `False`. `False` disables `KConfig` and `KConfigWidgets` support (default is `True`)
|
- `WITH_KCONFIG` - `True` builds the `KConfig` and `KConfigWidgets` capability module if such packages are installed and if not goes to `False`. `False` disables `KConfig` and `KConfigWidgets` support (default is `True`)
|
||||||
- `WITH_OMEMO` - `True` builds the OMEMO encryption, requires `qxmpp` of version >= 1.5.0 built with OMEMO support. `False` disables OMEMO support (default is `False`)
|
- `WITH_OMEMO` - `True` builds the OMEMO encryption, requires `qxmpp` of version >= 1.5.0 built with OMEMO support. `False` disables OMEMO support (default is `False`)
|
||||||
|
- `QT_VERSION_MAJOR` - `6` builds against Qt 6, `5` builds against Qt 6, corresponding version of lmdbal and qxmpp should be installed. By default it picks your system default Qt
|
||||||
|
|
||||||
## License
|
## License
|
||||||
|
|
||||||
|
@ -23,10 +23,7 @@ set(HEADER_FILES
|
|||||||
squawk.h
|
squawk.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE ${SOURCE_FILES})
|
||||||
${SOURCE_FILES}
|
|
||||||
${HEADER_FILES}
|
|
||||||
)
|
|
||||||
|
|
||||||
target_include_directories(squawk PRIVATE ${LMDB_INCLUDE_DIRS})
|
target_include_directories(squawk PRIVATE ${LMDB_INCLUDE_DIRS})
|
||||||
|
|
||||||
@ -34,3 +31,4 @@ add_subdirectory(handlers)
|
|||||||
add_subdirectory(passwordStorageEngines)
|
add_subdirectory(passwordStorageEngines)
|
||||||
add_subdirectory(components)
|
add_subdirectory(components)
|
||||||
add_subdirectory(delayManager)
|
add_subdirectory(delayManager)
|
||||||
|
add_subdirectory(utils)
|
||||||
|
@ -81,6 +81,7 @@ Core::Account::Account(
|
|||||||
config.setDomain(p_server);
|
config.setDomain(p_server);
|
||||||
config.setPassword(p_password);
|
config.setPassword(p_password);
|
||||||
config.setAutoAcceptSubscriptions(true);
|
config.setAutoAcceptSubscriptions(true);
|
||||||
|
// config.setIgnoreSslErrors(true);
|
||||||
// config.setAutoReconnectionEnabled(false);
|
// config.setAutoReconnectionEnabled(false);
|
||||||
delay = new DelayManager::Manager(getBareJid());
|
delay = new DelayManager::Manager(getBareJid());
|
||||||
QObject::connect(delay, &DelayManager::Manager::gotInfo, this, &Account::infoReady);
|
QObject::connect(delay, &DelayManager::Manager::gotInfo, this, &Account::infoReady);
|
||||||
|
@ -12,7 +12,4 @@ set(HEADER_FILES
|
|||||||
archive.h
|
archive.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE ${SOURCE_FILES})
|
||||||
${SOURCE_FILES}
|
|
||||||
${HEADER_FILES}
|
|
||||||
)
|
|
||||||
|
@ -550,10 +550,8 @@ void Core::NetworkAccess::moveFilesDirectory(const QString& newPath) {
|
|||||||
QDir dir(currentPath);
|
QDir dir(currentPath);
|
||||||
bool success = true;
|
bool success = true;
|
||||||
qDebug() << "moving" << currentPath << "to" << newPath;
|
qDebug() << "moving" << currentPath << "to" << newPath;
|
||||||
for (QFileInfo fileInfo : dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System)) {
|
for (QString fileName : dir.entryList(QDir::Files | QDir::Dirs | QDir::NoDotAndDotDot | QDir::Hidden | QDir::System))
|
||||||
QString fileName = fileInfo.fileName();
|
|
||||||
success = dir.rename(fileName, newPath + QDir::separator() + fileName) && success;
|
success = dir.rename(fileName, newPath + QDir::separator() + fileName) && success;
|
||||||
}
|
|
||||||
|
|
||||||
if (!success)
|
if (!success)
|
||||||
qDebug() << "couldn't move downloads directory, most probably downloads will be broken";
|
qDebug() << "couldn't move downloads directory, most probably downloads will be broken";
|
||||||
|
@ -431,7 +431,7 @@ QMap<QString, QVariant> Core::MessageHandler::getChanges(Shared::Message& data,
|
|||||||
}
|
}
|
||||||
|
|
||||||
QXmppMessage Core::MessageHandler::createPacket(const Shared::Message& data, const QDateTime& time, const QString& originalId) const {
|
QXmppMessage Core::MessageHandler::createPacket(const Shared::Message& data, const QDateTime& time, const QString& originalId) const {
|
||||||
QXmppMessage msg(acc->getFullJid(), data.getTo(), data.getBody(), data.getThread());
|
QXmppMessage msg(QString(), data.getTo(), data.getBody(), data.getThread());
|
||||||
QString id(data.getId());
|
QString id(data.getId());
|
||||||
|
|
||||||
if (originalId.size() > 0)
|
if (originalId.size() > 0)
|
||||||
@ -492,7 +492,7 @@ void Core::MessageHandler::prepareUpload(const Shared::Message& data, bool newMe
|
|||||||
QFileInfo file(path);
|
QFileInfo file(path);
|
||||||
if (file.exists() && file.isReadable()) {
|
if (file.exists() && file.isReadable()) {
|
||||||
pendingStateMessages.insert(std::make_pair(id, jid));
|
pendingStateMessages.insert(std::make_pair(id, jid));
|
||||||
uploadingSlotsQueue.emplace_back(path, id);
|
uploadingSlotsQueue.emplace_back(file, id);
|
||||||
if (uploadingSlotsQueue.size() == 1)
|
if (uploadingSlotsQueue.size() == 1)
|
||||||
acc->um->requestUploadSlot(file);
|
acc->um->requestUploadSlot(file);
|
||||||
} else {
|
} else {
|
||||||
@ -505,10 +505,10 @@ void Core::MessageHandler::onUploadSlotReceived(const QXmppHttpUploadSlotIq& slo
|
|||||||
if (uploadingSlotsQueue.size() == 0) {
|
if (uploadingSlotsQueue.size() == 0) {
|
||||||
qDebug() << "HTTP Upload manager of account" << acc->name << "reports about success requesting upload slot, but none was requested";
|
qDebug() << "HTTP Upload manager of account" << acc->name << "reports about success requesting upload slot, but none was requested";
|
||||||
} else {
|
} else {
|
||||||
const std::pair<QString, QString>& pair = uploadingSlotsQueue.front();
|
const std::pair<QFileInfo, QString>& pair = uploadingSlotsQueue.front();
|
||||||
const QString& mId = pair.second;
|
const QString& mId = pair.second;
|
||||||
QString palJid = pendingStateMessages.at(mId);
|
QString palJid = pendingStateMessages.at(mId);
|
||||||
acc->network->uploadFile({acc->name, palJid, mId}, pair.first, slot.putUrl(), slot.getUrl(), slot.putHeaders());
|
acc->network->uploadFile({acc->name, palJid, mId}, pair.first.path(), slot.putUrl(), slot.getUrl(), slot.putHeaders());
|
||||||
|
|
||||||
uploadingSlotsQueue.pop_front();
|
uploadingSlotsQueue.pop_front();
|
||||||
if (uploadingSlotsQueue.size() > 0)
|
if (uploadingSlotsQueue.size() > 0)
|
||||||
@ -522,7 +522,7 @@ void Core::MessageHandler::onUploadSlotRequestFailed(const QXmppHttpUploadReques
|
|||||||
qDebug() << "HTTP Upload manager of account" << acc->name << "reports about an error requesting upload slot, but none was requested";
|
qDebug() << "HTTP Upload manager of account" << acc->name << "reports about an error requesting upload slot, but none was requested";
|
||||||
qDebug() << err;
|
qDebug() << err;
|
||||||
} else {
|
} else {
|
||||||
const std::pair<QString, QString>& pair = uploadingSlotsQueue.front();
|
const std::pair<QFileInfo, QString>& pair = uploadingSlotsQueue.front();
|
||||||
qDebug() << "Error requesting upload slot for file" << pair.first << "in account" << acc->name << ":" << err;
|
qDebug() << "Error requesting upload slot for file" << pair.first << "in account" << acc->name << ":" << err;
|
||||||
handleUploadError(pendingStateMessages.at(pair.second), pair.second, err);
|
handleUploadError(pendingStateMessages.at(pair.second), pair.second, err);
|
||||||
|
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
#include <deque>
|
#include <deque>
|
||||||
#include <map>
|
#include <map>
|
||||||
@ -81,7 +82,7 @@ private:
|
|||||||
Account* acc;
|
Account* acc;
|
||||||
std::map<QString, QString> pendingStateMessages; //key is message id, value is JID
|
std::map<QString, QString> pendingStateMessages; //key is message id, value is JID
|
||||||
std::map<QString, QString> pendingCorrectionMessages; //key is new mesage, value is originalOne
|
std::map<QString, QString> pendingCorrectionMessages; //key is new mesage, value is originalOne
|
||||||
std::deque<std::pair<QString, QString>> uploadingSlotsQueue;
|
std::deque<std::pair<QFileInfo, QString>> uploadingSlotsQueue;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
if (WITH_KWALLET)
|
if (WITH_KWALLET)
|
||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE kwallet.cpp)
|
||||||
kwallet.cpp
|
|
||||||
kwallet.h
|
|
||||||
)
|
|
||||||
|
|
||||||
add_subdirectory(wrappers)
|
add_subdirectory(wrappers)
|
||||||
target_include_directories(squawk PRIVATE $<TARGET_PROPERTY:KF5::Wallet,INTERFACE_INCLUDE_DIRECTORIES>)
|
target_include_directories(squawk PRIVATE $<TARGET_PROPERTY:KF${QT_VERSION_MAJOR}::Wallet,INTERFACE_INCLUDE_DIRECTORIES>)
|
||||||
endif ()
|
endif ()
|
||||||
|
@ -28,7 +28,8 @@ Core::PSE::KWallet::CreateFolder Core::PSE::KWallet::createFolder = 0;
|
|||||||
Core::PSE::KWallet::SetFolder Core::PSE::KWallet::setFolder = 0;
|
Core::PSE::KWallet::SetFolder Core::PSE::KWallet::setFolder = 0;
|
||||||
|
|
||||||
Core::PSE::KWallet::SupportState Core::PSE::KWallet::sState = Core::PSE::KWallet::initial;
|
Core::PSE::KWallet::SupportState Core::PSE::KWallet::sState = Core::PSE::KWallet::initial;
|
||||||
QLibrary Core::PSE::KWallet::lib("kwalletWrapper");
|
|
||||||
|
QLibrary Core::PSE::KWallet::lib(QString("%1/kwalletWrapper").arg(PLUGIN_PATH));
|
||||||
|
|
||||||
Core::PSE::KWallet::KWallet():
|
Core::PSE::KWallet::KWallet():
|
||||||
QObject(),
|
QObject(),
|
||||||
|
@ -27,7 +27,7 @@
|
|||||||
#include <map>
|
#include <map>
|
||||||
#include <set>
|
#include <set>
|
||||||
|
|
||||||
#include <KF5/KWallet/KWallet>
|
#include <KWallet>
|
||||||
|
|
||||||
namespace Core {
|
namespace Core {
|
||||||
namespace PSE {
|
namespace PSE {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
add_library(kwalletWrapper SHARED kwallet.cpp)
|
add_library(kwalletWrapper SHARED kwallet.cpp)
|
||||||
target_link_libraries(kwalletWrapper PRIVATE KF5::Wallet)
|
|
||||||
|
|
||||||
install(TARGETS kwalletWrapper LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
target_link_libraries(kwalletWrapper PRIVATE KF${QT_VERSION_MAJOR}::Wallet)
|
||||||
|
|
||||||
|
install(TARGETS kwalletWrapper LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/squawk)
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <KF5/KWallet/KWallet>
|
#include <KWallet>
|
||||||
|
|
||||||
extern "C" KWallet::Wallet* openWallet(const QString &name, WId w, KWallet::Wallet::OpenType ot = KWallet::Wallet::Synchronous) {
|
extern "C" KWallet::Wallet* openWallet(const QString &name, WId w, KWallet::Wallet::OpenType ot = KWallet::Wallet::Synchronous) {
|
||||||
return KWallet::Wallet::openWallet(name, w, ot);
|
return KWallet::Wallet::openWallet(name, w, ot);
|
||||||
|
@ -22,6 +22,8 @@
|
|||||||
#include <QDir>
|
#include <QDir>
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
|
|
||||||
|
#include "utils/jammer.h"
|
||||||
|
|
||||||
Core::Squawk::Squawk(QObject* parent):
|
Core::Squawk::Squawk(QObject* parent):
|
||||||
QObject(parent),
|
QObject(parent),
|
||||||
accounts(),
|
accounts(),
|
||||||
@ -29,10 +31,10 @@ Core::Squawk::Squawk(QObject* parent):
|
|||||||
state(Shared::Availability::offline),
|
state(Shared::Availability::offline),
|
||||||
network(),
|
network(),
|
||||||
isInitialized(false),
|
isInitialized(false),
|
||||||
clientCache(),
|
|
||||||
#ifdef WITH_KWALLET
|
#ifdef WITH_KWALLET
|
||||||
kwallet()
|
kwallet(),
|
||||||
#endif
|
#endif
|
||||||
|
clientCache()
|
||||||
{
|
{
|
||||||
connect(&network, &NetworkAccess::loadFileProgress, this, &Squawk::fileProgress);
|
connect(&network, &NetworkAccess::loadFileProgress, this, &Squawk::fileProgress);
|
||||||
connect(&network, &NetworkAccess::loadFileError, this, &Squawk::fileError);
|
connect(&network, &NetworkAccess::loadFileError, this, &Squawk::fileError);
|
||||||
@ -71,7 +73,6 @@ void Core::Squawk::stop() {
|
|||||||
QSettings settings;
|
QSettings settings;
|
||||||
settings.beginGroup("core");
|
settings.beginGroup("core");
|
||||||
settings.beginWriteArray("accounts");
|
settings.beginWriteArray("accounts");
|
||||||
SimpleCrypt crypto(passwordHash);
|
|
||||||
for (std::deque<Account*>::size_type i = 0; i < accounts.size(); ++i) {
|
for (std::deque<Account*>::size_type i = 0; i < accounts.size(); ++i) {
|
||||||
settings.setArrayIndex(i);
|
settings.setArrayIndex(i);
|
||||||
Account* acc = accounts[i];
|
Account* acc = accounts[i];
|
||||||
@ -84,7 +85,7 @@ void Core::Squawk::stop() {
|
|||||||
password = acc->getPassword();
|
password = acc->getPassword();
|
||||||
break;
|
break;
|
||||||
case Shared::AccountPassword::jammed:
|
case Shared::AccountPassword::jammed:
|
||||||
password = crypto.encryptToString(acc->getPassword());
|
password = Jammer::encrypt(acc->getPassword(), passwordHash);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -697,17 +698,16 @@ void Core::Squawk::readSettings() {
|
|||||||
settings.value("passwordType", static_cast<int>(Shared::AccountPassword::plain)).toInt()
|
settings.value("passwordType", static_cast<int>(Shared::AccountPassword::plain)).toInt()
|
||||||
);
|
);
|
||||||
|
|
||||||
|
QString name = settings.value("name").toString();
|
||||||
QString password = settings.value("password", "").toString();
|
QString password = settings.value("password", "").toString();
|
||||||
if (passwordType == Shared::AccountPassword::jammed) {
|
if (passwordType == Shared::AccountPassword::jammed)
|
||||||
SimpleCrypt crypto(passwordHash);
|
password = Jammer::decrypt(password, passwordHash);
|
||||||
password = crypto.decryptToString(password);
|
|
||||||
}
|
|
||||||
|
|
||||||
addAccount(
|
addAccount(
|
||||||
settings.value("login").toString(),
|
settings.value("login").toString(),
|
||||||
settings.value("server").toString(),
|
settings.value("server").toString(),
|
||||||
password,
|
password,
|
||||||
settings.value("name").toString(),
|
name,
|
||||||
settings.value("resource").toString(),
|
settings.value("resource").toString(),
|
||||||
settings.value("active").toBool(),
|
settings.value("active").toBool(),
|
||||||
passwordType
|
passwordType
|
||||||
|
@ -33,7 +33,6 @@
|
|||||||
#include "shared/global.h"
|
#include "shared/global.h"
|
||||||
#include "shared/info.h"
|
#include "shared/info.h"
|
||||||
#include "shared/clientinfo.h"
|
#include "shared/clientinfo.h"
|
||||||
#include "external/simpleCrypt/simplecrypt.h"
|
|
||||||
|
|
||||||
#include <core/components/clientcache.h>
|
#include <core/components/clientcache.h>
|
||||||
#include <core/components/networkaccess.h>
|
#include <core/components/networkaccess.h>
|
||||||
@ -42,10 +41,8 @@
|
|||||||
#include "passwordStorageEngines/kwallet.h"
|
#include "passwordStorageEngines/kwallet.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace Core
|
namespace Core {
|
||||||
{
|
class Squawk : public QObject {
|
||||||
class Squawk : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -140,12 +137,13 @@ private:
|
|||||||
Shared::Availability state;
|
Shared::Availability state;
|
||||||
NetworkAccess network;
|
NetworkAccess network;
|
||||||
bool isInitialized;
|
bool isInitialized;
|
||||||
ClientCache clientCache;
|
|
||||||
|
|
||||||
#ifdef WITH_KWALLET
|
#ifdef WITH_KWALLET
|
||||||
PSE::KWallet kwallet;
|
PSE::KWallet kwallet;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
ClientCache clientCache;
|
||||||
|
|
||||||
private slots:
|
private slots:
|
||||||
void addAccount(
|
void addAccount(
|
||||||
const QString& login,
|
const QString& login,
|
||||||
|
9
core/utils/CMakeLists.txt
Normal file
9
core/utils/CMakeLists.txt
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
set(SOURCE_FILES
|
||||||
|
jammer.cpp
|
||||||
|
)
|
||||||
|
|
||||||
|
set(HEADER_FILES
|
||||||
|
jammer.h
|
||||||
|
)
|
||||||
|
|
||||||
|
target_sources(squawk PRIVATE ${SOURCE_FILES})
|
94
core/utils/jammer.cpp
Normal file
94
core/utils/jammer.cpp
Normal file
@ -0,0 +1,94 @@
|
|||||||
|
/*
|
||||||
|
* Squawk messenger.
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "jammer.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
|
#include <openssl/evp.h>
|
||||||
|
#include <openssl/err.h>
|
||||||
|
|
||||||
|
struct CipherCtxDeleter {
|
||||||
|
void operator()(EVP_CIPHER_CTX* ctx) const {
|
||||||
|
EVP_CIPHER_CTX_free(ctx);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
typedef std::unique_ptr<EVP_CIPHER_CTX, CipherCtxDeleter> CipherCtx;
|
||||||
|
|
||||||
|
QString Core::Jammer::encrypt(const QString& plaintext, qint64 key) {
|
||||||
|
QByteArray encryptedData = process(plaintext.toUtf8(), intToKey(key), true);
|
||||||
|
|
||||||
|
return QString::fromUtf8(encryptedData.toHex());
|
||||||
|
}
|
||||||
|
|
||||||
|
QString Core::Jammer::decrypt(const QString& ciphertext, qint64 key) {
|
||||||
|
QByteArray encryptedData = QByteArray::fromHex(ciphertext.toUtf8());
|
||||||
|
QByteArray decryptedData = process(encryptedData, intToKey(key), false);
|
||||||
|
|
||||||
|
return QString::fromUtf8(decryptedData);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string Core::Jammer::getOpenSSLErrorString() {
|
||||||
|
unsigned long errCode = ERR_get_error();
|
||||||
|
if (errCode == 0) {
|
||||||
|
return "No OpenSSL error";
|
||||||
|
}
|
||||||
|
const char *errMsg = ERR_reason_error_string(errCode);
|
||||||
|
return errMsg ? std::string(errMsg) : "Unknown OpenSSL error";
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Core::Jammer::process(const QByteArray& input, const QByteArray& key, bool encrypt) {
|
||||||
|
CipherCtx ctx(EVP_CIPHER_CTX_new());
|
||||||
|
if (!ctx)
|
||||||
|
throw std::runtime_error("Failed to create password jammer context");
|
||||||
|
|
||||||
|
QByteArray output(input.size() + 16, 0);
|
||||||
|
int outputLength = 0;
|
||||||
|
int finalLength = 0;
|
||||||
|
|
||||||
|
if (!ctx)
|
||||||
|
throw std::runtime_error("Failed to create EVP_CIPHER_CTX: " + getOpenSSLErrorString());
|
||||||
|
|
||||||
|
if (EVP_CipherInit_ex(ctx.get(), EVP_chacha20(), nullptr, toUChar(key), nullptr, encrypt) != 1)
|
||||||
|
throw std::runtime_error("EVP_CipherInit_ex failed. " + getOpenSSLErrorString());
|
||||||
|
|
||||||
|
if (EVP_CipherUpdate(ctx.get(), toUChar(output), &outputLength, toUChar(input), input.size()) != 1)
|
||||||
|
throw std::runtime_error("EVP_CipherUpdate failed. " + getOpenSSLErrorString());
|
||||||
|
|
||||||
|
if (EVP_CipherFinal_ex(ctx.get(), toUChar(output) + outputLength, &finalLength) != 1)
|
||||||
|
throw std::runtime_error("EVP_CipherFinal_ex failed. " + getOpenSSLErrorString());
|
||||||
|
|
||||||
|
output.resize(outputLength + finalLength);
|
||||||
|
|
||||||
|
return output;
|
||||||
|
}
|
||||||
|
|
||||||
|
QByteArray Core::Jammer::intToKey(qint64 key, int keySize) {
|
||||||
|
QByteArray keyBytes(reinterpret_cast<const char *>(&key), sizeof(key));
|
||||||
|
while (keyBytes.size() < keySize)
|
||||||
|
keyBytes.append(keyBytes);
|
||||||
|
|
||||||
|
keyBytes.truncate(keySize);
|
||||||
|
return keyBytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned char* Core::Jammer::toUChar(QByteArray& data) {
|
||||||
|
return reinterpret_cast<unsigned char *>(data.data());}
|
||||||
|
|
||||||
|
const unsigned char* Core::Jammer::toUChar(const QByteArray& data) {
|
||||||
|
return reinterpret_cast<const unsigned char *>(data.constData());}
|
44
core/utils/jammer.h
Normal file
44
core/utils/jammer.h
Normal file
@ -0,0 +1,44 @@
|
|||||||
|
/*
|
||||||
|
* Squawk messenger.
|
||||||
|
* Copyright (C) 2019 Yury Gubich <blue@macaw.me>
|
||||||
|
*
|
||||||
|
* 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 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* 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, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdexcept>
|
||||||
|
|
||||||
|
#include <QByteArray>
|
||||||
|
#include <QString>
|
||||||
|
|
||||||
|
namespace Core {
|
||||||
|
|
||||||
|
class Jammer {
|
||||||
|
public:
|
||||||
|
static QString encrypt(const QString& plaintext, qint64 key);
|
||||||
|
static QString decrypt(const QString& ciphertext, qint64 key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Jammer() = delete;
|
||||||
|
|
||||||
|
static QByteArray process(const QByteArray& input, const QByteArray& key, bool encrypt);
|
||||||
|
static QByteArray intToKey(qint64 key, int keySize = 32);
|
||||||
|
|
||||||
|
static unsigned char* toUChar(QByteArray& data);
|
||||||
|
static const unsigned char* toUChar(const QByteArray& data);
|
||||||
|
static std::string getOpenSSLErrorString();
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
10
external/simpleCrypt/CMakeLists.txt
vendored
10
external/simpleCrypt/CMakeLists.txt
vendored
@ -1,10 +0,0 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
|
||||||
project(simplecrypt LANGUAGES CXX)
|
|
||||||
|
|
||||||
set(CMAKE_AUTOMOC ON)
|
|
||||||
|
|
||||||
find_package(Qt5 COMPONENTS Core REQUIRED)
|
|
||||||
|
|
||||||
add_library(simpleCrypt STATIC simplecrypt.cpp simplecrypt.h)
|
|
||||||
|
|
||||||
target_link_libraries(simpleCrypt Qt5::Core)
|
|
248
external/simpleCrypt/simplecrypt.cpp
vendored
248
external/simpleCrypt/simplecrypt.cpp
vendored
@ -1,248 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2011, Andre Somers
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the Rathenau Instituut, Andre Somers nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
#include "simplecrypt.h"
|
|
||||||
#include <QByteArray>
|
|
||||||
#include <QtDebug>
|
|
||||||
#include <QtGlobal>
|
|
||||||
#include <QDateTime>
|
|
||||||
#include <QCryptographicHash>
|
|
||||||
#include <QDataStream>
|
|
||||||
|
|
||||||
SimpleCrypt::SimpleCrypt():
|
|
||||||
m_key(0),
|
|
||||||
m_compressionMode(CompressionAuto),
|
|
||||||
m_protectionMode(ProtectionChecksum),
|
|
||||||
m_lastError(ErrorNoError) {}
|
|
||||||
|
|
||||||
SimpleCrypt::SimpleCrypt(quint64 key):
|
|
||||||
m_key(key),
|
|
||||||
m_compressionMode(CompressionAuto),
|
|
||||||
m_protectionMode(ProtectionChecksum),
|
|
||||||
m_lastError(ErrorNoError)
|
|
||||||
{
|
|
||||||
splitKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleCrypt::setKey(quint64 key)
|
|
||||||
{
|
|
||||||
m_key = key;
|
|
||||||
splitKey();
|
|
||||||
}
|
|
||||||
|
|
||||||
void SimpleCrypt::splitKey()
|
|
||||||
{
|
|
||||||
m_keyParts.clear();
|
|
||||||
m_keyParts.resize(8);
|
|
||||||
for (int i=0;i<8;i++) {
|
|
||||||
quint64 part = m_key;
|
|
||||||
for (int j=i; j>0; j--)
|
|
||||||
part = part >> 8;
|
|
||||||
part = part & 0xff;
|
|
||||||
m_keyParts[i] = static_cast<char>(part);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray SimpleCrypt::encryptToByteArray(const QString& plaintext)
|
|
||||||
{
|
|
||||||
QByteArray plaintextArray = plaintext.toUtf8();
|
|
||||||
return encryptToByteArray(plaintextArray);
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray SimpleCrypt::encryptToByteArray(QByteArray plaintext)
|
|
||||||
{
|
|
||||||
if (m_keyParts.isEmpty()) {
|
|
||||||
qWarning() << "No key set.";
|
|
||||||
m_lastError = ErrorNoKeySet;
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
QByteArray ba = plaintext;
|
|
||||||
|
|
||||||
CryptoFlags flags = CryptoFlagNone;
|
|
||||||
if (m_compressionMode == CompressionAlways) {
|
|
||||||
ba = qCompress(ba, 9); //maximum compression
|
|
||||||
flags |= CryptoFlagCompression;
|
|
||||||
} else if (m_compressionMode == CompressionAuto) {
|
|
||||||
QByteArray compressed = qCompress(ba, 9);
|
|
||||||
if (compressed.count() < ba.count()) {
|
|
||||||
ba = compressed;
|
|
||||||
flags |= CryptoFlagCompression;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray integrityProtection;
|
|
||||||
if (m_protectionMode == ProtectionChecksum) {
|
|
||||||
flags |= CryptoFlagChecksum;
|
|
||||||
QDataStream s(&integrityProtection, QIODevice::WriteOnly);
|
|
||||||
s << qChecksum(ba.constData(), ba.length());
|
|
||||||
} else if (m_protectionMode == ProtectionHash) {
|
|
||||||
flags |= CryptoFlagHash;
|
|
||||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
|
||||||
hash.addData(ba);
|
|
||||||
|
|
||||||
integrityProtection += hash.result();
|
|
||||||
}
|
|
||||||
|
|
||||||
//prepend a random char to the string
|
|
||||||
char randomChar = char(QRandomGenerator::global()->generate() & 0xFF);
|
|
||||||
ba = randomChar + integrityProtection + ba;
|
|
||||||
|
|
||||||
int pos(0);
|
|
||||||
char lastChar(0);
|
|
||||||
|
|
||||||
int cnt = ba.count();
|
|
||||||
|
|
||||||
while (pos < cnt) {
|
|
||||||
ba[pos] = ba.at(pos) ^ m_keyParts.at(pos % 8) ^ lastChar;
|
|
||||||
lastChar = ba.at(pos);
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray resultArray;
|
|
||||||
resultArray.append(char(0x03)); //version for future updates to algorithm
|
|
||||||
resultArray.append(char(flags)); //encryption flags
|
|
||||||
resultArray.append(ba);
|
|
||||||
|
|
||||||
m_lastError = ErrorNoError;
|
|
||||||
return resultArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SimpleCrypt::encryptToString(const QString& plaintext)
|
|
||||||
{
|
|
||||||
QByteArray plaintextArray = plaintext.toUtf8();
|
|
||||||
QByteArray cypher = encryptToByteArray(plaintextArray);
|
|
||||||
QString cypherString = QString::fromLatin1(cypher.toBase64());
|
|
||||||
return cypherString;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SimpleCrypt::encryptToString(QByteArray plaintext)
|
|
||||||
{
|
|
||||||
QByteArray cypher = encryptToByteArray(plaintext);
|
|
||||||
QString cypherString = QString::fromLatin1(cypher.toBase64());
|
|
||||||
return cypherString;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SimpleCrypt::decryptToString(const QString &cyphertext)
|
|
||||||
{
|
|
||||||
QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
|
|
||||||
QByteArray plaintextArray = decryptToByteArray(cyphertextArray);
|
|
||||||
QString plaintext = QString::fromUtf8(plaintextArray, plaintextArray.size());
|
|
||||||
|
|
||||||
return plaintext;
|
|
||||||
}
|
|
||||||
|
|
||||||
QString SimpleCrypt::decryptToString(QByteArray cypher)
|
|
||||||
{
|
|
||||||
QByteArray ba = decryptToByteArray(cypher);
|
|
||||||
QString plaintext = QString::fromUtf8(ba, ba.size());
|
|
||||||
|
|
||||||
return plaintext;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray SimpleCrypt::decryptToByteArray(const QString& cyphertext)
|
|
||||||
{
|
|
||||||
QByteArray cyphertextArray = QByteArray::fromBase64(cyphertext.toLatin1());
|
|
||||||
QByteArray ba = decryptToByteArray(cyphertextArray);
|
|
||||||
|
|
||||||
return ba;
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray SimpleCrypt::decryptToByteArray(QByteArray cypher)
|
|
||||||
{
|
|
||||||
if (m_keyParts.isEmpty()) {
|
|
||||||
qWarning() << "No key set.";
|
|
||||||
m_lastError = ErrorNoKeySet;
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
QByteArray ba = cypher;
|
|
||||||
|
|
||||||
if( cypher.count() < 3 )
|
|
||||||
return QByteArray();
|
|
||||||
|
|
||||||
char version = ba.at(0);
|
|
||||||
|
|
||||||
if (version !=3) { //we only work with version 3
|
|
||||||
m_lastError = ErrorUnknownVersion;
|
|
||||||
qWarning() << "Invalid version or not a cyphertext.";
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
CryptoFlags flags = CryptoFlags(ba.at(1));
|
|
||||||
|
|
||||||
ba = ba.mid(2);
|
|
||||||
int pos(0);
|
|
||||||
int cnt(ba.count());
|
|
||||||
char lastChar = 0;
|
|
||||||
|
|
||||||
while (pos < cnt) {
|
|
||||||
char currentChar = ba[pos];
|
|
||||||
ba[pos] = ba.at(pos) ^ lastChar ^ m_keyParts.at(pos % 8);
|
|
||||||
lastChar = currentChar;
|
|
||||||
++pos;
|
|
||||||
}
|
|
||||||
|
|
||||||
ba = ba.mid(1); //chop off the random number at the start
|
|
||||||
|
|
||||||
bool integrityOk(true);
|
|
||||||
if (flags.testFlag(CryptoFlagChecksum)) {
|
|
||||||
if (ba.length() < 2) {
|
|
||||||
m_lastError = ErrorIntegrityFailed;
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
quint16 storedChecksum;
|
|
||||||
{
|
|
||||||
QDataStream s(&ba, QIODevice::ReadOnly);
|
|
||||||
s >> storedChecksum;
|
|
||||||
}
|
|
||||||
ba = ba.mid(2);
|
|
||||||
quint16 checksum = qChecksum(ba.constData(), ba.length());
|
|
||||||
integrityOk = (checksum == storedChecksum);
|
|
||||||
} else if (flags.testFlag(CryptoFlagHash)) {
|
|
||||||
if (ba.length() < 20) {
|
|
||||||
m_lastError = ErrorIntegrityFailed;
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
QByteArray storedHash = ba.left(20);
|
|
||||||
ba = ba.mid(20);
|
|
||||||
QCryptographicHash hash(QCryptographicHash::Sha1);
|
|
||||||
hash.addData(ba);
|
|
||||||
integrityOk = (hash.result() == storedHash);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!integrityOk) {
|
|
||||||
m_lastError = ErrorIntegrityFailed;
|
|
||||||
return QByteArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (flags.testFlag(CryptoFlagCompression))
|
|
||||||
ba = qUncompress(ba);
|
|
||||||
|
|
||||||
m_lastError = ErrorNoError;
|
|
||||||
return ba;
|
|
||||||
}
|
|
226
external/simpleCrypt/simplecrypt.h
vendored
226
external/simpleCrypt/simplecrypt.h
vendored
@ -1,226 +0,0 @@
|
|||||||
/*
|
|
||||||
Copyright (c) 2011, Andre Somers
|
|
||||||
All rights reserved.
|
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without
|
|
||||||
modification, are permitted provided that the following conditions are met:
|
|
||||||
* Redistributions of source code must retain the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer.
|
|
||||||
* Redistributions in binary form must reproduce the above copyright
|
|
||||||
notice, this list of conditions and the following disclaimer in the
|
|
||||||
documentation and/or other materials provided with the distribution.
|
|
||||||
* Neither the name of the Rathenau Instituut, Andre Somers nor the
|
|
||||||
names of its contributors may be used to endorse or promote products
|
|
||||||
derived from this software without specific prior written permission.
|
|
||||||
|
|
||||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
|
||||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
||||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
||||||
DISCLAIMED. IN NO EVENT SHALL ANDRE SOMERS BE LIABLE FOR ANY
|
|
||||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
|
||||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
|
||||||
LOSS OF USE, DATA, OR #######; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
|
||||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
|
||||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
|
||||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef SIMPLECRYPT_H
|
|
||||||
#define SIMPLECRYPT_H
|
|
||||||
#include <QString>
|
|
||||||
#include <QVector>
|
|
||||||
#include <QFlags>
|
|
||||||
#include <QRandomGenerator>
|
|
||||||
|
|
||||||
/**
|
|
||||||
@ short Simple encrypt*ion and decryption of strings and byte arrays
|
|
||||||
|
|
||||||
This class provides a simple implementation of encryption and decryption
|
|
||||||
of strings and byte arrays.
|
|
||||||
|
|
||||||
@warning The encryption provided by this class is NOT strong encryption. It may
|
|
||||||
help to shield things from curious eyes, but it will NOT stand up to someone
|
|
||||||
determined to break the encryption. Don't say you were not warned.
|
|
||||||
|
|
||||||
The class uses a 64 bit key. Simply create an instance of the class, set the key,
|
|
||||||
and use the encryptToString() method to calculate an encrypted version of the input string.
|
|
||||||
To decrypt that string again, use an instance of SimpleCrypt initialized with
|
|
||||||
the same key, and call the decryptToString() method with the encrypted string. If the key
|
|
||||||
matches, the decrypted version of the string will be returned again.
|
|
||||||
|
|
||||||
If you do not provide a key, or if something else is wrong, the encryption and
|
|
||||||
decryption function will return an empty string or will return a string containing nonsense.
|
|
||||||
lastError() will return a value indicating if the method was succesful, and if not, why not.
|
|
||||||
|
|
||||||
SimpleCrypt is prepared for the case that the encryption and decryption
|
|
||||||
algorithm is changed in a later version, by prepending a version identifier to the cypertext.
|
|
||||||
*/
|
|
||||||
class SimpleCrypt
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
/**
|
|
||||||
CompressionMode describes if compression will be applied to the data to be
|
|
||||||
encrypted.
|
|
||||||
*/
|
|
||||||
enum CompressionMode {
|
|
||||||
CompressionAuto, /*!< Only apply compression if that results in a shorter plaintext. */
|
|
||||||
CompressionAlways, /*!< Always apply compression. Note that for short inputs, a compression may result in longer data */
|
|
||||||
CompressionNever /*!< Never apply compression. */
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
IntegrityProtectionMode describes measures taken to make it possible to detect problems with the data
|
|
||||||
or wrong decryption keys.
|
|
||||||
|
|
||||||
Measures involve adding a checksum or a cryptograhpic hash to the data to be encrypted. This
|
|
||||||
increases the length of the resulting cypertext, but makes it possible to check if the plaintext
|
|
||||||
appears to be valid after decryption.
|
|
||||||
*/
|
|
||||||
enum IntegrityProtectionMode {
|
|
||||||
ProtectionNone, /*!< The integerity of the encrypted data is not protected. It is not really possible to detect a wrong key, for instance. */
|
|
||||||
ProtectionChecksum,/*!< A simple checksum is used to verify that the data is in order. If not, an empty string is returned. */
|
|
||||||
ProtectionHash /*!< A cryptographic hash is used to verify the integrity of the data. This method produces a much stronger, but longer check */
|
|
||||||
};
|
|
||||||
/**
|
|
||||||
Error describes t*he type of error that occured.
|
|
||||||
*/
|
|
||||||
enum Error {
|
|
||||||
ErrorNoError, /*!< No error occurred. */
|
|
||||||
ErrorNoKeySet, /*!< No key was set. You can not encrypt or decrypt without a valid key. */
|
|
||||||
ErrorUnknownVersion, /*!< The version of this data is unknown, or the data is otherwise not valid. */
|
|
||||||
ErrorIntegrityFailed, /*!< The integrity check of the data failed. Perhaps the wrong key was used. */
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
Constructor. *
|
|
||||||
|
|
||||||
Constructs a SimpleCrypt instance without a valid key set on it.
|
|
||||||
*/
|
|
||||||
SimpleCrypt();
|
|
||||||
/**
|
|
||||||
Constructor. *
|
|
||||||
|
|
||||||
Constructs a SimpleCrypt instance and initializes it with the given @arg key.
|
|
||||||
*/
|
|
||||||
explicit SimpleCrypt(quint64 key);
|
|
||||||
|
|
||||||
/**
|
|
||||||
( Re-) initializes* the key with the given @arg key.
|
|
||||||
*/
|
|
||||||
void setKey(quint64 key);
|
|
||||||
/**
|
|
||||||
Returns true if SimpleCrypt has been initialized with a key.
|
|
||||||
*/
|
|
||||||
bool hasKey() const {return !m_keyParts.isEmpty();}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sets the compress*ion mode to use when encrypting data. The default mode is Auto.
|
|
||||||
|
|
||||||
Note that decryption is not influenced by this mode, as the decryption recognizes
|
|
||||||
what mode was used when encrypting.
|
|
||||||
*/
|
|
||||||
void setCompressionMode(CompressionMode mode) {m_compressionMode = mode;}
|
|
||||||
/**
|
|
||||||
Returns the CompressionMode that is currently in use.
|
|
||||||
*/
|
|
||||||
CompressionMode compressionMode() const {return m_compressionMode;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Sets the integrity mode to use when encrypting data. The default mode is Checksum.
|
|
||||||
|
|
||||||
Note that decryption is not influenced by this mode, as the decryption recognizes
|
|
||||||
what mode was used when encrypting.
|
|
||||||
*/
|
|
||||||
void setIntegrityProtectionMode(IntegrityProtectionMode mode) {m_protectionMode = mode;}
|
|
||||||
/**
|
|
||||||
Returns the IntegrityProtectionMode that is currently in use.
|
|
||||||
*/
|
|
||||||
IntegrityProtectionMode integrityProtectionMode() const {return m_protectionMode;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Returns the last *error that occurred.
|
|
||||||
*/
|
|
||||||
Error lastError() const {return m_lastError;}
|
|
||||||
|
|
||||||
/**
|
|
||||||
Encrypts the @arg* plaintext string with the key the class was initialized with, and returns
|
|
||||||
a cyphertext the result. The result is a base64 encoded version of the binary array that is the
|
|
||||||
actual result of the string, so it can be stored easily in a text format.
|
|
||||||
*/
|
|
||||||
QString encryptToString(const QString& plaintext) ;
|
|
||||||
/**
|
|
||||||
Encrypts the @arg* plaintext QByteArray with the key the class was initialized with, and returns
|
|
||||||
a cyphertext the result. The result is a base64 encoded version of the binary array that is the
|
|
||||||
actual result of the encryption, so it can be stored easily in a text format.
|
|
||||||
*/
|
|
||||||
QString encryptToString(QByteArray plaintext) ;
|
|
||||||
/**
|
|
||||||
Encrypts the @arg* plaintext string with the key the class was initialized with, and returns
|
|
||||||
a binary cyphertext in a QByteArray the result.
|
|
||||||
|
|
||||||
This method returns a byte array, that is useable for storing a binary format. If you need
|
|
||||||
a string you can store in a text file, use encryptToString() instead.
|
|
||||||
*/
|
|
||||||
QByteArray encryptToByteArray(const QString& plaintext) ;
|
|
||||||
/**
|
|
||||||
Encrypts the @arg* plaintext QByteArray with the key the class was initialized with, and returns
|
|
||||||
a binary cyphertext in a QByteArray the result.
|
|
||||||
|
|
||||||
This method returns a byte array, that is useable for storing a binary format. If you need
|
|
||||||
a string you can store in a text file, use encryptToString() instead.
|
|
||||||
*/
|
|
||||||
QByteArray encryptToByteArray(QByteArray plaintext) ;
|
|
||||||
|
|
||||||
/**
|
|
||||||
Decrypts a cypher*text string encrypted with this class with the set key back to the
|
|
||||||
plain text version.
|
|
||||||
|
|
||||||
If an error occured, such as non-matching keys between encryption and decryption,
|
|
||||||
an empty string or a string containing nonsense may be returned.
|
|
||||||
*/
|
|
||||||
QString decryptToString(const QString& cyphertext) ;
|
|
||||||
/**
|
|
||||||
Decrypts a cypher*text string encrypted with this class with the set key back to the
|
|
||||||
plain text version.
|
|
||||||
|
|
||||||
If an error occured, such as non-matching keys between encryption and decryption,
|
|
||||||
an empty string or a string containing nonsense may be returned.
|
|
||||||
*/
|
|
||||||
QByteArray decryptToByteArray(const QString& cyphertext) ;
|
|
||||||
/**
|
|
||||||
Decrypts a cypher*text binary encrypted with this class with the set key back to the
|
|
||||||
plain text version.
|
|
||||||
|
|
||||||
If an error occured, such as non-matching keys between encryption and decryption,
|
|
||||||
an empty string or a string containing nonsense may be returned.
|
|
||||||
*/
|
|
||||||
QString decryptToString(QByteArray cypher) ;
|
|
||||||
/**
|
|
||||||
Decrypts a cypher*text binary encrypted with this class with the set key back to the
|
|
||||||
plain text version.
|
|
||||||
|
|
||||||
If an error occured, such as non-matching keys between encryption and decryption,
|
|
||||||
an empty string or a string containing nonsense may be returned.
|
|
||||||
*/
|
|
||||||
QByteArray decryptToByteArray(QByteArray cypher) ;
|
|
||||||
|
|
||||||
//enum to describe options that have been used for the encryption. Currently only one, but
|
|
||||||
//that only leaves room for future extensions like adding a cryptographic hash...
|
|
||||||
enum CryptoFlag{CryptoFlagNone = 0,
|
|
||||||
CryptoFlagCompression = 0x01,
|
|
||||||
CryptoFlagChecksum = 0x02,
|
|
||||||
CryptoFlagHash = 0x04
|
|
||||||
};
|
|
||||||
Q_DECLARE_FLAGS(CryptoFlags, CryptoFlag);
|
|
||||||
private:
|
|
||||||
|
|
||||||
void splitKey();
|
|
||||||
|
|
||||||
quint64 m_key;
|
|
||||||
QVector<char> m_keyParts;
|
|
||||||
CompressionMode m_compressionMode;
|
|
||||||
IntegrityProtectionMode m_protectionMode;
|
|
||||||
Error m_lastError;
|
|
||||||
};
|
|
||||||
Q_DECLARE_OPERATORS_FOR_FLAGS(SimpleCrypt::CryptoFlags)
|
|
||||||
|
|
||||||
#endif // SimpleCrypt_H
|
|
@ -58,6 +58,7 @@ Root::~Root() {
|
|||||||
delete gui;
|
delete gui;
|
||||||
if (core != nullptr)
|
if (core != nullptr)
|
||||||
delete core;
|
delete core;
|
||||||
|
|
||||||
delete coreThread;
|
delete coreThread;
|
||||||
}
|
}
|
||||||
delete global;
|
delete global;
|
||||||
@ -72,13 +73,13 @@ void Root::initializeTranslation() {
|
|||||||
bool found = false;
|
bool found = false;
|
||||||
for (QString share : shares) {
|
for (QString share : shares) {
|
||||||
found = currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", share + "/l10n");
|
found = currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", share + "/l10n");
|
||||||
if (found) {
|
if (found)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if (!found) {
|
if (!found)
|
||||||
currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", QCoreApplication::applicationDirPath());
|
currentTranslator.load(QLocale(), QLatin1String("squawk"), ".", QCoreApplication::applicationDirPath());
|
||||||
}
|
|
||||||
|
|
||||||
installTranslator(¤tTranslator);
|
installTranslator(¤tTranslator);
|
||||||
}
|
}
|
||||||
@ -94,20 +95,18 @@ bool Root::initializeSettings() {
|
|||||||
QVariant vs = settings.value("style");
|
QVariant vs = settings.value("style");
|
||||||
if (vs.isValid()) {
|
if (vs.isValid()) {
|
||||||
QString style = vs.toString().toLower();
|
QString style = vs.toString().toLower();
|
||||||
if (style != "system") {
|
if (style != "system")
|
||||||
Shared::Global::setStyle(style);
|
Shared::Global::setStyle(style);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (Shared::Global::supported("colorSchemeTools")) {
|
if (Shared::Global::supported("colorSchemeTools")) {
|
||||||
QVariant vt = settings.value("theme");
|
QVariant vt = settings.value("theme");
|
||||||
if (vt.isValid()) {
|
if (vt.isValid()) {
|
||||||
QString theme = vt.toString();
|
QString theme = vt.toString();
|
||||||
if (theme.toLower() != "system") {
|
if (theme.toLower() != "system")
|
||||||
Shared::Global::setTheme(theme);
|
Shared::Global::setTheme(theme);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
QString path = Shared::downloadsPathCheck();
|
QString path = Shared::downloadsPathCheck();
|
||||||
if (path.size() > 0) {
|
if (path.size() > 0) {
|
||||||
|
@ -1,19 +1,19 @@
|
|||||||
# Maintainer: Yury Gubich <blue@macaw.me>
|
# Maintainer: Yury Gubich <blue@macaw.me>
|
||||||
pkgname=squawk
|
pkgname=squawk
|
||||||
pkgver=0.2.3
|
pkgver=0.2.4
|
||||||
pkgrel=1
|
pkgrel=1
|
||||||
pkgdesc="An XMPP desktop messenger, written on pure c++ (qt)"
|
pkgdesc="An XMPP desktop messenger, written on pure c++ (qt)"
|
||||||
arch=('i686' 'x86_64')
|
arch=('i686' 'x86_64')
|
||||||
url="https://git.macaw.me/blue/squawk"
|
url="https://git.macaw.me/blue/squawk"
|
||||||
license=('GPL3')
|
license=('GPL3')
|
||||||
depends=('hicolor-icon-theme' 'desktop-file-utils' 'lmdbal' 'qxmpp-qt5')
|
depends=('hicolor-icon-theme' 'desktop-file-utils' 'lmdbal-qt6' 'qxmpp-qt6')
|
||||||
makedepends=('cmake>=3.3' 'imagemagick' 'qt5-tools' 'boost')
|
makedepends=('cmake>=3.3' 'imagemagick' 'qt6-tools' 'boost')
|
||||||
optdepends=('kwallet5: secure password storage (requires rebuild)'
|
optdepends=('kwallet6: secure password storage (requires rebuild)'
|
||||||
'kconfig5: system themes support (requires rebuild)'
|
'kconfig6: system themes support (requires rebuild)'
|
||||||
'kconfigwidgets5: system themes support (requires rebuild)'
|
'kconfigwidgets6: system themes support (requires rebuild)'
|
||||||
'kio5: better show in folder action (requires rebuild)')
|
'kio6: better show in folder action (requires rebuild)')
|
||||||
|
|
||||||
source=("$pkgname-$pkgver.tar.gz::https://git.macaw.me/blue/$pkgname/archive/$pkgver.tar.gz")
|
source=("$pkgname-$pkgver-$pkgrel.tar.gz::https://git.macaw.me/blue/$pkgname/archive/$pkgver.tar.gz")
|
||||||
sha256sums=('SKIP')
|
sha256sums=('SKIP')
|
||||||
build() {
|
build() {
|
||||||
cd "$srcdir/squawk"
|
cd "$srcdir/squawk"
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
configure_file(squawk.desktop squawk.desktop COPYONLY)
|
configure_file(squawk.desktop squawk.desktop COPYONLY)
|
||||||
|
|
||||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||||
|
|
||||||
|
configure_file(macaw.me.squawk.appdata.xml macaw.me.squawk.appdata.xml COPYONLY)
|
||||||
|
|
||||||
|
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/macaw.me.squawk.appdata.xml DESTINATION ${CMAKE_INSTALL_DATADIR}/metainfo)
|
||||||
|
33
packaging/macaw.me.squawk.appdata.xml
Normal file
33
packaging/macaw.me.squawk.appdata.xml
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<component xmlns:xi="http://www.w3.org/2001/XInclude" xmlns:its="http://www.w3.org/2005/11/its" xmlns="https://specifications.freedesktop.org/metainfo/1.0" type="desktop-application">
|
||||||
|
<id>macaw.me.squawk</id>
|
||||||
|
<metadata_license>CC0-1.0</metadata_license>
|
||||||
|
<project_license>GPL-3.0+</project_license>
|
||||||
|
<name>Squawk</name>
|
||||||
|
<summary>Desktop Qt based XMPP messenger</summary>
|
||||||
|
<description>
|
||||||
|
<p>
|
||||||
|
Squawk is a lightweight XMPP desktop messenger.
|
||||||
|
The primary objective of this project is to offer
|
||||||
|
you a fast and user-friendly messaging experience
|
||||||
|
that closely aligns with your system’s style, while
|
||||||
|
also minimizing resource consumption.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
Squawk is still at a very early stage and might not suit
|
||||||
|
everyone but you are welcome to try it out.
|
||||||
|
</p>
|
||||||
|
</description>
|
||||||
|
<launchable type="desktop-id">macaw.me.squawk.desktop</launchable>
|
||||||
|
<screenshots>
|
||||||
|
<screenshot type="default">
|
||||||
|
<image>https://macaw.me/projects/squawk/0.2.2.png</image>
|
||||||
|
<caption>View XMPP contacts and conversations</caption>
|
||||||
|
</screenshot>
|
||||||
|
</screenshots>
|
||||||
|
<url type="homepage">https://macaw.me/projects/squawk/</url>
|
||||||
|
<provides>
|
||||||
|
<binary>squawk</binary>
|
||||||
|
</provides>
|
||||||
|
<update_contact>blue@macaw.me</update_contact>
|
||||||
|
</component>
|
@ -1,7 +1,7 @@
|
|||||||
[Desktop Entry]
|
[Desktop Entry]
|
||||||
|
|
||||||
Type=Application
|
Type=Application
|
||||||
Version=1.0
|
Version=0.2.4
|
||||||
Name=Squawk
|
Name=Squawk
|
||||||
GenericName=Instant Messenger
|
GenericName=Instant Messenger
|
||||||
GenericName[ru]=Мгновенные сообщения
|
GenericName[ru]=Мгновенные сообщения
|
||||||
|
@ -1,14 +1,14 @@
|
|||||||
if (WITH_KIO)
|
if (WITH_KIO)
|
||||||
add_library(openFileManagerWindowJob SHARED openfilemanagerwindowjob.cpp)
|
add_library(openFileManagerWindowJob SHARED openfilemanagerwindowjob.cpp)
|
||||||
target_link_libraries(openFileManagerWindowJob PRIVATE KF5::KIOWidgets)
|
target_link_libraries(openFileManagerWindowJob PRIVATE KF${QT_VERSION_MAJOR}::KIOWidgets)
|
||||||
|
|
||||||
install(TARGETS openFileManagerWindowJob LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(TARGETS openFileManagerWindowJob LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/squawk)
|
||||||
endif ()
|
endif ()
|
||||||
|
|
||||||
if (WITH_KCONFIG)
|
if (WITH_KCONFIG)
|
||||||
add_library(colorSchemeTools SHARED colorschemetools.cpp)
|
add_library(colorSchemeTools SHARED colorschemetools.cpp)
|
||||||
target_link_libraries(colorSchemeTools PRIVATE KF5::ConfigCore)
|
target_link_libraries(colorSchemeTools PRIVATE KF${QT_VERSION_MAJOR}::ConfigCore)
|
||||||
target_link_libraries(colorSchemeTools PRIVATE KF5::ConfigWidgets)
|
target_link_libraries(colorSchemeTools PRIVATE KF${QT_VERSION_MAJOR}::ConfigWidgets)
|
||||||
|
|
||||||
install(TARGETS colorSchemeTools LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
install(TARGETS colorSchemeTools LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR}/squawk)
|
||||||
endif()
|
endif()
|
||||||
|
@ -20,9 +20,9 @@
|
|||||||
#include <QPainter>
|
#include <QPainter>
|
||||||
#include <QFileInfo>
|
#include <QFileInfo>
|
||||||
|
|
||||||
#include <KConfigCore/KSharedConfig>
|
#include <KSharedConfig>
|
||||||
#include <KConfigCore/KConfigGroup>
|
#include <KConfigGroup>
|
||||||
#include <KConfigWidgets/KColorScheme>
|
#include <KColorScheme>
|
||||||
|
|
||||||
QPixmap createPixmap(int size, const QBrush& window, const QBrush& button, const QBrush& view, const QBrush& selection);
|
QPixmap createPixmap(int size, const QBrush& window, const QBrush& button, const QBrush& view, const QBrush& selection);
|
||||||
|
|
||||||
|
@ -3,11 +3,8 @@ target_sources(squawk PRIVATE resources.qrc)
|
|||||||
configure_file(images/logo.svg squawk.svg COPYONLY)
|
configure_file(images/logo.svg squawk.svg COPYONLY)
|
||||||
configure_file(squawk.rc squawk.rc COPYONLY)
|
configure_file(squawk.rc squawk.rc COPYONLY)
|
||||||
|
|
||||||
if(WIN32)
|
set(CONVERT_BIN magick)
|
||||||
set(CONVERT_BIN magick convert)
|
|
||||||
else(WIN32)
|
|
||||||
set(CONVERT_BIN convert)
|
|
||||||
endif(WIN32)
|
|
||||||
execute_process(COMMAND ${CONVERT_BIN} -background none -size 48x48 squawk.svg squawk48.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -size 48x48 squawk.svg squawk48.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND ${CONVERT_BIN} -background none -size 64x64 squawk.svg squawk64.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -size 64x64 squawk.svg squawk64.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND ${CONVERT_BIN} -background none -size 128x128 squawk.svg squawk128.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -size 128x128 squawk.svg squawk128.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
@ -22,16 +19,16 @@ endif(WIN32)
|
|||||||
|
|
||||||
if (APPLE)
|
if (APPLE)
|
||||||
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/icns.iconset")
|
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/icns.iconset")
|
||||||
execute_process(COMMAND convert -background none -size 16x16 squawk.svg icns.iconset/icon_16x16.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -size 16x16 squawk.svg icns.iconset/icon_16x16.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !32x32 squawk.svg "icns.iconset/icon_16x16@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !32x32 squawk.svg "icns.iconset/icon_16x16@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !32x32 squawk.svg "icns.iconset/icon_32x32.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !32x32 squawk.svg "icns.iconset/icon_32x32.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !64x64 squawk.svg "icns.iconset/icon_32x32@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !64x64 squawk.svg "icns.iconset/icon_32x32@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !128x128 squawk.svg "icns.iconset/icon_128x128.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !128x128 squawk.svg "icns.iconset/icon_128x128.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !256x256 squawk.svg "icns.iconset/icon_128x128@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !256x256 squawk.svg "icns.iconset/icon_128x128@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !256x256 squawk.svg "icns.iconset/icon_256x256.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !256x256 squawk.svg "icns.iconset/icon_256x256.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !512x512 squawk.svg "icns.iconset/icon_256x256@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !512x512 squawk.svg "icns.iconset/icon_256x256@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !512x512 squawk.svg "icns.iconset/icon_512x512.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !512x512 squawk.svg "icns.iconset/icon_512x512.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND convert -background none -resize !1024x1024 squawk.svg "icns.iconset/icon_512x512@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND ${CONVERT_BIN} -background none -resize !1024x1024 squawk.svg "icns.iconset/icon_512x512@2x.png" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
execute_process(COMMAND iconutil -c icns "icns.iconset" -o "squawk.icns" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
execute_process(COMMAND iconutil -c icns "icns.iconset" -o "squawk.icns" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
|
||||||
set(MACOSX_BUNDLE_ICON_FILE squawk.icns)
|
set(MACOSX_BUNDLE_ICON_FILE squawk.icns)
|
||||||
set(MACOSX_BUNDLE_ICON_FILE ${MACOSX_BUNDLE_ICON_FILE} PARENT_SCOPE)
|
set(MACOSX_BUNDLE_ICON_FILE ${MACOSX_BUNDLE_ICON_FILE} PARENT_SCOPE)
|
||||||
|
@ -39,7 +39,4 @@ set(HEADER_FILES
|
|||||||
defines.h
|
defines.h
|
||||||
)
|
)
|
||||||
|
|
||||||
target_sources(squawk PRIVATE
|
target_sources(squawk PRIVATE ${SOURCE_FILES} ${HEADER_FILES})
|
||||||
${SOURCE_FILES}
|
|
||||||
${HEADER_FILES}
|
|
||||||
)
|
|
||||||
|
@ -14,11 +14,11 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#ifndef SHARED_CLIENTID_H
|
#pragma once
|
||||||
#define SHARED_CLIENTID_H
|
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
|
#include <QMetaType>
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
|
|
||||||
@ -54,5 +54,3 @@ Q_DECLARE_METATYPE(Shared::ClientId)
|
|||||||
|
|
||||||
QDataStream& operator << (QDataStream& stream, const Shared::ClientId& info);
|
QDataStream& operator << (QDataStream& stream, const Shared::ClientId& info);
|
||||||
QDataStream& operator >> (QDataStream& stream, Shared::ClientId& info);
|
QDataStream& operator >> (QDataStream& stream, Shared::ClientId& info);
|
||||||
|
|
||||||
#endif // SHARED_CLIENTID_H
|
|
||||||
|
@ -14,10 +14,10 @@
|
|||||||
// You should have received a copy of the GNU General Public License
|
// You should have received a copy of the GNU General Public License
|
||||||
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
#ifndef SHARED_CLIENTINFO_H
|
#pragma once
|
||||||
#define SHARED_CLIENTINFO_H
|
|
||||||
|
|
||||||
#include <set>
|
#include <set>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
#include <QDataStream>
|
#include <QDataStream>
|
||||||
#include <QString>
|
#include <QString>
|
||||||
@ -54,5 +54,3 @@ private:
|
|||||||
|
|
||||||
QDataStream& operator << (QDataStream& stream, const Shared::ClientInfo& info);
|
QDataStream& operator << (QDataStream& stream, const Shared::ClientInfo& info);
|
||||||
QDataStream& operator >> (QDataStream& stream, Shared::ClientInfo& info);
|
QDataStream& operator >> (QDataStream& stream, Shared::ClientInfo& info);
|
||||||
|
|
||||||
#endif // SHARED_CLIENTINFO_H
|
|
||||||
|
@ -16,9 +16,6 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef SHARED_DEFINES_H
|
#pragma once
|
||||||
#define SHARED_DEFINES_H
|
|
||||||
|
|
||||||
#define SHARED_UNUSED(x) (void)(x)
|
#define SHARED_UNUSED(x) (void)(x)
|
||||||
|
|
||||||
#endif
|
|
||||||
|
@ -19,8 +19,10 @@
|
|||||||
#include "global.h"
|
#include "global.h"
|
||||||
#include <QFontDatabase>
|
#include <QFontDatabase>
|
||||||
|
|
||||||
|
#include "defines.h"
|
||||||
#include "enums.h"
|
#include "enums.h"
|
||||||
#include "ui/models/roster.h"
|
#include "ui/models/roster.h"
|
||||||
|
|
||||||
#ifdef WITH_OMEMO
|
#ifdef WITH_OMEMO
|
||||||
constexpr bool OMEMO_SUPPORT = true;
|
constexpr bool OMEMO_SUPPORT = true;
|
||||||
#else
|
#else
|
||||||
@ -36,12 +38,11 @@ QFont getFont (QFontDatabase::SystemFont type, bool bold = false, bool italic =
|
|||||||
|
|
||||||
if (factor != 1.0) {
|
if (factor != 1.0) {
|
||||||
float ps = font.pointSizeF();
|
float ps = font.pointSizeF();
|
||||||
if (ps != -1) {
|
if (ps != -1)
|
||||||
font.setPointSizeF(ps * factor);
|
font.setPointSizeF(ps * factor);
|
||||||
} else {
|
else
|
||||||
font.setPointSize(font.pointSize() * factor);
|
font.setPointSize(font.pointSize() * factor);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return font;
|
return font;
|
||||||
}
|
}
|
||||||
@ -50,12 +51,12 @@ Shared::Global* Shared::Global::instance = 0;
|
|||||||
const std::set<QString> Shared::Global::supportedImagesExts = {"png", "jpg", "webp", "jpeg", "gif", "svg"};
|
const std::set<QString> Shared::Global::supportedImagesExts = {"png", "jpg", "webp", "jpeg", "gif", "svg"};
|
||||||
|
|
||||||
#ifdef WITH_KIO
|
#ifdef WITH_KIO
|
||||||
QLibrary Shared::Global::openFileManagerWindowJob("openFileManagerWindowJob");
|
QLibrary Shared::Global::openFileManagerWindowJob(QString("%1/openFileManagerWindowJob").arg(PLUGIN_PATH));
|
||||||
Shared::Global::HighlightInFileManager Shared::Global::hfm = 0;
|
Shared::Global::HighlightInFileManager Shared::Global::hfm = 0;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef WITH_KCONFIG
|
#ifdef WITH_KCONFIG
|
||||||
QLibrary Shared::Global::colorSchemeTools("colorSchemeTools");
|
QLibrary Shared::Global::colorSchemeTools(QString("%1/colorSchemeTools").arg(PLUGIN_PATH));
|
||||||
Shared::Global::CreatePreview Shared::Global::createPreview = 0;
|
Shared::Global::CreatePreview Shared::Global::createPreview = 0;
|
||||||
Shared::Global::DeletePreview Shared::Global::deletePreview = 0;
|
Shared::Global::DeletePreview Shared::Global::deletePreview = 0;
|
||||||
Shared::Global::ColorSchemeName Shared::Global::colorSchemeName = 0;
|
Shared::Global::ColorSchemeName Shared::Global::colorSchemeName = 0;
|
||||||
@ -148,7 +149,7 @@ Shared::Global::Global():
|
|||||||
smallFontMetrics(smallFont),
|
smallFontMetrics(smallFont),
|
||||||
headerFontMetrics(headerFont),
|
headerFontMetrics(headerFont),
|
||||||
titleFontMetrics(titleFont),
|
titleFontMetrics(titleFont),
|
||||||
pluginSupport({
|
optionalFeatures({
|
||||||
{"KWallet", false},
|
{"KWallet", false},
|
||||||
{"openFileManagerWindowJob", false},
|
{"openFileManagerWindowJob", false},
|
||||||
{"colorSchemeTools", false}
|
{"colorSchemeTools", false}
|
||||||
@ -197,8 +198,7 @@ Shared::Global::Global():
|
|||||||
|
|
||||||
|
|
||||||
static const QSize defaultIconFileInfoHeight(50, 50);
|
static const QSize defaultIconFileInfoHeight(50, 50);
|
||||||
Shared::Global::FileInfo Shared::Global::getFileInfo(const QString& path)
|
Shared::Global::FileInfo Shared::Global::getFileInfo(const QString& path) {
|
||||||
{
|
|
||||||
std::map<QString, FileInfo>::const_iterator itr = instance->fileCache.find(path);
|
std::map<QString, FileInfo>::const_iterator itr = instance->fileCache.find(path);
|
||||||
if (itr == instance->fileCache.end()) {
|
if (itr == instance->fileCache.end()) {
|
||||||
QMimeDatabase db;
|
QMimeDatabase db;
|
||||||
@ -275,17 +275,17 @@ QString Shared::Global::getName(EncryptionProtocol ep) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void Shared::Global::setSupported(const QString& pluginName, bool support) {
|
void Shared::Global::setSupported(const QString& pluginName, bool support) {
|
||||||
std::map<QString, bool>::iterator itr = instance->pluginSupport.find(pluginName);
|
std::map<QString, bool>::iterator itr = instance->optionalFeatures.find(pluginName);
|
||||||
if (itr != instance->pluginSupport.end()) {
|
if (itr != instance->optionalFeatures.end()) {
|
||||||
itr->second = support;
|
itr->second = support;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Shared::Global::supported(const QString& pluginName) {
|
bool Shared::Global::supported(const QString& pluginName) {
|
||||||
std::map<QString, bool>::iterator itr = instance->pluginSupport.find(pluginName);
|
std::map<QString, bool>::iterator itr = instance->optionalFeatures.find(pluginName);
|
||||||
if (itr != instance->pluginSupport.end()) {
|
if (itr != instance->optionalFeatures.end())
|
||||||
return itr->second;
|
return itr->second;
|
||||||
}
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -317,7 +317,7 @@ void Shared::Global::highlightInFileManager(const QString& path)
|
|||||||
qDebug() << "requested to highlight in file manager url" << path << "but it's not supported: squawk wasn't compiled to support it, trying fallback";
|
qDebug() << "requested to highlight in file manager url" << path << "but it's not supported: squawk wasn't compiled to support it, trying fallback";
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QFileInfo info = path;
|
QFileInfo info(path);
|
||||||
if (info.exists()) {
|
if (info.exists()) {
|
||||||
QProcess proc;
|
QProcess proc;
|
||||||
proc.start("xdg-mime", query);
|
proc.start("xdg-mime", query);
|
||||||
@ -325,11 +325,10 @@ void Shared::Global::highlightInFileManager(const QString& path)
|
|||||||
QString output = proc.readLine().simplified();
|
QString output = proc.readLine().simplified();
|
||||||
|
|
||||||
QString folder;
|
QString folder;
|
||||||
if (info.isDir()) {
|
if (info.isDir())
|
||||||
folder = info.canonicalFilePath();
|
folder = info.canonicalFilePath();
|
||||||
} else {
|
else
|
||||||
folder = info.canonicalPath();
|
folder = info.canonicalPath();
|
||||||
}
|
|
||||||
|
|
||||||
if (output.contains(dolphinReg)) {
|
if (output.contains(dolphinReg)) {
|
||||||
//there is a bug on current (21.04.0) dolphin, it works correct only if you already have dolphin launched
|
//there is a bug on current (21.04.0) dolphin, it works correct only if you already have dolphin launched
|
||||||
@ -356,27 +355,32 @@ void Shared::Global::highlightInFileManager(const QString& path)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QIcon Shared::Global::createThemePreview(const QString& path) {
|
QIcon Shared::Global::createThemePreview(const QString& path) {
|
||||||
|
#ifdef WITH_KCONFIG
|
||||||
if (supported("colorSchemeTools")) {
|
if (supported("colorSchemeTools")) {
|
||||||
QIcon* icon = createPreview(path);
|
QIcon* icon = createPreview(path);
|
||||||
QIcon localIcon = *icon;
|
QIcon localIcon = *icon;
|
||||||
deletePreview(icon);
|
deletePreview(icon);
|
||||||
return localIcon;
|
return localIcon;
|
||||||
} else {
|
|
||||||
return QIcon();
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return QIcon();
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Shared::Global::getColorSchemeName(const QString& path) {
|
QString Shared::Global::getColorSchemeName(const QString& path) {
|
||||||
|
#ifdef WITH_KCONFIG
|
||||||
if (supported("colorSchemeTools")) {
|
if (supported("colorSchemeTools")) {
|
||||||
QString res;
|
QString res;
|
||||||
colorSchemeName(path, res);
|
colorSchemeName(path, res);
|
||||||
return res;
|
return res;
|
||||||
} else {
|
|
||||||
return "";
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shared::Global::setTheme(const QString& path) {
|
void Shared::Global::setTheme(const QString& path) {
|
||||||
|
#ifdef WITH_KCONFIG
|
||||||
if (supported("colorSchemeTools")) {
|
if (supported("colorSchemeTools")) {
|
||||||
if (path.toLower() == "system") {
|
if (path.toLower() == "system") {
|
||||||
QApplication::setPalette(getInstance()->defaultSystemPalette);
|
QApplication::setPalette(getInstance()->defaultSystemPalette);
|
||||||
@ -386,23 +390,26 @@ void Shared::Global::setTheme(const QString& path) {
|
|||||||
QApplication::setPalette(pallete);
|
QApplication::setPalette(pallete);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
|
SHARED_UNUSED(path);
|
||||||
|
qDebug("setTheme() was called, but this version of squawk was compiled without KConfig support, ignoring");
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shared::Global::setStyle(const QString& style) {
|
void Shared::Global::setStyle(const QString& style) {
|
||||||
if (style.toLower() == "system") {
|
if (style.toLower() == "system")
|
||||||
QApplication::setStyle(getInstance()->defaultSystemStyle);
|
QApplication::setStyle(getInstance()->defaultSystemStyle);
|
||||||
} else {
|
else
|
||||||
QApplication::setStyle(style);
|
QApplication::setStyle(style);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
#define FROM_INT_INPL(Enum) \
|
#define FROM_INT_INPL(Enum) \
|
||||||
template<> \
|
template<> \
|
||||||
Enum Shared::Global::fromInt(int src) \
|
Enum Shared::Global::fromInt(int src) \
|
||||||
{ \
|
{ \
|
||||||
if (src < static_cast<int>(Enum##Lowest) || src > static_cast<int>(Enum##Highest)) { \
|
if (src < static_cast<int>(Enum##Lowest) || src > static_cast<int>(Enum##Highest)) \
|
||||||
throw EnumOutOfRange(#Enum); \
|
throw EnumOutOfRange(#Enum); \
|
||||||
} \
|
\
|
||||||
return static_cast<Enum>(src); \
|
return static_cast<Enum>(src); \
|
||||||
} \
|
} \
|
||||||
template<> \
|
template<> \
|
||||||
|
@ -135,7 +135,7 @@ namespace Shared {
|
|||||||
private:
|
private:
|
||||||
static Global* instance;
|
static Global* instance;
|
||||||
|
|
||||||
std::map<QString, bool> pluginSupport;
|
std::map<QString, bool> optionalFeatures;
|
||||||
std::map<QString, FileInfo> fileCache;
|
std::map<QString, FileInfo> fileCache;
|
||||||
|
|
||||||
#ifdef WITH_KIO
|
#ifdef WITH_KIO
|
||||||
|
@ -43,3 +43,19 @@ Shared::MessageInfo & Shared::MessageInfo::operator=(const Shared::MessageInfo&
|
|||||||
|
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDataStream& operator >> (QDataStream& in, Shared::MessageInfo& info) {
|
||||||
|
in >> info.account;
|
||||||
|
in >> info.jid;
|
||||||
|
in >> info.messageId;
|
||||||
|
|
||||||
|
return in;
|
||||||
|
}
|
||||||
|
|
||||||
|
QDataStream& operator <<( QDataStream& out, const Shared::MessageInfo& info) {
|
||||||
|
out << info.account;
|
||||||
|
out << info.jid;
|
||||||
|
out << info.messageId;
|
||||||
|
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
@ -19,6 +19,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <QString>
|
#include <QString>
|
||||||
|
#include <QDataStream>
|
||||||
|
|
||||||
namespace Shared {
|
namespace Shared {
|
||||||
struct MessageInfo {
|
struct MessageInfo {
|
||||||
@ -34,3 +35,6 @@ struct MessageInfo {
|
|||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QDataStream& operator << (QDataStream& out, const Shared::MessageInfo& info);
|
||||||
|
QDataStream& operator >> (QDataStream& in, Shared::MessageInfo& info);
|
||||||
|
@ -49,7 +49,7 @@ Progress::Progress(quint16 p_size, QWidget* parent):
|
|||||||
|
|
||||||
QGridLayout* layout = new QGridLayout();
|
QGridLayout* layout = new QGridLayout();
|
||||||
setLayout(layout);
|
setLayout(layout);
|
||||||
layout->setMargin(0);
|
layout->setContentsMargins(0, 0, 0, 0);
|
||||||
layout->setVerticalSpacing(0);
|
layout->setVerticalSpacing(0);
|
||||||
layout->setHorizontalSpacing(0);
|
layout->setHorizontalSpacing(0);
|
||||||
|
|
||||||
|
@ -26,6 +26,7 @@ Account::Account():
|
|||||||
m_ui->setupUi(this);
|
m_ui->setupUi(this);
|
||||||
|
|
||||||
connect(m_ui->passwordType, qOverload<int>(&QComboBox::currentIndexChanged), this, &Account::onComboboxChange);
|
connect(m_ui->passwordType, qOverload<int>(&QComboBox::currentIndexChanged), this, &Account::onComboboxChange);
|
||||||
|
QStandardItemModel *model = static_cast<QStandardItemModel*>(m_ui->passwordType->model());
|
||||||
|
|
||||||
for (int i = static_cast<int>(Shared::AccountPasswordLowest); i < static_cast<int>(Shared::AccountPasswordHighest) + 1; ++i) {
|
for (int i = static_cast<int>(Shared::AccountPasswordLowest); i < static_cast<int>(Shared::AccountPasswordHighest) + 1; ++i) {
|
||||||
Shared::AccountPassword ap = static_cast<Shared::AccountPassword>(i);
|
Shared::AccountPassword ap = static_cast<Shared::AccountPassword>(i);
|
||||||
@ -34,18 +35,14 @@ Account::Account():
|
|||||||
m_ui->passwordType->setCurrentIndex(static_cast<int>(Shared::AccountPassword::plain));
|
m_ui->passwordType->setCurrentIndex(static_cast<int>(Shared::AccountPassword::plain));
|
||||||
|
|
||||||
if (!Shared::Global::supported("KWallet")) {
|
if (!Shared::Global::supported("KWallet")) {
|
||||||
QStandardItemModel *model = static_cast<QStandardItemModel*>(m_ui->passwordType->model());
|
|
||||||
QStandardItem *item = model->item(static_cast<int>(Shared::AccountPassword::kwallet));
|
QStandardItem *item = model->item(static_cast<int>(Shared::AccountPassword::kwallet));
|
||||||
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
item->setFlags(item->flags() & ~Qt::ItemIsEnabled);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Account::~Account()
|
Account::~Account() {}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QMap<QString, QVariant> Account::value() const
|
QMap<QString, QVariant> Account::value() const {
|
||||||
{
|
|
||||||
QMap<QString, QVariant> map;
|
QMap<QString, QVariant> map;
|
||||||
map["login"] = m_ui->login->text();
|
map["login"] = m_ui->login->text();
|
||||||
map["password"] = m_ui->password->text();
|
map["password"] = m_ui->password->text();
|
||||||
@ -58,13 +55,11 @@ QMap<QString, QVariant> Account::value() const
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::lockId()
|
void Account::lockId() {
|
||||||
{
|
|
||||||
m_ui->name->setReadOnly(true);;
|
m_ui->name->setReadOnly(true);;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::setData(const QMap<QString, QVariant>& data)
|
void Account::setData(const QMap<QString, QVariant>& data) {
|
||||||
{
|
|
||||||
m_ui->login->setText(data.value("login").toString());
|
m_ui->login->setText(data.value("login").toString());
|
||||||
m_ui->password->setText(data.value("password").toString());
|
m_ui->password->setText(data.value("password").toString());
|
||||||
m_ui->server->setText(data.value("server").toString());
|
m_ui->server->setText(data.value("server").toString());
|
||||||
@ -73,8 +68,7 @@ void Account::setData(const QMap<QString, QVariant>& data)
|
|||||||
m_ui->passwordType->setCurrentIndex(data.value("passwordType").toInt());
|
m_ui->passwordType->setCurrentIndex(data.value("passwordType").toInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
void Account::onComboboxChange(int index)
|
void Account::onComboboxChange(int index) {
|
||||||
{
|
|
||||||
QString description = Shared::Global::getDescription(Shared::Global::fromInt<Shared::AccountPassword>(index));
|
QString description = Shared::Global::getDescription(Shared::Global::fromInt<Shared::AccountPassword>(index));
|
||||||
m_ui->comment->setText(description);
|
m_ui->comment->setText(description);
|
||||||
}
|
}
|
||||||
|
@ -500,7 +500,7 @@ void Conversation::onFeedContext(const QPoint& pos) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
QString path = Shared::resolvePath(item->getAttachPath());
|
QString path = Shared::resolvePath(item->getAttachPath());
|
||||||
if (path.size() > 0) {
|
if (!path.isEmpty()) {
|
||||||
showMenu = true;
|
showMenu = true;
|
||||||
QAction* open = contextMenu->addAction(Shared::icon("document-preview"), tr("Open"));
|
QAction* open = contextMenu->addAction(Shared::icon("document-preview"), tr("Open"));
|
||||||
connect(open, &QAction::triggered, [path]() {
|
connect(open, &QAction::triggered, [path]() {
|
||||||
@ -513,7 +513,7 @@ void Conversation::onFeedContext(const QPoint& pos) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool hasAttach = item->getAttachPath() > 0 || item->getOutOfBandUrl() > 0;
|
bool hasAttach = !item->getAttachPath().isEmpty() || !item->getOutOfBandUrl().isEmpty();
|
||||||
//the only mandatory condition - is for the message to be outgoing, the rest is just a good intention on the server
|
//the only mandatory condition - is for the message to be outgoing, the rest is just a good intention on the server
|
||||||
if (item->getOutgoing() && !hasAttach && index.row() < 100 && item->getTime().daysTo(QDateTime::currentDateTimeUtc()) < 20) {
|
if (item->getOutgoing() && !hasAttach && index.row() < 100 && item->getTime().daysTo(QDateTime::currentDateTimeUtc()) < 20) {
|
||||||
showMenu = true;
|
showMenu = true;
|
||||||
|
@ -141,7 +141,15 @@ void FeedView::updateGeometries() {
|
|||||||
const QStyle* st = style();
|
const QStyle* st = style();
|
||||||
|
|
||||||
QSize layoutBounds = maximumViewportSize();
|
QSize layoutBounds = maximumViewportSize();
|
||||||
QStyleOptionViewItem option = viewOptions();
|
|
||||||
|
|
||||||
|
QStyleOptionViewItem option;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
initViewItemOption(&option);
|
||||||
|
#else
|
||||||
|
option = viewOptions();
|
||||||
|
#endif
|
||||||
|
|
||||||
option.rect.setHeight(maxMessageHeight);
|
option.rect.setHeight(maxMessageHeight);
|
||||||
option.rect.setWidth(layoutBounds.width());
|
option.rect.setWidth(layoutBounds.width());
|
||||||
int frameAroundContents = 0;
|
int frameAroundContents = 0;
|
||||||
@ -182,7 +190,11 @@ void FeedView::updateGeometries() {
|
|||||||
previousOffset += elementMargin;
|
previousOffset += elementMargin;
|
||||||
}
|
}
|
||||||
lastDate = currentDate;
|
lastDate = currentDate;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
QSize messageSize = itemDelegateForIndex(index)->sizeHint(option, index);
|
||||||
|
#else
|
||||||
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
|
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
|
||||||
|
#endif
|
||||||
uint32_t offsetX(0);
|
uint32_t offsetX(0);
|
||||||
if (specialDelegate) {
|
if (specialDelegate) {
|
||||||
if (index.data(Models::MessageFeed::SentByMe).toBool())
|
if (index.data(Models::MessageFeed::SentByMe).toBool())
|
||||||
@ -232,7 +244,11 @@ bool FeedView::tryToCalculateGeometriesWithNoScrollbars(const QStyleOptionViewIt
|
|||||||
previousOffset += elementMargin;
|
previousOffset += elementMargin;
|
||||||
}
|
}
|
||||||
lastDate = currentDate;
|
lastDate = currentDate;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
QSize messageSize = itemDelegateForIndex(index)->sizeHint(option, index);
|
||||||
|
#else
|
||||||
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
|
QSize messageSize = itemDelegate(index)->sizeHint(option, index);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (previousOffset + messageSize.height() + elementMargin > totalHeight)
|
if (previousOffset + messageSize.height() + elementMargin > totalHeight)
|
||||||
return false;
|
return false;
|
||||||
@ -288,8 +304,14 @@ void FeedView::paintEvent(QPaintEvent* event) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QStyleOptionViewItem option;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
initViewItemOption(&option);
|
||||||
|
#else
|
||||||
|
option = viewOptions();
|
||||||
|
#endif
|
||||||
|
|
||||||
QPainter painter(vp);
|
QPainter painter(vp);
|
||||||
QStyleOptionViewItem option = viewOptions();
|
|
||||||
option.features = QStyleOptionViewItem::WrapText;
|
option.features = QStyleOptionViewItem::WrapText;
|
||||||
QPoint cursor = vp->mapFromGlobal(QCursor::pos());
|
QPoint cursor = vp->mapFromGlobal(QCursor::pos());
|
||||||
|
|
||||||
@ -319,7 +341,12 @@ void FeedView::paintEvent(QPaintEvent* event) {
|
|||||||
stripe.setWidth(viewportRect.width());
|
stripe.setWidth(viewportRect.width());
|
||||||
bool mouseOver = stripe.contains(cursor) && viewportRect.contains(cursor);
|
bool mouseOver = stripe.contains(cursor) && viewportRect.contains(cursor);
|
||||||
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
option.state.setFlag(QStyle::State_MouseOver, mouseOver);
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
itemDelegateForIndex(index)->paint(&painter, option, index);
|
||||||
|
#else
|
||||||
itemDelegate(index)->paint(&painter, option, index);
|
itemDelegate(index)->paint(&painter, option, index);
|
||||||
|
#endif
|
||||||
|
|
||||||
if (!lastDate.isNull() && currentDate.daysTo(lastDate) > 0)
|
if (!lastDate.isNull() && currentDate.daysTo(lastDate) > 0)
|
||||||
drawDateDevider(option.rect.bottom(), lastDate, painter);
|
drawDateDevider(option.rect.bottom(), lastDate, painter);
|
||||||
@ -379,8 +406,12 @@ void FeedView::setAnchorHovered(Shared::Hover type) {
|
|||||||
void FeedView::mouseMoveEvent(QMouseEvent* event) {
|
void FeedView::mouseMoveEvent(QMouseEvent* event) {
|
||||||
if (!isVisible())
|
if (!isVisible())
|
||||||
return;
|
return;
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
dragEndPoint = event->position().toPoint();
|
||||||
|
#else
|
||||||
dragEndPoint = event->localPos().toPoint();
|
dragEndPoint = event->localPos().toPoint();
|
||||||
|
#endif
|
||||||
|
|
||||||
if (mousePressed) {
|
if (mousePressed) {
|
||||||
QPoint distance = dragStartPoint - dragEndPoint;
|
QPoint distance = dragStartPoint - dragEndPoint;
|
||||||
if (distance.manhattanLength() > 5)
|
if (distance.manhattanLength() > 5)
|
||||||
@ -423,7 +454,11 @@ void FeedView::mousePressEvent(QMouseEvent* event) {
|
|||||||
|
|
||||||
mousePressed = event->button() == Qt::LeftButton;
|
mousePressed = event->button() == Qt::LeftButton;
|
||||||
if (mousePressed) {
|
if (mousePressed) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
dragStartPoint = event->position().toPoint();
|
||||||
|
#else
|
||||||
dragStartPoint = event->localPos().toPoint();
|
dragStartPoint = event->localPos().toPoint();
|
||||||
|
#endif
|
||||||
if (specialDelegate && specialModel) {
|
if (specialDelegate && specialModel) {
|
||||||
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
|
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
|
||||||
QString lastSelectedId = del->clearSelection();
|
QString lastSelectedId = del->clearSelection();
|
||||||
@ -441,7 +476,11 @@ void FeedView::mouseDoubleClickEvent(QMouseEvent* event) {
|
|||||||
QAbstractItemView::mouseDoubleClickEvent(event);
|
QAbstractItemView::mouseDoubleClickEvent(event);
|
||||||
mousePressed = event->button() == Qt::LeftButton;
|
mousePressed = event->button() == Qt::LeftButton;
|
||||||
if (mousePressed) {
|
if (mousePressed) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
dragStartPoint = event->position().toPoint();
|
||||||
|
#else
|
||||||
dragStartPoint = event->localPos().toPoint();
|
dragStartPoint = event->localPos().toPoint();
|
||||||
|
#endif
|
||||||
if (specialDelegate && specialModel) {
|
if (specialDelegate && specialModel) {
|
||||||
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
|
MessageDelegate* del = static_cast<MessageDelegate*>(itemDelegate());
|
||||||
QString lastSelectedId = del->clearSelection();
|
QString lastSelectedId = del->clearSelection();
|
||||||
@ -469,7 +508,11 @@ void FeedView::mouseReleaseEvent(QMouseEvent* event) {
|
|||||||
|
|
||||||
if (mousePressed) {
|
if (mousePressed) {
|
||||||
if (!dragging && specialDelegate) {
|
if (!dragging && specialDelegate) {
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
QPoint point = event->position().toPoint();
|
||||||
|
#else
|
||||||
QPoint point = event->localPos().toPoint();
|
QPoint point = event->localPos().toPoint();
|
||||||
|
#endif
|
||||||
QModelIndex index = indexAt(point);
|
QModelIndex index = indexAt(point);
|
||||||
if (index.isValid()) {
|
if (index.isValid()) {
|
||||||
QRect rect = visualRect(index);
|
QRect rect = visualRect(index);
|
||||||
|
@ -16,8 +16,7 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef FEEDVIEW_H
|
#pragma once
|
||||||
#define FEEDVIEW_H
|
|
||||||
|
|
||||||
#include <QAbstractItemView>
|
#include <QAbstractItemView>
|
||||||
#include <QDesktopServices>
|
#include <QDesktopServices>
|
||||||
@ -30,11 +29,7 @@
|
|||||||
#include <ui/utils/progress.h>
|
#include <ui/utils/progress.h>
|
||||||
#include <shared/utils.h>
|
#include <shared/utils.h>
|
||||||
|
|
||||||
/**
|
class FeedView : public QAbstractItemView {
|
||||||
* @todo write docs
|
|
||||||
*/
|
|
||||||
class FeedView : public QAbstractItemView
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
FeedView(QWidget* parent = nullptr);
|
FeedView(QWidget* parent = nullptr);
|
||||||
@ -111,5 +106,3 @@ private:
|
|||||||
static const std::set<int> geometryChangingRoles;
|
static const std::set<int> geometryChangingRoles;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif //FEEDVIEW_H
|
|
||||||
|
@ -659,7 +659,7 @@ QLabel * MessageDelegate::getStatusIcon(const Models::FeedItem& data) const {
|
|||||||
QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast<uint8_t>(data.state)]));
|
QIcon q(Shared::icon(Shared::messageStateThemeIcons[static_cast<uint8_t>(data.state)]));
|
||||||
QString tt = Shared::Global::getName(data.state);
|
QString tt = Shared::Global::getName(data.state);
|
||||||
if (data.state == Shared::Message::State::error) {
|
if (data.state == Shared::Message::State::error) {
|
||||||
if (data.error > 0)
|
if (data.error.size() > 0)
|
||||||
tt += ": " + data.error;
|
tt += ": " + data.error;
|
||||||
}
|
}
|
||||||
if (result->toolTip() != tt) { //If i just assign pixmap every time unconditionally
|
if (result->toolTip() != tt) { //If i just assign pixmap every time unconditionally
|
||||||
|
@ -21,36 +21,39 @@
|
|||||||
SettingsList::SettingsList(QWidget* parent):
|
SettingsList::SettingsList(QWidget* parent):
|
||||||
QListWidget(parent),
|
QListWidget(parent),
|
||||||
lastWidth(0)
|
lastWidth(0)
|
||||||
{
|
{}
|
||||||
|
|
||||||
|
SettingsList::~SettingsList() {}
|
||||||
|
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
void SettingsList::initViewItemOption(QStyleOptionViewItem* option) const {
|
||||||
|
QListWidget::initViewItemOption(option);
|
||||||
|
if (!iconSize().isValid())
|
||||||
|
option->decorationSize.setWidth(lastWidth);
|
||||||
|
|
||||||
|
option->rect.setWidth(lastWidth);
|
||||||
}
|
}
|
||||||
|
#else
|
||||||
SettingsList::~SettingsList()
|
QStyleOptionViewItem SettingsList::viewOptions() const {
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
QStyleOptionViewItem SettingsList::viewOptions() const
|
|
||||||
{
|
|
||||||
QStyleOptionViewItem option = QListWidget::viewOptions();
|
QStyleOptionViewItem option = QListWidget::viewOptions();
|
||||||
if (!iconSize().isValid()) {
|
if (!iconSize().isValid())
|
||||||
option.decorationSize.setWidth(lastWidth);
|
option.decorationSize.setWidth(lastWidth);
|
||||||
}
|
|
||||||
option.rect.setWidth(lastWidth);
|
option.rect.setWidth(lastWidth);
|
||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void SettingsList::resizeEvent(QResizeEvent* event)
|
void SettingsList::resizeEvent(QResizeEvent* event) {
|
||||||
{
|
|
||||||
lastWidth = event->size().width();
|
lastWidth = event->size().width();
|
||||||
QListWidget::resizeEvent(event);
|
QListWidget::resizeEvent(event);
|
||||||
}
|
}
|
||||||
|
|
||||||
QRect SettingsList::visualRect(const QModelIndex& index) const
|
QRect SettingsList::visualRect(const QModelIndex& index) const {
|
||||||
{
|
|
||||||
QRect res = QListWidget::visualRect(index);
|
QRect res = QListWidget::visualRect(index);
|
||||||
if (index.isValid()) {
|
if (index.isValid())
|
||||||
res.setWidth(lastWidth);
|
res.setWidth(lastWidth);
|
||||||
}
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -16,29 +16,28 @@
|
|||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef UI_SETTINGSLIST_H
|
#pragma once
|
||||||
#define UI_SETTINGSLIST_H
|
|
||||||
|
|
||||||
#include <QListWidget>
|
#include <QListWidget>
|
||||||
#include <QResizeEvent>
|
#include <QResizeEvent>
|
||||||
|
#include <QStyleOptionViewItem>
|
||||||
|
|
||||||
/**
|
class SettingsList : public QListWidget {
|
||||||
* @todo write docs
|
|
||||||
*/
|
|
||||||
class SettingsList : public QListWidget
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
SettingsList(QWidget* parent = nullptr);
|
SettingsList(QWidget* parent = nullptr);
|
||||||
~SettingsList();
|
~SettingsList();
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
#if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0)
|
||||||
|
void initViewItemOption(QStyleOptionViewItem* option) const override;
|
||||||
|
#else
|
||||||
QStyleOptionViewItem viewOptions() const override;
|
QStyleOptionViewItem viewOptions() const override;
|
||||||
|
#endif
|
||||||
|
|
||||||
void resizeEvent(QResizeEvent * event) override;
|
void resizeEvent(QResizeEvent * event) override;
|
||||||
QRect visualRect(const QModelIndex & index) const override;
|
QRect visualRect(const QModelIndex & index) const override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
int lastWidth;
|
int lastWidth;
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // UI_SETTINGSLIST_H
|
|
||||||
|
Loading…
Reference in New Issue
Block a user