safePasswords #36
@ -2,6 +2,7 @@
|
||||
|
||||
## Squawk 0.1.4 (UNRELEASED)
|
||||
### New features
|
||||
- message line now is in the same window with roster (new window dialog is still able to opened on double click)
|
||||
- several ways to manage your account password:
|
||||
- store it in plain text with the config (like it always was)
|
||||
- store it in config jammed (local hashing with the constant seed, not secure at all but might look like it is)
|
||||
|
@ -67,9 +67,6 @@ Here is the list of keys you can pass to configuration phase of `cmake ..`.
|
||||
- `SYSTEM_QXMPP` - `True` tries to link against `qxmpp` installed in the system, `False` builds bundled `qxmpp` library (default is `True`)
|
||||
- `WITH_KWALLET` - `True` builds the `KWallet` capability module if `KWallet` is installed and if not goes to `False`. `False` disables `KWallet` support (default is `True`)
|
||||
|
||||
|
||||
Each key is supposed to be passed like that
|
||||
|
||||
## License
|
||||
|
||||
This project is licensed under the GPLv3 License - see the [LICENSE.md](LICENSE.md) file for details
|
||||
|
@ -1,7 +1,6 @@
|
||||
cmake_minimum_required(VERSION 3.0)
|
||||
project(pse)
|
||||
|
||||
|
||||
if (WITH_KWALLET)
|
||||
set(CMAKE_AUTOMOC ON)
|
||||
|
||||
@ -36,7 +35,3 @@ if (WITH_KWALLET)
|
||||
|
||||
install(TARGETS kwalletWrapper DESTINATION ${CMAKE_INSTALL_LIBDIR})
|
||||
endif()
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -386,6 +386,16 @@ bool Models::Roster::ElId::operator <(const Models::Roster::ElId& other) const
|
||||
}
|
||||
}
|
||||
|
||||
bool Models::Roster::ElId::operator!=(const Models::Roster::ElId& other) const
|
||||
{
|
||||
return !(operator == (other));
|
||||
}
|
||||
|
||||
bool Models::Roster::ElId::operator==(const Models::Roster::ElId& other) const
|
||||
{
|
||||
return (account == other.account) && (name == other.name);
|
||||
}
|
||||
|
||||
void Models::Roster::onAccountDataChanged(const QModelIndex& tl, const QModelIndex& br, const QVector<int>& roles)
|
||||
{
|
||||
if (tl.column() == 0) {
|
||||
|
@ -109,6 +109,8 @@ public:
|
||||
const QString name;
|
||||
|
||||
bool operator < (const ElId& other) const;
|
||||
bool operator == (const ElId& other) const;
|
||||
bool operator != (const ElId& other) const;
|
||||
};
|
||||
};
|
||||
|
||||
|
212
ui/squawk.cpp
212
ui/squawk.cpp
@ -32,7 +32,8 @@ Squawk::Squawk(QWidget *parent) :
|
||||
requestedFiles(),
|
||||
vCards(),
|
||||
requestedAccountsForPasswords(),
|
||||
prompt(0)
|
||||
prompt(0),
|
||||
currentConversation(0)
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
m_ui->roster->setModel(&rosterModel);
|
||||
@ -55,6 +56,7 @@ Squawk::Squawk(QWidget *parent) :
|
||||
connect(m_ui->roster, &QTreeView::doubleClicked, this, &Squawk::onRosterItemDoubleClicked);
|
||||
connect(m_ui->roster, &QTreeView::customContextMenuRequested, this, &Squawk::onRosterContextMenu);
|
||||
connect(m_ui->roster, &QTreeView::collapsed, this, &Squawk::onItemCollepsed);
|
||||
connect(m_ui->roster->selectionModel(), &QItemSelectionModel::currentRowChanged, this, &Squawk::onRosterSelectionChanged);
|
||||
|
||||
connect(rosterModel.accountsModel, &Models::Accounts::sizeChanged, this, &Squawk::onAccountsSizeChanged);
|
||||
//m_ui->mainToolBar->addWidget(m_ui->comboBox);
|
||||
@ -74,6 +76,10 @@ Squawk::Squawk(QWidget *parent) :
|
||||
restoreState(settings.value("state").toByteArray());
|
||||
}
|
||||
settings.endGroup();
|
||||
|
||||
if (settings.contains("splitter")) {
|
||||
m_ui->splitter->restoreState(settings.value("splitter").toByteArray());
|
||||
}
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
@ -344,16 +350,7 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
||||
if (conv != 0) {
|
||||
if (created) {
|
||||
conv->setAttribute(Qt::WA_DeleteOnClose);
|
||||
|
||||
connect(conv, &Conversation::destroyed, this, &Squawk::onConversationClosed);
|
||||
connect(conv, qOverload<const Shared::Message&>(&Conversation::sendMessage), this, qOverload<const Shared::Message&>(&Squawk::onConversationMessage));
|
||||
connect(conv, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage),
|
||||
this, qOverload<const Shared::Message&, const QString&>(&Squawk::onConversationMessage));
|
||||
connect(conv, &Conversation::requestArchive, this, &Squawk::onConversationRequestArchive);
|
||||
connect(conv, &Conversation::requestLocalFile, this, &Squawk::onConversationRequestLocalFile);
|
||||
connect(conv, &Conversation::downloadFile, this, &Squawk::onConversationDownloadFile);
|
||||
connect(conv, &Conversation::shown, this, &Squawk::onConversationShown);
|
||||
|
||||
subscribeConversation(conv);
|
||||
conversations.insert(std::make_pair(*id, conv));
|
||||
|
||||
if (created) {
|
||||
@ -372,6 +369,7 @@ void Squawk::onRosterItemDoubleClicked(const QModelIndex& item)
|
||||
}
|
||||
}
|
||||
|
||||
delete id;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -387,9 +385,8 @@ void Squawk::onConversationClosed(QObject* parent)
|
||||
Conversation* conv = static_cast<Conversation*>(sender());
|
||||
Models::Roster::ElId id(conv->getAccount(), conv->getJid());
|
||||
Conversations::const_iterator itr = conversations.find(id);
|
||||
if (itr == conversations.end()) {
|
||||
qDebug() << "Conversation has been closed but can not be found among other opened conversations, application is most probably going to crash";
|
||||
return;
|
||||
if (itr != conversations.end()) {
|
||||
conversations.erase(itr);
|
||||
}
|
||||
if (conv->isMuc) {
|
||||
Room* room = static_cast<Room*>(conv);
|
||||
@ -397,7 +394,6 @@ void Squawk::onConversationClosed(QObject* parent)
|
||||
emit setRoomJoined(id.account, id.name, false);
|
||||
}
|
||||
}
|
||||
conversations.erase(itr);
|
||||
}
|
||||
|
||||
void Squawk::onConversationDownloadFile(const QString& messageId, const QString& url)
|
||||
@ -429,6 +425,9 @@ void Squawk::fileProgress(const QString& messageId, qreal value)
|
||||
if (c != conversations.end()) {
|
||||
c->second->responseFileProgress(messageId, value);
|
||||
}
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
currentConversation->responseFileProgress(messageId, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -447,6 +446,9 @@ void Squawk::fileError(const QString& messageId, const QString& error)
|
||||
if (c != conversations.end()) {
|
||||
c->second->fileError(messageId, error);
|
||||
}
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
currentConversation->fileError(messageId, error);
|
||||
}
|
||||
}
|
||||
requestedFiles.erase(itr);
|
||||
}
|
||||
@ -466,6 +468,9 @@ void Squawk::fileLocalPathResponse(const QString& messageId, const QString& path
|
||||
if (c != conversations.end()) {
|
||||
c->second->responseLocalFile(messageId, path);
|
||||
}
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
currentConversation->responseLocalFile(messageId, path);
|
||||
}
|
||||
}
|
||||
|
||||
requestedFiles.erase(itr);
|
||||
@ -490,18 +495,33 @@ void Squawk::onConversationRequestLocalFile(const QString& messageId, const QStr
|
||||
void Squawk::accountMessage(const QString& account, const Shared::Message& data)
|
||||
{
|
||||
const QString& from = data.getPenPalJid();
|
||||
Conversations::iterator itr = conversations.find({account, from});
|
||||
Models::Roster::ElId id({account, from});
|
||||
Conversations::iterator itr = conversations.find(id);
|
||||
bool found = false;
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
currentConversation->addMessage(data);
|
||||
QApplication::alert(this);
|
||||
if (!isVisible() && !data.getForwarded()) {
|
||||
notify(account, data);
|
||||
}
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (itr != conversations.end()) {
|
||||
Conversation* conv = itr->second;
|
||||
conv->addMessage(data);
|
||||
QApplication::alert(conv);
|
||||
if (conv->isMinimized()) {
|
||||
if (!found && conv->isMinimized()) {
|
||||
rosterModel.addMessage(account, data);
|
||||
}
|
||||
if (!conv->isVisible() && !data.getForwarded()) {
|
||||
notify(account, data);
|
||||
}
|
||||
} else {
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
rosterModel.addMessage(account, data);
|
||||
if (!data.getForwarded()) {
|
||||
QApplication::alert(this);
|
||||
@ -512,14 +532,26 @@ void Squawk::accountMessage(const QString& account, const Shared::Message& data)
|
||||
|
||||
void Squawk::changeMessage(const QString& account, const QString& jid, const QString& id, const QMap<QString, QVariant>& data)
|
||||
{
|
||||
Conversations::iterator itr = conversations.find({account, jid});
|
||||
Models::Roster::ElId eid({account, jid});
|
||||
bool found = false;
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getId() == eid) {
|
||||
currentConversation->changeMessage(id, data);
|
||||
QApplication::alert(this);
|
||||
found = true;
|
||||
}
|
||||
|
||||
Conversations::iterator itr = conversations.find(eid);
|
||||
if (itr != conversations.end()) {
|
||||
Conversation* conv = itr->second;
|
||||
conv->changeMessage(id, data);
|
||||
if (conv->isMinimized()) {
|
||||
if (!found && conv->isMinimized()) {
|
||||
rosterModel.changeMessage(account, jid, id, data);
|
||||
}
|
||||
} else {
|
||||
found = true;
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
rosterModel.changeMessage(account, jid, id, data);
|
||||
}
|
||||
}
|
||||
@ -559,13 +591,37 @@ void Squawk::onConversationMessage(const Shared::Message& msg)
|
||||
{
|
||||
Conversation* conv = static_cast<Conversation*>(sender());
|
||||
emit sendMessage(conv->getAccount(), msg);
|
||||
Models::Roster::ElId id = conv->getId();
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
if (conv == currentConversation) {
|
||||
Conversations::iterator itr = conversations.find(id);
|
||||
if (itr != conversations.end()) {
|
||||
itr->second->addMessage(msg);
|
||||
}
|
||||
} else {
|
||||
currentConversation->addMessage(msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Squawk::onConversationMessage(const Shared::Message& msg, const QString& path)
|
||||
{
|
||||
Conversation* conv = static_cast<Conversation*>(sender());
|
||||
Models::Roster::ElId id = conv->getId();
|
||||
std::map<QString, std::set<Models::Roster::ElId>>::iterator itr = requestedFiles.insert(std::make_pair(msg.getId(), std::set<Models::Roster::ElId>())).first;
|
||||
itr->second.insert(Models::Roster::ElId(conv->getAccount(), conv->getJid()));
|
||||
itr->second.insert(id);
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
if (conv == currentConversation) {
|
||||
Conversations::iterator itr = conversations.find(id);
|
||||
if (itr != conversations.end()) {
|
||||
itr->second->appendMessageWithUpload(msg, path);
|
||||
}
|
||||
} else {
|
||||
currentConversation->appendMessageWithUpload(msg, path);
|
||||
}
|
||||
}
|
||||
|
||||
emit sendMessage(conv->getAccount(), msg, path);
|
||||
}
|
||||
@ -580,6 +636,10 @@ void Squawk::responseArchive(const QString& account, const QString& jid, const s
|
||||
{
|
||||
Models::Roster::ElId id(account, jid);
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getId() == id) {
|
||||
currentConversation->responseArchive(list);
|
||||
}
|
||||
|
||||
Conversations::const_iterator itr = conversations.find(id);
|
||||
if (itr != conversations.end()) {
|
||||
itr->second->responseArchive(list);
|
||||
@ -603,6 +663,13 @@ void Squawk::removeAccount(const QString& account)
|
||||
++itr;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentConversation != 0 && currentConversation->getAccount() == account) {
|
||||
currentConversation->deleteLater();
|
||||
currentConversation = 0;
|
||||
m_ui->filler->show();
|
||||
}
|
||||
|
||||
rosterModel.removeAccount(account);
|
||||
}
|
||||
|
||||
@ -761,7 +828,9 @@ void Squawk::onRosterContextMenu(const QPoint& point)
|
||||
unsub->setEnabled(active);
|
||||
connect(unsub, &QAction::triggered, [this, id]() {
|
||||
emit setRoomAutoJoin(id.account, id.name, false);
|
||||
if (conversations.find(id) == conversations.end()) { //to leave the room if it's not opened in a conversation window
|
||||
if (conversations.find(id) == conversations.end()
|
||||
&& (currentConversation == 0 || currentConversation->getId() != id)
|
||||
) { //to leave the room if it's not opened in a conversation window
|
||||
emit setRoomJoined(id.account, id.name, false);
|
||||
}
|
||||
});
|
||||
@ -770,7 +839,9 @@ void Squawk::onRosterContextMenu(const QPoint& point)
|
||||
unsub->setEnabled(active);
|
||||
connect(unsub, &QAction::triggered, [this, id]() {
|
||||
emit setRoomAutoJoin(id.account, id.name, true);
|
||||
if (conversations.find(id) == conversations.end()) { //to join the room if it's not already joined
|
||||
if (conversations.find(id) == conversations.end()
|
||||
&& (currentConversation == 0 || currentConversation->getId() != id)
|
||||
) { //to join the room if it's not already joined
|
||||
emit setRoomJoined(id.account, id.name, true);
|
||||
}
|
||||
});
|
||||
@ -897,7 +968,6 @@ void Squawk::readSettings()
|
||||
} // need to fix that
|
||||
settings.endArray();
|
||||
}
|
||||
|
||||
settings.endGroup();
|
||||
}
|
||||
|
||||
@ -910,6 +980,8 @@ void Squawk::writeSettings()
|
||||
settings.setValue("state", saveState());
|
||||
settings.endGroup();
|
||||
|
||||
settings.setValue("splitter", m_ui->splitter->saveState());
|
||||
|
||||
settings.setValue("availability", m_ui->comboBox->currentIndex());
|
||||
settings.beginWriteArray("connectedAccounts");
|
||||
int size = rosterModel.accountsModel->rowCount(QModelIndex());
|
||||
@ -1008,3 +1080,93 @@ void Squawk::onPasswordPromptRejected()
|
||||
emit responsePassword(requestedAccountsForPasswords.front(), prompt->textValue());
|
||||
onPasswordPromptDone();
|
||||
}
|
||||
|
||||
void Squawk::subscribeConversation(Conversation* conv)
|
||||
{
|
||||
connect(conv, &Conversation::destroyed, this, &Squawk::onConversationClosed);
|
||||
connect(conv, qOverload<const Shared::Message&>(&Conversation::sendMessage), this, qOverload<const Shared::Message&>(&Squawk::onConversationMessage));
|
||||
connect(conv, qOverload<const Shared::Message&, const QString&>(&Conversation::sendMessage),
|
||||
this, qOverload<const Shared::Message&, const QString&>(&Squawk::onConversationMessage));
|
||||
connect(conv, &Conversation::requestArchive, this, &Squawk::onConversationRequestArchive);
|
||||
connect(conv, &Conversation::requestLocalFile, this, &Squawk::onConversationRequestLocalFile);
|
||||
connect(conv, &Conversation::downloadFile, this, &Squawk::onConversationDownloadFile);
|
||||
connect(conv, &Conversation::shown, this, &Squawk::onConversationShown);
|
||||
}
|
||||
|
||||
void Squawk::onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous)
|
||||
{
|
||||
if (current.isValid()) {
|
||||
Models::Item* node = static_cast<Models::Item*>(current.internalPointer());
|
||||
Models::Contact* contact = 0;
|
||||
Models::Room* room = 0;
|
||||
QString res;
|
||||
Models::Roster::ElId* id = 0;
|
||||
switch (node->type) {
|
||||
case Models::Item::contact:
|
||||
contact = static_cast<Models::Contact*>(node);
|
||||
id = new Models::Roster::ElId(contact->getAccountName(), contact->getJid());
|
||||
break;
|
||||
case Models::Item::presence:
|
||||
contact = static_cast<Models::Contact*>(node->parentItem());
|
||||
id = new Models::Roster::ElId(contact->getAccountName(), contact->getJid());
|
||||
res = node->getName();
|
||||
break;
|
||||
case Models::Item::room:
|
||||
room = static_cast<Models::Room*>(node);
|
||||
id = new Models::Roster::ElId(room->getAccountName(), room->getJid());
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (id != 0) {
|
||||
if (currentConversation != 0) {
|
||||
if (currentConversation->getJid() == id->name) {
|
||||
if (contact != 0) {
|
||||
currentConversation->setPalResource(res);
|
||||
}
|
||||
} else {
|
||||
currentConversation->deleteLater();
|
||||
}
|
||||
} else {
|
||||
m_ui->filler->hide();
|
||||
}
|
||||
|
||||
Models::Account* acc = rosterModel.getAccount(id->account);
|
||||
Models::Contact::Messages deque;
|
||||
if (contact != 0) {
|
||||
currentConversation = new Chat(acc, contact);
|
||||
contact->getMessages(deque);
|
||||
} else if (room != 0) {
|
||||
currentConversation = new Room(acc, room);
|
||||
room->getMessages(deque);
|
||||
|
||||
if (!room->getJoined()) {
|
||||
emit setRoomJoined(id->account, id->name, true);
|
||||
}
|
||||
}
|
||||
if (!testAttribute(Qt::WA_TranslucentBackground)) {
|
||||
currentConversation->setFeedFrames(true, false, true, true);
|
||||
}
|
||||
|
||||
subscribeConversation(currentConversation);
|
||||
for (Models::Contact::Messages::const_iterator itr = deque.begin(), end = deque.end(); itr != end; ++itr) {
|
||||
currentConversation->addMessage(*itr);
|
||||
}
|
||||
|
||||
if (res.size() > 0) {
|
||||
currentConversation->setPalResource(res);
|
||||
}
|
||||
|
||||
m_ui->splitter->insertWidget(1, currentConversation);
|
||||
|
||||
delete id;
|
||||
} else {
|
||||
if (currentConversation != 0) {
|
||||
currentConversation->deleteLater();
|
||||
currentConversation = 0;
|
||||
m_ui->filler->show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -124,6 +124,7 @@ private:
|
||||
std::map<QString, VCard*> vCards;
|
||||
std::deque<QString> requestedAccountsForPasswords;
|
||||
QInputDialog* prompt;
|
||||
Conversation* currentConversation;
|
||||
|
||||
protected:
|
||||
void closeEvent(QCloseEvent * event) override;
|
||||
@ -153,10 +154,12 @@ private slots:
|
||||
void onItemCollepsed(const QModelIndex& index);
|
||||
void onPasswordPromptAccepted();
|
||||
void onPasswordPromptRejected();
|
||||
void onRosterSelectionChanged(const QModelIndex& current, const QModelIndex& previous);
|
||||
|
||||
private:
|
||||
void checkNextAccountForPassword();
|
||||
void onPasswordPromptDone();
|
||||
void subscribeConversation(Conversation* conv);
|
||||
};
|
||||
|
||||
#endif // SQUAWK_H
|
||||
|
148
ui/squawk.ui
148
ui/squawk.ui
@ -6,8 +6,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>385</width>
|
||||
<height>508</height>
|
||||
<width>718</width>
|
||||
<height>720</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
@ -17,7 +17,7 @@
|
||||
<enum>Qt::ToolButtonFollowStyle</enum>
|
||||
</property>
|
||||
<widget class="QWidget" name="centralWidget">
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
@ -30,42 +30,112 @@
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="0" column="0">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="editable">
|
||||
<item>
|
||||
<widget class="QSplitter" name="splitter">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="handleWidth">
|
||||
<number>1</number>
|
||||
</property>
|
||||
<property name="childrenCollapsible">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QTreeView" name="roster">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
<widget class="QWidget" name="widget" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="minimumSize">
|
||||
<size>
|
||||
<width>200</width>
|
||||
<height>0</height>
|
||||
</size>
|
||||
</property>
|
||||
<property name="maximumSize">
|
||||
<size>
|
||||
<width>400</width>
|
||||
<height>16777215</height>
|
||||
</size>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout_2">
|
||||
<property name="leftMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="topMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="rightMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<property name="bottomMargin">
|
||||
<number>0</number>
|
||||
</property>
|
||||
<item row="2" column="1">
|
||||
<widget class="QTreeView" name="roster">
|
||||
<property name="frameShape">
|
||||
<enum>QFrame::NoFrame</enum>
|
||||
</property>
|
||||
<property name="frameShadow">
|
||||
<enum>QFrame::Sunken</enum>
|
||||
</property>
|
||||
<property name="uniformRowHeights">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="animated">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="allColumnsShowFocus">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
<property name="expandsOnDoubleClick">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<attribute name="headerVisible">
|
||||
<bool>false</bool>
|
||||
</attribute>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QComboBox" name="comboBox">
|
||||
<property name="editable">
|
||||
<bool>false</bool>
|
||||
</property>
|
||||
<property name="currentText">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="currentIndex">
|
||||
<number>-1</number>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="filler" native="true">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QGridLayout" name="gridLayout">
|
||||
<item row="0" column="0">
|
||||
<widget class="QLabel" name="label">
|
||||
<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>
|
||||
</property>
|
||||
<property name="alignment">
|
||||
<set>Qt::AlignCenter</set>
|
||||
</property>
|
||||
<property name="wordWrap">
|
||||
<bool>true</bool>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
@ -75,8 +145,8 @@
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>385</width>
|
||||
<height>22</height>
|
||||
<width>718</width>
|
||||
<height>27</height>
|
||||
</rect>
|
||||
</property>
|
||||
<widget class="QMenu" name="menuSettings">
|
||||
|
@ -427,6 +427,12 @@ void MessageLine::fileError(const QString& messageId, const QString& error)
|
||||
}
|
||||
|
||||
void MessageLine::appendMessageWithUpload(const Shared::Message& msg, const QString& path)
|
||||
{
|
||||
appendMessageWithUploadNoSiganl(msg, path);
|
||||
emit uploadFile(msg, path);
|
||||
}
|
||||
|
||||
void MessageLine::appendMessageWithUploadNoSiganl(const Shared::Message& msg, const QString& path)
|
||||
{
|
||||
message(msg, true);
|
||||
QString id = msg.getId();
|
||||
@ -436,9 +442,9 @@ void MessageLine::appendMessageWithUpload(const Shared::Message& msg, const QStr
|
||||
ui->showComment(tr("Uploading..."));
|
||||
uploading.insert(std::make_pair(id, ui));
|
||||
uploadPaths.insert(std::make_pair(id, path));
|
||||
emit uploadFile(msg, path);
|
||||
}
|
||||
|
||||
|
||||
void MessageLine::onUpload()
|
||||
{
|
||||
//TODO retry
|
||||
|
@ -53,6 +53,7 @@ public:
|
||||
void fileError(const QString& messageId, const QString& error);
|
||||
void fileProgress(const QString& messageId, qreal progress);
|
||||
void appendMessageWithUpload(const Shared::Message& msg, const QString& path);
|
||||
void appendMessageWithUploadNoSiganl(const Shared::Message& msg, const QString& path);
|
||||
void removeMessage(const QString& messageId);
|
||||
void setMyAvatarPath(const QString& p_path);
|
||||
void setPalAvatar(const QString& jid, const QString& path);
|
||||
|
@ -210,6 +210,11 @@ void Conversation::onEnterPressed()
|
||||
}
|
||||
}
|
||||
|
||||
void Conversation::appendMessageWithUpload(const Shared::Message& data, const QString& path)
|
||||
{
|
||||
line->appendMessageWithUploadNoSiganl(data, path);
|
||||
}
|
||||
|
||||
void Conversation::onMessagesResize(int amount)
|
||||
{
|
||||
manualSliderChange = true;
|
||||
@ -334,6 +339,11 @@ void Conversation::responseLocalFile(const QString& messageId, const QString& pa
|
||||
line->responseLocalFile(messageId, path);
|
||||
}
|
||||
|
||||
Models::Roster::ElId Conversation::getId() const
|
||||
{
|
||||
return {getAccount(), getJid()};
|
||||
}
|
||||
|
||||
void Conversation::addAttachedFile(const QString& path)
|
||||
{
|
||||
QMimeDatabase db;
|
||||
@ -397,6 +407,10 @@ void Conversation::onTextEditDocSizeChanged(const QSizeF& size)
|
||||
m_ui->messageEditor->setMaximumHeight(int(size.height()));
|
||||
}
|
||||
|
||||
void Conversation::setFeedFrames(bool top, bool right, bool bottom, bool left)
|
||||
{
|
||||
static_cast<DropShadowEffect*>(m_ui->scrollArea->graphicsEffect())->setFrame(top, right, bottom, left);
|
||||
}
|
||||
|
||||
bool VisibilityCatcher::eventFilter(QObject* obj, QEvent* event)
|
||||
{
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "shared/message.h"
|
||||
#include "order.h"
|
||||
#include "ui/models/account.h"
|
||||
#include "ui/models/roster.h"
|
||||
#include "ui/utils/messageline.h"
|
||||
#include "ui/utils/resizer.h"
|
||||
#include "ui/utils/flowlayout.h"
|
||||
@ -72,6 +73,7 @@ public:
|
||||
QString getJid() const;
|
||||
QString getAccount() const;
|
||||
QString getPalResource() const;
|
||||
Models::Roster::ElId getId() const;
|
||||
virtual void addMessage(const Shared::Message& data);
|
||||
|
||||
void setPalResource(const QString& res);
|
||||
@ -82,6 +84,8 @@ public:
|
||||
void responseFileProgress(const QString& messageId, qreal progress);
|
||||
virtual void setAvatar(const QString& path);
|
||||
void changeMessage(const QString& id, const QMap<QString, QVariant>& data);
|
||||
void setFeedFrames(bool top, bool right, bool bottom, bool left);
|
||||
virtual void appendMessageWithUpload(const Shared::Message& data, const QString& path);
|
||||
|
||||
signals:
|
||||
void sendMessage(const Shared::Message& message);
|
||||
|
@ -10,6 +10,12 @@
|
||||
<height>658</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
|
||||
<horstretch>2</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="horizontalLayout">
|
||||
<property name="spacing">
|
||||
<number>0</number>
|
||||
@ -206,7 +212,7 @@
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>520</width>
|
||||
<height>389</height>
|
||||
<height>392</height>
|
||||
</rect>
|
||||
</property>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout_2">
|
||||
|
Loading…
Reference in New Issue
Block a user