Browse Source

Recent list (right click empty list to test)

pull/2157/merge
TheSpiritXIII 10 years ago committed by tux3
parent
commit
15f10c2f34
  1. 6
      qtox.pro
  2. 31
      src/persistence/settings.cpp
  3. 5
      src/persistence/settings.h
  4. 309
      src/widget/categorywidget.cpp
  5. 78
      src/widget/categorywidget.h
  6. 327
      src/widget/circlewidget.cpp
  7. 57
      src/widget/circlewidget.h
  8. 4
      src/widget/form/chatform.cpp
  9. 211
      src/widget/friendlistwidget.cpp
  10. 9
      src/widget/friendlistwidget.h
  11. 13
      src/widget/genericchatitemwidget.cpp
  12. 13
      src/widget/genericchatitemwidget.h
  13. 15
      src/widget/widget.cpp

6
qtox.pro

@ -492,7 +492,8 @@ SOURCES += \ @@ -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 += \ @@ -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

31
src/persistence/settings.cpp

@ -296,6 +296,7 @@ void Settings::loadPersonnal(Profile* profile) @@ -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) @@ -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) @@ -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};

5
src/persistence/settings.h

@ -25,6 +25,7 @@ @@ -25,6 +25,7 @@
#include <QObject>
#include <QPixmap>
#include <QMutex>
#include <QDate>
#include "src/core/corestructs.h"
class ToxId;
@ -231,6 +232,9 @@ public: @@ -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: @@ -369,6 +373,7 @@ private:
QString addr;
QString autoAcceptDir;
int circleID = -1;
QDate activity = QDate();
};
struct circleProp

309
src/widget/categorywidget.cpp

@ -0,0 +1,309 @@ @@ -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);
}

78
src/widget/categorywidget.h

@ -0,0 +1,78 @@ @@ -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

327
src/widget/circlewidget.cpp

@ -1,26 +1,31 @@ @@ -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,
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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file 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 @@ @@ -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_) @@ -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) @@ -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) @@ -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) @@ -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()
{
Settings::getInstance().setCircleName(id, getName());
}
void CircleWidget::onExpand()
{
Settings::getInstance().setCircleExpanded(id, isExpanded());
}
void CircleWidget::onAddFriendWidget(FriendWidget* w)
{
statusLabel->setText(QString::number(listLayout->friendOnlineCount()) + QStringLiteral(" / ") + QString::number(listLayout->friendTotalCount()));
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), id);
}
void CircleWidget::updateID(int index)
@ -407,17 +176,17 @@ 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);

57
src/widget/circlewidget.h

@ -1,79 +1,52 @@ @@ -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,
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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file 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"
class QVBoxLayout;
class QHBoxLayout;
class QLabel;
class FriendListWidget;
class FriendListLayout;
class FriendWidget;
#include "categorywidget.h"
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

4
src/widget/form/chatform.cpp

@ -1048,6 +1048,10 @@ void ChatForm::SendMessageStr(QString msg) @@ -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());
}
}

211
src/widget/friendlistwidget.cpp

@ -32,6 +32,84 @@ @@ -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) @@ -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) @@ -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) @@ -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 (mode == Name)
{
int circleId = Settings::getInstance().getFriendCircleID(FriendList::findFriend(w->friendId)->getToxId());
CircleWidget* circleWidget = CircleWidget::getFromID(circleId);
if (circleWidget == nullptr || add)
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
{
if (circleId != -1)
Settings::getInstance().setFriendCircleID(FriendList::findFriend(w->friendId)->getToxId(), -1);
listLayout->addFriendWidget(w, s);
return;
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());
}
circleWidget->addFriendWidget(w, s);
}
// update widget after add/delete/hide/show
@ -297,6 +477,15 @@ void FriendListWidget::reDraw() @@ -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);

9
src/widget/friendlistwidget.h

@ -38,7 +38,14 @@ class FriendListWidget : public QWidget @@ -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: @@ -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

13
src/widget/genericchatitemwidget.cpp

@ -1,15 +1,20 @@ @@ -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,
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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file 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"

13
src/widget/genericchatitemwidget.h

@ -1,15 +1,20 @@ @@ -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,
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.
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
See the COPYING file 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

15
src/widget/widget.cpp

@ -234,11 +234,6 @@ void Widget::init() @@ -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 @@ -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) @@ -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)

Loading…
Cancel
Save