2014-08-22 23:19:16 +08:00
|
|
|
/*
|
2015-06-06 09:40:08 +08:00
|
|
|
Copyright © 2014-2015 by The qTox Project
|
|
|
|
|
2014-08-22 23:19:16 +08:00
|
|
|
This file is part of qTox, a Qt-based graphical interface for Tox.
|
|
|
|
|
2015-06-06 09:40:08 +08:00
|
|
|
qTox is libre software: you can redistribute it and/or modify
|
2014-08-22 23:19:16 +08:00
|
|
|
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.
|
2015-06-06 09:40:08 +08:00
|
|
|
|
|
|
|
qTox is distributed in the hope that it will be useful,
|
2014-08-22 23:19:16 +08:00
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
2015-06-06 09:40:08 +08:00
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
2014-08-22 23:19:16 +08:00
|
|
|
|
2015-06-06 09:40:08 +08:00
|
|
|
You should have received a copy of the GNU General Public License
|
|
|
|
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
2014-08-22 23:19:16 +08:00
|
|
|
*/
|
2015-06-07 11:20:06 +08:00
|
|
|
|
2014-08-22 23:19:16 +08:00
|
|
|
#include "friendlistwidget.h"
|
2015-06-07 11:20:06 +08:00
|
|
|
#include "friendlistlayout.h"
|
2015-03-12 08:23:22 +08:00
|
|
|
#include "src/friend.h"
|
|
|
|
#include "src/friendlist.h"
|
2015-06-07 11:20:06 +08:00
|
|
|
#include "src/misc/settings.h"
|
|
|
|
#include "friendwidget.h"
|
2015-05-28 01:17:12 +08:00
|
|
|
#include "groupwidget.h"
|
2015-05-28 22:28:11 +08:00
|
|
|
#include "circlewidget.h"
|
2015-06-10 01:40:45 +08:00
|
|
|
#include "widget.h"
|
2015-06-07 11:20:06 +08:00
|
|
|
#include <QGridLayout>
|
|
|
|
#include <QMimeData>
|
|
|
|
#include <QDragEnterEvent>
|
|
|
|
#include <QDragLeaveEvent>
|
2015-05-28 01:17:12 +08:00
|
|
|
#include <cassert>
|
2014-08-22 23:19:16 +08:00
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
FriendListWidget::FriendListWidget(Widget* parent, bool groupsOnTop)
|
2015-06-03 21:51:23 +08:00
|
|
|
: QWidget(parent)
|
|
|
|
, groupsOnTop(groupsOnTop)
|
2014-08-22 23:19:16 +08:00
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
listLayout = new FriendListLayout();
|
2015-05-29 00:58:44 +08:00
|
|
|
setLayout(listLayout);
|
2014-08-22 23:19:16 +08:00
|
|
|
setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
|
2015-05-28 01:17:12 +08:00
|
|
|
|
2015-06-06 00:57:05 +08:00
|
|
|
circleLayout.getLayout()->setSpacing(0);
|
|
|
|
circleLayout.getLayout()->setMargin(0);
|
2015-06-02 02:39:40 +08:00
|
|
|
|
2015-06-03 21:51:23 +08:00
|
|
|
groupLayout.getLayout()->setSpacing(0);
|
|
|
|
groupLayout.getLayout()->setMargin(0);
|
|
|
|
|
2015-06-06 00:57:05 +08:00
|
|
|
listLayout->addLayout(circleLayout.getLayout());
|
2015-05-29 00:58:44 +08:00
|
|
|
|
2015-06-03 21:51:23 +08:00
|
|
|
onGroupchatPositionChanged(groupsOnTop);
|
|
|
|
|
2015-05-29 00:58:44 +08:00
|
|
|
setAcceptDrops(true);
|
2014-08-22 23:19:16 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::addGroupWidget(GroupWidget* widget)
|
2014-08-22 23:19:16 +08:00
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
groupLayout.addSortedWidget(widget);
|
|
|
|
connect(widget, &GroupWidget::renameRequested, this, &FriendListWidget::renameGroupWidget);
|
2015-06-07 11:20:06 +08:00
|
|
|
|
|
|
|
// Only rename group if groups are visible.
|
|
|
|
if (Widget::getInstance()->groupsVisible())
|
|
|
|
widget->rename();
|
2014-08-22 23:19:16 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::addFriendWidget(FriendWidget* w, Status s, int circleIndex)
|
2015-05-31 03:10:43 +08:00
|
|
|
{
|
2015-06-05 23:15:59 +08:00
|
|
|
CircleWidget* circleWidget = CircleWidget::getFromID(circleIndex);
|
|
|
|
if (circleWidget == nullptr)
|
2015-05-31 03:10:43 +08:00
|
|
|
moveWidget(w, s, true);
|
|
|
|
else
|
2015-06-05 23:15:59 +08:00
|
|
|
circleWidget->addFriendWidget(w, s);
|
2015-05-31 03:10:43 +08:00
|
|
|
}
|
|
|
|
|
2015-06-04 04:18:40 +08:00
|
|
|
void FriendListWidget::addCircleWidget(int id)
|
2015-05-31 03:10:43 +08:00
|
|
|
{
|
2015-06-07 11:20:06 +08:00
|
|
|
createCircleWidget(id);
|
2015-05-31 03:10:43 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::addCircleWidget(FriendWidget* friendWidget)
|
2015-05-28 01:17:12 +08:00
|
|
|
{
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* circleWidget = createCircleWidget();
|
2015-05-29 21:26:43 +08:00
|
|
|
if (friendWidget != nullptr)
|
|
|
|
{
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* circleOriginal = CircleWidget::getFromID(Settings::getInstance().getFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId()));
|
|
|
|
|
2015-05-29 21:26:43 +08:00
|
|
|
circleWidget->addFriendWidget(friendWidget, FriendList::findFriend(friendWidget->friendId)->getStatus());
|
2015-06-06 03:34:32 +08:00
|
|
|
circleWidget->setExpanded(true);
|
2015-06-07 11:20:06 +08:00
|
|
|
|
|
|
|
Widget::getInstance()->searchCircle(circleWidget);
|
|
|
|
|
|
|
|
if (circleOriginal != nullptr)
|
|
|
|
Widget::getInstance()->searchCircle(circleOriginal);
|
2015-05-29 21:26:43 +08:00
|
|
|
}
|
2015-05-29 06:36:21 +08:00
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::removeCircleWidget(CircleWidget* widget)
|
2015-05-29 06:36:21 +08:00
|
|
|
{
|
2015-06-06 00:57:05 +08:00
|
|
|
circleLayout.removeSortedWidget(widget);
|
2015-05-29 06:36:21 +08:00
|
|
|
widget->deleteLater();
|
2015-05-28 01:17:12 +08:00
|
|
|
}
|
|
|
|
|
2015-05-28 22:28:11 +08:00
|
|
|
void FriendListWidget::searchChatrooms(const QString &searchString, bool hideOnline, bool hideOffline, bool hideGroups)
|
|
|
|
{
|
2015-06-06 00:57:05 +08:00
|
|
|
groupLayout.search(searchString, hideGroups);
|
2015-06-03 21:51:23 +08:00
|
|
|
listLayout->searchChatrooms(searchString, hideOnline, hideOffline);
|
2015-06-06 00:57:05 +08:00
|
|
|
for (int i = 0; i != circleLayout.getLayout()->count(); ++i)
|
2015-05-28 22:28:11 +08:00
|
|
|
{
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* circleWidget = static_cast<CircleWidget*>(circleLayout.getLayout()->itemAt(i)->widget());
|
|
|
|
circleWidget->search(searchString, true, hideOnline, hideOffline);
|
2015-05-28 22:28:11 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-08 02:25:05 +08:00
|
|
|
void FriendListWidget::renameGroupWidget(GroupWidget* groupWidget, const QString &newName)
|
2015-05-28 01:17:12 +08:00
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
groupLayout.removeSortedWidget(groupWidget);
|
|
|
|
groupWidget->setName(newName);
|
|
|
|
groupLayout.addSortedWidget(groupWidget);
|
2015-06-07 11:20:06 +08:00
|
|
|
reDraw(); // Prevent artifacts.
|
2014-08-22 23:19:16 +08:00
|
|
|
}
|
|
|
|
|
2015-06-02 02:39:40 +08:00
|
|
|
void FriendListWidget::renameCircleWidget(const QString &newName)
|
|
|
|
{
|
|
|
|
assert(sender() != nullptr);
|
|
|
|
|
|
|
|
CircleWidget* circleWidget = dynamic_cast<CircleWidget*>(sender());
|
|
|
|
assert(circleWidget != nullptr);
|
|
|
|
|
2015-06-08 02:25:05 +08:00
|
|
|
// Rename after removing so you can find it successfully.
|
2015-06-06 00:57:05 +08:00
|
|
|
circleLayout.removeSortedWidget(circleWidget);
|
2015-06-02 02:39:40 +08:00
|
|
|
circleWidget->setName(newName);
|
2015-06-06 00:57:05 +08:00
|
|
|
circleLayout.addSortedWidget(circleWidget);
|
2015-06-02 02:39:40 +08:00
|
|
|
}
|
|
|
|
|
2015-03-12 08:41:18 +08:00
|
|
|
void FriendListWidget::onGroupchatPositionChanged(bool top)
|
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
groupsOnTop = top;
|
|
|
|
listLayout->removeItem(groupLayout.getLayout());
|
2015-03-26 00:27:33 +08:00
|
|
|
if (top)
|
2015-03-23 17:38:24 +08:00
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
listLayout->insertLayout(0, groupLayout.getLayout());
|
2015-03-12 08:41:18 +08:00
|
|
|
}
|
2015-03-23 17:38:24 +08:00
|
|
|
else
|
|
|
|
{
|
2015-06-03 21:51:23 +08:00
|
|
|
listLayout->insertLayout(1, groupLayout.getLayout());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void FriendListWidget::cycleContacts(GenericChatroomWidget* activeChatroomWidget, bool forward)
|
|
|
|
{
|
|
|
|
if (activeChatroomWidget == nullptr)
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
|
|
int index = -1;
|
|
|
|
QLayout* currentLayout = nullptr;
|
|
|
|
|
2015-06-06 01:38:07 +08:00
|
|
|
CircleWidget* circleWidget = nullptr;
|
2015-06-03 21:51:23 +08:00
|
|
|
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(activeChatroomWidget);
|
2015-06-06 01:38:07 +08:00
|
|
|
|
|
|
|
if (friendWidget != nullptr)
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
2015-06-06 03:34:32 +08:00
|
|
|
circleWidget = CircleWidget::getFromID(Settings::getInstance().getFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId()));
|
2015-06-06 01:38:07 +08:00
|
|
|
if (circleWidget != nullptr)
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
2015-06-06 01:38:07 +08:00
|
|
|
if (circleWidget->cycleContacts(friendWidget, forward))
|
|
|
|
return;
|
2015-06-03 21:51:23 +08:00
|
|
|
|
2015-06-06 01:38:07 +08:00
|
|
|
index = circleLayout.indexOfSortedWidget(circleWidget);
|
|
|
|
currentLayout = circleLayout.getLayout();
|
|
|
|
}
|
|
|
|
else
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
|
|
|
currentLayout = listLayout->getLayoutOnline();
|
|
|
|
index = listLayout->indexOfFriendWidget(friendWidget, true);
|
|
|
|
if (index == -1)
|
|
|
|
{
|
|
|
|
currentLayout = listLayout->getLayoutOffline();
|
|
|
|
index = listLayout->indexOfFriendWidget(friendWidget, false);
|
|
|
|
}
|
|
|
|
}
|
2015-06-06 01:38:07 +08:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
GroupWidget* groupWidget = dynamic_cast<GroupWidget*>(activeChatroomWidget);
|
|
|
|
if (groupWidget != nullptr)
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
2015-06-06 01:38:07 +08:00
|
|
|
currentLayout = groupLayout.getLayout();
|
|
|
|
index = groupLayout.indexOfSortedWidget(groupWidget);
|
2015-06-03 21:51:23 +08:00
|
|
|
}
|
2015-06-06 01:38:07 +08:00
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
};
|
2015-06-03 21:51:23 +08:00
|
|
|
}
|
|
|
|
|
|
|
|
index += forward ? 1 : -1;
|
|
|
|
for (;;)
|
|
|
|
{
|
|
|
|
// Bounds checking.
|
|
|
|
if (index < 0)
|
|
|
|
{
|
|
|
|
currentLayout = nextLayout(currentLayout, forward);
|
|
|
|
index = currentLayout->count() - 1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
else if (index >= currentLayout->count())
|
|
|
|
{
|
|
|
|
currentLayout = nextLayout(currentLayout, forward);
|
|
|
|
index = 0;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Go to the actual next index.
|
|
|
|
if (currentLayout == listLayout->getLayoutOnline() || currentLayout == listLayout->getLayoutOffline() || currentLayout == groupLayout.getLayout())
|
|
|
|
{
|
|
|
|
GenericChatroomWidget* chatWidget = dynamic_cast<GenericChatroomWidget*>(currentLayout->itemAt(index)->widget());
|
|
|
|
if (chatWidget != nullptr)
|
|
|
|
emit chatWidget->chatroomWidgetClicked(chatWidget);
|
|
|
|
return;
|
|
|
|
}
|
2015-06-06 00:57:05 +08:00
|
|
|
else if (currentLayout == circleLayout.getLayout())
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
|
|
|
circleWidget = dynamic_cast<CircleWidget*>(currentLayout->itemAt(index)->widget());
|
|
|
|
if (circleWidget != nullptr)
|
|
|
|
{
|
|
|
|
if (!circleWidget->cycleContacts(forward))
|
|
|
|
{
|
|
|
|
// Skip empty or finished circles.
|
|
|
|
index += forward ? 1 : -1;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return;
|
|
|
|
}
|
2015-03-12 08:41:18 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-05-29 21:26:43 +08:00
|
|
|
QVector<CircleWidget*> FriendListWidget::getAllCircles()
|
|
|
|
{
|
|
|
|
QVector<CircleWidget*> vec;
|
2015-06-06 00:57:05 +08:00
|
|
|
vec.reserve(circleLayout.getLayout()->count());
|
|
|
|
for (int i = 0; i < circleLayout.getLayout()->count(); ++i)
|
2015-05-29 21:26:43 +08:00
|
|
|
{
|
2015-06-06 00:57:05 +08:00
|
|
|
vec.push_back(dynamic_cast<CircleWidget*>(circleLayout.getLayout()->itemAt(i)->widget()));
|
2015-05-29 21:26:43 +08:00
|
|
|
}
|
|
|
|
return vec;
|
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::dragEnterEvent(QDragEnterEvent* event)
|
2015-05-29 00:58:44 +08:00
|
|
|
{
|
|
|
|
if (event->mimeData()->hasFormat("friend"))
|
|
|
|
event->acceptProposedAction();
|
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::dropEvent(QDropEvent* event)
|
2015-05-29 00:58:44 +08:00
|
|
|
{
|
|
|
|
if (event->mimeData()->hasFormat("friend"))
|
|
|
|
{
|
|
|
|
int friendId = event->mimeData()->data("friend").toInt();
|
2015-06-07 11:20:06 +08:00
|
|
|
Friend* f = FriendList::findFriend(friendId);
|
2015-05-29 00:58:44 +08:00
|
|
|
assert(f != nullptr);
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
FriendWidget* widget = f->getFriendWidget();
|
2015-05-29 00:58:44 +08:00
|
|
|
assert(widget != nullptr);
|
|
|
|
|
|
|
|
// Update old circle after moved.
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* circleWidget = CircleWidget::getFromID(Settings::getInstance().getFriendCircleID(f->getToxId()));
|
2015-05-29 00:58:44 +08:00
|
|
|
|
|
|
|
listLayout->addFriendWidget(widget, f->getStatus());
|
|
|
|
|
|
|
|
if (circleWidget != nullptr)
|
|
|
|
{
|
|
|
|
// In case the status was changed while moving, update both.
|
2015-05-31 03:10:43 +08:00
|
|
|
circleWidget->updateStatus();
|
2015-05-29 00:58:44 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
void FriendListWidget::moveWidget(FriendWidget* w, Status s, bool add)
|
2014-08-22 23:19:16 +08:00
|
|
|
{
|
2015-06-06 03:34:32 +08:00
|
|
|
int circleId = Settings::getInstance().getFriendCircleID(FriendList::findFriend(w->friendId)->getToxId());
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* circleWidget = CircleWidget::getFromID(circleId);
|
2015-05-28 01:17:12 +08:00
|
|
|
|
2015-05-28 22:28:11 +08:00
|
|
|
if (circleWidget == nullptr || add)
|
2015-03-23 17:38:24 +08:00
|
|
|
{
|
2015-06-05 00:30:24 +08:00
|
|
|
if (circleId != -1)
|
2015-06-06 03:34:32 +08:00
|
|
|
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), -1);
|
2015-05-28 22:28:11 +08:00
|
|
|
listLayout->addFriendWidget(w, s);
|
|
|
|
return;
|
2015-03-12 08:23:22 +08:00
|
|
|
}
|
2015-05-28 08:45:23 +08:00
|
|
|
|
2015-05-28 22:28:11 +08:00
|
|
|
circleWidget->addFriendWidget(w, s);
|
2014-08-22 23:19:16 +08:00
|
|
|
}
|
2015-06-03 18:26:48 +08:00
|
|
|
|
|
|
|
// update widget after add/delete/hide/show
|
|
|
|
void FriendListWidget::reDraw()
|
|
|
|
{
|
|
|
|
hide();
|
|
|
|
show();
|
|
|
|
resize(QSize()); //lifehack
|
|
|
|
}
|
2015-06-03 21:51:23 +08:00
|
|
|
|
2015-06-07 11:20:06 +08:00
|
|
|
CircleWidget* FriendListWidget::createCircleWidget(int id)
|
|
|
|
{
|
|
|
|
CircleWidget* circleWidget = new CircleWidget(this, id);
|
|
|
|
circleLayout.addSortedWidget(circleWidget);
|
|
|
|
connect(this, &FriendListWidget::onCompactChanged, circleWidget, &CircleWidget::onCompactChanged);
|
|
|
|
connect(circleWidget, &CircleWidget::renameRequested, this, &FriendListWidget::renameCircleWidget);
|
|
|
|
circleWidget->show(); // Avoid flickering.
|
|
|
|
return circleWidget;
|
|
|
|
}
|
|
|
|
|
2015-06-03 21:51:23 +08:00
|
|
|
QLayout* FriendListWidget::nextLayout(QLayout* layout, bool forward) const
|
|
|
|
{
|
|
|
|
if (layout == groupLayout.getLayout())
|
|
|
|
{
|
|
|
|
if (forward)
|
|
|
|
{
|
|
|
|
if (groupsOnTop)
|
|
|
|
return listLayout->getLayoutOnline();
|
|
|
|
return listLayout->getLayoutOffline();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (groupsOnTop)
|
2015-06-06 00:57:05 +08:00
|
|
|
return circleLayout.getLayout();
|
2015-06-03 21:51:23 +08:00
|
|
|
return listLayout->getLayoutOnline();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (layout == listLayout->getLayoutOnline())
|
|
|
|
{
|
|
|
|
if (forward)
|
|
|
|
{
|
|
|
|
if (groupsOnTop)
|
|
|
|
return listLayout->getLayoutOffline();
|
|
|
|
return groupLayout.getLayout();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
if (groupsOnTop)
|
|
|
|
return groupLayout.getLayout();
|
2015-06-06 00:57:05 +08:00
|
|
|
return circleLayout.getLayout();
|
2015-06-03 21:51:23 +08:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (layout == listLayout->getLayoutOffline())
|
|
|
|
{
|
|
|
|
if (forward)
|
2015-06-06 00:57:05 +08:00
|
|
|
return circleLayout.getLayout();
|
2015-06-03 21:51:23 +08:00
|
|
|
else if (groupsOnTop)
|
|
|
|
return listLayout->getLayoutOnline();
|
|
|
|
return groupLayout.getLayout();
|
|
|
|
}
|
2015-06-06 00:57:05 +08:00
|
|
|
else if (layout == circleLayout.getLayout())
|
2015-06-03 21:51:23 +08:00
|
|
|
{
|
|
|
|
if (forward)
|
|
|
|
{
|
|
|
|
if (groupsOnTop)
|
|
|
|
return groupLayout.getLayout();
|
|
|
|
return listLayout->getLayoutOnline();
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return listLayout->getLayoutOffline();
|
|
|
|
}
|
|
|
|
return nullptr;
|
|
|
|
}
|