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

Recent list (right click empty list to test)

This commit is contained in:
TheSpiritXIII 2015-06-11 15:27:54 -04:00 committed by tux3
parent 62873e9d71
commit 15f10c2f34
13 changed files with 736 additions and 352 deletions

View File

@ -492,7 +492,8 @@ SOURCES += \
src/widget/circlewidget.cpp \
src/widget/genericchatitemwidget.cpp \
src/widget/friendlistlayout.cpp \
src/widget/genericchatitemlayout.cpp
src/widget/genericchatitemlayout.cpp \
src/widget/categorywidget.cpp
HEADERS += \
src/audio/audio.h \
@ -534,4 +535,5 @@ HEADERS += \
src/widget/circlewidget.h \
src/widget/genericchatitemwidget.h \
src/widget/friendlistlayout.h \
src/widget/genericchatitemlayout.h
src/widget/genericchatitemlayout.h \
src/widget/categorywidget.h

View File

@ -296,6 +296,7 @@ void Settings::loadPersonnal(Profile* profile)
fp.alias = ps.value("alias").toString();
fp.autoAcceptDir = ps.value("autoAcceptDir").toString();
fp.circleID = ps.value("circle", -1).toInt();
fp.activity = ps.value("activity").toDate();
friendLst[ToxId(fp.addr).publicKey] = fp;
}
ps.endArray();
@ -467,6 +468,7 @@ void Settings::savePersonal(QString profileName, QString password)
ps.setValue("alias", frnd.alias);
ps.setValue("autoAcceptDir", frnd.autoAcceptDir);
ps.setValue("circle", frnd.circleID);
ps.setValue("activity", frnd.activity);
index++;
}
ps.endArray();
@ -1313,6 +1315,35 @@ void Settings::setFriendCircleID(const ToxId &id, int circleID)
savePersonal();
}
QDate Settings::getFriendActivity(const ToxId &id) const
{
QString key = id.publicKey;
auto it = friendLst.find(key);
if (it != friendLst.end())
return it->activity;
return QDate();
}
void Settings::setFriendActivity(const ToxId &id, const QDate &activity)
{
QString key = id.publicKey;
auto it = friendLst.find(key);
if (it != friendLst.end())
it->activity = activity;
else
{
friendProp fp;
fp.addr = key;
fp.alias = "";
fp.autoAcceptDir = "";
fp.circleID = -1;
fp.activity = activity;
friendLst[key] = fp;
}
savePersonal();
}
void Settings::removeFriendSettings(const ToxId &id)
{
QMutexLocker locker{&bigLock};

View File

@ -25,6 +25,7 @@
#include <QObject>
#include <QPixmap>
#include <QMutex>
#include <QDate>
#include "src/core/corestructs.h"
class ToxId;
@ -231,6 +232,9 @@ public:
int getFriendCircleID(const ToxId &id) const;
void setFriendCircleID(const ToxId &id, int circleID);
QDate getFriendActivity(const ToxId &id) const;
void setFriendActivity(const ToxId &id, const QDate &date);
void removeFriendSettings(const ToxId &id);
bool getFauxOfflineMessaging() const;
@ -369,6 +373,7 @@ private:
QString addr;
QString autoAcceptDir;
int circleID = -1;
QDate activity = QDate();
};
struct circleProp

View File

