1
0
mirror of https://github.com/qTox/qTox.git synced 2024-03-22 14:00:36 +08:00

fixing conflict

This commit is contained in:
agilob 2015-03-14 11:36:38 +00:00
commit a501620d92
No known key found for this signature in database
GPG Key ID: 34568050DBCCB997
30 changed files with 707 additions and 532 deletions

View File

@ -29,8 +29,8 @@ FORMS += \
src/mainwindow.ui \ src/mainwindow.ui \
src/widget/form/settings/generalsettings.ui \ src/widget/form/settings/generalsettings.ui \
src/widget/form/settings/avsettings.ui \ src/widget/form/settings/avsettings.ui \
src/widget/form/settings/identitysettings.ui \
src/widget/form/settings/privacysettings.ui \ src/widget/form/settings/privacysettings.ui \
src/widget/form/profileform.ui \
src/widget/form/loadhistorydialog.ui \ src/widget/form/loadhistorydialog.ui \
src/widget/form/setpassworddialog.ui \ src/widget/form/setpassworddialog.ui \
src/chatlog/content/filetransferwidget.ui \ src/chatlog/content/filetransferwidget.ui \
@ -323,10 +323,10 @@ contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) {
src/widget/form/settingswidget.h \ src/widget/form/settingswidget.h \
src/widget/form/settings/genericsettings.h \ src/widget/form/settings/genericsettings.h \
src/widget/form/settings/generalform.h \ src/widget/form/settings/generalform.h \
src/widget/form/settings/identityform.h \
src/widget/form/settings/privacyform.h \ src/widget/form/settings/privacyform.h \
src/widget/form/settings/avform.h \ src/widget/form/settings/avform.h \
src/widget/form/filesform.h \ src/widget/form/filesform.h \
src/widget/form/profileform.h \
src/widget/tool/chattextedit.h \ src/widget/tool/chattextedit.h \
src/widget/tool/friendrequestdialog.h \ src/widget/tool/friendrequestdialog.h \
src/widget/friendwidget.h \ src/widget/friendwidget.h \
@ -351,9 +351,9 @@ contains(ENABLE_SYSTRAY_GTK_BACKEND, NO) {
src/widget/form/addfriendform.cpp \ src/widget/form/addfriendform.cpp \
src/widget/form/settingswidget.cpp \ src/widget/form/settingswidget.cpp \
src/widget/form/settings/generalform.cpp \ src/widget/form/settings/generalform.cpp \
src/widget/form/settings/identityform.cpp \
src/widget/form/settings/privacyform.cpp \ src/widget/form/settings/privacyform.cpp \
src/widget/form/settings/avform.cpp \ src/widget/form/settings/avform.cpp \
src/widget/form/profileform.cpp \
src/widget/form/filesform.cpp \ src/widget/form/filesform.cpp \
src/widget/tool/chattextedit.cpp \ src/widget/tool/chattextedit.cpp \
src/widget/tool/friendrequestdialog.cpp \ src/widget/tool/friendrequestdialog.cpp \

View File

@ -242,11 +242,12 @@ void Audio::playMono16Sound(const QByteArray& data)
} }
void Audio::playGroupAudioQueued(Tox*,int group, int peer, const int16_t* data, void Audio::playGroupAudioQueued(Tox*,int group, int peer, const int16_t* data,
unsigned samples, uint8_t channels, unsigned sample_rate,void*) unsigned samples, uint8_t channels, unsigned sample_rate, void* core)
{ {
QMetaObject::invokeMethod(instance, "playGroupAudio", Qt::BlockingQueuedConnection, QMetaObject::invokeMethod(instance, "playGroupAudio", Qt::BlockingQueuedConnection,
Q_ARG(int,group), Q_ARG(int,peer), Q_ARG(const int16_t*,data), Q_ARG(int,group), Q_ARG(int,peer), Q_ARG(const int16_t*,data),
Q_ARG(unsigned,samples), Q_ARG(uint8_t,channels), Q_ARG(unsigned,sample_rate)); Q_ARG(unsigned,samples), Q_ARG(uint8_t,channels), Q_ARG(unsigned,sample_rate));
emit static_cast<Core*>(core)->groupPeerAudioPlaying(group, peer);
} }
void Audio::playGroupAudio(int group, int peer, const int16_t* data, void Audio::playGroupAudio(int group, int peer, const int16_t* data,

View File

@ -24,6 +24,7 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QFileDialog> #include <QFileDialog>
#include <QFile> #include <QFile>
#include <QBuffer>
#include <QMessageBox> #include <QMessageBox>
#include <QDesktopServices> #include <QDesktopServices>
#include <QDesktopWidget> #include <QDesktopWidget>
@ -435,7 +436,7 @@ void FileTransferWidget::handleButton(QPushButton *btn)
else if (btn->objectName() == "dir") else if (btn->objectName() == "dir")
{ {
QString dirPath = QFileInfo(fileInfo.filePath).dir().path(); QString dirPath = QFileInfo(fileInfo.filePath).dir().path();
QDesktopServices::openUrl(QUrl("file://" + dirPath, QUrl::TolerantMode)); QDesktopServices::openUrl(QUrl::fromLocalFile(dirPath));
} }
} }
@ -451,22 +452,13 @@ void FileTransferWidget::showPreview(const QString &filename)
ui->previewLabel->setPixmap(pmap); ui->previewLabel->setPixmap(pmap);
ui->previewLabel->show(); ui->previewLabel->show();
// Show preview, but make sure it's not larger than 50% of the screen width/height // Show mouseover preview, but make sure it's not larger than 50% of the screen width/height
QRect maxSize = QApplication::desktop()->screenGeometry(); QRect desktopSize = QApplication::desktop()->screenGeometry();
maxSize.setWidth(0.5*maxSize.width()); QImage image = QImage(filename).scaled(0.5*desktopSize.width(), 0.5*desktopSize.height(), Qt::KeepAspectRatio, Qt::SmoothTransformation);
maxSize.setHeight(0.5*maxSize.height()); QByteArray imageData;
QBuffer buffer(&imageData);
QImage image = QImage(filename); image.save(&buffer, "PNG");
QSize imageSize(image.width(), image.height()); ui->previewLabel->setToolTip("<img src=data:image/png;base64," + imageData.toBase64() + "/>");
if (imageSize.width() > maxSize.width() || imageSize.height() > maxSize.height())
{
imageSize.scale(maxSize.width(), maxSize.height(), Qt::KeepAspectRatio);
ui->previewLabel->setToolTip("<html><img src="+QUrl::toPercentEncoding(filename)+" width="+QString::number(imageSize.width())+" height="+QString::number(imageSize.height())+"/></html>");
}
else
{
ui->previewLabel->setToolTip("<html><img src"+QUrl::toPercentEncoding(filename)+"/></html>");
}
} }
} }

View File

@ -221,6 +221,9 @@ void Text::hoverMoveEvent(QGraphicsSceneHoverEvent *event)
setCursor(QCursor(Qt::PointingHandCursor)); setCursor(QCursor(Qt::PointingHandCursor));
else else
setCursor(QCursor()); setCursor(QCursor());
// tooltip
setToolTip(extractImgTooltip(cursorFromPos(event->scenePos(), false)));
} }
QString Text::getText() const QString Text::getText() const
@ -287,10 +290,10 @@ QSizeF Text::idealSize()
return size; return size;
} }
int Text::cursorFromPos(QPointF scenePos) const int Text::cursorFromPos(QPointF scenePos, bool fuzzy) const
{ {
if(doc) if(doc)
return doc->documentLayout()->hitTest(mapFromScene(scenePos), Qt::FuzzyHit); return doc->documentLayout()->hitTest(mapFromScene(scenePos), fuzzy ? Qt::FuzzyHit : Qt::ExactHit);
return -1; return -1;
} }
@ -348,3 +351,17 @@ QString Text::extractSanitizedText(int from, int to) const
return txt; return txt;
} }
QString Text::extractImgTooltip(int pos) const
{
for(QTextBlock::Iterator itr = doc->firstBlock().begin(); itr!=doc->firstBlock().end(); ++itr)
{
if(itr.fragment().contains(pos) && itr.fragment().charFormat().isImageFormat())
{
QTextImageFormat imgFmt = itr.fragment().charFormat().toImageFormat();
return imgFmt.toolTip();
}
}
return QString();
}

View File

@ -61,11 +61,12 @@ protected:
void freeResources(); void freeResources();
QSizeF idealSize(); QSizeF idealSize();
int cursorFromPos(QPointF scenePos) const; int cursorFromPos(QPointF scenePos, bool fuzzy = true) const;
int getSelectionEnd() const; int getSelectionEnd() const;
int getSelectionStart() const; int getSelectionStart() const;
bool hasSelection() const; bool hasSelection() const;
QString extractSanitizedText(int from, int to) const; QString extractSanitizedText(int from, int to) const;
QString extractImgTooltip(int pos) const;
private: private:
QTextDocument* doc = nullptr; QTextDocument* doc = nullptr;

