mirror of https://github.com/qTox/qTox.git
42 changed files with 2768 additions and 459 deletions
@ -0,0 +1,333 @@
@@ -0,0 +1,333 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include "categorywidget.h" |
||||
#include "friendlistlayout.h" |
||||
#include "friendlistwidget.h" |
||||
#include "friendwidget.h" |
||||
#include "src/widget/style.h" |
||||
#include "tool/croppinglabel.h" |
||||
#include <QBoxLayout> |
||||
#include <QMouseEvent> |
||||
|
||||
#include <QApplication> |
||||
|
||||
void emitChatroomWidget(QLayout* layout, int index) |
||||
{ |
||||
GenericChatroomWidget* chatWidget = dynamic_cast<GenericChatroomWidget*>(layout->itemAt(index)->widget()); |
||||
if (chatWidget != nullptr) |
||||
emit chatWidget->chatroomWidgetClicked(chatWidget); |
||||
} |
||||
|
||||
CategoryWidget::CategoryWidget(QWidget* parent) |
||||
: GenericChatItemWidget(parent) |
||||
{ |
||||
container = new QWidget(this); |
||||
container->setObjectName("circleWidgetContainer"); |
||||
container->setLayoutDirection(Qt::LeftToRight); |
||||
|
||||
statusLabel = new QLabel(this); |
||||
statusLabel->setObjectName("status"); |
||||
statusLabel->setTextFormat(Qt::PlainText); |
||||
|
||||
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarRightArrow.svg")); |
||||
|
||||
fullLayout = new QVBoxLayout(this); |
||||
fullLayout->setSpacing(0); |
||||
fullLayout->setMargin(0); |
||||
fullLayout->addWidget(container); |
||||
|
||||
lineFrame = new QFrame(container); |
||||
lineFrame->setObjectName("line"); |
||||
lineFrame->setFrameShape(QFrame::HLine); |
||||
lineFrame->setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Minimum); |
||||
lineFrame->resize(0, 0); |
||||
|
||||
listLayout = new FriendListLayout(); |
||||
listWidget = new QWidget(this); |
||||
listWidget->setLayout(listLayout); |
||||
fullLayout->addWidget(listWidget); |
||||
|
||||
setAcceptDrops(true); |
||||
|
||||
onCompactChanged(isCompact()); |
||||
|
||||
setExpanded(true, false); |
||||
updateStatus(); |
||||
} |
||||
|
||||
bool CategoryWidget::isExpanded() const |
||||
{ |
||||
return expanded; |
||||
} |
||||
|
||||
void CategoryWidget::setExpanded(bool isExpanded, bool save) |
||||
{ |
||||
expanded = isExpanded; |
||||
setMouseTracking(true); |
||||
listWidget->setVisible(isExpanded); |
||||
|
||||
if (isExpanded) |
||||
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarDownArrow.svg")); |
||||
else |
||||
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarRightArrow.svg")); |
||||
|
||||
// The listWidget will recieve a enterEvent for some reason if now visible.
|
||||
// Using the following, we prevent that.
|
||||
QApplication::processEvents(QEventLoop::ExcludeSocketNotifiers); |
||||
container->hide(); |
||||
container->show(); |
||||
|
||||
if (save) |
||||
onExpand(); |
||||
} |
||||
|
||||
void CategoryWidget::leaveEvent(QEvent *event) |
||||
{ |
||||
event->ignore(); |
||||
} |
||||
|
||||
void CategoryWidget::setName(const QString &name, bool save) |
||||
{ |
||||
nameLabel->setText(name); |
||||
|
||||
if (isCompact()) |
||||
nameLabel->minimizeMaximumWidth(); |
||||
|
||||
if (save) |
||||
onSetName(); |
||||
} |
||||
|
||||
void CategoryWidget::editName() |
||||
{ |
||||
nameLabel->editBegin(); |
||||
nameLabel->setMaximumWidth(QWIDGETSIZE_MAX); |
||||
} |
||||
|
||||
void CategoryWidget::addFriendWidget(FriendWidget* w, Status s) |
||||
{ |
||||
listLayout->addFriendWidget(w, s); |
||||
updateStatus(); |
||||
onAddFriendWidget(w); |
||||
w->reloadTheme(); // Otherwise theme will change when moving to another circle.
|
||||
} |
||||
|
||||
void CategoryWidget::removeFriendWidget(FriendWidget* w, Status s) |
||||
{ |
||||
listLayout->removeFriendWidget(w, s); |
||||
updateStatus(); |
||||
} |
||||
|
||||
void CategoryWidget::updateStatus() |
||||
{ |
||||
statusLabel->setText(QString::number(listLayout->friendOnlineCount()) + QStringLiteral(" / ") + QString::number(listLayout->friendTotalCount())); |
||||
} |
||||
|
||||
bool CategoryWidget::hasChatrooms() const |
||||
{ |
||||
return listLayout->hasChatrooms(); |
||||
} |
||||
|
||||
void CategoryWidget::search(const QString &searchString, bool updateAll, bool hideOnline, bool hideOffline) |
||||
{ |
||||
if (updateAll) |
||||
{ |
||||
listLayout->searchChatrooms(searchString, hideOnline, hideOffline); |
||||
} |
||||
bool inCategory = searchString.isEmpty() && !(hideOnline && hideOffline); |
||||
setVisible(inCategory || listLayout->hasChatrooms()); |
||||
} |
||||
|
||||
bool CategoryWidget::cycleContacts(bool forward) |
||||
{ |
||||
if (listLayout->friendTotalCount() == 0) |
||||
{ |
||||
return false; |
||||
} |
||||
if (forward) |
||||
{ |
||||
if (listLayout->getLayoutOnline()->count() != 0) |
||||
{ |
||||
setExpanded(true); |
||||
emitChatroomWidget(listLayout->getLayoutOnline(), 0); |
||||
return true; |
||||
} |
||||
else if (listLayout->getLayoutOffline()->count() != 0) |
||||
{ |
||||
setExpanded(true); |
||||
emitChatroomWidget(listLayout->getLayoutOffline(), 0); |
||||
return true; |
||||
} |
||||
} |
||||
else |
||||
{ |
||||
if (listLayout->getLayoutOffline()->count() != 0) |
||||
{ |
||||
setExpanded(true); |
||||
emitChatroomWidget(listLayout->getLayoutOffline(), listLayout->getLayoutOffline()->count() - 1); |
||||
return true; |
||||
} |
||||
else if (listLayout->getLayoutOnline()->count() != 0) |
||||
{ |
||||
setExpanded(true); |
||||
emitChatroomWidget(listLayout->getLayoutOnline(), listLayout->getLayoutOnline()->count() - 1); |
||||
return true; |
||||
} |
||||
} |
||||
return false; |
||||
} |
||||
|
||||
bool CategoryWidget::cycleContacts(FriendWidget* activeChatroomWidget, bool forward) |
||||
{ |
||||
int index = -1; |
||||
QLayout* currentLayout = nullptr; |
||||
|
||||
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(activeChatroomWidget); |
||||
if (friendWidget != nullptr) |
||||
{ |
||||
currentLayout = listLayout->getLayoutOnline(); |
||||
index = listLayout->indexOfFriendWidget(friendWidget, true); |
||||
if (index == -1) |
||||
{ |
||||
currentLayout = listLayout->getLayoutOffline(); |
||||
index = listLayout->indexOfFriendWidget(friendWidget, false); |
||||
} |
||||
} |
||||
else |
||||
return false; |
||||
|
||||
index += forward ? 1 : -1; |
||||
for (;;) |
||||
{ |
||||
// Bounds checking.
|
||||
if (index < 0) |
||||
{ |
||||
if (currentLayout == listLayout->getLayoutOffline()) |
||||
currentLayout = listLayout->getLayoutOnline(); |
||||
else |
||||
return false; |
||||
|
||||
index = currentLayout->count() - 1; |
||||
continue; |
||||
} |
||||
else if (index >= currentLayout->count()) |
||||
{ |
||||
if (currentLayout == listLayout->getLayoutOnline()) |
||||
currentLayout = listLayout->getLayoutOffline(); |
||||
else |
||||
return false; |
||||
|
||||
index = 0; |
||||
continue; |
||||
} |
||||
|
||||
GenericChatroomWidget* chatWidget = dynamic_cast<GenericChatroomWidget*>(currentLayout->itemAt(index)->widget()); |
||||
if (chatWidget != nullptr) |
||||
emit chatWidget->chatroomWidgetClicked(chatWidget); |
||||
return true; |
||||
} |
||||
|
||||
return false; |
||||
} |
||||
|
||||
void CategoryWidget::onCompactChanged(bool _compact) |
||||
{ |
||||
delete topLayout; |
||||
delete mainLayout; |
||||
|
||||
topLayout = new QHBoxLayout; |
||||
topLayout->setSpacing(0); |
||||
topLayout->setMargin(0); |
||||
|
||||
(void)_compact; |
||||
setCompact(true); |
||||
|
||||
if (true) |
||||
{ |
||||
nameLabel->minimizeMaximumWidth(); |
||||
|
||||
mainLayout = nullptr; |
||||
|
||||
container->setFixedHeight(25); |
||||
container->setLayout(topLayout); |
||||
|
||||
topLayout->addSpacing(18); |
||||
topLayout->addWidget(&statusPic); |
||||
topLayout->addSpacing(5); |
||||
topLayout->addWidget(nameLabel, 100); |
||||
topLayout->addWidget(lineFrame, 1); |
||||
topLayout->addSpacing(5); |
||||
topLayout->addWidget(statusLabel); |
||||
topLayout->addSpacing(5); |
||||
topLayout->activate(); |
||||
} |
||||
/*else
|
||||
{ |
||||
nameLabel->setMaximumWidth(QWIDGETSIZE_MAX); |
||||
|
||||
mainLayout = new QVBoxLayout(); |
||||
mainLayout->setSpacing(0); |
||||
mainLayout->setContentsMargins(20, 0, 20, 0); |
||||
|
||||
container->setFixedHeight(25); |
||||
container->setLayout(mainLayout); |
||||
|
||||
topLayout->addWidget(&statusPic); |
||||
topLayout->addSpacing(10); |
||||
topLayout->addWidget(nameLabel, 1); |
||||
topLayout->addSpacing(5); |
||||
topLayout->addWidget(statusLabel); |
||||
topLayout->activate(); |
||||
|
||||
mainLayout->addStretch(); |
||||
mainLayout->addLayout(topLayout); |
||||
mainLayout->addWidget(lineFrame); |
||||
mainLayout->addStretch(); |
||||
mainLayout->activate(); |
||||
}*/ |
||||
|
||||
Style::repolish(this); |
||||
} |
||||
|
||||
void CategoryWidget::mouseReleaseEvent(QMouseEvent* event) |
||||
{ |
||||
if (event->button() == Qt::LeftButton) |
||||
setExpanded(!expanded); |
||||
} |
||||
|
||||
void CategoryWidget::setContainerAttribute(Qt::WidgetAttribute attribute, bool enabled) |
||||
{ |
||||
container->setAttribute(attribute, enabled); |
||||
Style::repolish(container); |
||||
} |
||||
|
||||
QLayout* CategoryWidget::friendOfflineLayout() const |
||||
{ |
||||
return listLayout->getLayoutOffline(); |
||||
} |
||||
|
||||
QLayout* CategoryWidget::friendOnlineLayout() const |
||||
{ |
||||
return listLayout->getLayoutOnline(); |
||||
} |
||||
|
||||
void CategoryWidget::moveFriendWidgets(FriendListWidget* friendList) |
||||
{ |
||||
listLayout->moveFriendWidgets(friendList); |
||||
} |
@ -0,0 +1,80 @@
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#ifndef CATEGORYWIDGET_H |
||||
#define CATEGORYWIDGET_H |
||||
|
||||
#include "genericchatitemwidget.h" |
||||
#include "src/core/corestructs.h" |
||||
|
||||
class FriendListLayout; |
||||
class FriendListWidget; |
||||
class FriendWidget; |
||||
class QVBoxLayout; |
||||
class QHBoxLayout; |
||||
|
||||
class CategoryWidget : public GenericChatItemWidget |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
CategoryWidget(QWidget* parent = 0); |
||||
|
||||
bool isExpanded() const; |
||||
void setExpanded(bool isExpanded, bool save = true); |
||||
void setName(const QString &name, bool save = true); |
||||
|
||||
void addFriendWidget(FriendWidget* w, Status s); |
||||
void removeFriendWidget(FriendWidget* w, Status s); |
||||
void updateStatus(); |
||||
|
||||
bool hasChatrooms() const; |
||||
bool cycleContacts(bool forward); |
||||
bool cycleContacts(FriendWidget* activeChatroomWidget, bool forward); |
||||
void search(const QString &searchString, bool updateAll = false, bool hideOnline = false, bool hideOffline = false); |
||||
|
||||
public slots: |
||||
void onCompactChanged(bool compact); |
||||
|
||||
protected: |
||||
virtual void leaveEvent(QEvent* event) final override; |
||||
virtual void mouseReleaseEvent(QMouseEvent* event) final override; |
||||
|
||||
void editName(); |
||||
void setContainerAttribute(Qt::WidgetAttribute attribute, bool enabled); |
||||
QLayout* friendOnlineLayout() const; |
||||
QLayout* friendOfflineLayout() const; |
||||
void moveFriendWidgets(FriendListWidget* friendList); |
||||
|
||||
private: |
||||
virtual void onSetName() {} |
||||
virtual void onExpand() {} |
||||
virtual void onAddFriendWidget(FriendWidget*) {} |
||||
|
||||
QWidget* listWidget; |
||||
FriendListLayout* listLayout; |
||||
QVBoxLayout* fullLayout; |
||||
QVBoxLayout* mainLayout = nullptr; |
||||
QHBoxLayout* topLayout = nullptr; |
||||
QLabel* statusLabel; |
||||
QWidget* container; |
||||
QFrame* lineFrame; |
||||
bool expanded = false; |
||||
}; |
||||
|
||||
#endif // CATEGORYWIDGET_H
|
@ -0,0 +1,196 @@
@@ -0,0 +1,196 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include "circlewidget.h" |
||||
#include "friendwidget.h" |
||||
#include "friendlistwidget.h" |
||||
#include "tool/croppinglabel.h" |
||||
#include "src/persistence/settings.h" |
||||
#include "src/friendlist.h" |
||||
#include "src/friend.h" |
||||
#include "widget.h" |
||||
#include <QVariant> |
||||
#include <QBoxLayout> |
||||
#include <QMouseEvent> |
||||
#include <QDragEnterEvent> |
||||
#include <QMimeData> |
||||
#include <QMenu> |
||||
#include <cassert> |
||||
|
||||
QHash<int, CircleWidget*> CircleWidget::circleList; |
||||
|
||||
CircleWidget::CircleWidget(FriendListWidget* parent, int id) |
||||
: CategoryWidget(parent) |
||||
, id(id) |
||||
{ |
||||
setName(Settings::getInstance().getCircleName(id), false); |
||||
circleList[id] = this; |
||||
|
||||
connect(nameLabel, &CroppingLabel::editFinished, [this](const QString &newName) |
||||
{ |
||||
if (!newName.isEmpty()) |
||||
emit renameRequested(this, newName); |
||||
}); |
||||
|
||||
connect(nameLabel, &CroppingLabel::editRemoved, [this]() |
||||
{ |
||||
if (isCompact()) |
||||
nameLabel->minimizeMaximumWidth(); |
||||
}); |
||||
|
||||
setExpanded(Settings::getInstance().getCircleExpanded(id), false); |
||||
updateStatus(); |
||||
} |
||||
|
||||
CircleWidget::~CircleWidget() |
||||
{ |
||||
if (circleList[id] == this) |
||||
circleList.remove(id); |
||||
} |
||||
|
||||
void CircleWidget::editName() |
||||
{ |
||||
CategoryWidget::editName(); |
||||
} |
||||
|
||||
CircleWidget* CircleWidget::getFromID(int id) |
||||
{ |
||||
auto circleIt = circleList.find(id); |
||||
|
||||
if (circleIt != circleList.end()) |
||||
return circleIt.value(); |
||||
|
||||
return nullptr; |
||||
} |
||||
|
||||
void CircleWidget::contextMenuEvent(QContextMenuEvent* event) |
||||
{ |
||||
QMenu menu; |
||||
QAction* renameAction = menu.addAction(tr("Rename circle", "Menu for renaming a circle")); |
||||
QAction* removeAction = menu.addAction(tr("Remove circle", "Menu for removing a circle")); |
||||
|
||||
QAction* selectedItem = menu.exec(mapToGlobal(event->pos())); |
||||
if (selectedItem == renameAction) |
||||
{ |
||||
editName(); |
||||
} |
||||
else if (selectedItem == removeAction) |
||||
{ |
||||
FriendListWidget* friendList = static_cast<FriendListWidget*>(parentWidget()); |
||||
moveFriendWidgets(friendList); |
||||
|
||||
friendList->removeCircleWidget(this); |
||||
|
||||
int replacedCircle = Settings::getInstance().removeCircle(id); |
||||
|
||||
auto circleReplace = circleList.find(replacedCircle); |
||||
if (circleReplace != circleList.end()) |
||||
circleReplace.value()->updateID(id); |
||||
else |
||||
assert(true); // This should never happen.
|
||||
|
||||
circleList.remove(replacedCircle); |
||||
} |
||||
setContainerAttribute(Qt::WA_UnderMouse, false); |
||||
} |
||||
|
||||
void CircleWidget::dragEnterEvent(QDragEnterEvent* event) |
||||
{ |
||||
if (event->mimeData()->hasFormat("friend")) |
||||
event->acceptProposedAction(); |
||||
|
||||
setContainerAttribute(Qt::WA_UnderMouse, true); // Simulate hover.
|
||||
} |
||||
|
||||
void CircleWidget::dragLeaveEvent(QDragLeaveEvent* ) |
||||
{ |
||||
setContainerAttribute(Qt::WA_UnderMouse, false); |
||||
} |
||||
|
||||
void CircleWidget::dropEvent(QDropEvent* event) |
||||
{ |
||||
if (event->mimeData()->hasFormat("friend")) |
||||
{ |
||||
setExpanded(true, false); |
||||
|
||||
int friendId = event->mimeData()->data("friend").toInt(); |
||||
Friend* f = FriendList::findFriend(friendId); |
||||
assert(f != nullptr); |
||||
|
||||
FriendWidget* widget = f->getFriendWidget(); |
||||
assert(widget != nullptr); |
||||
|
||||
// Update old circle after moved.
|
||||
CircleWidget* circleWidget = getFromID(Settings::getInstance().getFriendCircleID(f->getToxId())); |
||||
|
||||
addFriendWidget(widget, f->getStatus()); |
||||
Settings::getInstance().savePersonal(); |
||||
|
||||
if (circleWidget != nullptr) |
||||
{ |
||||
circleWidget->updateStatus(); |
||||
Widget::getInstance()->searchCircle(circleWidget); |
||||
} |
||||
|
||||
setContainerAttribute(Qt::WA_UnderMouse, false); |
||||
} |
||||
} |
||||
|
||||
void CircleWidget::onSetName() |
||||
{ |
||||
Settings::getInstance().setCircleName(id, getName()); |
||||
} |
||||
|
||||
void CircleWidget::onExpand() |
||||
{ |
||||
Settings::getInstance().setCircleExpanded(id, isExpanded()); |
||||
Settings::getInstance().savePersonal(); |
||||
} |
||||
|
||||
void CircleWidget::onAddFriendWidget(FriendWidget* w) |
||||
{ |
||||
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), id); |
||||
} |
||||
|
||||
void CircleWidget::updateID(int index) |
||||
{ |
||||
// For when a circle gets destroyed, another takes its id.
|
||||
// This function updates all friends widgets for this new id.
|
||||
|
||||
if (id == index) |
||||
return; |
||||
|
||||
id = index; |
||||
circleList[id] = this; |
||||
|
||||
for (int i = 0; i < friendOnlineLayout()->count(); ++i) |
||||
{ |
||||
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOnlineLayout()->itemAt(i)); |
||||
|
||||
if (friendWidget != nullptr) |
||||
Settings::getInstance().setFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId(), id); |
||||
} |
||||
for (int i = 0; i < friendOfflineLayout()->count(); ++i) |
||||
{ |
||||
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOfflineLayout()->itemAt(i)); |
||||
|
||||
if (friendWidget != nullptr) |
||||
Settings::getInstance().setFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId(), id); |
||||
} |
||||
} |
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#ifndef CIRCLEWIDGET_H |
||||
#define CIRCLEWIDGET_H |
||||
|
||||
#include "categorywidget.h" |
||||
|
||||
class CircleWidget final : public CategoryWidget |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
CircleWidget(FriendListWidget* parent, int id); |
||||
~CircleWidget(); |
||||
|
||||
void editName(); |
||||
static CircleWidget* getFromID(int id); |
||||
|
||||
signals: |
||||
void renameRequested(CircleWidget* circleWidget, const QString &newName); |
||||
|
||||
protected: |
||||
virtual void contextMenuEvent(QContextMenuEvent* event) final override; |
||||
virtual void dragEnterEvent(QDragEnterEvent* event) final override; |
||||
virtual void dragLeaveEvent(QDragLeaveEvent* event) final override; |
||||
virtual void dropEvent(QDropEvent* event) final override; |
||||
|
||||
private: |
||||
virtual void onSetName() final override; |
||||
virtual void onExpand() final override; |
||||
virtual void onAddFriendWidget(FriendWidget* w) final override; |
||||
void updateID(int index); |
||||
|
||||
static QHash<int, CircleWidget*> circleList; |
||||
int id; |
||||
}; |
||||
|
||||
#endif // CIRCLEWIDGET_H
|
@ -0,0 +1,124 @@
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
This program is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
||||
See the COPYING file for more details. |
||||
*/ |
||||
|
||||
#include "friendlistlayout.h" |
||||
#include "src/friend.h" |
||||
#include "src/friendlist.h" |
||||
#include "friendwidget.h" |
||||
#include "friendlistwidget.h" |
||||
#include <cassert> |
||||
|
||||
FriendListLayout::FriendListLayout() |
||||
{ |
||||
setSpacing(0); |
||||
setMargin(0); |
||||
|
||||
friendOnlineLayout.getLayout()->setSpacing(0); |
||||
friendOnlineLayout.getLayout()->setMargin(0); |
||||
|
||||
friendOfflineLayout.getLayout()->setSpacing(0); |
||||
friendOfflineLayout.getLayout()->setMargin(0); |
||||
|
||||
addLayout(friendOnlineLayout.getLayout()); |
||||
addLayout(friendOfflineLayout.getLayout()); |
||||
} |
||||
|
||||
FriendListLayout::FriendListLayout(QWidget* parent) |
||||
: QVBoxLayout(parent) |
||||
{ |
||||
FriendListLayout(); |
||||
} |
||||
|
||||
void FriendListLayout::addFriendWidget(FriendWidget* w, Status s) |
||||
{ |
||||
friendOfflineLayout.removeSortedWidget(w); |
||||
friendOnlineLayout.removeSortedWidget(w); |
||||
|
||||
if (s == Status::Offline) |
||||
{ |
||||
friendOfflineLayout.addSortedWidget(w); |
||||
return; |
||||
} |
||||
|
||||
friendOnlineLayout.addSortedWidget(w); |
||||
} |
||||
|
||||
void FriendListLayout::removeFriendWidget(FriendWidget *widget, Status s) |
||||
{ |
||||
if (s == Status::Offline) |
||||
friendOfflineLayout.removeSortedWidget(widget); |
||||
else |
||||
friendOnlineLayout.removeSortedWidget(widget); |
||||
} |
||||
|
||||
int FriendListLayout::indexOfFriendWidget(FriendWidget* widget, bool online) const |
||||
{ |
||||
if (online) |
||||
return friendOnlineLayout.indexOfSortedWidget(widget); |
||||
return friendOfflineLayout.indexOfSortedWidget(widget); |
||||
} |
||||
|
||||
void FriendListLayout::moveFriendWidgets(FriendListWidget* listWidget) |
||||
{ |
||||
while (friendOnlineLayout.getLayout()->count() != 0) |
||||
{ |
||||
QWidget* getWidget = friendOnlineLayout.getLayout()->takeAt(0)->widget(); |
||||
|
||||
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(getWidget); |
||||
listWidget->moveWidget(friendWidget, FriendList::findFriend(friendWidget->friendId)->getStatus(), true); |
||||
} |
||||
while (friendOfflineLayout.getLayout()->count() != 0) |
||||
{ |
||||
QWidget* getWidget = friendOfflineLayout.getLayout()->takeAt(0)->widget(); |
||||
|
||||
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(getWidget); |
||||
listWidget->moveWidget(friendWidget, FriendList::findFriend(friendWidget->friendId)->getStatus(), true); |
||||
} |
||||
} |
||||
|
||||
int FriendListLayout::friendOnlineCount() const |
||||
{ |
||||
return friendOnlineLayout.getLayout()->count(); |
||||
} |
||||
|
||||
int FriendListLayout::friendTotalCount() const |
||||
{ |
||||
return friendOfflineLayout.getLayout()->count() + friendOnlineCount(); |
||||
} |
||||
|
||||
bool FriendListLayout::hasChatrooms() const |
||||
{ |
||||
return !(friendOfflineLayout.getLayout()->isEmpty() && friendOnlineLayout.getLayout()->isEmpty()); |
||||
} |
||||
|
||||
void FriendListLayout::searchChatrooms(const QString& searchString, bool hideOnline, bool hideOffline) |
||||
{ |
||||
friendOnlineLayout.search(searchString, hideOnline); |
||||
friendOfflineLayout.search(searchString, hideOffline); |
||||
} |
||||
|
||||
QLayout* FriendListLayout::getLayoutOnline() const |
||||
{ |
||||
return friendOnlineLayout.getLayout(); |
||||
} |
||||
|
||||
QLayout* FriendListLayout::getLayoutOffline() const |
||||
{ |
||||
return friendOfflineLayout.getLayout(); |
||||
} |
||||
|
||||
QLayout* FriendListLayout::getFriendLayout(Status s) const |
||||
{ |
||||
return s == Status::Offline ? friendOfflineLayout.getLayout() : friendOnlineLayout.getLayout(); |
||||
} |
@ -0,0 +1,52 @@
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
This program is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
||||
See the COPYING file for more details. |
||||
*/ |
||||
|
||||
#ifndef FRIENDLISTLAYOUT_H |
||||
#define FRIENDLISTLAYOUT_H |
||||
|
||||
#include <QBoxLayout> |
||||
#include "src/core/corestructs.h" |
||||
#include "genericchatitemlayout.h" |
||||
|
||||
class FriendWidget; |
||||
class FriendListWidget; |
||||
|
||||
class FriendListLayout : public QVBoxLayout |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
explicit FriendListLayout(); |
||||
explicit FriendListLayout(QWidget* parent); |
||||
|
||||
void addFriendWidget(FriendWidget* widget, Status s); |
||||
void removeFriendWidget(FriendWidget* widget, Status s); |
||||
int indexOfFriendWidget(FriendWidget* widget, bool online) const; |
||||
void moveFriendWidgets(FriendListWidget* listWidget); |
||||
int friendOnlineCount() const; |
||||
int friendTotalCount() const; |
||||
|
||||
bool hasChatrooms() const; |
||||
void searchChatrooms(const QString& searchString, bool hideOnline = false, bool hideOffline = false); |
||||
|
||||
QLayout* getLayoutOnline() const; |
||||
QLayout* getLayoutOffline() const; |
||||
|
||||
private: |
||||
QLayout* getFriendLayout(Status s) const; |
||||
|
||||
GenericChatItemLayout friendOnlineLayout; |
||||
GenericChatItemLayout friendOfflineLayout; |
||||
}; |
||||
|
||||
#endif // FRIENDLISTLAYOUT_H
|
@ -0,0 +1,127 @@
@@ -0,0 +1,127 @@
|
||||
/*
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
This program is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
||||
See the COPYING file for more details. |
||||
*/ |
||||
|
||||
#include "genericchatitemlayout.h" |
||||
#include "genericchatitemwidget.h" |
||||
#include <QBoxLayout> |
||||
#include <QCollator> |
||||
#include <cassert> |
||||
|
||||
// As this layout sorts widget, extra care must be taken when inserting widgets.
|
||||
// Prefer using the build in add and remove functions for modifying widgets.
|
||||
// Inserting widgets other ways would cause this layout to be unable to sort.
|
||||
// As such, they are protected using asserts.
|
||||
|
||||
GenericChatItemLayout::GenericChatItemLayout() |
||||
: layout(new QVBoxLayout()) |
||||
{ |
||||
} |
||||
|
||||
GenericChatItemLayout::~GenericChatItemLayout() |
||||
{ |
||||
delete layout; |
||||
} |
||||
|
||||
void GenericChatItemLayout::addSortedWidget(GenericChatItemWidget* widget, int stretch, Qt::Alignment alignment) |
||||
{ |
||||
int closest = indexOfClosestSortedWidget(widget); |
||||
layout->insertWidget(closest, widget, stretch, alignment); |
||||
} |
||||
|
||||
int GenericChatItemLayout::indexOfSortedWidget(GenericChatItemWidget* widget) const |
||||
{ |
||||
if (layout->count() == 0) |
||||
return -1; |
||||
|
||||
int index = indexOfClosestSortedWidget(widget); |
||||
|
||||
if (index >= layout->count()) |
||||
return -1; |
||||
|
||||
GenericChatItemWidget* atMid = dynamic_cast<GenericChatItemWidget*>(layout->itemAt(index)->widget()); |
||||
assert(atMid != nullptr); |
||||
|
||||
if (atMid == widget) |
||||
return index; |
||||
|
||||
return -1; |
||||
} |
||||
|
||||
bool GenericChatItemLayout::existsSortedWidget(GenericChatItemWidget* widget) const |
||||
{ |
||||
return indexOfSortedWidget(widget) != -1; |
||||
} |
||||
|
||||
void GenericChatItemLayout::removeSortedWidget(GenericChatItemWidget* widget) |
||||
{ |
||||
if (layout->isEmpty()) |
||||
return; |
||||
|
||||
int index = indexOfClosestSortedWidget(widget); |
||||
|
||||
if (layout->itemAt(index) == nullptr) |
||||
return; |
||||
|
||||
GenericChatItemWidget* atMid = dynamic_cast<GenericChatItemWidget*>(layout->itemAt(index)->widget()); |
||||
assert(atMid != nullptr); |
||||
|
||||
if (atMid == widget) |
||||
layout->removeWidget(widget); |
||||
} |
||||
|
||||
void GenericChatItemLayout::search(const QString &searchString, bool hideAll) |
||||
{ |
||||
for (int index = 0; index < layout->count(); ++index) |
||||
{ |
||||
GenericChatItemWidget* widgetAt = dynamic_cast<GenericChatItemWidget*>(layout->itemAt(index)->widget()); |
||||
assert(widgetAt != nullptr); |
||||
|
||||
widgetAt->searchName(searchString, hideAll); |
||||
} |
||||
} |
||||
|
||||
QLayout* GenericChatItemLayout::getLayout() const |
||||
{ |
||||
return layout; |
||||
} |
||||
|
||||
int GenericChatItemLayout::indexOfClosestSortedWidget(GenericChatItemWidget* widget) const |
||||
{ |
||||
// Binary search: Deferred test of equality.
|
||||
int min = 0, max = layout->count(), mid; |
||||
while (min < max) |
||||
{ |
||||
mid = (max - min) / 2 + min; |
||||
GenericChatItemWidget* atMid = dynamic_cast<GenericChatItemWidget*>(layout->itemAt(mid)->widget()); |
||||
assert(atMid != nullptr); |
||||
|
||||
bool lessThan = false; |
||||
|
||||
QCollator collator; |
||||
collator.setNumericMode(true); |
||||
|
||||
int compareValue = collator.compare(atMid->getName(), widget->getName()); |
||||
|
||||
if (compareValue < 0) |
||||
lessThan = true; |
||||
else if (compareValue == 0) |
||||
lessThan = atMid < widget; // Consistent ordering.
|
||||
|
||||
if (lessThan) |
||||
min = mid + 1; |
||||
else |
||||
max = mid; |
||||
} |
||||
return min; |
||||
} |
@ -0,0 +1,43 @@
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
This program is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
This program is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
||||
|
||||
See the COPYING file for more details. |
||||
*/ |
||||
#ifndef GENERICCHATITEMLAYOUT_H |
||||
#define GENERICCHATITEMLAYOUT_H |
||||
|
||||
#include <Qt> |
||||
|
||||
class QLayout; |
||||
class QVBoxLayout; |
||||
class GenericChatItemWidget; |
||||
|
||||
class GenericChatItemLayout |
||||
{ |
||||
public: |
||||
|
||||
GenericChatItemLayout(); |
||||
~GenericChatItemLayout(); |
||||
|
||||
void addSortedWidget(GenericChatItemWidget* widget, int stretch = 0, Qt::Alignment alignment = 0); |
||||
int indexOfSortedWidget(GenericChatItemWidget* widget) const; |
||||
bool existsSortedWidget(GenericChatItemWidget* widget) const; |
||||
void removeSortedWidget(GenericChatItemWidget* widget); |
||||
void search(const QString &searchString, bool hideAll = false); |
||||
|
||||
QLayout* getLayout() const; |
||||
|
||||
private: |
||||
int indexOfClosestSortedWidget(GenericChatItemWidget* widget) const; |
||||
QVBoxLayout* layout; |
||||
}; |
||||
|
||||
#endif // GENERICCHATITEMLAYOUT_H
|
@ -0,0 +1,54 @@
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#include "genericchatitemwidget.h" |
||||
#include "src/widget/style.h" |
||||
#include "src/persistence/settings.h" |
||||
#include "src/widget/tool/croppinglabel.h" |
||||
#include <QVariant> |
||||
|
||||
GenericChatItemWidget::GenericChatItemWidget(QWidget *parent) |
||||
: QFrame(parent) |
||||
{ |
||||
setProperty("compact", Settings::getInstance().getCompactLayout()); |
||||
|
||||
nameLabel = new CroppingLabel(this); |
||||
nameLabel->setObjectName("name"); |
||||
nameLabel->setTextFormat(Qt::PlainText); |
||||
} |
||||
|
||||
bool GenericChatItemWidget::isCompact() const |
||||
{ |
||||
return compact; |
||||
} |
||||
|
||||
void GenericChatItemWidget::setCompact(bool compact) |
||||
{ |
||||
this->compact = compact; |
||||
} |
||||
|
||||
QString GenericChatItemWidget::getName() const |
||||
{ |
||||
return nameLabel->fullText(); |
||||
} |
||||
|
||||
void GenericChatItemWidget::searchName(const QString &searchString, bool hide) |
||||
{ |
||||
setVisible(!hide && getName().contains(searchString, Qt::CaseInsensitive)); |
||||
} |
@ -0,0 +1,58 @@
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
Copyright © 2015 by The qTox Project |
||||
|
||||
This file is part of qTox, a Qt-based graphical interface for Tox. |
||||
|
||||
qTox is libre software: you can redistribute it and/or modify |
||||
it under the terms of the GNU General Public License as published by |
||||
the Free Software Foundation, either version 3 of the License, or |
||||
(at your option) any later version. |
||||
|
||||
qTox is distributed in the hope that it will be useful, |
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of |
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||||
GNU General Public License for more details. |
||||
|
||||
You should have received a copy of the GNU General Public License |
||||
along with qTox. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/ |
||||
|
||||
#ifndef GENERICCHATITEMWIDGET_H |
||||
#define GENERICCHATITEMWIDGET_H |
||||
|
||||
#include <QFrame> |
||||
#include <QLabel> |
||||
|
||||
class CroppingLabel; |
||||
|
||||
class GenericChatItemWidget : public QFrame |
||||
{ |
||||
Q_OBJECT |
||||
public: |
||||
enum ItemType |
||||
{ |
||||
GroupItem, |
||||
FriendOfflineItem, |
||||
FriendOnlineItem |
||||
}; |
||||
|
||||
GenericChatItemWidget(QWidget *parent = 0); |
||||
|
||||
bool isCompact() const; |
||||
void setCompact(bool compact); |
||||
|
||||
QString getName() const; |
||||
|
||||
void searchName(const QString &searchString, bool hideAll); |
||||
|
||||
Q_PROPERTY(bool compact READ isCompact WRITE setCompact) |
||||
|
||||
protected: |
||||
CroppingLabel* nameLabel; |
||||
QLabel statusPic; |
||||
|
||||
private: |
||||
bool compact; |
||||
}; |
||||
|
||||
#endif // GENERICCHATITEMWIDGET_H
|
Loading…
Reference in new issue