@ -0,0 +1,309 @@
/*
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>
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)
{
setStyleSheet(Style::getStylesheet(":/ui/chatroomWidgets/circleWidget.css"));
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());
}
bool CategoryWidget::isExpanded() const
{
return expanded;
}
void CategoryWidget::setExpanded(bool isExpanded)
{
expanded = isExpanded;
listWidget->setVisible(isExpanded);
if (isExpanded)
{
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarDownArrow.svg"));
}
else
{
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarRightArrow.svg"));
}
onExpand();
}
void CategoryWidget::setName(const QString &name)
{
nameLabel->setText(name);
if (isCompact())
nameLabel->minimizeMaximumWidth();
onSetName();
}
void CategoryWidget::editName()
{
nameLabel->editBegin();
nameLabel->setMaximumWidth(QWIDGETSIZE_MAX);
}
void CategoryWidget::addFriendWidget(FriendWidget* w, Status s)
{
listLayout->addFriendWidget(w, s);
updateStatus();
onAddFriendWidget(w);
}
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);
setCompact(_compact);
if (isCompact())
{
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(55);
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);
}

View File

@ -0,0 +1,78 @@
/*
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);
void setName(const QString &name);
void addFriendWidget(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 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

View File

@ -1,26 +1,31 @@
/*
Copyright © 2015 by The qTox Project
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
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.
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.
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/widget/style.h"
#include "src/persistence/settings.h"
#include "src/friendlist.h"
#include "src/friend.h"
#include "friendwidget.h"
#include "friendlistlayout.h"
#include "friendlistwidget.h"
#include "src/widget/tool/croppinglabel.h"
#include "widget.h"
#include <QVariant>
#include <QLabel>
@ -33,43 +38,10 @@
QHash<int, CircleWidget*> CircleWidget::circleList;
CircleWidget::CircleWidget(FriendListWidget *parent, int id_)
: GenericChatItemWidget(parent)
CircleWidget::CircleWidget(FriendListWidget* parent, int id_)
: CategoryWidget(parent)
, id(id_)
{
setStyleSheet(Style::getStylesheet(":/ui/chatroomWidgets/circleWidget.css"));
container = new QWidget(this);
container->setObjectName("circleWidgetContainer");
container->setLayoutDirection(Qt::LeftToRight);
// status text
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());
if (id != -1)
{
setName(Settings::getInstance().getCircleName(id));
@ -102,159 +74,12 @@ CircleWidget::CircleWidget(FriendListWidget *parent, int id_)
circleList[id] = this;
if (isNew)
renameCircle();
editName();
setExpanded(Settings::getInstance().getCircleExpanded(id));
updateStatus();
}
void CircleWidget::addFriendWidget(FriendWidget *w, Status s)
{
listLayout->addFriendWidget(w, s);
updateStatus();
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), id);
}
void CircleWidget::setExpanded(bool isExpanded)
{
expanded = isExpanded;
listWidget->setVisible(isExpanded);
if (isExpanded)
{
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarDownArrow.svg"));
}
else
{
statusPic.setPixmap(QPixmap(":/ui/chatArea/scrollBarRightArrow.svg"));
}
Settings::getInstance().setCircleExpanded(id, isExpanded);
}
void CircleWidget::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());
}
void CircleWidget::setName(const QString &name)
{
nameLabel->setText(name);
Settings::getInstance().setCircleName(id, name);
if (isCompact())
nameLabel->minimizeMaximumWidth();
}
void CircleWidget::renameCircle()
{
nameLabel->editBegin();
nameLabel->setMaximumWidth(QWIDGETSIZE_MAX);
}
void emitChatroomWidget(QLayout* layout, int index)
{
GenericChatroomWidget* chatWidget = dynamic_cast<GenericChatroomWidget*>(layout->itemAt(index)->widget());
if (chatWidget != nullptr)
emit chatWidget->chatroomWidgetClicked(chatWidget);
}
bool CircleWidget::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 CircleWidget::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;
}
CircleWidget* CircleWidget::getFromID(int id)
{
auto circleIt = circleList.find(id);
@ -263,77 +88,19 @@ CircleWidget* CircleWidget::getFromID(int id)
return nullptr;
}
void CircleWidget::onCompactChanged(bool _compact)
{
delete topLayout;
delete mainLayout;
topLayout = new QHBoxLayout;
topLayout->setSpacing(0);
topLayout->setMargin(0);
setProperty("compact", _compact);
if (property("compact").toBool())
{
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(55);
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 CircleWidget::contextMenuEvent(QContextMenuEvent *event)
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* 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()));
QAction* selectedItem = menu.exec(mapToGlobal(event->pos()));
if (selectedItem == renameAction)
renameCircle();
editName();
else if (selectedItem == removeAction)
{
FriendListWidget* friendList = dynamic_cast<FriendListWidget*>(parentWidget());
listLayout->moveFriendWidgets(friendList);
moveFriendWidgets(friendList);
friendList->removeCircleWidget(this);
@ -344,43 +111,36 @@ void CircleWidget::contextMenuEvent(QContextMenuEvent *event)
if (circleReplace != circleList.end())
circleReplace.value()->updateID(id);
}
setContainerAttribute(Qt::WA_UnderMouse, false);
}
void CircleWidget::mouseReleaseEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton)
setExpanded(!expanded);
}
void CircleWidget::dragEnterEvent(QDragEnterEvent *event)
void CircleWidget::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasFormat("friend"))
event->acceptProposedAction();
container->setAttribute(Qt::WA_UnderMouse, true); // Simulate hover.
Style::repolish(container);
setContainerAttribute(Qt::WA_UnderMouse, true); // Simulate hover.
}
void CircleWidget::dragLeaveEvent(QDragLeaveEvent *)
void CircleWidget::dragLeaveEvent(QDragLeaveEvent* )
{
container->setAttribute(Qt::WA_UnderMouse, false);
Style::repolish(container);
setContainerAttribute(Qt::WA_UnderMouse, false);
}
void CircleWidget::dropEvent(QDropEvent *event)
void CircleWidget::dropEvent(QDropEvent* event)
{
if (event->mimeData()->hasFormat("friend"))
{
setExpanded(true);
int friendId = event->mimeData()->data("friend").toInt();
Friend *f = FriendList::findFriend(friendId);
Friend* f = FriendList::findFriend(friendId);
assert(f != nullptr);
FriendWidget *widget = f->getFriendWidget();
FriendWidget* widget = f->getFriendWidget();
assert(widget != nullptr);
// Update old circle after moved.
CircleWidget *circleWidget = getFromID(Settings::getInstance().getFriendCircleID(f->getToxId()));
CircleWidget* circleWidget = getFromID(Settings::getInstance().getFriendCircleID(f->getToxId()));
addFriendWidget(widget, f->getStatus());
@ -390,14 +150,23 @@ void CircleWidget::dropEvent(QDropEvent *event)
Widget::getInstance()->searchCircle(circleWidget);
}
container->setAttribute(Qt::WA_UnderMouse, false);
Style::repolish(container);
setContainerAttribute(Qt::WA_UnderMouse, false);
}
}
void CircleWidget::updateStatus()
void CircleWidget::onSetName()
{
statusLabel->setText(QString::number(listLayout->friendOnlineCount()) + QStringLiteral(" / ") + QString::number(listLayout->friendTotalCount()));
Settings::getInstance().setCircleName(id, getName());
}
void CircleWidget::onExpand()
{
Settings::getInstance().setCircleExpanded(id, isExpanded());
}
void CircleWidget::onAddFriendWidget(FriendWidget* w)
{
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), id);
}
void CircleWidget::updateID(int index)
@ -407,17 +176,17 @@ void CircleWidget::updateID(int index)
id = index;
circleList[id] = this;
for (int i = 0; i < listLayout->getLayoutOnline()->count(); ++i)
for (int i = 0; i < friendOnlineLayout()->count(); ++i)
{
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(listLayout->getLayoutOnline()->itemAt(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 < listLayout->getLayoutOffline()->count(); ++i)
for (int i = 0; i < friendOfflineLayout()->count(); ++i)
{
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(listLayout->getLayoutOffline()->itemAt(i));
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOfflineLayout()->itemAt(i));
if (friendWidget != nullptr)
{
Settings::getInstance().setFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId(), id);

View File

@ -1,79 +1,52 @@
/*
Copyright © 2015 by The qTox Project
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
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.
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.
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 "genericchatitemwidget.h"
#include "src/core/corestructs.h"
#include "categorywidget.h"
class QVBoxLayout;
class QHBoxLayout;
class QLabel;
class FriendListWidget;
class FriendListLayout;
class FriendWidget;
class CircleWidget final : public GenericChatItemWidget
class CircleWidget final : public CategoryWidget
{
Q_OBJECT
public:
CircleWidget(FriendListWidget* parent = 0, int id = -1);
void addFriendWidget(FriendWidget* w, Status s);
void expand();
void setExpanded(bool isExpanded);
void updateStatus();
void setName(const QString &name);
void renameCircle();
bool cycleContacts(bool forward);
bool cycleContacts(FriendWidget* activeChatroomWidget, bool forward);
void search(const QString &searchString, bool updateAll = false, bool hideOnline = false, bool hideOffline = false);
static CircleWidget* getFromID(int id);
signals:
void renameRequested(CircleWidget* circleWidget, const QString &newName);
public slots:
void onCompactChanged(bool compact);
protected:
virtual void contextMenuEvent(QContextMenuEvent* event) final override;
virtual void mouseReleaseEvent(QMouseEvent* 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;
bool expanded = false;
FriendListLayout* listLayout;
QVBoxLayout* fullLayout;
QVBoxLayout* mainLayout = nullptr;
QLabel* statusLabel;
QFrame* lineFrame;
QWidget* container;
QHBoxLayout* topLayout = nullptr;
QWidget* listWidget;
};
#endif // CIRCLEWIDGET_H

View File

@ -1048,6 +1048,10 @@ void ChatForm::SendMessageStr(QString msg)
getOfflineMsgEngine()->registerReceipt(rec, id, ma);
msgEdit->setLastMessage(msg); //set last message only when sending it
QDate date = Settings::getInstance().getFriendActivity(f->getToxId());
if (date != QDate::currentDate())
Settings::getInstance().setFriendActivity(f->getToxId(), QDate::currentDate());
}
}

View File

@ -32,6 +32,84 @@
#include <QDragLeaveEvent>
#include <cassert>
enum Time : int
{
Today = 0,
Yesterday = 1,
ThisWeek = 2,
ThisMonth = 3,
Month1Ago = 4,
Month2Ago = 5,
Month3Ago = 6,
Month4Ago = 7,
Month5Ago = 8,
LongAgo = 9,
Never = 10
};
bool last7DaysWasLastMonth()
{
return QDate::currentDate().addDays(-7).month() == QDate::currentDate().month();
}
Time getTime(const QDate date)
{
if (date == QDate())
return Never;
QDate today = QDate::currentDate();
if (date == today)
return Today;
today = today.addDays(-1);
if (date == today)
return Yesterday;
today = today.addDays(-6);
if (date >= today)
return ThisWeek;
today = today.addDays(-today.day() + 1); // Go to the beginning of the month.
if (last7DaysWasLastMonth())
{
if (date >= today)
return ThisMonth;
today = today.addMonths(-1);
}
if (date >= today)
return Month1Ago;
today = today.addMonths(-1);
if (date >= today)
return Month2Ago;
today = today.addMonths(-1);
if (date >= today)
return Month3Ago;
today = today.addMonths(-1);
if (date >= today)
return Month4Ago;
today = today.addMonths(-1);
if (date >= today)
return Month5Ago;
return LongAgo;
}
int toIndex(Time time)
{
if (time < ThisMonth)
return time;
if (!last7DaysWasLastMonth())
return time - 1;
return time;
}
FriendListWidget::FriendListWidget(Widget* parent, bool groupsOnTop)
: QWidget(parent)
, groupsOnTop(groupsOnTop)
@ -46,13 +124,104 @@ FriendListWidget::FriendListWidget(Widget* parent, bool groupsOnTop)
groupLayout.getLayout()->setSpacing(0);
groupLayout.getLayout()->setMargin(0);
listLayout->addLayout(circleLayout.getLayout());
setMode(Name);
onGroupchatPositionChanged(groupsOnTop);
setAcceptDrops(true);
}
void FriendListWidget::setMode(Mode mode)
{
this->mode = mode;
if (mode == Name)
{
for (int i = 0; i < Settings::getInstance().getCircleCount(); ++i)
{
addCircleWidget(i);
}
listLayout->addLayout(circleLayout.getLayout());
}
else if (mode == Activity)
{
activityLayout = new QVBoxLayout(this);
CategoryWidget* categoryToday = new CategoryWidget(this);
categoryToday->setName(tr("Today", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryToday);
CategoryWidget* categoryYesterday = new CategoryWidget(this);
categoryYesterday->setName(tr("Yesterday", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryYesterday);
CategoryWidget* categoryLastWeek = new CategoryWidget(this);
categoryLastWeek->setName(tr("Last 7 days", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryLastWeek);
QDate currentDate = QDate::currentDate();
if (last7DaysWasLastMonth())
{
CategoryWidget* categoryThisMonth = new CategoryWidget(this);
categoryThisMonth ->setName(tr("This month", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryThisMonth);
currentDate = currentDate.addMonths(-1);
}
CategoryWidget* categoryLast1Month = new CategoryWidget(this);
categoryLast1Month ->setName(QDate::longMonthName(currentDate.month()));
activityLayout->addWidget(categoryLast1Month);
currentDate = currentDate.addMonths(-1);
CategoryWidget* categoryLast2Month = new CategoryWidget(this);
categoryLast2Month ->setName(QDate::longMonthName(currentDate.month()));
activityLayout->addWidget(categoryLast2Month);
currentDate = currentDate.addMonths(-1);
CategoryWidget* categoryLast3Month = new CategoryWidget(this);
categoryLast3Month ->setName(QDate::longMonthName(currentDate.month()));
activityLayout->addWidget(categoryLast3Month);
currentDate = currentDate.addMonths(-1);
CategoryWidget* categoryLast4Month = new CategoryWidget(this);
categoryLast4Month ->setName(QDate::longMonthName(currentDate.month()));
activityLayout->addWidget(categoryLast4Month);
currentDate = currentDate.addMonths(-1);
CategoryWidget* categoryLast5Month = new CategoryWidget(this);
categoryLast5Month ->setName(QDate::longMonthName(currentDate.month()));
activityLayout->addWidget(categoryLast5Month);
CategoryWidget* categoryOlder = new CategoryWidget(this);
categoryOlder->setName(tr("Older than 6 Months", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryOlder);
CategoryWidget* categoryNever = new CategoryWidget(this);
categoryNever->setName(tr("Never", "Category for sorting friends by activity"));
activityLayout->addWidget(categoryNever);
QList<Friend*> friendList = FriendList::getAllFriends();
for (Friend* contact : friendList)
{
QDate activityDate = Settings::getInstance().getFriendActivity(contact->getToxId());
Time time = getTime(activityDate);
CategoryWidget* categoryWidget = dynamic_cast<CategoryWidget*>(activityLayout->itemAt(time)->widget());
categoryWidget->addFriendWidget(contact->getFriendWidget(), contact->getStatus());
}
for (int i = 0; i < activityLayout->count(); ++i)
{
CategoryWidget* categoryWidget = dynamic_cast<CategoryWidget*>(activityLayout->itemAt(i)->widget());
categoryWidget->setVisible(categoryWidget->hasChatrooms());
}
listLayout->removeItem(listLayout->getLayoutOnline());
listLayout->removeItem(listLayout->getLayoutOffline());
listLayout->removeItem(circleLayout.getLayout());
listLayout->insertLayout(0, activityLayout);
}
}
void FriendListWidget::addGroupWidget(GroupWidget* widget)
{
groupLayout.addSortedWidget(widget);
@ -80,7 +249,7 @@ void FriendListWidget::addCircleWidget(int id)
void FriendListWidget::addCircleWidget(FriendWidget* friendWidget)
{
CircleWidget* circleWidget = createCircleWidget();
if (friendWidget != nullptr)
if (circleWidget != nullptr && friendWidget != nullptr)
{
CircleWidget* circleOriginal = CircleWidget::getFromID(Settings::getInstance().getFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId()));
@ -273,18 +442,29 @@ void FriendListWidget::dropEvent(QDropEvent* event)
void FriendListWidget::moveWidget(FriendWidget* w, Status s, bool add)
{
int circleId = Settings::getInstance().getFriendCircleID(FriendList::findFriend(w->friendId)->getToxId());
CircleWidget* circleWidget = CircleWidget::getFromID(circleId);
if (circleWidget == nullptr || add)
if (mode == Name)
{
if (circleId != -1)
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), -1);
listLayout->addFriendWidget(w, s);
return;
}
int circleId = Settings::getInstance().getFriendCircleID(FriendList::findFriend(w->friendId)->getToxId());
CircleWidget* circleWidget = CircleWidget::getFromID(circleId);
circleWidget->addFriendWidget(w, s);
if (circleWidget == nullptr || add)
{
if (circleId != -1)
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), -1);
listLayout->addFriendWidget(w, s);
return;
}
circleWidget->addFriendWidget(w, s);
}
else
{
Friend* contact = FriendList::findFriend(w->friendId);
QDate activityDate = Settings::getInstance().getFriendActivity(contact->getToxId());
Time time = getTime(activityDate);
CategoryWidget* categoryWidget = dynamic_cast<CategoryWidget*>(activityLayout->itemAt(time)->widget());
categoryWidget->addFriendWidget(contact->getFriendWidget(), contact->getStatus());
}
}
// update widget after add/delete/hide/show
@ -297,6 +477,15 @@ void FriendListWidget::reDraw()
CircleWidget* FriendListWidget::createCircleWidget(int id)
{
if (id == -1)
{
id = Settings::getInstance().addCircle();
Settings::getInstance().setCircleName(id, tr("Circle #%1").arg(id + 1));
}
if (mode == Activity)
return nullptr;
CircleWidget* circleWidget = new CircleWidget(this, id);
circleLayout.addSortedWidget(circleWidget);
connect(this, &FriendListWidget::onCompactChanged, circleWidget, &CircleWidget::onCompactChanged);

View File

@ -38,7 +38,14 @@ class FriendListWidget : public QWidget
{
Q_OBJECT
public:
enum Mode : uint8_t
{
Name,
Activity,
};
explicit FriendListWidget(Widget* parent, bool groupsOnTop = true);
void setMode(Mode mode);
void addGroupWidget(GroupWidget* widget);
void addFriendWidget(FriendWidget* w, Status s, int circleIndex);
@ -69,10 +76,12 @@ private:
CircleWidget* createCircleWidget(int id = -1);
QLayout* nextLayout(QLayout* layout, bool forward) const;
Mode mode;
bool groupsOnTop;
FriendListLayout* listLayout;
GenericChatItemLayout circleLayout;
GenericChatItemLayout groupLayout;
QVBoxLayout* activityLayout;
};
#endif // FRIENDLISTWIDGET_H

View File

@ -1,15 +1,20 @@
/*
Copyright © 2015 by The qTox Project
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
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.
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.
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"

View File

@ -1,15 +1,20 @@
/*
Copyright © 2015 by The qTox Project
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
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.
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.
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

View File

@ -234,11 +234,6 @@ void Widget::init()
if (!Settings::getInstance().getShowSystemTray())
show();
for (int i = 0; i < Settings::getInstance().getCircleCount(); ++i)
{
contactListWidget->addCircleWidget(i);
}
}
bool Widget::eventFilter(QObject *obj, QEvent *event)
@ -775,6 +770,11 @@ void Widget::onFriendMessageReceived(int friendId, const QString& message, bool
windowTitle += " (" + f->getFriendWidget()->getStatusString() + ")";
setWindowTitle(windowTitle);
}
QDate activity = Settings::getInstance().getFriendActivity(f->getToxId());
qDebug() << "YOLOOLOLOLO" << activity;
if (activity != QDate::currentDate())
Settings::getInstance().setFriendActivity(f->getToxId(), QDate::currentDate());
}
void Widget::onReceiptRecieved(int friendId, int receipt)
@ -1468,12 +1468,17 @@ void Widget::friendListContextMenu(const QPoint &pos)
{
QMenu menu(this);
QAction *addCircleAction = menu.addAction(tr("Add new circle..."));
QAction *switchMode = menu.addAction("Switch to Recent (BETA)");
QAction *chosenAction = menu.exec(ui->friendList->mapToGlobal(pos));
if (chosenAction == addCircleAction)
{
contactListWidget->addCircleWidget();
}
else if (chosenAction == switchMode)
{
contactListWidget->setMode(FriendListWidget::Activity);
}
}
void Widget::setActiveToolMenuButton(ActiveToolMenuButton newActiveButton)