Compare commits

...

5 Commits

Author SHA1 Message Date
53d56278ed gen id for message without id 2021-07-11 19:07:49 +08:00
f2894be3a5 change cache file size 2021-07-11 18:30:23 +08:00
7ca46b0663 fix context menu 2021-07-09 10:46:19 +08:00
39af2b06b6 macos fix 2021-07-07 23:04:22 +08:00
5d1f4cc36f wip 2021-07-07 21:45:08 +08:00
21 changed files with 233 additions and 40 deletions

View File

@ -18,15 +18,17 @@ if(NOT CMAKE_BUILD_TYPE)
set(CMAKE_BUILD_TYPE Debug) set(CMAKE_BUILD_TYPE Debug)
endif() endif()
set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra") if(CMAKE_COMPILER_IS_GNUCXX)
set(CMAKE_CXX_FLAGS_RELEASE "-O3") set(CMAKE_CXX_FLAGS_DEBUG "-g -Wall -Wextra")
set(CMAKE_CXX_FLAGS_RELEASE "-O3")
endif(CMAKE_COMPILER_IS_GNUCXX)
message("Build type: ${CMAKE_BUILD_TYPE}") message("Build type: ${CMAKE_BUILD_TYPE}")
set(squawk_SRC set(squawk_SRC
main.cpp main.cpp
exception.cpp exception.cpp
signalcatcher.cpp
shared/global.cpp shared/global.cpp
shared/utils.cpp shared/utils.cpp
shared/message.cpp shared/message.cpp
@ -34,6 +36,12 @@ set(squawk_SRC
shared/icons.cpp shared/icons.cpp
) )
if (WIN32)
list(APPEND squawk_SRC signalcatcher_win32.cpp)
else (WIN32)
list(APPEND squawk_SRC signalcatcher.cpp)
endif (WIN32)
set(squawk_HEAD set(squawk_HEAD
exception.h exception.h
signalcatcher.h signalcatcher.h
@ -47,10 +55,44 @@ set(squawk_HEAD
) )
configure_file(resources/images/logo.svg squawk.svg COPYONLY) configure_file(resources/images/logo.svg squawk.svg COPYONLY)
execute_process(COMMAND convert -background none -size 48x48 squawk.svg squawk48.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) configure_file(squawk.rc squawk.rc COPYONLY)
execute_process(COMMAND convert -background none -size 64x64 squawk.svg squawk64.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) if (WIN32)
execute_process(COMMAND convert -background none -size 128x128 squawk.svg squawk128.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) execute_process(COMMAND magick convert -background none -size 48x48 squawk.svg squawk48.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND convert -background none -size 256x256 squawk.svg squawk256.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) execute_process(COMMAND magick convert -background none -size 64x64 squawk.svg squawk64.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND magick convert -background none -size 128x128 squawk.svg squawk128.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND magick convert -background none -size 256x256 squawk.svg squawk256.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND magick convert squawk48.png squawk64.png squawk256.png squawk.ico WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(SQUAWK_WIN_RC "${CMAKE_CURRENT_BINARY_DIR}/squawk.rc")
else (WIN32)
execute_process(COMMAND convert -background none -size 48x48 squawk.svg squawk48.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND convert -background none -size 64x64 squawk.svg squawk64.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND convert -background none -size 128x128 squawk.svg squawk128.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
execute_process(COMMAND convert -background none -size 256x256 squawk.svg squawk256.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
endif (WIN32)
if (APPLE)
file(MAKE_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}/icns.iconset")
execute_process(COMMAND which convert WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE ret)
message("AAA ${ret}")
execute_process(COMMAND echo $PATH WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE ret)
message("AAA ${ret} $ENV{PATH}")
execute_process(COMMAND convert -background none -size 16x16 squawk.svg icns.iconset/icon_16x16.png WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR} RESULT_VARIABLE ret)
message("AAA ${ret}")
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 -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 -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 -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 -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 iconutil -c icns "icns.iconset" -o "squawk.icns" WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR})
set(MACOSX_BUNDLE_ICON_FILE squawk.icns)
set(APP_ICON_MACOSX ${CMAKE_CURRENT_BINARY_DIR}/squawk.icns)
set_source_files_properties(${APP_ICON_MACOSX} PROPERTIES
MACOSX_PACKAGE_LOCATION "Resources")
endif (APPLE)
configure_file(packaging/squawk.desktop squawk.desktop COPYONLY) configure_file(packaging/squawk.desktop squawk.desktop COPYONLY)
@ -92,7 +134,7 @@ if (WITH_KWALLET)
endif() endif()
endif() endif()
add_executable(squawk ${squawk_SRC} ${squawk_HEAD} ${RCC}) add_executable(squawk WIN32 ${squawk_SRC} ${squawk_HEAD} ${RCC} ${SQUAWK_WIN_RC} ${APP_ICON_MACOSX})
target_link_libraries(squawk Qt5::Widgets) target_link_libraries(squawk Qt5::Widgets)
add_subdirectory(ui) add_subdirectory(ui)
@ -102,7 +144,6 @@ add_subdirectory(external/simpleCrypt)
target_link_libraries(squawk squawkUI) target_link_libraries(squawk squawkUI)
target_link_libraries(squawk squawkCORE) target_link_libraries(squawk squawkCORE)
target_link_libraries(squawk uuid)
add_dependencies(${CMAKE_PROJECT_NAME} translations) add_dependencies(${CMAKE_PROJECT_NAME} translations)

View File

@ -8,6 +8,12 @@ find_package(Qt5Gui CONFIG REQUIRED)
find_package(Qt5Network CONFIG REQUIRED) find_package(Qt5Network CONFIG REQUIRED)
find_package(Qt5Xml CONFIG REQUIRED) find_package(Qt5Xml CONFIG REQUIRED)
find_path(LMDB_INCLUDE_DIR NAMES lmdb.h PATHS "${LMDB_DIR}/include")
set(LMDB_LIBRARIES "${LMDB_DIR}/lib/liblmdb.a" )
message(${LMDB_INCLUDE_DIR})
message(${LMDB_LIBRARIES})
set(squawkCORE_SRC set(squawkCORE_SRC
squawk.cpp squawk.cpp
account.cpp account.cpp
@ -27,6 +33,7 @@ add_subdirectory(passwordStorageEngines)
# Tell CMake to create the helloworld executable # Tell CMake to create the helloworld executable
add_library(squawkCORE ${squawkCORE_SRC}) add_library(squawkCORE ${squawkCORE_SRC})
target_include_directories(squawkCORE PUBLIC ${LMDB_INCLUDE_DIR})
if(SYSTEM_QXMPP) if(SYSTEM_QXMPP)
get_target_property(QXMPP_INTERFACE_INCLUDE_DIRECTORIES QXmpp::QXmpp INTERFACE_INCLUDE_DIRECTORIES) get_target_property(QXMPP_INTERFACE_INCLUDE_DIRECTORIES QXmpp::QXmpp INTERFACE_INCLUDE_DIRECTORIES)
@ -39,7 +46,8 @@ target_link_libraries(squawkCORE Qt5::Network)
target_link_libraries(squawkCORE Qt5::Gui) target_link_libraries(squawkCORE Qt5::Gui)
target_link_libraries(squawkCORE Qt5::Xml) target_link_libraries(squawkCORE Qt5::Xml)
target_link_libraries(squawkCORE qxmpp) target_link_libraries(squawkCORE qxmpp)
target_link_libraries(squawkCORE lmdb) # target_link_libraries(squawkCORE lmdb)
target_link_libraries(squawkCORE ${LMDB_LIBRARIES})
target_link_libraries(squawkCORE simpleCrypt) target_link_libraries(squawkCORE simpleCrypt)
if (WITH_KWALLET) if (WITH_KWALLET)
target_link_libraries(squawkCORE kwalletPSE) target_link_libraries(squawkCORE kwalletPSE)

View File

@ -19,6 +19,7 @@
#include "account.h" #include "account.h"
#include <QXmppMessage.h> #include <QXmppMessage.h>
#include <QDateTime> #include <QDateTime>
#include "shared/utils.h"
using namespace Core; using namespace Core;
@ -405,9 +406,13 @@ void Core::Account::sendMessage(const Shared::Message& data) {
void Core::Account::sendMessage(const Shared::Message& data, const QString& path) { void Core::Account::sendMessage(const Shared::Message& data, const QString& path) {
mh->sendMessage(data, path);} mh->sendMessage(data, path);}
void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMessage& msg) void Core::Account::onMamMessageReceived(const QString& queryId, const QXmppMessage& msgConst)
{ {
if (msg.id().size() > 0 && (msg.body().size() > 0 || msg.outOfBandUrl().size() > 0)) { QXmppMessage msg(msgConst);
if (msg.id().size() == 0) {
msg.setId(Shared::generateUUID() + QStringLiteral("-squawkgenerated"));
}
if ((msg.body().size() > 0 || msg.outOfBandUrl().size() > 0)) {
std::map<QString, QString>::const_iterator itr = archiveQueries.find(queryId); std::map<QString, QString>::const_iterator itr = archiveQueries.find(queryId);
if (itr != archiveQueries.end()) { if (itr != archiveQueries.end()) {
QString jid = itr->second; QString jid = itr->second;

View File

@ -58,7 +58,7 @@ void Core::Archive::open(const QString& account)
} }
mdb_env_set_maxdbs(environment, 5); mdb_env_set_maxdbs(environment, 5);
mdb_env_set_mapsize(environment, 512UL * 1024UL * 1024UL); mdb_env_set_mapsize(environment, 16UL * 1024UL * 1024UL);
mdb_env_open(environment, path.toStdString().c_str(), 0, 0664); mdb_env_open(environment, path.toStdString().c_str(), 0, 0664);
MDB_txn *txn; MDB_txn *txn;

View File

@ -119,8 +119,9 @@ void Core::Squawk::newAccountRequest(const QMap<QString, QVariant>& map)
QString server = map.value("server").toString(); QString server = map.value("server").toString();
QString password = map.value("password").toString(); QString password = map.value("password").toString();
QString resource = map.value("resource").toString(); QString resource = map.value("resource").toString();
int passwordType = map.value("passwordType").toInt();
addAccount(login, server, password, name, resource, Shared::AccountPassword::plain); addAccount(login, server, password, name, resource, Shared::Global::fromInt<Shared::AccountPassword>(passwordType));
} }
void Core::Squawk::addAccount( void Core::Squawk::addAccount(

View File

@ -171,7 +171,7 @@ private:
Shared::AccountPassword passwordType Shared::AccountPassword passwordType
); );
static const quint64 passwordHash = 0x08d054225ac4871d; static const quint64 passwordHash = 0x3c5bb27570f50e11;
}; };
} }

View File

@ -40,6 +40,7 @@ int main(int argc, char *argv[])
QApplication app(argc, argv); QApplication app(argc, argv);
SignalCatcher sc(&app); SignalCatcher sc(&app);
QApplication::setOrganizationName("squawk");
QApplication::setApplicationName("squawk"); QApplication::setApplicationName("squawk");
QApplication::setApplicationDisplayName("Squawk"); QApplication::setApplicationDisplayName("Squawk");
QApplication::setApplicationVersion("0.1.5"); QApplication::setApplicationVersion("0.1.5");

View File

@ -17,15 +17,11 @@
*/ */
#include "utils.h" #include "utils.h"
#include <QUuid>
QString Shared::generateUUID() QString Shared::generateUUID()
{ {
uuid_t uuid; return QUuid::createUuid().toString();
uuid_generate(uuid);
char uuid_str[36];
uuid_unparse_lower(uuid, uuid_str);
return uuid_str;
} }

View File

@ -23,7 +23,6 @@
#include <QColor> #include <QColor>
#include <QRegularExpression> #include <QRegularExpression>
#include <uuid/uuid.h>
#include <vector> #include <vector>
namespace Shared { namespace Shared {

42
signalcatcher_win32.cpp Normal file
View File

@ -0,0 +1,42 @@
/*
* 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 "signalcatcher.h"
#include <unistd.h>
SignalCatcher::SignalCatcher(QCoreApplication *p_app, QObject *parent):
QObject(parent),
app(p_app)
{
}
SignalCatcher::~SignalCatcher()
{}
void SignalCatcher::handleSigInt()
{
}
void SignalCatcher::intSignalHandler(int unused)
{
}
int SignalCatcher::setup_unix_signal_handlers()
{
return 0;
}

1
squawk.rc Normal file
View File

@ -0,0 +1 @@
IDI_ICON1 ICON "squawk.ico"

View File

@ -36,6 +36,10 @@ set(squawkUI_SRC
utils/dropshadoweffect.cpp utils/dropshadoweffect.cpp
) )
qt5_wrap_ui(squawkUI_SRC
squawk.ui
)
# Tell CMake to create the helloworld executable # Tell CMake to create the helloworld executable
add_library(squawkUI ${squawkUI_SRC}) add_library(squawkUI ${squawkUI_SRC})

View File

@ -982,6 +982,7 @@ void Squawk::readSettings()
void Squawk::writeSettings() void Squawk::writeSettings()
{ {
QSettings settings; QSettings settings;
qDebug() << "settings.fileName: " << settings.fileName();
settings.beginGroup("ui"); settings.beginGroup("ui");
settings.beginGroup("window"); settings.beginGroup("window");
settings.setValue("geometry", saveGeometry()); settings.setValue("geometry", saveGeometry());
@ -1023,6 +1024,7 @@ void Squawk::writeSettings()
} }
settings.endGroup(); settings.endGroup();
settings.endGroup(); settings.endGroup();
} }
void Squawk::onItemCollepsed(const QModelIndex& index) void Squawk::onItemCollepsed(const QModelIndex& index)

View File

@ -33,6 +33,9 @@ Badge::Badge(const QString& p_id, const QString& p_text, const QIcon& icon, QWid
image->setPixmap(icon.pixmap(25, 25)); image->setPixmap(icon.pixmap(25, 25));
closeButton->setIcon(QIcon::fromTheme("tab-close")); closeButton->setIcon(QIcon::fromTheme("tab-close"));
QIcon qIcon;
qIcon.addFile(QString::fromUtf8(":/images/fallback/dark/big/edit-none.svg"), QSize(), QIcon::Normal, QIcon::Off);
closeButton->setIcon(qIcon);
closeButton->setMaximumHeight(25); closeButton->setMaximumHeight(25);
closeButton->setMaximumWidth(25); closeButton->setMaximumWidth(25);

View File

@ -203,16 +203,23 @@ void Message::showFile(const QString& path)
file = new Image(path); file = new Image(path);
} else { } else {
file = new QLabel(); file = new QLabel();
file->setPixmap(QIcon::fromTheme(type.iconName()).pixmap(50)); QIcon qIcon = QIcon::fromTheme(type.iconName());
if (qIcon.isNull()) {
qIcon.addFile(QString::fromUtf8(":/images/fallback/dark/big/mail-attachment.svg"), QSize(), QIcon::Normal, QIcon::Off);
}
file->setPixmap(qIcon.pixmap(50));
file->setAlignment(Qt::AlignCenter); file->setAlignment(Qt::AlignCenter);
showComment(info.fileName(), true); showComment(info.fileName(), true);
} }
file->setContextMenuPolicy(Qt::ActionsContextMenu); file->setContextMenuPolicy(Qt::ActionsContextMenu);
QAction* openAction = new QAction(QIcon::fromTheme("document-new-from-template"), tr("Open"), file); QAction* openAction = new QAction(QIcon::fromTheme("document-new-from-template"), tr("Open"), this);
connect(openAction, &QAction::triggered, [path]() { //TODO need to get rid of this shame connect(openAction, &QAction::triggered, [path]() { //TODO need to get rid of this shame
QDesktopServices::openUrl(QUrl::fromLocalFile(path)); QDesktopServices::openUrl(QUrl::fromLocalFile(path));
}); });
file->addAction(openAction); file->addAction(openAction);
fileComment->setContextMenuPolicy(Qt::ActionsContextMenu);
fileComment->addAction(openAction);
bodyLayout->insertWidget(2, file); bodyLayout->insertWidget(2, file);
hasFile = true; hasFile = true;
} }

View File

@ -38,7 +38,8 @@ MessageLine::MessageLine(bool p_room, QWidget* parent):
downloading(), downloading(),
room(p_room), room(p_room),
busyShown(false), busyShown(false),
progress() progress(),
lastHeight(0)
{ {
setContentsMargins(0, 0, 0, 0); setContentsMargins(0, 0, 0, 0);
layout->setContentsMargins(0, 0, 0, 0); layout->setContentsMargins(0, 0, 0, 0);
@ -163,6 +164,7 @@ MessageLine::Position MessageLine::message(const Shared::Message& msg, bool forc
emit requestLocalFile(msg.getId(), msg.getOutOfBandUrl()); emit requestLocalFile(msg.getId(), msg.getOutOfBandUrl());
connect(message, &Message::buttonClicked, this, &MessageLine::onDownload); connect(message, &Message::buttonClicked, this, &MessageLine::onDownload);
} }
qDebug() << "inserted message " << id;
return res; return res;
} }
@ -309,7 +311,11 @@ void MessageLine::movePalAvatarToEx(const QString& name)
void MessageLine::resizeEvent(QResizeEvent* event) void MessageLine::resizeEvent(QResizeEvent* event)
{ {
QWidget::resizeEvent(event); QWidget::resizeEvent(event);
emit resize(event->size().height() - event->oldSize().height());
qDebug() << "Resize(unordered): " << event->size().height() << event->oldSize().height();
qDebug() << "Resize: " << height() << lastHeight;
emit resize(height() - lastHeight);
lastHeight = height();
} }
@ -328,6 +334,7 @@ void MessageLine::showBusyIndicator()
layout->insertWidget(0, &progress); layout->insertWidget(0, &progress);
progress.start(); progress.start();
busyShown = true; busyShown = true;
qDebug() << "showBusyIndicator";
} }
} }
@ -337,6 +344,7 @@ void MessageLine::hideBusyIndicator()
progress.stop(); progress.stop();
layout->removeWidget(&progress); layout->removeWidget(&progress);
busyShown = false; busyShown = false;
qDebug() << "hideBusyIndicator";
} }
} }

View File

@ -103,6 +103,7 @@ private:
bool room; bool room;
bool busyShown; bool busyShown;
Progress progress; Progress progress;
int lastHeight;
}; };
#endif // MESSAGELINE_H #endif // MESSAGELINE_H

View File

@ -21,6 +21,15 @@ set(squawkWidgets_SRC
joinconference.cpp joinconference.cpp
) )
qt5_wrap_ui(squawkWidgets_SRC
account.ui
accounts.ui
conversation.ui
joinconference.ui
newcontact.ui
vcard/vcard.ui
)
# Tell CMake to create the helloworld executable # Tell CMake to create the helloworld executable
add_library(squawkWidgets ${squawkWidgets_SRC}) add_library(squawkWidgets ${squawkWidgets_SRC})

View File

@ -21,6 +21,7 @@
#include "ui/utils/dropshadoweffect.h" #include "ui/utils/dropshadoweffect.h"
#include <QDebug> #include <QDebug>
#include <QClipboard>
#include <QScrollBar> #include <QScrollBar>
#include <QTimer> #include <QTimer>
#include <QFileDialog> #include <QFileDialog>
@ -28,6 +29,9 @@
#include <unistd.h> #include <unistd.h>
#include <QAbstractTextDocumentLayout> #include <QAbstractTextDocumentLayout>
#include <QCoreApplication> #include <QCoreApplication>
#include <QTemporaryFile>
#include <QDir>
#include <QMenu>
Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, const QString pRes, QWidget* parent): Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, const QString pRes, QWidget* parent):
QWidget(parent), QWidget(parent),
@ -50,7 +54,8 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
manualSliderChange(false), manualSliderChange(false),
requestingHistory(false), requestingHistory(false),
everShown(false), everShown(false),
tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1) tsb(QApplication::style()->styleHint(QStyle::SH_ScrollBar_Transient) == 1),
pasteImageAction(nullptr)
{ {
m_ui->setupUi(this); m_ui->setupUi(this);
@ -63,6 +68,7 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
statusLabel = m_ui->statusLabel; statusLabel = m_ui->statusLabel;
connect(&ker, &KeyEnterReceiver::enterPressed, this, &Conversation::onEnterPressed); connect(&ker, &KeyEnterReceiver::enterPressed, this, &Conversation::onEnterPressed);
connect(&ker, &KeyEnterReceiver::imagePasted, this, &Conversation::onImagePasted);
connect(&scrollResizeCatcher, &Resizer::resized, this, &Conversation::onScrollResize); connect(&scrollResizeCatcher, &Resizer::resized, this, &Conversation::onScrollResize);
connect(&vis, &VisibilityCatcher::shown, this, &Conversation::onScrollResize); connect(&vis, &VisibilityCatcher::shown, this, &Conversation::onScrollResize);
connect(&vis, &VisibilityCatcher::hidden, this, &Conversation::onScrollResize); connect(&vis, &VisibilityCatcher::hidden, this, &Conversation::onScrollResize);
@ -78,6 +84,20 @@ Conversation::Conversation(bool muc, Models::Account* acc, const QString pJid, c
m_ui->messageEditor->installEventFilter(&ker); m_ui->messageEditor->installEventFilter(&ker);
QAction* pasteImageAction = new QAction(tr("Paste Image"), this);
connect(pasteImageAction, &QAction::triggered, this, &Conversation::onImagePasted);
m_ui->messageEditor->setContextMenuPolicy(Qt::CustomContextMenu);
connect(m_ui->messageEditor, &QTextEdit::customContextMenuRequested, this, [this, pasteImageAction](const QPoint &pos) {
pasteImageAction->setEnabled(Conversation::checkClipboardImage());
QMenu *editorMenu = m_ui->messageEditor->createStandardContextMenu();
editorMenu->addSeparator();
editorMenu->addAction(pasteImageAction);
editorMenu->exec(this->m_ui->messageEditor->mapToGlobal(pos));
});
QScrollBar* vs = m_ui->scrollArea->verticalScrollBar(); QScrollBar* vs = m_ui->scrollArea->verticalScrollBar();
m_ui->scrollArea->setWidget(line); m_ui->scrollArea->setWidget(line);
vs->installEventFilter(&vis); vs->installEventFilter(&vis);
@ -204,10 +224,20 @@ bool KeyEnterReceiver::eventFilter(QObject* obj, QEvent* event)
} }
} }
} }
if (k == Qt::Key_V && key->modifiers() & Qt::CTRL) {
if (Conversation::checkClipboardImage()) {
emit imagePasted();
return true;
}
}
} }
return QObject::eventFilter(obj, event); return QObject::eventFilter(obj, event);
} }
bool Conversation::checkClipboardImage() {
return !QApplication::clipboard()->image().isNull();
}
QString Conversation::getPalResource() const QString Conversation::getPalResource() const
{ {
return activePalResource; return activePalResource;
@ -239,6 +269,20 @@ void Conversation::onEnterPressed()
} }
} }
void Conversation::onImagePasted()
{
QImage image = QApplication::clipboard()->image();
if (image.isNull()) {
return;
}
QTemporaryFile *tempFile = new QTemporaryFile(QDir::tempPath() + QStringLiteral("/squawk_img_attach_XXXXXX.png"), QApplication::instance());
tempFile->open();
image.save(tempFile, "PNG");
tempFile->close();
qDebug() << "image on paste temp file: " << tempFile->fileName();
addAttachedFile(tempFile->fileName());
}
void Conversation::appendMessageWithUpload(const Shared::Message& data, const QString& path) void Conversation::appendMessageWithUpload(const Shared::Message& data, const QString& path)
{ {
line->appendMessageWithUploadNoSiganl(data, path); line->appendMessageWithUploadNoSiganl(data, path);
@ -247,18 +291,28 @@ void Conversation::appendMessageWithUpload(const Shared::Message& data, const QS
void Conversation::onMessagesResize(int amount) void Conversation::onMessagesResize(int amount)
{ {
manualSliderChange = true; manualSliderChange = true;
qDebug() << "Scroll: " << scroll;
switch (scroll) { switch (scroll) {
case down: case down:
qDebug() << "setValue 1: " << m_ui->scrollArea->verticalScrollBar()->maximum();
m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->maximum()); m_ui->scrollArea->verticalScrollBar()->setValue(m_ui->scrollArea->verticalScrollBar()->maximum());
break; break;
case keep: { case keep: {
int max = m_ui->scrollArea->verticalScrollBar()->maximum(); int max = m_ui->scrollArea->verticalScrollBar()->maximum();
int value = m_ui->scrollArea->verticalScrollBar()->value() + amount; int value = m_ui->scrollArea->verticalScrollBar()->value() + amount;
m_ui->scrollArea->verticalScrollBar()->setValue(value); m_ui->scrollArea->verticalScrollBar()->setValue(value);
qDebug() << "setValue 2 max: " << max;
qDebug() << "setValue 2 value: " << m_ui->scrollArea->verticalScrollBar()->value();
qDebug() << "setValue 2 amount: " << amount;
qDebug() << "setValue 2: " << value;
qDebug() << "isMax: " << (value > max);
if (value == max) { if (value > max) {
qDebug() << "setValue 2 scroll = down";
scroll = down; scroll = down;
m_ui->scrollArea->verticalScrollBar()->setValue(max);
} else { } else {
qDebug() << "setValue 2 scroll = nothing";
scroll = nothing; scroll = nothing;
} }
} }
@ -273,14 +327,17 @@ void Conversation::onSliderValueChanged(int value)
{ {
if (!manualSliderChange) { if (!manualSliderChange) {
if (value == m_ui->scrollArea->verticalScrollBar()->maximum()) { if (value == m_ui->scrollArea->verticalScrollBar()->maximum()) {
qDebug() << "onSliderValueChanged: scroll = down";
scroll = down; scroll = down;
} else { } else {
if (!requestingHistory && value == 0) { if (!requestingHistory && value == 0) {
requestingHistory = true; requestingHistory = true;
line->showBusyIndicator(); line->showBusyIndicator();
emit requestArchive(line->firstMessageId()); emit requestArchive(line->firstMessageId());
qDebug() << "onSliderValueChanged: scroll = keep";
scroll = keep; scroll = keep;
} else { } else {
qDebug() << "onSliderValueChanged: scroll = nothing";
scroll = nothing; scroll = nothing;
} }
} }
@ -290,6 +347,7 @@ void Conversation::onSliderValueChanged(int value)
void Conversation::responseArchive(const std::list<Shared::Message> list) void Conversation::responseArchive(const std::list<Shared::Message> list)
{ {
requestingHistory = false; requestingHistory = false;
qDebug() << "responseArchive scroll = keep";
scroll = keep; scroll = keep;
line->hideBusyIndicator(); line->hideBusyIndicator();
@ -304,6 +362,7 @@ void Conversation::showEvent(QShowEvent* event)
everShown = true; everShown = true;
line->showBusyIndicator(); line->showBusyIndicator();
requestingHistory = true; requestingHistory = true;
qDebug() << "showEvent scroll = keep";
scroll = keep; scroll = keep;
emit requestArchive(line->firstMessageId()); emit requestArchive(line->firstMessageId());
} }

View File

@ -52,6 +52,7 @@ protected:
signals: signals:
void enterPressed(); void enterPressed();
void imagePasted();
}; };
class VisibilityCatcher : public QObject { class VisibilityCatcher : public QObject {
@ -90,6 +91,7 @@ public:
void changeMessage(const QString& id, const QMap<QString, QVariant>& data); void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
void setFeedFrames(bool top, bool right, bool bottom, bool left); void setFeedFrames(bool top, bool right, bool bottom, bool left);
virtual void appendMessageWithUpload(const Shared::Message& data, const QString& path); virtual void appendMessageWithUpload(const Shared::Message& data, const QString& path);
static bool checkClipboardImage();
signals: signals:
void sendMessage(const Shared::Message& message); void sendMessage(const Shared::Message& message);
@ -113,6 +115,7 @@ protected:
protected slots: protected slots:
void onEnterPressed(); void onEnterPressed();
void onImagePasted();
void onMessagesResize(int amount); void onMessagesResize(int amount);
void onSliderValueChanged(int value); void onSliderValueChanged(int value);
void onAttach(); void onAttach();
@ -151,6 +154,7 @@ protected:
bool requestingHistory; bool requestingHistory;
bool everShown; bool everShown;
bool tsb; //transient scroll bars bool tsb; //transient scroll bars
QAction *pasteImageAction;
}; };
#endif // CONVERSATION_H #endif // CONVERSATION_H

View File

@ -243,7 +243,7 @@
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>520</width> <width>520</width>
<height>385</height> <height>380</height>
</rect> </rect>
</property> </property>
<layout class="QHBoxLayout" name="horizontalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
@ -325,8 +325,8 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="smiley-shape"> <iconset resource="../../resources/resources.qrc">
<normaloff>.</normaloff>.</iconset> <normaloff>:/images/fallback/dark/big/unfavorite.svg</normaloff>:/images/fallback/dark/big/unfavorite.svg</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -352,8 +352,8 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="mail-attachment-symbolic"> <iconset resource="../../resources/resources.qrc">
<normaloff>.</normaloff>.</iconset> <normaloff>:/images/fallback/dark/big/mail-attachment.svg</normaloff>:/images/fallback/dark/big/mail-attachment.svg</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -366,8 +366,8 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="edit-clear-all"> <iconset resource="../../resources/resources.qrc">
<normaloff>.</normaloff>.</iconset> <normaloff>:/images/fallback/dark/big/clean.svg</normaloff>:/images/fallback/dark/big/clean.svg</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -386,8 +386,8 @@
<string/> <string/>
</property> </property>
<property name="icon"> <property name="icon">
<iconset theme="document-send"> <iconset resource="../../resources/resources.qrc">
<normaloff>.</normaloff>.</iconset> <normaloff>:/images/fallback/dark/big/send.svg</normaloff>:/images/fallback/dark/big/send.svg</iconset>
</property> </property>
<property name="flat"> <property name="flat">
<bool>true</bool> <bool>true</bool>
@ -454,8 +454,8 @@ background-color: transparent
<string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt; <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;
&lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt; &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;
p, li { white-space: pre-wrap; } p, li { white-space: pre-wrap; }
&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Liberation Sans'; font-size:10pt; font-weight:400; font-style:normal;&quot;&gt; &lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'SimSun'; font-size:9pt; font-weight:400; font-style:normal;&quot;&gt;
&lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string> &lt;p style=&quot;-qt-paragraph-type:empty; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px; font-family:'Liberation Sans'; font-size:10pt;&quot;&gt;&lt;br /&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>
</property> </property>
<property name="acceptRichText"> <property name="acceptRichText">
<bool>false</bool> <bool>false</bool>
@ -473,6 +473,8 @@ p, li { white-space: pre-wrap; }
</item> </item>
</layout> </layout>
</widget> </widget>
<resources/> <resources>
<include location="../../resources/resources.qrc"/>
</resources>
<connections/> <connections/>
</ui> </ui>