View File

@ -171,6 +171,7 @@ signals:
void groupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); void groupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction);
void groupNamelistChanged(int groupnumber, int peernumber, uint8_t change); void groupNamelistChanged(int groupnumber, int peernumber, uint8_t change);
void groupTitleChanged(int groupnumber, const QString& author, const QString& title); void groupTitleChanged(int groupnumber, const QString& author, const QString& title);
void groupPeerAudioPlaying(int groupnumber, int peernumber);
void usernameSet(const QString& username); void usernameSet(const QString& username);
void statusMessageSet(const QString& message); void statusMessageSet(const QString& message);

View File

@ -76,7 +76,7 @@ void Core::prepareCall(int friendId, int callId, ToxAv* toxav, bool videoEnabled
#ifdef QTOX_FILTER_AUDIO #ifdef QTOX_FILTER_AUDIO
if (Settings::getInstance().getFilterAudio()) if (Settings::getInstance().getFilterAudio())
{ {
Core::filterer[callId] = new AudioFilterer(); filterer[callId] = new AudioFilterer();
filterer[callId]->startFilter(48000); filterer[callId]->startFilter(48000);
} }
else else
@ -257,13 +257,23 @@ void Core::sendCallAudio(int callId, ToxAv* toxav)
if (Audio::tryCaptureSamples(buf, framesize)) if (Audio::tryCaptureSamples(buf, framesize))
{ {
#ifdef QTOX_FILTER_AUDIO #ifdef QTOX_FILTER_AUDIO
if (filterer[callId]) if (Settings::getInstance().getFilterAudio())
{ {
if (!filterer[callId])
{
filterer[callId] = new AudioFilterer();
filterer[callId]->startFilter(48000);
}
// is a null op #ifndef ALC_LOOPBACK_CAPTURE_SAMPLES // is a null op #ifndef ALC_LOOPBACK_CAPTURE_SAMPLES
Audio::getEchoesToFilter(filterer[callId], framesize); Audio::getEchoesToFilter(filterer[callId], framesize);
filterer[callId]->filterAudio((int16_t*) buf, framesize); filterer[callId]->filterAudio((int16_t*) buf, framesize);
} }
else if (filterer[callId])
{
delete filterer[callId];
filterer[callId] = nullptr;
}
#endif #endif
uint8_t dest[bufsize]; uint8_t dest[bufsize];

View File

@ -303,7 +303,7 @@ void Core::saveConfiguration(const QString& path)
if (!pwsaltedkeys[ptMain]) if (!pwsaltedkeys[ptMain])
{ {
// probably zero chance event // probably zero chance event
GUI::showWarning(tr("NO Password"), tr("Encryption is enabled, but there is no password! Encryption will be disabled.")); GUI::showWarning(tr("NO Password"), tr("Local file encryption is enabled, but there is no password! It will be disabled."));
Settings::getInstance().setEncryptTox(false); Settings::getInstance().setEncryptTox(false);
tox_save(tox, data); tox_save(tox, data);
} }

View File

@ -72,7 +72,6 @@ void Group::updatePeer(int peerId, QString name)
QString toxid = id.publicKey; QString toxid = id.publicKey;
peers[peerId] = name; peers[peerId] = name;
toxids[toxid] = name; toxids[toxid] = name;
Friend *f = FriendList::findFriend(id); Friend *f = FriendList::findFriend(id);
if (f) if (f)
{ {
@ -95,17 +94,16 @@ void Group::setName(const QString& name)
void Group::regeneratePeerList() void Group::regeneratePeerList()
{ {
QList<QString> peerLst = Core::getInstance()->getGroupPeerNames(groupId); peers = Core::getInstance()->getGroupPeerNames(groupId);
peers.clear();
toxids.clear(); toxids.clear();
nPeers = peerLst.size(); nPeers = peers.size();
for (int i = 0; i < peerLst.size(); i++) for (int i = 0; i < nPeers; i++)
{ {
ToxID id = Core::getInstance()->getGroupPeerToxID(groupId, i); ToxID id = Core::getInstance()->getGroupPeerToxID(groupId, i);
if (id.isMine())
selfPeerNum = i;
QString toxid = id.publicKey; QString toxid = id.publicKey;
peers[i] = peerLst.at(i); toxids[toxid] = peers[i];
toxids[toxid] = peerLst.at(i);
Friend *f = FriendList::findFriend(id); Friend *f = FriendList::findFriend(id);
if (f) if (f)
{ {
@ -145,9 +143,12 @@ GroupWidget *Group::getGroupWidget()
QStringList Group::getPeerList() const QStringList Group::getPeerList() const
{ {
QStringList peerNames(peers.values()); return peers;
peerNames.sort(Qt::CaseInsensitive); }
return peerNames;
bool Group::isSelfPeerNumber(int num) const
{
return num == selfPeerNum;
} }
void Group::setEventFlag(int f) void Group::setEventFlag(int f)

View File

@ -19,6 +19,7 @@
#include <QMap> #include <QMap>
#include <QObject> #include <QObject>
#include <QStringList>
#define RETRY_PEER_INFO_INTERVAL 500 #define RETRY_PEER_INFO_INTERVAL 500
@ -39,6 +40,7 @@ public:
int getPeersCount() const; int getPeersCount() const;
void regeneratePeerList(); void regeneratePeerList();
QStringList getPeerList() const; QStringList getPeerList() const;
bool isSelfPeerNumber(int peernumber) const;
GroupChatForm *getChatForm(); GroupChatForm *getChatForm();
GroupWidget *getGroupWidget(); GroupWidget *getGroupWidget();
@ -62,11 +64,12 @@ public:
private: private:
GroupWidget* widget; GroupWidget* widget;
GroupChatForm* chatForm; GroupChatForm* chatForm;
QMap<int, QString> peers; QStringList peers;
QMap<QString, QString> toxids; QMap<QString, QString> toxids;
int hasNewMessages, userWasMentioned; int hasNewMessages, userWasMentioned;
int groupId; int groupId;
int nPeers; int nPeers;
int selfPeerNum = -1;
bool avGroupchat; bool avGroupchat;
}; };

View File

@ -855,6 +855,9 @@ QSplitter:handle{
<bold>true</bold> <bold>true</bold>
</font> </font>
</property> </property>
<property name="cursor">
<cursorShape>PointingHandCursor</cursorShape>
</property>
<property name="text"> <property name="text">
<string>Your name</string> <string>Your name</string>
</property> </property>
@ -1037,8 +1040,8 @@ QSplitter:handle{
<rect> <rect>
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>284</width> <width>285</width>
<height>399</height> <height>381</height>
</rect> </rect>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_5"/> <layout class="QVBoxLayout" name="verticalLayout_5"/>
@ -1779,7 +1782,7 @@ QSplitter:handle{
<x>0</x> <x>0</x>
<y>0</y> <y>0</y>
<width>775</width> <width>775</width>
<height>20</height> <height>22</height>
</rect> </rect>
</property> </property>
</widget> </widget>

View File

@ -293,7 +293,7 @@ private:
bool enableLogging; bool enableLogging;
bool encryptLogs; bool encryptLogs;
bool encryptTox; bool encryptTox = false;
int autoAwayTime; int autoAwayTime;

View File

@ -93,26 +93,27 @@ void Nexus::start()
//connect(androidgui, &AndroidGUI::friendRequestAccepted, core, &Core::acceptFriendRequest); //connect(androidgui, &AndroidGUI::friendRequestAccepted, core, &Core::acceptFriendRequest);
//connect(androidgui, &AndroidGUI::changeProfile, core, &Core::switchConfiguration); //connect(androidgui, &AndroidGUI::changeProfile, core, &Core::switchConfiguration);
#else #else
connect(core, &Core::connected, widget, &Widget::onConnected); connect(core, &Core::connected, widget, &Widget::onConnected);
connect(core, &Core::disconnected, widget, &Widget::onDisconnected); connect(core, &Core::disconnected, widget, &Widget::onDisconnected);
connect(core, &Core::failedToStart, widget, &Widget::onFailedToStartCore); connect(core, &Core::failedToStart, widget, &Widget::onFailedToStartCore);
connect(core, &Core::badProxy, widget, &Widget::onBadProxyCore); connect(core, &Core::badProxy, widget, &Widget::onBadProxyCore);
connect(core, &Core::statusSet, widget, &Widget::onStatusSet); connect(core, &Core::statusSet, widget, &Widget::onStatusSet);
connect(core, &Core::usernameSet, widget, &Widget::setUsername); connect(core, &Core::usernameSet, widget, &Widget::setUsername);
connect(core, &Core::statusMessageSet, widget, &Widget::setStatusMessage); connect(core, &Core::statusMessageSet, widget, &Widget::setStatusMessage);
connect(core, &Core::selfAvatarChanged, widget, &Widget::onSelfAvatarLoaded); connect(core, &Core::selfAvatarChanged, widget, &Widget::onSelfAvatarLoaded);
connect(core, &Core::friendAdded, widget, &Widget::addFriend); connect(core, &Core::friendAdded, widget, &Widget::addFriend);
connect(core, &Core::failedToAddFriend, widget, &Widget::addFriendFailed); connect(core, &Core::failedToAddFriend, widget, &Widget::addFriendFailed);
connect(core, &Core::friendUsernameChanged, widget, &Widget::onFriendUsernameChanged); connect(core, &Core::friendUsernameChanged, widget, &Widget::onFriendUsernameChanged);
connect(core, &Core::friendStatusChanged, widget, &Widget::onFriendStatusChanged); connect(core, &Core::friendStatusChanged, widget, &Widget::onFriendStatusChanged);
connect(core, &Core::friendStatusMessageChanged, widget, &Widget::onFriendStatusMessageChanged); connect(core, &Core::friendStatusMessageChanged, widget, &Widget::onFriendStatusMessageChanged);
connect(core, &Core::friendRequestReceived, widget, &Widget::onFriendRequestReceived); connect(core, &Core::friendRequestReceived, widget, &Widget::onFriendRequestReceived);
connect(core, &Core::friendMessageReceived, widget, &Widget::onFriendMessageReceived); connect(core, &Core::friendMessageReceived, widget, &Widget::onFriendMessageReceived);
connect(core, &Core::receiptRecieved, widget, &Widget::onReceiptRecieved); connect(core, &Core::receiptRecieved, widget, &Widget::onReceiptRecieved);
connect(core, &Core::groupInviteReceived, widget, &Widget::onGroupInviteReceived); connect(core, &Core::groupInviteReceived, widget, &Widget::onGroupInviteReceived);
connect(core, &Core::groupMessageReceived, widget, &Widget::onGroupMessageReceived); connect(core, &Core::groupMessageReceived, widget, &Widget::onGroupMessageReceived);
connect(core, &Core::groupNamelistChanged, widget, &Widget::onGroupNamelistChanged); connect(core, &Core::groupNamelistChanged, widget, &Widget::onGroupNamelistChanged);
connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged); connect(core, &Core::groupTitleChanged, widget, &Widget::onGroupTitleChanged);
connect(core, &Core::groupPeerAudioPlaying, widget, &Widget::onGroupPeerAudioPlaying);
connect(core, &Core::emptyGroupCreated, widget, &Widget::onEmptyGroupCreated); connect(core, &Core::emptyGroupCreated, widget, &Widget::onEmptyGroupCreated);
connect(core, &Core::avInvite, widget, &Widget::playRingtone); connect(core, &Core::avInvite, widget, &Widget::playRingtone);
connect(core, &Core::blockingClearContacts, widget, &Widget::clearContactsList, Qt::BlockingQueuedConnection); connect(core, &Core::blockingClearContacts, widget, &Widget::clearContactsList, Qt::BlockingQueuedConnection);

View File

@ -26,6 +26,7 @@
#include "src/misc/cdata.h" #include "src/misc/cdata.h"
#include "src/toxdns.h" #include "src/toxdns.h"
#include "src/misc/settings.h" #include "src/misc/settings.h"
#include "src/widget/gui.h"
AddFriendForm::AddFriendForm() AddFriendForm::AddFriendForm()
{ {
@ -73,15 +74,6 @@ QString AddFriendForm::getMessage() const
return !msg.isEmpty() ? msg : message.placeholderText(); return !msg.isEmpty() ? msg : message.placeholderText();
} }
void AddFriendForm::showWarning(const QString &message) const
{
QMessageBox warning(main);
warning.setWindowTitle("Tox");
warning.setText(message);
warning.setIcon(QMessageBox::Warning);
warning.exec();
}
void AddFriendForm::onUsernameSet(const QString& username) void AddFriendForm::onUsernameSet(const QString& username)
{ {
message.setPlaceholderText(tr("%1 here! Tox me maybe?","Default message in friend requests if the field is left blank. Write something appropriate!").arg(username)); message.setPlaceholderText(tr("%1 here! Tox me maybe?","Default message in friend requests if the field is left blank. Write something appropriate!").arg(username));
@ -92,10 +84,10 @@ void AddFriendForm::onSendTriggered()
QString id = toxId.text().trimmed(); QString id = toxId.text().trimmed();
if (id.isEmpty()) { if (id.isEmpty()) {
showWarning(tr("Please fill in a valid Tox ID","Tox ID of the friend you're sending a friend request to")); GUI::showWarning(tr("Couldn't add friend"), tr("Please fill in a valid Tox ID","Tox ID of the friend you're sending a friend request to"));
} else if (ToxID::isToxId(id)) { } else if (ToxID::isToxId(id)) {
if (id.toUpper() == Core::getInstance()->getSelfId().toString().toUpper()) if (id.toUpper() == Core::getInstance()->getSelfId().toString().toUpper())
showWarning(tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend")); GUI::showWarning(tr("Couldn't add friend"), tr("You can't add yourself as a friend!","When trying to add your own Tox ID as friend"));
else else
emit friendRequested(id, getMessage()); emit friendRequested(id, getMessage());
this->toxId.clear(); this->toxId.clear();
@ -113,7 +105,7 @@ Ignore the proxy and connect to the Internet directly?"), QMessageBox::Yes|QMess
if (toxId.toString().isEmpty()) if (toxId.toString().isEmpty())
{ {
showWarning(tr("This Tox ID does not exist","DNS error")); GUI::showWarning(tr("Couldn't add friend"), tr("This Tox ID does not exist","DNS error"));
return; return;
} }

View File

@ -38,9 +38,6 @@ public:
signals: signals:
void friendRequested(const QString& friendAddress, const QString& message); void friendRequested(const QString& friendAddress, const QString& message);
protected:
void showWarning(const QString& message) const;
public slots: public slots:
void onUsernameSet(const QString& userName); void onUsernameSet(const QString& userName);

View File

@ -387,7 +387,6 @@ void ChatForm::onAvEnd(int FriendId, int)
enableCallButtons(); enableCallButtons();
stopCounter(); stopCounter();
netcam->hide(); netcam->hide();
} }
@ -563,6 +562,12 @@ void ChatForm::onHangupCallTriggered()
{ {
qDebug() << "onHangupCallTriggered"; qDebug() << "onHangupCallTriggered";
//Fixes an OS X bug with ending a call while in full screen
if(netcam->isFullScreen())
{
netcam->showNormal();
}
audioInputFlag = false; audioInputFlag = false;
audioOutputFlag = false; audioOutputFlag = false;
emit hangupCall(callId); emit hangupCall(callId);

View File

@ -29,6 +29,7 @@
#include "src/historykeeper.h" #include "src/historykeeper.h"
#include "src/misc/flowlayout.h" #include "src/misc/flowlayout.h"
#include <QDebug> #include <QDebug>
#include <QTimer>
GroupChatForm::GroupChatForm(Group* chatGroup) GroupChatForm::GroupChatForm(Group* chatGroup)
: group(chatGroup), inCall{false} : group(chatGroup), inCall{false}
@ -98,15 +99,21 @@ void GroupChatForm::onSendTriggered()
if (msg.isEmpty()) if (msg.isEmpty())
return; return;
msgEdit->setLastMessage(msg);
msgEdit->clear(); msgEdit->clear();
if (msg.startsWith("/me ")) if (group->getPeersCount() != 1)
{ {
msg = msg.right(msg.length() - 4); if (msg.startsWith("/me "))
emit sendAction(group->getGroupId(), msg); {
} else { msg = msg.right(msg.length() - 4);
emit sendMessage(group->getGroupId(), msg); emit sendAction(group->getGroupId(), msg);
}
else
emit sendMessage(group->getGroupId(), msg);
} }
else
addSelfMessage(msg, msg.startsWith("/me "), QDateTime::currentDateTime(), true);
} }
void GroupChatForm::onUserListChanged() void GroupChatForm::onUserListChanged()
@ -120,19 +127,45 @@ void GroupChatForm::onUserListChanged()
delete child->widget(); delete child->widget();
delete child; delete child;
} }
peerLabels.clear();
QStringList names(group->getPeerList()); // the list needs peers in peernumber order, nameLayout needs alphabetical
QMap<QString, QLabel*> orderizer;
// first traverse in peer number order, storing the QLabels as necessary
QStringList names = group->getPeerList();
unsigned nNames = names.size(); unsigned nNames = names.size();
for (unsigned i=0; i<nNames; ++i) for (unsigned i=0; i<nNames; ++i)
{ {
QString nameStr = names[i]; peerLabels.append(new QLabel(names[i]));
if (i!=nNames-1) peerLabels[i]->setTextFormat(Qt::PlainText);
nameStr+=", "; orderizer[names[i]] = peerLabels[i];
QLabel* nameLabel = new QLabel(nameStr); if (group->isSelfPeerNumber(i))
nameLabel->setObjectName("peersLabel"); peerLabels[i]->setStyleSheet("QLabel {color : green;}");
nameLabel->setTextFormat(Qt::PlainText);
namesListLayout->addWidget(nameLabel);
} }
// now alphabetize and add to layout
names.sort(Qt::CaseInsensitive);
for (unsigned i=0; i<nNames; ++i)
{
QLabel* label = orderizer[names[i]];
if (i != nNames - 1)
label->setText(label->text() + ", ");
namesListLayout->addWidget(label);
}
}
void GroupChatForm::peerAudioPlaying(int peer)
{
peerLabels[peer]->setStyleSheet("QLabel {color : red;}");
if (!peerAudioTimers[peer])
{
peerAudioTimers[peer] = new QTimer(this);
peerAudioTimers[peer]->setSingleShot(true);
connect(peerAudioTimers[peer], &QTimer::timeout, [=]{this->peerLabels[peer]->setStyleSheet("");
delete this->peerAudioTimers[peer];
this->peerAudioTimers[peer] = nullptr;});
}
peerAudioTimers[peer]->start(500);
} }
void GroupChatForm::dragEnterEvent(QDragEnterEvent *ev) void GroupChatForm::dragEnterEvent(QDragEnterEvent *ev)

View File

@ -18,11 +18,13 @@
#define GROUPCHATFORM_H #define GROUPCHATFORM_H
#include "genericchatform.h" #include "genericchatform.h"
#include <QMap>
namespace Ui {class MainWindow;} namespace Ui {class MainWindow;}
class Group; class Group;
class TabCompleter; class TabCompleter;
class FlowLayout; class FlowLayout;
class QTimer;
class GroupChatForm : public GenericChatForm class GroupChatForm : public GenericChatForm
{ {
@ -31,6 +33,7 @@ public:
GroupChatForm(Group* chatGroup); GroupChatForm(Group* chatGroup);
void onUserListChanged(); void onUserListChanged();
void peerAudioPlaying(int peer);
void keyPressEvent(QKeyEvent* ev); void keyPressEvent(QKeyEvent* ev);
void keyReleaseEvent(QKeyEvent* ev); void keyReleaseEvent(QKeyEvent* ev);
@ -51,6 +54,8 @@ protected:
private: private:
Group* group; Group* group;
QList<QLabel*> peerLabels; // maps peernumbers to the QLabels in namesListLayout
QMap<int, QTimer*> peerAudioTimers; // timeout = peer stopped sending audio
FlowLayout* namesListLayout; FlowLayout* namesListLayout;
QLabel *nusersLabel; QLabel *nusersLabel;
TabCompleter* tabber; TabCompleter* tabber;

View File

@ -15,31 +15,64 @@
*/ */
#include "src/core.h" #include "src/core.h"
#include "ui_identitysettings.h" #include "src/nexus.h"
#include "identityform.h" #include "ui_profileform.h"
#include "profileform.h"
#include "ui_mainwindow.h"
#include "src/widget/form/settingswidget.h" #include "src/widget/form/settingswidget.h"
#include "src/widget/maskablepixmapwidget.h"
#include "src/misc/settings.h" #include "src/misc/settings.h"
#include "src/widget/croppinglabel.h" #include "src/widget/croppinglabel.h"
#include "src/widget/widget.h" #include "src/widget/widget.h"
#include "src/widget/gui.h" #include "src/widget/gui.h"
#include "src/historykeeper.h" #include "src/historykeeper.h"
#include "src/misc/style.h" #include "src/misc/style.h"
#include "src/misc/qrwidget.h"
#include "qrencode.h"
#include <QLabel> #include <QLabel>
#include <QLineEdit> #include <QLineEdit>
#include <QGroupBox>
#include <QApplication> #include <QApplication>
#include <QClipboard> #include <QClipboard>
#include <QInputDialog> #include <QInputDialog>
#include <QFileDialog> #include <QFileDialog>
#include "src/misc/qrwidget.h" #include <QBuffer>
#include "qrencode.h"
IdentityForm::IdentityForm() :
GenericForm(tr("Identity"), QPixmap(":/img/settings/identity.png")) void ProfileForm::refreshProfiles()
{
bodyUI->profiles->clear();
for (QString profile : Settings::getInstance().searchProfiles())
bodyUI->profiles->addItem(profile);
QString current = Settings::getInstance().getCurrentProfile();
if (current != "")
bodyUI->profiles->setCurrentText(current);
}
ProfileForm::ProfileForm(QWidget *parent) :
QWidget(parent)
{ {
bodyUI = new Ui::IdentitySettings; bodyUI = new Ui::IdentitySettings;
bodyUI->setupUi(this); bodyUI->setupUi(this);
core = Core::getInstance(); core = Core::getInstance();
head = new QWidget(this);
QHBoxLayout* headLayout = new QHBoxLayout();
head->setLayout(headLayout);
QLabel* imgLabel = new QLabel();
headLayout->addWidget(imgLabel);
QLabel* nameLabel = new QLabel();
QFont bold;
bold.setBold(true);
nameLabel->setFont(bold);
headLayout->addWidget(nameLabel);
headLayout->addStretch(1);
nameLabel->setText(tr("User Profile"));
imgLabel->setPixmap(QPixmap(":/img/settings/identity.png").scaledToHeight(40, Qt::SmoothTransformation));
// tox // tox
toxId = new ClickableTE(); toxId = new ClickableTE();
toxId->setReadOnly(true); toxId->setReadOnly(true);
@ -48,42 +81,62 @@ IdentityForm::IdentityForm() :
bodyUI->toxGroup->layout()->addWidget(toxId); bodyUI->toxGroup->layout()->addWidget(toxId);
profilePicture = new MaskablePixmapWidget(this, QSize(64, 64), ":/img/avatar_mask.png");
profilePicture->setPixmap(QPixmap(":/img/contact_dark.png"));
profilePicture->setClickable(true);
connect(profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked()));
QHBoxLayout *publicGrouplayout = qobject_cast<QHBoxLayout*>(bodyUI->publicGroup->layout());
publicGrouplayout->insertWidget(0, profilePicture);
publicGrouplayout->insertSpacing(1, 7);
timer.setInterval(750); timer.setInterval(750);
timer.setSingleShot(true); timer.setSingleShot(true);
connect(&timer, &QTimer::timeout, this, [=]() {bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace("", "")); hasCheck = false;}); connect(&timer, &QTimer::timeout, this, [=]() {bodyUI->toxIdLabel->setText(bodyUI->toxIdLabel->text().replace("", "")); hasCheck = false;});
connect(bodyUI->toxIdLabel, SIGNAL(clicked()), this, SLOT(copyIdClicked())); connect(bodyUI->toxIdLabel, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked())); connect(toxId, SIGNAL(clicked()), this, SLOT(copyIdClicked()));
connect(core, &Core::idSet, this, &IdentityForm::setToxId); connect(core, &Core::idSet, this, &ProfileForm::setToxId);
connect(core, &Core::statusSet, this, &ProfileForm::onStatusSet);
connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited())); connect(bodyUI->userName, SIGNAL(editingFinished()), this, SLOT(onUserNameEdited()));
connect(bodyUI->statusMessage, SIGNAL(editingFinished()), this, SLOT(onStatusMessageEdited())); connect(bodyUI->statusMessage, SIGNAL(editingFinished()), this, SLOT(onStatusMessageEdited()));
connect(bodyUI->loadButton, &QPushButton::clicked, this, &IdentityForm::onLoadClicked); connect(bodyUI->loadButton, &QPushButton::clicked, this, &ProfileForm::onLoadClicked);
connect(bodyUI->renameButton, &QPushButton::clicked, this, &IdentityForm::onRenameClicked); connect(bodyUI->renameButton, &QPushButton::clicked, this, &ProfileForm::onRenameClicked);
connect(bodyUI->exportButton, &QPushButton::clicked, this, &IdentityForm::onExportClicked); connect(bodyUI->exportButton, &QPushButton::clicked, this, &ProfileForm::onExportClicked);
connect(bodyUI->deleteButton, &QPushButton::clicked, this, &IdentityForm::onDeleteClicked); connect(bodyUI->deleteButton, &QPushButton::clicked, this, &ProfileForm::onDeleteClicked);
connect(bodyUI->importButton, &QPushButton::clicked, this, &IdentityForm::onImportClicked); connect(bodyUI->importButton, &QPushButton::clicked, this, &ProfileForm::onImportClicked);
connect(bodyUI->newButton, &QPushButton::clicked, this, &IdentityForm::onNewClicked); connect(bodyUI->newButton, &QPushButton::clicked, this, &ProfileForm::onNewClicked);
connect(core, &Core::avStart, this, &IdentityForm::disableSwitching); connect(core, &Core::avStart, this, &ProfileForm::disableSwitching);
connect(core, &Core::avStarting, this, &IdentityForm::disableSwitching); connect(core, &Core::avStarting, this, &ProfileForm::disableSwitching);
connect(core, &Core::avInvite, this, &IdentityForm::disableSwitching); connect(core, &Core::avInvite, this, &ProfileForm::disableSwitching);
connect(core, &Core::avRinging, this, &IdentityForm::disableSwitching); connect(core, &Core::avRinging, this, &ProfileForm::disableSwitching);
connect(core, &Core::avCancel, this, &IdentityForm::enableSwitching); connect(core, &Core::avCancel, this, &ProfileForm::enableSwitching);
connect(core, &Core::avEnd, this, &IdentityForm::enableSwitching); connect(core, &Core::avEnd, this, &ProfileForm::enableSwitching);
connect(core, &Core::avEnding, this, &IdentityForm::enableSwitching); connect(core, &Core::avEnding, this, &ProfileForm::enableSwitching);
connect(core, &Core::avPeerTimeout, this, &IdentityForm::enableSwitching); connect(core, &Core::avPeerTimeout, this, &ProfileForm::enableSwitching);
connect(core, &Core::avRequestTimeout, this, &IdentityForm::enableSwitching); connect(core, &Core::avRequestTimeout, this, &ProfileForm::enableSwitching);
connect(core, &Core::usernameSet, this, [=](const QString& val) { bodyUI->userName->setText(val); }); connect(core, &Core::usernameSet, this, [=](const QString& val) { bodyUI->userName->setText(val); });
connect(core, &Core::statusMessageSet, this, [=](const QString& val) { bodyUI->statusMessage->setText(val); }); connect(core, &Core::statusMessageSet, this, [=](const QString& val) { bodyUI->statusMessage->setText(val); });
} }
IdentityForm::~IdentityForm() ProfileForm::~ProfileForm()
{ {
delete bodyUI; delete bodyUI;
head->deleteLater();
} }
void IdentityForm::copyIdClicked() void ProfileForm::show(Ui::MainWindow &ui)
{
ui.mainHead->layout()->addWidget(head);
ui.mainContent->layout()->addWidget(this);
head->show();
QWidget::show();
bodyUI->userName->setFocus(Qt::OtherFocusReason);
bodyUI->userName->selectAll();
}
void ProfileForm::copyIdClicked()
{ {
toxId->selectAll(); toxId->selectAll();
QString txt = toxId->text(); QString txt = toxId->text();
@ -99,32 +152,22 @@ void IdentityForm::copyIdClicked()
timer.start(); timer.start();
} }
void IdentityForm::onUserNameEdited() void ProfileForm::onUserNameEdited()
{ {
Core::getInstance()->setUsername(bodyUI->userName->text()); Core::getInstance()->setUsername(bodyUI->userName->text());
} }
void IdentityForm::onStatusMessageEdited() void ProfileForm::onStatusMessageEdited()
{ {
Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text()); Core::getInstance()->setStatusMessage(bodyUI->statusMessage->text());
} }
void IdentityForm::present() void ProfileForm::onSelfAvatarLoaded(const QPixmap& pic)
{ {
toxId->setText(Core::getInstance()->getSelfId().toString()); profilePicture->setPixmap(pic);
toxId->setCursorPosition(0);
bodyUI->profiles->clear();
for (QString profile : Settings::getInstance().searchProfiles())
bodyUI->profiles->addItem(profile);
QString current = Settings::getInstance().getCurrentProfile();
if (current != "")
bodyUI->profiles->setCurrentText(current);
bodyUI->userName->setText(Core::getInstance()->getUsername());
bodyUI->statusMessage->setText(Core::getInstance()->getStatusMessage());
} }
void IdentityForm::setToxId(const QString& id) void ProfileForm::setToxId(const QString& id)
{ {
toxId->setText(id); toxId->setText(id);
toxId->setCursorPosition(0); toxId->setCursorPosition(0);
@ -135,7 +178,54 @@ void IdentityForm::setToxId(const QString& id)
toxId->setToolTip(qrcode->getImageAsText()); toxId->setToolTip(qrcode->getImageAsText());
} }
void IdentityForm::onLoadClicked() void ProfileForm::onAvatarClicked()
{
QString filename = QFileDialog::getOpenFileName(this,
tr("Choose a profile picture"),
QDir::homePath(),
Nexus::getSupportedImageFilter());
if (filename.isEmpty())
return;
QFile file(filename);
file.open(QIODevice::ReadOnly);
if (!file.isOpen())
{
QMessageBox::critical(this, tr("Error"), tr("Unable to open this file"));
return;
}
QPixmap pic;
if (!pic.loadFromData(file.readAll()))
{
QMessageBox::critical(this, tr("Error"), tr("Unable to read this image"));
return;
}
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH)
{
pic = pic.scaled(64,64, Qt::KeepAspectRatio, Qt::SmoothTransformation);
bytes.clear();
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
}
if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH)
{
QMessageBox::critical(this, tr("Error"), tr("This image is too big"));
return;
}
Nexus::getCore()->setAvatar(TOX_AVATAR_FORMAT_PNG, bytes);
}
void ProfileForm::onLoadClicked()
{ {
if (bodyUI->profiles->currentText() != Settings::getInstance().getCurrentProfile()) if (bodyUI->profiles->currentText() != Settings::getInstance().getCurrentProfile())
{ {
@ -148,7 +238,7 @@ void IdentityForm::onLoadClicked()
} }
} }
void IdentityForm::onRenameClicked() void ProfileForm::onRenameClicked()
{ {
QString cur = bodyUI->profiles->currentText(); QString cur = bodyUI->profiles->currentText();
QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur); QString title = tr("Rename \"%1\"", "renaming a profile").arg(cur);
@ -176,7 +266,7 @@ void IdentityForm::onRenameClicked()
} while (true); } while (true);
} }
void IdentityForm::onExportClicked() void ProfileForm::onExportClicked()
{ {
QString current = bodyUI->profiles->currentText() + Core::TOX_EXT; QString current = bodyUI->profiles->currentText() + Core::TOX_EXT;
QString path = QFileDialog::getSaveFileName(this, tr("Export profile", "save dialog title"), QString path = QFileDialog::getSaveFileName(this, tr("Export profile", "save dialog title"),
@ -201,7 +291,7 @@ void IdentityForm::onExportClicked()
} }
} }
void IdentityForm::onDeleteClicked() void ProfileForm::onDeleteClicked()
{ {
if (Settings::getInstance().getCurrentProfile() == bodyUI->profiles->currentText()) if (Settings::getInstance().getCurrentProfile() == bodyUI->profiles->currentText())
{ {
@ -226,7 +316,7 @@ void IdentityForm::onDeleteClicked()
} }
} }
void IdentityForm::onImportClicked() void ProfileForm::onImportClicked()
{ {
QString path = QFileDialog::getOpenFileName(this, QString path = QFileDialog::getOpenFileName(this,
tr("Import profile", "import dialog title"), tr("Import profile", "import dialog title"),
@ -256,18 +346,23 @@ void IdentityForm::onImportClicked()
bodyUI->profiles->addItem(profile); bodyUI->profiles->addItem(profile);
} }
void IdentityForm::onNewClicked() void ProfileForm::onStatusSet(Status)
{
refreshProfiles();
}
void ProfileForm::onNewClicked()
{ {
emit Widget::getInstance()->changeProfile(QString()); emit Widget::getInstance()->changeProfile(QString());
} }
void IdentityForm::disableSwitching() void ProfileForm::disableSwitching()
{ {
bodyUI->loadButton->setEnabled(false); bodyUI->loadButton->setEnabled(false);
bodyUI->newButton->setEnabled(false); bodyUI->newButton->setEnabled(false);
} }
void IdentityForm::enableSwitching() void ProfileForm::enableSwitching()
{ {
if (!core->anyActiveCalls()) if (!core->anyActiveCalls())
{ {
@ -275,3 +370,9 @@ void IdentityForm::enableSwitching()
bodyUI->newButton->setEnabled(true); bodyUI->newButton->setEnabled(true);
} }
} }
void ProfileForm::showEvent(QShowEvent *event)
{
refreshProfiles();
QWidget::showEvent(event);
}

View File

@ -17,18 +17,19 @@
#ifndef IDENTITYFORM_H #ifndef IDENTITYFORM_H
#define IDENTITYFORM_H #define IDENTITYFORM_H
#include "genericsettings.h"
#include <QGroupBox>
#include <QTextEdit>
#include <QLineEdit> #include <QLineEdit>
#include <QLabel> #include <QLabel>
#include <QTimer> #include <QTimer>
#include <QVBoxLayout>
#include "src/core.h"
class CroppingLabel; class CroppingLabel;
class Core; class Core;
class MaskablePixmapWidget;
namespace Ui { namespace Ui {
class IdentitySettings; class IdentitySettings;
class MainWindow;
} }
class ClickableTE : public QLineEdit class ClickableTE : public QLineEdit
@ -42,22 +43,26 @@ protected:
void mouseReleaseEvent(QMouseEvent*) {emit clicked();} void mouseReleaseEvent(QMouseEvent*) {emit clicked();}
}; };
class IdentityForm : public GenericForm class ProfileForm : public QWidget
{ {
Q_OBJECT Q_OBJECT
public: public:
IdentityForm(); ProfileForm(QWidget *parent = nullptr);
~IdentityForm(); ~ProfileForm();
void show(Ui::MainWindow &ui);
virtual void present();
signals: signals:
void userNameChanged(QString); void userNameChanged(QString);
void statusMessageChanged(QString); void statusMessageChanged(QString);
public slots:
void onSelfAvatarLoaded(const QPixmap &pic);
void onStatusSet(Status status);
private slots: private slots:
void setToxId(const QString& id); void setToxId(const QString& id);
void copyIdClicked(); void copyIdClicked();
void onAvatarClicked();
void onUserNameEdited(); void onUserNameEdited();
void onStatusMessageEdited(); void onStatusMessageEdited();
void onLoadClicked(); void onLoadClicked();
@ -69,8 +74,14 @@ private slots:
void disableSwitching(); void disableSwitching();
void enableSwitching(); void enableSwitching();
protected:
virtual void showEvent(QShowEvent *);
private: private:
void refreshProfiles();
Ui::IdentitySettings* bodyUI; Ui::IdentitySettings* bodyUI;
MaskablePixmapWidget* profilePicture;
QWidget *head;
Core* core; Core* core;
QTimer timer; QTimer timer;
bool hasCheck = false; bool hasCheck = false;

View File

@ -47,44 +47,48 @@
<property name="spacing"> <property name="spacing">
<number>9</number> <number>9</number>
</property> </property>
<item alignment="Qt::AlignTop"> <item>
<widget class="QGroupBox" name="publicGroup"> <widget class="QGroupBox" name="publicGroup">
<property name="title"> <property name="title">
<string>Public Information</string> <string>Public Information</string>
</property> </property>
<layout class="QVBoxLayout" name="verticalLayout_2"> <layout class="QHBoxLayout" name="horizontalLayout_2">
<item> <item>
<widget class="QLabel" name="userNameLabel"> <layout class="QVBoxLayout" name="publicFieldsLayout">
<property name="text"> <item>
<string>Name</string> <widget class="QLabel" name="userNameLabel">
</property> <property name="text">
</widget> <string>Name</string>
</item> </property>
<item> </widget>
<widget class="QLineEdit" name="userName"/> </item>
</item> <item>
<item> <widget class="QLineEdit" name="userName"/>
<widget class="QLabel" name="statusMessageLabel"> </item>
<property name="text"> <item>
<string>Status</string> <widget class="QLabel" name="statusMessageLabel">
</property> <property name="text">
</widget> <string>Status</string>
</item> </property>
<item> </widget>
<widget class="QLineEdit" name="statusMessage"/> </item>
<item>
<widget class="QLineEdit" name="statusMessage"/>
</item>
</layout>
</item> </item>
</layout> </layout>
</widget> </widget>
</item> </item>
<item alignment="Qt::AlignTop"> <item alignment="Qt::AlignTop">
<widget class="QGroupBox" name="toxGroup"> <widget class="QGroupBox" name="toxGroup">
<property name="title">
<string>Tox ID</string>
</property>
<property name="toolTip"> <property name="toolTip">
<string comment="Tox ID tooltip">This bunch of characters tells other Tox clients how to contact you. <string comment="Tox ID tooltip">This bunch of characters tells other Tox clients how to contact you.
Share it with your friends to communicate.</string> Share it with your friends to communicate.</string>
</property> </property>
<property name="title">
<string>Tox ID</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout_3"> <layout class="QVBoxLayout" name="verticalLayout_3">
<item> <item>
<widget class="CroppingLabel" name="toxIdLabel"> <widget class="CroppingLabel" name="toxIdLabel">
@ -113,15 +117,15 @@ Share it with your friends to communicate.</string>
</item> </item>
<item> <item>
<widget class="QComboBox" name="profiles"> <widget class="QComboBox" name="profiles">
<property name="toolTip">
<string comment="toolTip for currently set profile">Currently selected profile.</string>
</property>
<property name="sizePolicy"> <property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed"> <sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch> <horstretch>0</horstretch>
<verstretch>0</verstretch> <verstretch>0</verstretch>
</sizepolicy> </sizepolicy>
</property> </property>
<property name="toolTip">
<string comment="toolTip for currently set profile">Currently selected profile.</string>
</property>
</widget> </widget>
</item> </item>
</layout> </layout>
@ -140,23 +144,23 @@ Share it with your friends to communicate.</string>
</item> </item>
<item> <item>
<widget class="QPushButton" name="renameButton"> <widget class="QPushButton" name="renameButton">
<property name="text">
<string comment="rename profile button">Rename</string>
</property>
<property name="toolTip"> <property name="toolTip">
<string comment="tooltip for renaming profile button">Rename selected profile.</string> <string comment="tooltip for renaming profile button">Rename selected profile.</string>
</property> </property>
<property name="text">
<string comment="rename profile button">Rename</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QPushButton" name="exportButton"> <widget class="QPushButton" name="exportButton">
<property name="text">
<string comment="export profile button">Export</string>
</property>
<property name="toolTip"> <property name="toolTip">
<string comment="tooltip for profile exporting button">Allows you to export your Tox profile to a file. <string comment="tooltip for profile exporting button">Allows you to export your Tox profile to a file.
Profile does not contain your history.</string> Profile does not contain your history.</string>
</property> </property>
<property name="text">
<string comment="export profile button">Export</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>
@ -175,12 +179,12 @@ Profile does not contain your history.</string>
<layout class="QHBoxLayout" name="profilesButtonsLayout2"> <layout class="QHBoxLayout" name="profilesButtonsLayout2">
<item> <item>
<widget class="QPushButton" name="importButton"> <widget class="QPushButton" name="importButton">
<property name="text">
<string comment="import profile button">Import a profile</string>
</property>
<property name="toolTip"> <property name="toolTip">
<string comment="tooltip for importing profile button">Import Tox profile from a .tox file.</string> <string comment="tooltip for importing profile button">Import Tox profile from a .tox file.</string>
</property> </property>
<property name="text">
<string comment="import profile button">Import a profile</string>
</property>
</widget> </widget>
</item> </item>
<item> <item>

View File

@ -199,7 +199,7 @@ void GeneralForm::onSetCloseToTray()
void GeneralForm::onSetLightTrayIcon() void GeneralForm::onSetLightTrayIcon()
{ {
Settings::getInstance().setLightTrayIcon(bodyUI->lightTrayIcon->isChecked()); Settings::getInstance().setLightTrayIcon(bodyUI->lightTrayIcon->isChecked());
Widget::getInstance()->updateTrayIcon(); Widget::getInstance()->updateIcons();
} }
void GeneralForm::onSetMinimizeToTray() void GeneralForm::onSetMinimizeToTray()

View File

@ -19,7 +19,6 @@
#include "ui_mainwindow.h" #include "ui_mainwindow.h"
#include "src/video/camera.h" #include "src/video/camera.h"
#include "src/widget/form/settings/generalform.h" #include "src/widget/form/settings/generalform.h"
#include "src/widget/form/settings/identityform.h"
#include "src/widget/form/settings/privacyform.h" #include "src/widget/form/settings/privacyform.h"
#include "src/widget/form/settings/avform.h" #include "src/widget/form/settings/avform.h"
#include "src/widget/form/settings/advancedform.h" #include "src/widget/form/settings/advancedform.h"
@ -52,12 +51,11 @@ SettingsWidget::SettingsWidget(QWidget* parent)
bodyLayout->addWidget(settingsWidgets); bodyLayout->addWidget(settingsWidgets);
GeneralForm* gfrm = new GeneralForm(this); GeneralForm* gfrm = new GeneralForm(this);
IdentityForm* ifrm = new IdentityForm;
PrivacyForm* pfrm = new PrivacyForm; PrivacyForm* pfrm = new PrivacyForm;
AVForm* avfrm = new AVForm; AVForm* avfrm = new AVForm;
AdvancedForm *expfrm = new AdvancedForm; AdvancedForm *expfrm = new AdvancedForm;
GenericForm* cfgForms[] = { gfrm, ifrm, pfrm, avfrm, expfrm }; GenericForm* cfgForms[] = { gfrm, pfrm, avfrm, expfrm };
for (GenericForm* cfgForm : cfgForms) for (GenericForm* cfgForm : cfgForms)
settingsWidgets->addTab(cfgForm, cfgForm->getFormIcon(), cfgForm->getFormName()); settingsWidgets->addTab(cfgForm, cfgForm->getFormIcon(), cfgForm->getFormName());

View File

@ -24,7 +24,6 @@
class Camera; class Camera;
class GenericForm; class GenericForm;
class GeneralForm; class GeneralForm;
class IdentityForm;
class PrivacyForm; class PrivacyForm;
class AVForm; class AVForm;
class QLabel; class QLabel;

View File

@ -51,7 +51,7 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent * event)
{ {
QPoint pos = event->globalPos(); QPoint pos = event->globalPos();
QMenu menu; QMenu menu;
QAction* setAlias = menu.addAction(tr("Set title...")); QAction* setTitle = menu.addAction(tr("Set title..."));
QAction* quitGroup = menu.addAction(tr("Quit group","Menu to quit a groupchat")); QAction* quitGroup = menu.addAction(tr("Quit group","Menu to quit a groupchat"));
QAction* selectedItem = menu.exec(pos); QAction* selectedItem = menu.exec(pos);
@ -59,7 +59,7 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent * event)
{ {
if (selectedItem == quitGroup) if (selectedItem == quitGroup)
emit removeGroup(groupId); emit removeGroup(groupId);
else if (selectedItem == setAlias) else if (selectedItem == setTitle)
{ {
bool ok; bool ok;
Group* g = GroupList::findGroup(groupId); Group* g = GroupList::findGroup(groupId);
@ -69,6 +69,13 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent * event)
if (ok && alias != nameLabel->fullText()) if (ok && alias != nameLabel->fullText())
emit g->getChatForm()->groupTitleChanged(groupId, alias.left(128)); emit g->getChatForm()->groupTitleChanged(groupId, alias.left(128));
/* according to agilob:
* Moving mouse pointer over groupwidget results in CSS effect
* mouse-over(?). Changing group title repaints only changed
* element - title, the rest of the widget stays in the same CSS as it
* was on mouse over. Repainting whole widget fixes style problem.
*/
this->repaint();
} }
} }
} }

