safePasswords #36
@ -1,6 +1,6 @@
|
||||
# Changelog
|
||||
|
||||
## Squawk 0.1.4 (UNRELEASED)
|
||||
## Squawk 0.1.4 (Apr 14, 2020)
|
||||
### New features
|
||||
- message line now is in the same window with roster (new window dialog is still able to opened on context menu)
|
||||
- several new ways to manage your account password:
|
||||
@ -8,6 +8,7 @@
|
||||
- store it in config jammed (local hashing with the constant seed, not secure at all but might look like it is)
|
||||
- ask the account password on each program launch
|
||||
- store it in KWallet which is dynamically loaded
|
||||
- dragging into conversation now attach files
|
||||
|
||||
### Bug fixes
|
||||
- never updating MUC avatars now get updated
|
||||
@ -15,6 +16,7 @@
|
||||
- statuses now behave better: they wrap if they don't fit, you can select them, you can follow links from there
|
||||
- messages and statuses don't loose content if you use < ore > symbols
|
||||
- now avatars of those who are not in the MUC right now but was also display next to the message
|
||||
- fix crash on attempt to attach the same file for the second time
|
||||
|
||||
|
||||
## Squawk 0.1.3 (Mar 31, 2020)
|
||||
|
@ -109,9 +109,9 @@ add_dependencies(${CMAKE_PROJECT_NAME} translations)
|
||||
# Install the executable
|
||||
install(TARGETS squawk DESTINATION ${CMAKE_INSTALL_BINDIR})
|
||||
install(FILES ${QM_FILES} DESTINATION ${CMAKE_INSTALL_DATADIR}/squawk/l10n)
|
||||
install(FILES squawk.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
|
||||
install(FILES squawk48.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/48x48/apps RENAME squawk.png)
|
||||
install(FILES squawk64.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/64x64/apps RENAME squawk.png)
|
||||
install(FILES squawk128.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/128x128/apps RENAME squawk.png)
|
||||
install(FILES squawk256.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps RENAME squawk.png)
|
||||
install(FILES squawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk.svg DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/scalable/apps)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk48.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/48x48/apps RENAME squawk.png)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk64.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/64x64/apps RENAME squawk.png)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk128.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/128x128/apps RENAME squawk.png)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk256.png DESTINATION ${CMAKE_INSTALL_DATADIR}/icons/hicolor/256x256/apps RENAME squawk.png)
|
||||
install(FILES ${CMAKE_CURRENT_BINARY_DIR}/squawk.desktop DESTINATION ${CMAKE_INSTALL_DATADIR}/applications)
|
||||
|
@ -4,7 +4,7 @@
|
||||
[![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)
|
||||
|
||||
![Squawk screenshot](https://macaw.me/images/squawk/0.1.3.png)
|
||||
![Squawk screenshot](https://macaw.me/images/squawk/0.1.4.png)
|
||||
|
||||
### Prerequisites
|
||||
|
||||
@ -13,6 +13,7 @@
|
||||
- lmdb
|
||||
- CMake 3.0 or higher
|
||||
- qxmpp 1.1.0 or higher
|
||||
- kwallet (optional)
|
||||
|
||||
### Getting
|
||||
|
||||
|
@ -41,11 +41,6 @@ Core::PSE::KWallet::KWallet():
|
||||
if (sState == initial) {
|
||||
lib.load();
|
||||
|
||||
if (!lib.isLoaded()) { //fallback from the build directory
|
||||
lib.setFileName("./core/passwordStorageEngines/libkwalletWrapper.so");
|
||||
lib.load();
|
||||
}
|
||||
|
||||
if (lib.isLoaded()) {
|
||||
openWallet = (OpenWallet) lib.resolve("openWallet");
|
||||
networkWallet = (NetworkWallet) lib.resolve("networkWallet");
|
||||
@ -81,7 +76,9 @@ void Core::PSE::KWallet::open()
|
||||
{
|
||||
if (sState == success) {
|
||||
if (cState == disconnected) {
|
||||
wallet = openWallet(networkWallet(), 0, ::KWallet::Wallet::Asynchronous);
|
||||
QString name;
|
||||
networkWallet(name);
|
||||
wallet = openWallet(name, 0, ::KWallet::Wallet::Asynchronous);
|
||||
if (wallet) {
|
||||
cState = connecting;
|
||||
connect(wallet, SIGNAL(walletOpened(bool)), this, SLOT(onWalletOpened(bool)));
|
||||
@ -89,6 +86,7 @@ void Core::PSE::KWallet::open()
|
||||
} else {
|
||||
everError = true;
|
||||
emit opened(false);
|
||||
rejectPending();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -79,7 +79,7 @@ private:
|
||||
|
||||
private:
|
||||
typedef ::KWallet::Wallet* (*OpenWallet)(const QString &, WId, ::KWallet::Wallet::OpenType);
|
||||
typedef const char* (*NetworkWallet)();
|
||||
typedef void (*NetworkWallet)(QString&);
|
||||
typedef void (*DeleteWallet)(::KWallet::Wallet*);
|
||||
typedef int (*ReadPassword)(::KWallet::Wallet*, const QString&, QString&);
|
||||
typedef int (*WritePassword)(::KWallet::Wallet*, const QString&, const QString&);
|
||||
|
@ -8,8 +8,8 @@ extern "C" void deleteWallet(KWallet::Wallet* w) {
|
||||
w->deleteLater();
|
||||
}
|
||||
|
||||
extern "C" const char* networkWallet() {
|
||||
return KWallet::Wallet::NetworkWallet().toStdString().c_str();
|
||||
extern "C" void networkWallet(QString& str) {
|
||||
str = KWallet::Wallet::NetworkWallet();
|
||||
}
|
||||
|
||||
extern "C" int readPassword(KWallet::Wallet* w, const QString &key, QString &value) {
|
||||
|
2
main.cpp
2
main.cpp
@ -42,7 +42,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
QApplication::setApplicationName("squawk");
|
||||
QApplication::setApplicationDisplayName("Squawk");
|
||||
QApplication::setApplicationVersion("0.1.3");
|
||||
QApplication::setApplicationVersion("0.1.4");
|
||||
|
||||
QTranslator qtTranslator;
|
||||
qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath));
|
||||
|
2
order.h
2
order.h
@ -29,7 +29,7 @@ namespace W
|
||||
template <typename data_type, typename comparator = std::less<data_type>>
|
||||
class Order
|
||||
{
|
||||
|
||||
public:
|
||||
class Duplicates:
|
||||
public Utils::Exception
|
||||
{
|
||||
|
@ -1,6 +1,6 @@
|
||||
# Maintainer: Yury Gubich <blue@macaw.me>
|
||||
pkgname=squawk
|
||||
pkgver=0.1.3
|
||||
pkgver=0.1.4
|
||||
pkgrel=1
|
||||
pkgdesc="An XMPP desktop messenger, written on pure c++ (qt)"
|
||||
arch=('i686' 'x86_64')
|
||||
@ -8,8 +8,10 @@ url="https://git.macaw.me/blue/squawk"
|
||||
license=('GPL3')
|
||||
depends=('hicolor-icon-theme' 'desktop-file-utils' 'lmdb' 'qxmpp>=1.1.0')
|
||||
makedepends=('cmake>=3.3' 'imagemagick' 'qt5-tools')
|
||||
optdepends=('kwallet: secure password storage (requires rebuild)')
|
||||
|
||||
source=("$pkgname-$pkgver.tar.gz")
|
||||
sha256sums=('adb172bb7d5b81bd9b83b192481a79ac985877e81604f401b3f2a08613b359bc')
|
||||
sha256sums=('3b290381eaf15a35d24a58a36c29eee375a4ea77b606124982a063d7ecf98870')
|
||||
build() {
|
||||
cd "$srcdir/squawk"
|
||||
cmake . -D CMAKE_INSTALL_PREFIX=/usr -D CMAKE_BUILD_TYPE=Release
|
||||
|
@ -33,9 +33,9 @@ static const QRegularExpression urlReg("(?<!<a\\shref=['\"])(?<!<img\\ssrc=['\"]
|
||||
"(?:https?|ftp):\\/\\/"
|
||||
"\\w+"
|
||||
"(?:"
|
||||
"[\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]?"
|
||||
"[\\w\\.\\,\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]?"
|
||||
"(?:"
|
||||
"\\([\\w\\.\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]+\\)"
|
||||
"\\([\\w\\.\\,\\/\\:\\;\\?\\&\\=\\@\\%\\#\\+\\-]+\\)"
|
||||
")?"
|
||||
")*"
|
||||
")");
|
||||
|
@ -119,6 +119,10 @@ p, li { white-space: pre-wrap; }
|
||||
<p style="-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;"><br /></p></body></html></source>
|
||||
<translation></translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Drop files here to attach them to your message</source>
|
||||
<translation>Бросьте файлы сюда для того что бы прикрепить их к сообщению</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>Global</name>
|
||||
@ -637,6 +641,10 @@ to be displayed as %1</source>
|
||||
<source>Password for account %1</source>
|
||||
<translation>Пароль для учетной записи %1</translation>
|
||||
</message>
|
||||
<message>
|
||||
<source>Please select a contact to start chatting</source>
|
||||
<translation>Выберите контакт или группу что бы начать переписку</translation>
|
||||
</message>
|
||||
</context>
|
||||
<context>
|
||||
<name>VCard</name>
|
||||
|
@ -34,7 +34,8 @@ Squawk::Squawk(QWidget *parent) :
|
||||
requestedAccountsForPasswords(),
|
||||
prompt(0),
|
||||
currentConversation(0),
|
||||
restoreSelection()
|
||||
restoreSelection(),
|
||||
needToRestore(false)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->roster->setModel(&rosterModel);
|
||||
@ -1139,6 +1140,7 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
|
||||
if (id != 0) {
|
||||
delete id;
|
||||
}
|
||||
needToRestore = true;
|
||||
restoreSelection = previous;
|
||||
return;
|
||||
}
|
||||
@ -1204,5 +1206,8 @@ void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIn
|
||||
|
||||
void Squawk::onContextAboutToHide()
|
||||
{
|
||||
if (needToRestore) {
|
||||
needToRestore = false;
|
||||
m_ui->roster->selectionModel()->setCurrentIndex(restoreSelection, QItemSelectionModel::ClearAndSelect);
|
||||
}
|
||||
}
|
||||
|
@ -126,6 +126,7 @@ private:
|
||||
QInputDialog* prompt;
|
||||
Conversation* currentConversation;
|
||||
QModelIndex restoreSelection;
|
||||
bool needToRestore;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent * event) override;
|
||||
|
12
ui/squawk.ui
12
ui/squawk.ui
@ -129,8 +129,18 @@
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>26</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string><html><head/><body><p><span style=" font-size:26pt;">Please select a contact to start chatting</span></p></body></html></string>
|
||||
<string>Please select a contact to start chatting</string>
|
||||
</property>
|
||||
<property name="textFormat">
|
||||
<enum>Qt::PlainText</enum>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
|
@ -44,6 +44,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
|
||||
statusIcon(0),
|
||||
statusLabel(0),
|
||||
filesLayout(0),
|
||||
overlay(new QWidget()),
|
||||
filesToAttach(),
|
||||
scroll(down),
|
||||
manualSliderChange(false),
|
||||
@ -92,15 +93,26 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
|
||||
line->setMyAvatarPath(acc->getAvatarPath());
|
||||
line->setMyName(acc->getName());
|
||||
|
||||
QFont nf = m_ui->nameLabel->font();
|
||||
nf.setBold(true);
|
||||
nf.setPointSize(nf.pointSize() + 2);
|
||||
m_ui->nameLabel->setFont(nf);
|
||||
|
||||
QFont sf = statusLabel->font();
|
||||
sf.setItalic(true);
|
||||
sf.setPointSize(sf.pointSize() - 2);
|
||||
statusLabel->setFont(sf);
|
||||
QGridLayout* gr = static_cast<QGridLayout*>(layout());
|
||||
QLabel* progressLabel = new QLabel(tr("Drop files here to attach them to your message"));
|
||||
gr->addWidget(overlay, 0, 0, 2, 1);
|
||||
QVBoxLayout* nl = new QVBoxLayout();
|
||||
QGraphicsOpacityEffect* opacity = new QGraphicsOpacityEffect();
|
||||
opacity->setOpacity(0.8);
|
||||
overlay->setLayout(nl);
|
||||
overlay->setBackgroundRole(QPalette::Base);
|
||||
overlay->setAutoFillBackground(true);
|
||||
overlay->setGraphicsEffect(opacity);
|
||||
progressLabel->setAlignment(Qt::AlignCenter);
|
||||
QFont pf = progressLabel->font();
|
||||
pf.setBold(true);
|
||||
pf.setPointSize(26);
|
||||
progressLabel->setWordWrap(true);
|
||||
progressLabel->setFont(pf);
|
||||
nl->addStretch();
|
||||
nl->addWidget(progressLabel);
|
||||
nl->addStretch();
|
||||
overlay->hide();
|
||||
|
||||
applyVisualEffects();
|
||||
}
|
||||
@ -362,11 +374,17 @@ void Conversation::addAttachedFile(const QString& path)
|
||||
Badge* badge = new Badge(path, info.fileName(), QIcon::fromTheme(type.iconName()));
|
||||
|
||||
connect(badge, &Badge::close, this, &Conversation::onBadgeClose);
|
||||
filesToAttach.push_back(badge); //TODO neet to check if there are any duplicated ids
|
||||
try {
|
||||
filesToAttach.push_back(badge);
|
||||
filesLayout->addWidget(badge);
|
||||
if (filesLayout->count() == 1) {
|
||||
filesLayout->setContentsMargins(3, 3, 3, 3);
|
||||
}
|
||||
} catch (const W::Order<Badge*, Badge::Comparator>::Duplicates& e) {
|
||||
delete badge;
|
||||
} catch (...) {
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
void Conversation::removeAttachedFile(Badge* badge)
|
||||
@ -421,6 +439,53 @@ void Conversation::setFeedFrames(bool top, bool right, bool bottom, bool left)
|
||||
static_cast<DropShadowEffect*>(m_ui->scrollArea->graphicsEffect())->setFrame(top, right, bottom, left);
|
||||
}
|
||||
|
||||
void Conversation::dragEnterEvent(QDragEnterEvent* event)
|
||||
{
|
||||
bool accept = false;
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
QList<QUrl> list = event->mimeData()->urls();
|
||||
for (const QUrl& url : list) {
|
||||
if (url.isLocalFile()) {
|
||||
QFileInfo info(url.toLocalFile());
|
||||
if (info.isReadable() && info.isFile()) {
|
||||
accept = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accept) {
|
||||
event->acceptProposedAction();
|
||||
overlay->show();
|
||||
}
|
||||
}
|
||||
|
||||
void Conversation::dragLeaveEvent(QDragLeaveEvent* event)
|
||||
{
|
||||
overlay->hide();
|
||||
}
|
||||
|
||||
void Conversation::dropEvent(QDropEvent* event)
|
||||
{
|
||||
bool accept = false;
|
||||
if (event->mimeData()->hasUrls()) {
|
||||
QList<QUrl> list = event->mimeData()->urls();
|
||||
for (const QUrl& url : list) {
|
||||
if (url.isLocalFile()) {
|
||||
QFileInfo info(url.toLocalFile());
|
||||
if (info.isReadable() && info.isFile()) {
|
||||
addAttachedFile(info.canonicalFilePath());
|
||||
accept = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (accept) {
|
||||
event->acceptProposedAction();
|
||||
}
|
||||
overlay->hide();
|
||||
}
|
||||
|
||||
bool VisibilityCatcher::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
if (event->type() == QEvent::Show) {
|
||||
|
@ -22,6 +22,8 @@
|
||||
#include <QWidget>
|
||||
#include <QScopedPointer>
|
||||
#include <QMap>
|
||||
#include <QMimeData>
|
||||
#include <QFileInfo>
|
||||
|
||||
#include "shared/message.h"
|
||||
#include "order.h"
|
||||
@ -105,6 +107,9 @@ protected:
|
||||
void addAttachedFile(const QString& path);
|
||||
void removeAttachedFile(Badge* badge);
|
||||
void clearAttachedFiles();
|
||||
void dragEnterEvent(QDragEnterEvent* event) override;
|
||||
void dragLeaveEvent(QDragLeaveEvent* event) override;
|
||||
void dropEvent(QDropEvent* event) override;
|
||||
|
||||
protected slots:
|
||||
void onEnterPressed();
|
||||
@ -138,6 +143,7 @@ protected:
|
||||
QLabel* statusIcon;
|
||||
QLabel* statusLabel;
|
||||
FlowLayout* filesLayout;
|
||||
QWidget* overlay;
|
||||
W::Order<Badge*, Badge::Comparator> filesToAttach;
|
||||
Scroll scroll;
|
||||
bool manualSliderChange;
|
||||
|
@ -16,10 +16,10 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
<property name="acceptDrops">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -32,7 +32,7 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="MinimumExpanding">
|
||||
@ -115,6 +115,13 @@
|
||||
</property>
|
||||
<item>
|
||||
<widget class="QLabel" name="nameLabel">
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>12</pointsize>
|
||||
<weight>75</weight>
|
||||
<bold>true</bold>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@ -128,6 +135,12 @@
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="font">
|
||||
<font>
|
||||
<pointsize>8</pointsize>
|
||||
<italic>true</italic>
|
||||
</font>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
@ -230,7 +243,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>392</height>
|
||||
<height>385</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
@ -258,7 +271,7 @@
|
||||
<zorder>widget_3</zorder>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QWidget" name="widget_2" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Maximum">
|
||||
|
@ -126,7 +126,11 @@ VCard::VCard(const QString& jid, bool edit, QWidget* parent):
|
||||
overlay->setAutoFillBackground(true);
|
||||
overlay->setGraphicsEffect(opacity);
|
||||
progressLabel->setAlignment(Qt::AlignCenter);
|
||||
progressLabel->setStyleSheet("font: 16pt");
|
||||
QFont pf = progressLabel->font();
|
||||
pf.setBold(true);
|
||||
pf.setPointSize(26);
|
||||
progressLabel->setFont(pf);
|
||||
progressLabel->setWordWrap(true);
|
||||
nl->addStretch();
|
||||
nl->addWidget(progress);
|
||||
nl->addWidget(progressLabel);
|
||||
|
Loading…
Reference in New Issue
Block a user