View File

@ -331,7 +331,7 @@ void SystemTrayIcon::setVisible(bool newState)
} }
} }
void SystemTrayIcon::setIcon(QIcon &&icon) void SystemTrayIcon::setIcon(QIcon &icon)
{ {
if (false); if (false);
#ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND #ifdef ENABLE_SYSTRAY_STATUSNOTIFIER_BACKEND

View File

@ -17,7 +17,7 @@ public:
void show(); void show();
void hide(); void hide();
void setVisible(bool); void setVisible(bool);
void setIcon(QIcon&& icon); void setIcon(QIcon &icon);
signals: signals:
void activated(QSystemTrayIcon::ActivationReason); void activated(QSystemTrayIcon::ActivationReason);

View File

@ -49,8 +49,6 @@
#include <QMouseEvent> #include <QMouseEvent>
#include <QClipboard> #include <QClipboard>
#include <QThread> #include <QThread>
#include <QFileDialog>
#include <QInputDialog>
#include <QDialogButtonBox> #include <QDialogButtonBox>
#include <QTimer> #include <QTimer>
#include <QStyleFactory> #include <QStyleFactory>
@ -149,7 +147,6 @@ void Widget::init()
ui->friendList->setWidget(contactListWidget); ui->friendList->setWidget(contactListWidget);
ui->friendList->setLayoutDirection(Qt::RightToLeft); ui->friendList->setLayoutDirection(Qt::RightToLeft);
ui->nameLabel->setEditable(true);
ui->statusLabel->setEditable(true); ui->statusLabel->setEditable(true);
ui->statusPanel->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css")); ui->statusPanel->setStyleSheet(Style::getStylesheet(":/ui/window/statusPanel.css"));
@ -172,23 +169,26 @@ void Widget::init()
Style::setThemeColor(Settings::getInstance().getThemeColor()); Style::setThemeColor(Settings::getInstance().getThemeColor());
reloadTheme(); reloadTheme();
updateIcons();
filesForm = new FilesForm(); filesForm = new FilesForm();
addFriendForm = new AddFriendForm; addFriendForm = new AddFriendForm;
profileForm = new ProfileForm();
settingsWidget = new SettingsWidget(); settingsWidget = new SettingsWidget();
Core* core = Nexus::getCore(); Core* core = Nexus::getCore();
connect(core, SIGNAL(fileDownloadFinished(const QString&)), filesForm, SLOT(onFileDownloadComplete(const QString&))); connect(core, SIGNAL(fileDownloadFinished(const QString&)), filesForm, SLOT(onFileDownloadComplete(const QString&)));
connect(core, SIGNAL(fileUploadFinished(const QString&)), filesForm, SLOT(onFileUploadComplete(const QString&))); connect(core, SIGNAL(fileUploadFinished(const QString&)), filesForm, SLOT(onFileUploadComplete(const QString&)));
connect(settingsWidget, &SettingsWidget::setShowSystemTray, this, &Widget::onSetShowSystemTray); connect(settingsWidget, &SettingsWidget::setShowSystemTray, this, &Widget::onSetShowSystemTray);
connect(core, SIGNAL(selfAvatarChanged(QPixmap)), profileForm, SLOT(onSelfAvatarLoaded(QPixmap)));
connect(ui->addButton, SIGNAL(clicked()), this, SLOT(onAddClicked())); connect(ui->addButton, SIGNAL(clicked()), this, SLOT(onAddClicked()));
connect(ui->groupButton, SIGNAL(clicked()), this, SLOT(onGroupClicked())); connect(ui->groupButton, SIGNAL(clicked()), this, SLOT(onGroupClicked()));
connect(ui->transferButton, SIGNAL(clicked()), this, SLOT(onTransferClicked())); connect(ui->transferButton, SIGNAL(clicked()), this, SLOT(onTransferClicked()));
connect(ui->settingsButton, SIGNAL(clicked()), this, SLOT(onSettingsClicked())); connect(ui->settingsButton, SIGNAL(clicked()), this, SLOT(onSettingsClicked()));
connect(ui->nameLabel, SIGNAL(textChanged(QString, QString)), this, SLOT(onUsernameChanged(QString, QString))); connect(profilePicture, &MaskablePixmapWidget::clicked, this, &Widget::showProfile);
connect(ui->nameLabel, &CroppingLabel::clicked, this, &Widget::showProfile);
connect(ui->statusLabel, SIGNAL(textChanged(QString, QString)), this, SLOT(onStatusMessageChanged(QString, QString))); connect(ui->statusLabel, SIGNAL(textChanged(QString, QString)), this, SLOT(onStatusMessageChanged(QString, QString)));
connect(ui->mainSplitter, &QSplitter::splitterMoved, this, &Widget::onSplitterMoved); connect(ui->mainSplitter, &QSplitter::splitterMoved, this, &Widget::onSplitterMoved);
connect(profilePicture, SIGNAL(clicked()), this, SLOT(onAvatarClicked()));
connect(addFriendForm, SIGNAL(friendRequested(QString, QString)), this, SIGNAL(friendRequested(QString, QString))); connect(addFriendForm, SIGNAL(friendRequested(QString, QString)), this, SIGNAL(friendRequested(QString, QString)));
connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck); connect(timer, &QTimer::timeout, this, &Widget::onUserAwayCheck);
connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick); connect(timer, &QTimer::timeout, this, &Widget::onEventIconTick);
@ -223,7 +223,7 @@ void Widget::setTranslation()
QCoreApplication::installTranslator(translator); QCoreApplication::installTranslator(translator);
} }
void Widget::updateTrayIcon() void Widget::updateIcons()
{ {
QString status; QString status;
if (eventIcon) if (eventIcon)
@ -234,10 +234,17 @@ void Widget::updateTrayIcon()
if (!status.length()) if (!status.length())
status = "offline"; status = "offline";
} }
QString color = Settings::getInstance().getLightTrayIcon() ? "light" : "dark";
QString pic = ":img/taskbar/" + color + "/taskbar_" + status + ".svg"; QIcon ico = QIcon::fromTheme("qtox-" + status);
if (ico.isNull())
{
QString color = Settings::getInstance().getLightTrayIcon() ? "light" : "dark";
ico = QIcon(":img/taskbar/" + color + "/taskbar_" + status + ".svg");
}
setWindowIcon(ico);
if (icon) if (icon)
icon->setIcon(QIcon(pic)); icon->setIcon(ico);
} }
Widget::~Widget() Widget::~Widget()
@ -247,6 +254,7 @@ Widget::~Widget()
if (icon) if (icon)
icon->hide(); icon->hide();
hideMainForms(); hideMainForms();
delete profileForm;
delete settingsWidget; delete settingsWidget;
delete addFriendForm; delete addFriendForm;
delete filesForm; delete filesForm;
@ -310,53 +318,6 @@ QString Widget::getUsername()
return Nexus::getCore()->getUsername(); return Nexus::getCore()->getUsername();
} }
void Widget::onAvatarClicked()
{
QString filename = QFileDialog::getOpenFileName(this,
tr("Choose a profile picture"),
QDir::homePath(),
Nexus::getSupportedImageFilter());
if (filename.isEmpty())
return;
QFile file(filename);
file.open(QIODevice::ReadOnly);
if (!file.isOpen())
{
QMessageBox::critical(this, tr("Error"), tr("Unable to open this file"));
return;
}
QPixmap pic;
if (!pic.loadFromData(file.readAll()))
{
QMessageBox::critical(this, tr("Error"), tr("Unable to read this image"));
return;
}
QByteArray bytes;
QBuffer buffer(&bytes);
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH)
{
pic = pic.scaled(64,64, Qt::KeepAspectRatio, Qt::SmoothTransformation);
bytes.clear();
buffer.open(QIODevice::WriteOnly);
pic.save(&buffer, "PNG");
buffer.close();
}
if (bytes.size() >= TOX_AVATAR_MAX_DATA_LENGTH)
{
QMessageBox::critical(this, tr("Error"), tr("This image is too big"));
return;
}
Nexus::getCore()->setAvatar(TOX_AVATAR_FORMAT_PNG, bytes);
}
void Widget::onSelfAvatarLoaded(const QPixmap& pic) void Widget::onSelfAvatarLoaded(const QPixmap& pic)
{ {
profilePicture->setPixmap(pic); profilePicture->setPixmap(pic);
@ -429,7 +390,7 @@ void Widget::onStatusSet(Status status)
ui->statusButton->setIcon(QIcon(":img/status/dot_away_2x.png")); ui->statusButton->setIcon(QIcon(":img/status/dot_away_2x.png"));
break; break;
} }
updateTrayIcon(); updateIcons();
} }
void Widget::setWindowTitle(const QString& title) void Widget::setWindowTitle(const QString& title)
@ -483,7 +444,7 @@ void Widget::confirmExecutableOpen(const QFileInfo file)
} }
else else
{ {
QDesktopServices::openUrl(QUrl("file://" + file.filePath(), QUrl::TolerantMode)); QDesktopServices::openUrl(QUrl::fromLocalFile(file.filePath()));
} }
} }
@ -532,6 +493,14 @@ void Widget::onSettingsClicked()
activeChatroomWidget = nullptr; activeChatroomWidget = nullptr;
} }
void Widget::showProfile() // onAvatarClicked, onUsernameClicked
{
hideMainForms();
profileForm->show(*ui);
setWindowTitle(tr("Profile"));
activeChatroomWidget = nullptr;
}
void Widget::hideMainForms() void Widget::hideMainForms()
{ {
QLayoutItem* item; QLayoutItem* item;
@ -937,6 +906,15 @@ void Widget::onGroupTitleChanged(int groupnumber, const QString& author, const Q
g->getChatForm()->addSystemInfoMessage(tr("%1 has set the title to %2").arg(author, title), ChatMessage::INFO, QDateTime::currentDateTime()); g->getChatForm()->addSystemInfoMessage(tr("%1 has set the title to %2").arg(author, title), ChatMessage::INFO, QDateTime::currentDateTime());
} }
void Widget::onGroupPeerAudioPlaying(int groupnumber, int peernumber)
{
Group* g = GroupList::findGroup(groupnumber);
if (!g)
return;
g->getChatForm()->peerAudioPlaying(peernumber);
}
void Widget::removeGroup(Group* g, bool fake) void Widget::removeGroup(Group* g, bool fake)
{ {
g->getGroupWidget()->setAsInactiveChatroom(); g->getGroupWidget()->setAsInactiveChatroom();
@ -1013,7 +991,7 @@ bool Widget::event(QEvent * e)
{ {
eventFlag = false; eventFlag = false;
eventIcon = false; eventIcon = false;
updateTrayIcon(); updateIcons();
} }
default: default:
break; break;
@ -1055,7 +1033,7 @@ void Widget::onEventIconTick()
if (eventFlag) if (eventFlag)
{ {
eventIcon ^= true; eventIcon ^= true;
updateTrayIcon(); updateIcons();
} }
} }
@ -1067,7 +1045,7 @@ void Widget::onTryCreateTrayIcon()
if (QSystemTrayIcon::isSystemTrayAvailable()) if (QSystemTrayIcon::isSystemTrayAvailable())
{ {
icon = new SystemTrayIcon; icon = new SystemTrayIcon;
updateTrayIcon(); updateIcons();
trayMenu = new QMenu; trayMenu = new QMenu;
actionQuit = new QAction(tr("&Quit"), this); actionQuit = new QAction(tr("&Quit"), this);

View File

@ -23,7 +23,7 @@
#include <QFileInfo> #include <QFileInfo>
#include "form/addfriendform.h" #include "form/addfriendform.h"
#include "form/settingswidget.h" #include "form/settingswidget.h"
#include "form/settings/identityform.h" #include "form/profileform.h"
#include "form/filesform.h" #include "form/filesform.h"
#include "src/corestructs.h" #include "src/corestructs.h"
@ -63,7 +63,7 @@ public:
bool getIsWindowMinimized(); bool getIsWindowMinimized();
void clearContactsList(); void clearContactsList();
void setTranslation(); void setTranslation();
void updateTrayIcon(); void updateIcons();
~Widget(); ~Widget();
virtual void closeEvent(QCloseEvent *event); virtual void closeEvent(QCloseEvent *event);
@ -102,6 +102,7 @@ public slots:
void onGroupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction); void onGroupMessageReceived(int groupnumber, int peernumber, const QString& message, bool isAction);
void onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t change); void onGroupNamelistChanged(int groupnumber, int peernumber, uint8_t change);
void onGroupTitleChanged(int groupnumber, const QString& author, const QString& title); void onGroupTitleChanged(int groupnumber, const QString& author, const QString& title);
void onGroupPeerAudioPlaying(int groupnumber, int peernumber);
void playRingtone(); void playRingtone();
void onFriendTypingChanged(int friendId, bool isTyping); void onFriendTypingChanged(int friendId, bool isTyping);
void nextContact(); void nextContact();
@ -121,7 +122,7 @@ private slots:
void onAddClicked(); void onAddClicked();
void onGroupClicked(); void onGroupClicked();
void onTransferClicked(); void onTransferClicked();
void onAvatarClicked(); void showProfile();
void onUsernameChanged(const QString& newUsername, const QString& oldUsername); void onUsernameChanged(const QString& newUsername, const QString& oldUsername);
void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage); void onStatusMessageChanged(const QString& newStatusMessage, const QString& oldStatusMessage);
void onChatroomWidgetClicked(GenericChatroomWidget *); void onChatroomWidgetClicked(GenericChatroomWidget *);
@ -160,6 +161,7 @@ private:
QSplitter *centralLayout; QSplitter *centralLayout;
QPoint dragPosition; QPoint dragPosition;
AddFriendForm *addFriendForm; AddFriendForm *addFriendForm;
ProfileForm *profileForm;
SettingsWidget *settingsWidget; SettingsWidget *settingsWidget;
FilesForm *filesForm; FilesForm *filesForm;
static Widget *instance; static Widget *instance;

569
translations/it.ts vendored

File diff suppressed because it is too large Load Diff