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

Merge branch 'multiwindow'

This commit is contained in:
tux3 2015-09-12 19:08:09 +02:00
commit 7dd66213cb
No known key found for this signature in database
GPG Key ID: 7E086DD661263264
48 changed files with 2425 additions and 905 deletions

View File

@ -495,7 +495,10 @@ SOURCES += \
src/widget/friendlistlayout.cpp \
src/widget/genericchatitemlayout.cpp \
src/widget/categorywidget.cpp \
src/widget/tool/removefrienddialog.cpp
src/widget/tool/removefrienddialog.cpp \
src/widget/contentlayout.cpp \
src/widget/contentdialog.cpp \
src/widget/tool/activatedialog.cpp
HEADERS += \
src/audio/audio.h \
@ -539,4 +542,7 @@ HEADERS += \
src/widget/friendlistlayout.h \
src/widget/genericchatitemlayout.h \
src/widget/categorywidget.h \
src/widget/contentlayout.h \
src/widget/contentdialog.h \
src/widget/tool/activatedialog.h \
src/widget/tool/removefrienddialog.h

View File

@ -84,6 +84,7 @@ void Group::updatePeer(int peerId, QString name)
widget->onUserListChanged();
chatForm->onUserListChanged();
emit userListChanged(getGroupWidget());
}
void Group::setName(const QString& name)
@ -91,7 +92,14 @@ void Group::setName(const QString& name)
chatForm->setName(name);
if (widget->isActive())
GUI::setWindowTitle(name);
GUI::setWindowTitle(name);
emit titleChanged(this->getGroupWidget());
}
QString Group::getName() const
{
return widget->getName();
}
void Group::regeneratePeerList()
@ -117,6 +125,7 @@ void Group::regeneratePeerList()
widget->onUserListChanged();
chatForm->onUserListChanged();
emit userListChanged(getGroupWidget());
}
bool Group::isAvGroupchat() const

View File

@ -61,9 +61,14 @@ public:
void updatePeer(int peerId, QString newName);
void setName(const QString& name);
QString getName() const;
QString resolveToxId(const ToxId &id) const;
signals:
void titleChanged(GroupWidget* widget);
void userListChanged(GroupWidget* widget);
private:
GroupWidget* widget;
GroupChatForm* chatForm;

View File

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>775</width>
<height>537</height>
<height>420</height>
</rect>
</property>
<property name="minimumSize">
@ -1288,555 +1288,6 @@ QSplitter:handle{
</item>
</layout>
</widget>
<widget class="QWidget" name="mainPanel" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>170</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>170</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Button">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Light">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Midlight">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Dark">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Mid">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>170</red>
<green>170</green>
<blue>170</blue>
</color>
</brush>
</colorrole>
<colorrole role="Text">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="BrightText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ButtonText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
<colorrole role="Base">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Window">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="Shadow">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
<colorrole role="AlternateBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>255</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipBase">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>255</red>
<green>255</green>
<blue>220</blue>
</color>
</brush>
</colorrole>
<colorrole role="ToolTipText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>0</red>
<green>0</green>
<blue>0</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="autoFillBackground">
<bool>true</bool>
</property>
<layout class="QVBoxLayout" name="verticalLayout_2" stretch="0,0,0">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QWidget" name="mainHead" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="baseSize">
<size>
<width>0</width>
<height>57</height>
</size>
</property>
<property name="mouseTracking">
<bool>true</bool>
</property>
</widget>
</item>
<item>
<widget class="QFrame" name="mainHLine">
<property name="minimumSize">
<size>
<width>0</width>
<height>1</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>1</height>
</size>
</property>
<property name="palette">
<palette>
<active>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>193</red>
<green>193</green>
<blue>193</blue>
</color>
</brush>
</colorrole>
</active>
<inactive>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>193</red>
<green>193</green>
<blue>193</blue>
</color>
</brush>
</colorrole>
</inactive>
<disabled>
<colorrole role="WindowText">
<brush brushstyle="SolidPattern">
<color alpha="255">
<red>127</red>
<green>127</green>
<blue>127</blue>
</color>
</brush>
</colorrole>
</disabled>
</palette>
</property>
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="mainContent" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>375</width>
<height>0</height>
</size>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
</layout>

View File

@ -42,6 +42,8 @@
#ifdef Q_OS_MAC
#include <QWindow>
#include <QMenuBar>
#include <QActionGroup>
#include <QSignalMapper>
#endif
static Nexus* nexus{nullptr};
@ -89,26 +91,44 @@ void Nexus::start()
qRegisterMetaType<ToxFile::FileDirection>("ToxFile::FileDirection");
qRegisterMetaType<std::shared_ptr<VideoFrame>>("std::shared_ptr<VideoFrame>");
loginScreen = new LoginScreen();
#ifdef Q_OS_MAC
globalMenuBar = new QMenuBar(0);
dockMenu = new QMenu(globalMenuBar);
windowMenu = globalMenuBar->addMenu(tr("Window"));
viewMenu = globalMenuBar->addMenu(QString());
windowMenu = globalMenuBar->addMenu(QString());
globalMenuBar->addAction(windowMenu->menuAction());
QAction* minimizeAction = Nexus::getInstance().windowMenu->addAction(tr("Minimize"));
fullscreenAction = viewMenu->addAction(QString());
fullscreenAction->setShortcut(QKeySequence::FullScreen);
connect(fullscreenAction, &QAction::triggered, this, &Nexus::toggleFullscreen);
minimizeAction = windowMenu->addAction(QString());
minimizeAction->setShortcut(Qt::CTRL + Qt::Key_M);
connect(minimizeAction, &QAction::triggered, [minimizeAction]()
connect(minimizeAction, &QAction::triggered, [this]()
{
minimizeAction->setEnabled(false);
QApplication::focusWindow()->showMinimized();
});
Nexus::getInstance().windowMenu->addSeparator();
windowMenu->addSeparator();
frontAction = windowMenu->addAction(QString());
connect(frontAction, &QAction::triggered, this, &Nexus::bringAllToFront);
QAction* quitAction = new QAction(globalMenuBar);
quitAction->setMenuRole(QAction::QuitRole);
connect(quitAction, &QAction::triggered, qApp, &QApplication::quit);
#endif
loginScreen = new LoginScreen();
windowMapper = new QSignalMapper(this);
connect(windowMapper, SIGNAL(mapped(QObject*)), this, SLOT(onOpenWindow(QObject*)));
connect(loginScreen, &LoginScreen::windowStateChanged, this, &Nexus::onWindowStateChanged);
retranslateUi();
#endif
if (profile)
showMainGUI();
@ -278,3 +298,131 @@ bool Nexus::tryRemoveFile(const QString& filepath)
tmp.remove();
return writable;
}
#ifdef Q_OS_MAC
void Nexus::retranslateUi()
{
viewMenu->menuAction()->setText(tr("View", "OS X Menu bar"));
windowMenu->menuAction()->setText(tr("Window", "OS X Menu bar"));
minimizeAction->setText(tr("Minimize", "OS X Menu bar"));
frontAction->setText((tr("Bring All to Front", "OS X Menu bar")));
}
void Nexus::onWindowStateChanged(Qt::WindowStates state)
{
minimizeAction->setEnabled(QApplication::activeWindow() != nullptr);
if (QApplication::activeWindow() != nullptr && sender() == QApplication::activeWindow())
{
if (state & Qt::WindowFullScreen)
minimizeAction->setEnabled(false);
if (state & Qt::WindowFullScreen)
fullscreenAction->setText(tr("Exit Fullscreen"));
else
fullscreenAction->setText(tr("Enter Fullscreen"));
updateWindows();
}
updateWindowsStates();
}
void Nexus::updateWindows()
{
updateWindowsArg(nullptr);
}
void Nexus::updateWindowsArg(QWindow* closedWindow)
{
QWindowList windowList = QApplication::topLevelWindows();
delete windowActions;
windowActions = new QActionGroup(this);
windowMenu->addSeparator();
QAction* dockLast;
if (dockMenu->actions().count() != 0)
dockLast = dockMenu->actions().first();
else
dockLast = nullptr;
QWindow* activeWindow;
if (QApplication::activeWindow())
activeWindow = QApplication::activeWindow()->windowHandle();
else
activeWindow = nullptr;
for (int i = 0; i < windowList.size(); ++i)
{
if (closedWindow == windowList[i])
continue;
QAction* action = windowActions->addAction(windowList[i]->title());
action->setCheckable(true);
action->setChecked(windowList[i] == activeWindow);
connect(action, SIGNAL(triggered()), windowMapper, SLOT(map()));
windowMapper->setMapping(action, windowList[i]);
windowMenu->addAction(action);
dockMenu->insertAction(dockLast, action);
}
if (!dockLast->isSeparator())
dockMenu->insertSeparator(dockLast);
}
void Nexus::updateWindowsClosed()
{
updateWindowsArg(static_cast<QWidget*>(sender())->windowHandle());
}
void Nexus::updateWindowsStates()
{
bool exists = false;
QWindowList windowList = QApplication::topLevelWindows();
for (QWindow* window : windowList)
{
if (!(window->windowState() & Qt::WindowMinimized))
{
exists = true;
break;
}
}
frontAction->setEnabled(exists);
}
void Nexus::onOpenWindow(QObject* object)
{
QWindow* window = static_cast<QWindow*>(object);
if (window->windowState() & QWindow::Minimized)
window->showNormal();
window->raise();
window->requestActivate();
}
void Nexus::toggleFullscreen()
{
QWidget* window = QApplication::activeWindow();
if (window->isFullScreen())
window->showNormal();
else
window->showFullScreen();
}
void Nexus::bringAllToFront()
{
QWindowList windowList = QApplication::topLevelWindows();
QWindow* focused = QApplication::focusWindow();
for (QWindow* window : windowList)
window->raise();
focused->raise();
}
#endif

View File

@ -32,6 +32,10 @@ class Core;
#ifdef Q_OS_MAC
class QMenuBar;
class QMenu;
class QAction;
class QWindow;
class QActionGroup;
class QSignalMapper;
#endif
/// This class is in charge of connecting various systems together
@ -59,7 +63,28 @@ public:
#ifdef Q_OS_MAC
QMenuBar* globalMenuBar;
QMenu* viewMenu;
QMenu* windowMenu;
QAction* minimizeAction;
QAction* fullscreenAction;
QAction* frontAction;
QMenu* dockMenu;
public slots:
void retranslateUi();
void onWindowStateChanged(Qt::WindowStates state);
void updateWindows();
void updateWindowsClosed();
void updateWindowsStates();
void onOpenWindow(QObject* object);
void toggleFullscreen();
void bringAllToFront();
private:
void updateWindowsArg(QWindow *closedWindow);
QSignalMapper* windowMapper;
QActionGroup* windowActions = nullptr;
#endif
private:

View File

@ -174,6 +174,8 @@ void Settings::loadGlobal()
globalAutoAcceptDir = s.value("globalAutoAcceptDir",
QStandardPaths::locate(QStandardPaths::HomeLocation, QString(), QStandardPaths::LocateDirectory)
).toString();
separateWindow = s.value("separateWindow", false).toBool();
dontGroupWindows = s.value("dontGroupWindows", true).toBool();
groupchatPosition = s.value("groupchatPosition", true).toBool();
s.endGroup();
@ -216,6 +218,9 @@ void Settings::loadGlobal()
windowGeometry = s.value("windowGeometry", QByteArray()).toByteArray();
windowState = s.value("windowState", QByteArray()).toByteArray();
splitterState = s.value("splitterState", QByteArray()).toByteArray();
dialogGeometry = s.value("dialogGeometry", QByteArray()).toByteArray();
dialogSplitterState = s.value("dialogSplitterState", QByteArray()).toByteArray();
dialogSettingsGeometry = s.value("dialogSettingsGeometry", QByteArray()).toByteArray();
s.endGroup();
s.beginGroup("Audio");
@ -375,6 +380,8 @@ void Settings::saveGlobal()
s.setValue("notifySound", notifySound);
s.setValue("groupAlwaysNotify", groupAlwaysNotify);
s.setValue("fauxOfflineMessaging", fauxOfflineMessaging);
s.setValue("separateWindow", separateWindow);
s.setValue("dontGroupWindows", dontGroupWindows);
s.setValue("groupchatPosition", groupchatPosition);
s.setValue("autoSaveEnabled", autoSaveEnabled);
s.setValue("globalAutoAcceptDir", globalAutoAcceptDir);
@ -410,6 +417,9 @@ void Settings::saveGlobal()
s.setValue("windowGeometry", windowGeometry);
s.setValue("windowState", windowState);
s.setValue("splitterState", splitterState);
s.setValue("dialogGeometry", dialogGeometry);
s.setValue("dialogSplitterState", dialogSplitterState);
s.setValue("dialogSettingsGeometry", dialogSettingsGeometry);
s.endGroup();
s.beginGroup("Audio");
@ -746,7 +756,7 @@ void Settings::setStatusChangeNotificationEnabled(bool newValue)
bool Settings::getShowInFront() const
{
QMutexLocker locker{&bigLock};
return showInFront;
return showInFront;
}
void Settings::setShowInFront(bool newValue)
@ -1090,6 +1100,42 @@ void Settings::setSplitterState(const QByteArray &value)
splitterState = value;
}
QByteArray Settings::getDialogGeometry() const
{
QMutexLocker locker{&bigLock};
return dialogGeometry;
}
void Settings::setDialogGeometry(const QByteArray &value)
{
QMutexLocker locker{&bigLock};
dialogGeometry = value;
}
QByteArray Settings::getDialogSplitterState() const
{
QMutexLocker locker{&bigLock};
return dialogSplitterState;
}
void Settings::setDialogSplitterState(const QByteArray &value)
{
QMutexLocker locker{&bigLock};
dialogSplitterState = value;
}
QByteArray Settings::getDialogSettingsGeometry() const
{
QMutexLocker locker{&bigLock};
return dialogSettingsGeometry;
}
void Settings::setDialogSettingsGeometry(const QByteArray &value)
{
QMutexLocker locker{&bigLock};
dialogSettingsGeometry = value;
}
bool Settings::isMinimizeOnCloseEnabled() const
{
QMutexLocker locker{&bigLock};
@ -1324,6 +1370,30 @@ void Settings::setCompactLayout(bool value)
compactLayout = value;
}
bool Settings::getSeparateWindow() const
{
QMutexLocker locker{&bigLock};
return separateWindow;
}
void Settings::setSeparateWindow(bool value)
{
QMutexLocker locker{&bigLock};
separateWindow = value;
}
bool Settings::getDontGroupWindows() const
{
QMutexLocker locker{&bigLock};
return dontGroupWindows;
}
void Settings::setDontGroupWindows(bool value)
{
QMutexLocker locker{&bigLock};
dontGroupWindows = value;
}
bool Settings::getGroupchatPosition() const
{
QMutexLocker locker{&bigLock};

View File

@ -217,6 +217,15 @@ public:
QByteArray getSplitterState() const;
void setSplitterState(const QByteArray &value);
QByteArray getDialogGeometry() const;
void setDialogGeometry(const QByteArray& value);
QByteArray getDialogSplitterState() const;
void setDialogSplitterState(const QByteArray &value);
QByteArray getDialogSettingsGeometry() const;
void setDialogSettingsGeometry(const QByteArray& value);
QString getFriendAdress(const QString &publicKey) const;
void updateFriendAdress(const QString &newAddr);
@ -237,6 +246,12 @@ public:
bool getCompactLayout() const;
void setCompactLayout(bool compact);
bool getSeparateWindow() const;
void setSeparateWindow(bool value);
bool getDontGroupWindows() const;
void setDontGroupWindows(bool value);
bool getGroupchatPosition() const;
void setGroupchatPosition(bool value);
@ -295,6 +310,8 @@ private:
bool fauxOfflineMessaging;
bool compactLayout;
bool groupchatPosition;
bool separateWindow;
bool dontGroupWindows;
bool enableIPv6;
QString translation;
bool makeToxPortable;
@ -334,6 +351,9 @@ private:
QByteArray windowGeometry;
QByteArray windowState;
QByteArray splitterState;
QByteArray dialogGeometry;
QByteArray dialogSplitterState;
QByteArray dialogSettingsGeometry;
QString style;
bool showSystemTray;

View File

@ -24,6 +24,7 @@
#include "src/persistence/settings.h"
#include "src/friendlist.h"
#include "src/friend.h"
#include "src/widget/contentdialog.h"
#include "widget.h"
#include <QVariant>
#include <QBoxLayout>
@ -84,29 +85,66 @@ 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* openAction = nullptr;
if (friendOfflineLayout()->count() + friendOnlineLayout()->count() > 0)
openAction = menu.addAction(tr("Open all in new window"));
QAction* selectedItem = menu.exec(mapToGlobal(event->pos()));
if (selectedItem == renameAction)
if (selectedItem)
{
editName();
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);
}
else if (selectedItem == openAction)
{
ContentDialog* dialog = Widget::getInstance()->createContentDialog();
for (int i = 0; i < friendOnlineLayout()->count(); ++i)
{
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOnlineLayout()->itemAt(i)->widget());
if (friendWidget != nullptr)
{
Friend* f = friendWidget->getFriend();
dialog->addFriend(friendWidget->friendId, f->getDisplayedName());
}
}
for (int i = 0; i < friendOfflineLayout()->count(); ++i)
{
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOfflineLayout()->itemAt(i)->widget());
if (friendWidget != nullptr)
{
Friend* f = friendWidget->getFriend();
dialog->addFriend(friendWidget->friendId, f->getDisplayedName());
}
}
dialog->show();
dialog->ensureSplitterVisible();
}
}
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);
}
@ -181,14 +219,14 @@ void CircleWidget::updateID(int index)
for (int i = 0; i < friendOnlineLayout()->count(); ++i)
{
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOnlineLayout()->itemAt(i));
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOnlineLayout()->itemAt(i)->widget());
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));
FriendWidget* friendWidget = dynamic_cast<FriendWidget*>(friendOfflineLayout()->itemAt(i)->widget());
if (friendWidget != nullptr)
Settings::getInstance().setFriendCircleID(FriendList::findFriend(friendWidget->friendId)->getToxId(), id);

View File

@ -0,0 +1,769 @@
/*
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 "contentdialog.h"
#include "contentlayout.h"
#include "friendwidget.h"
#include "groupwidget.h"
#include "style.h"
#include "widget.h"
#include "tool/adjustingscrollarea.h"
#include "src/persistence/settings.h"
#include "src/friend.h"
#include "src/friendlist.h"
#include "src/group.h"
#include "src/grouplist.h"
#include "src/widget/form/chatform.h"
#include "src/core/core.h"
#include "src/widget/friendlistlayout.h"
#include "src/widget/form/settingswidget.h"
#include "src/widget/translator.h"
#include <QBoxLayout>
#include <QSplitter>
#include <QGuiApplication>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QShortcut>
ContentDialog* ContentDialog::currentDialog = nullptr;
QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>> ContentDialog::friendList;
QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>> ContentDialog::groupList;
ContentDialog::ContentDialog(SettingsWidget* settingsWidget, QWidget* parent)
: ActivateDialog(parent, Qt::Window)
, activeChatroomWidget(nullptr)
, settingsWidget(settingsWidget)
{
QVBoxLayout* boxLayout = new QVBoxLayout(this);
boxLayout->setMargin(0);
boxLayout->setSpacing(0);
splitter = new QSplitter(this);
setStyleSheet("QSplitter{color: rgb(255, 255, 255);background-color: rgb(255, 255, 255);alternate-background-color: rgb(255, 255, 255);border-color: rgb(255, 255, 255);gridline-color: rgb(255, 255, 255);selection-color: rgb(255, 255, 255);selection-background-color: rgb(255, 255, 255);}QSplitter:handle{color: rgb(255, 255, 255);background-color: rgb(255, 255, 255);}");
splitter->setHandleWidth(6);
QWidget *friendWidget = new QWidget();
friendWidget->setSizePolicy(QSizePolicy::Minimum, QSizePolicy::Fixed);
friendWidget->setAutoFillBackground(true);
friendLayout = new FriendListLayout();
friendLayout->setMargin(0);
friendLayout->setSpacing(0);
friendWidget->setLayout(friendLayout);
onGroupchatPositionChanged(Settings::getInstance().getGroupchatPosition());
QScrollArea *friendScroll = new QScrollArea(this);
friendScroll->setMinimumWidth(220);
friendScroll->setFrameStyle(QFrame::NoFrame);
friendScroll->setLayoutDirection(Qt::RightToLeft);
friendScroll->setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
friendScroll->setStyleSheet(Style::getStylesheet(":/ui/friendList/friendList.css"));
friendScroll->setWidgetResizable(true);
friendScroll->setWidget(friendWidget);
QWidget* contentWidget = new QWidget(this);
contentWidget->setAutoFillBackground(true);
contentLayout = new ContentLayout(contentWidget);
contentLayout->setMargin(0);
contentLayout->setSpacing(0);
splitter->addWidget(friendScroll);
splitter->addWidget(contentWidget);
splitter->setStretchFactor(1, 1);
splitter->setCollapsible(1, false);
boxLayout->addWidget(splitter);
connect(splitter, &QSplitter::splitterMoved, this, &ContentDialog::saveSplitterState);
connect(settingsWidget, &SettingsWidget::groupchatPositionToggled, this, &ContentDialog::onGroupchatPositionChanged);
setMinimumSize(500, 220);
setAttribute(Qt::WA_DeleteOnClose);
QByteArray geometry = Settings::getInstance().getDialogGeometry();
if (!geometry.isNull())
restoreGeometry(geometry);
else
resize(720, 400);
QByteArray splitterState = Settings::getInstance().getDialogSplitterState();
if (!splitterState.isNull())
splitter->restoreState(splitterState);
currentDialog = this;
setAcceptDrops(true);
new QShortcut(Qt::CTRL + Qt::Key_Q, this, SLOT(close()));
new QShortcut(Qt::CTRL + Qt::SHIFT + Qt::Key_Tab, this, SLOT(previousContact()));
new QShortcut(Qt::CTRL + Qt::Key_Tab, this, SLOT(nextContact()));
new QShortcut(Qt::CTRL + Qt::Key_PageUp, this, SLOT(previousContact()));
new QShortcut(Qt::CTRL + Qt::Key_PageDown, this, SLOT(nextContact()));
connect(Core::getInstance(), &Core::usernameSet, this, &ContentDialog::updateTitleUsername);
Translator::registerHandler(std::bind(&ContentDialog::retranslateUi, this), this);
}
ContentDialog::~ContentDialog()
{
if (currentDialog == this)
currentDialog = nullptr;
auto friendIt = friendList.begin();
while (friendIt != friendList.end())
{
if (std::get<0>(friendIt.value()) == this)
{
friendIt = friendList.erase(friendIt);
continue;
}
++friendIt;
}
auto groupIt = groupList.begin();
while (groupIt != groupList.end())
{
if (std::get<0>(groupIt.value()) == this)
{
groupIt = groupList.erase(groupIt);
continue;
}
++groupIt;
}
Translator::unregister(this);
}
FriendWidget* ContentDialog::addFriend(int friendId, QString id)
{
FriendWidget* friendWidget = new FriendWidget(friendId, id);
friendLayout->addFriendWidget(friendWidget, FriendList::findFriend(friendId)->getStatus());
Friend* frnd = friendWidget->getFriend();
connect(frnd, &Friend::displayedNameChanged, this, &ContentDialog::updateFriendWidget);
connect(settingsWidget, &SettingsWidget::compactToggled, friendWidget, &FriendWidget::compactChange);
connect(friendWidget, &FriendWidget::chatroomWidgetClicked, this, &ContentDialog::onChatroomWidgetClicked);
connect(friendWidget, SIGNAL(chatroomWidgetClicked(GenericChatroomWidget*)), frnd->getChatForm(), SLOT(focusInput()));
connect(Core::getInstance(), &Core::friendAvatarChanged, friendWidget, &FriendWidget::onAvatarChange);
connect(Core::getInstance(), &Core::friendAvatarRemoved, friendWidget, &FriendWidget::onAvatarRemoved);
ContentDialog* lastDialog = getFriendDialog(friendId);
if (lastDialog != nullptr)
lastDialog->removeFriend(friendId);
friendList.insert(friendId, std::make_tuple(this, friendWidget));
onChatroomWidgetClicked(friendWidget, false);
return friendWidget;
}
GroupWidget* ContentDialog::addGroup(int groupId, const QString& name)
{
GroupWidget* groupWidget = new GroupWidget(groupId, name);
groupLayout.addSortedWidget(groupWidget);
Group* group = groupWidget->getGroup();
connect(group, &Group::titleChanged, this, &ContentDialog::updateGroupWidget);
connect(group, &Group::userListChanged, this, &ContentDialog::updateGroupWidget);
connect(settingsWidget, &SettingsWidget::compactToggled, groupWidget, &GroupWidget::compactChange);
connect(groupWidget, &GroupWidget::chatroomWidgetClicked, this, &ContentDialog::onChatroomWidgetClicked);
ContentDialog* lastDialog = getGroupDialog(groupId);
if (lastDialog != nullptr)
lastDialog->removeGroup(groupId);
groupList.insert(groupId, std::make_tuple(this, groupWidget));
onChatroomWidgetClicked(groupWidget, false);
return groupWidget;
}
void ContentDialog::removeFriend(int friendId)
{
auto iter = friendList.find(friendId);
if (iter == friendList.end())
return;
FriendWidget* chatroomWidget = static_cast<FriendWidget*>(std::get<1>(iter.value()));
disconnect(chatroomWidget->getFriend(), &Friend::displayedNameChanged, this, &ContentDialog::updateFriendWidget);
if (activeChatroomWidget == chatroomWidget)
{
// Need to find replacement to show here instead.
cycleContacts(true, false);
}
friendLayout->removeFriendWidget(chatroomWidget, Status::Offline);
friendLayout->removeFriendWidget(chatroomWidget, Status::Online);
chatroomWidget->deleteLater();
friendList.remove(friendId);
if (chatroomWidgetCount() == 0)
{
contentLayout->clear();
activeChatroomWidget = nullptr;
deleteLater();
}
else
{
update();
}
}
void ContentDialog::removeGroup(int groupId)
{
Group* group = GroupList::findGroup(groupId);
if (group)
{
disconnect(group, &Group::titleChanged, this, &ContentDialog::updateGroupWidget);
disconnect(group, &Group::userListChanged, this, &ContentDialog::updateGroupWidget);
}
auto iter = groupList.find(groupId);
if (iter == groupList.end())
return;
GenericChatroomWidget* chatroomWidget = std::get<1>(iter.value());
if (activeChatroomWidget == chatroomWidget)
{
// Need to find replacement to show here instead.
cycleContacts(true, false);
}
groupLayout.removeSortedWidget(chatroomWidget);
chatroomWidget->deleteLater();
groupList.remove(groupId);
if (chatroomWidgetCount() == 0)
{
contentLayout->clear();
activeChatroomWidget = nullptr;
deleteLater();
}
else
{
update();
}
}
bool ContentDialog::hasFriendWidget(int friendId, GenericChatroomWidget* chatroomWidget)
{
return hasWidget(friendId, chatroomWidget, friendList);
}
bool ContentDialog::hasGroupWidget(int groupId, GenericChatroomWidget *chatroomWidget)
{
return hasWidget(groupId, chatroomWidget, groupList);
}
int ContentDialog::chatroomWidgetCount() const
{
return friendLayout->friendTotalCount() + groupLayout.getLayout()->count();
}
void ContentDialog::ensureSplitterVisible()
{
if (splitter->sizes().at(0) == 0)
splitter->setSizes({1, 1});
update();
}
void ContentDialog::cycleContacts(bool forward, bool loop)
{
Settings::getInstance().getGroupchatPosition();
int index;
QLayout* currentLayout;
if (activeChatroomWidget->getFriend())
{
currentLayout = friendLayout->getLayoutOnline();
index = friendLayout->indexOfFriendWidget(activeChatroomWidget, true);
if (index == -1)
{
currentLayout = friendLayout->getLayoutOffline();
index = friendLayout->indexOfFriendWidget(activeChatroomWidget, false);
}
}
else
{
currentLayout = groupLayout.getLayout();
index = groupLayout.indexOfSortedWidget(activeChatroomWidget);
}
if (!loop && index == currentLayout->count() - 1)
{
bool groupsOnTop = Settings::getInstance().getGroupchatPosition();
bool offlineEmpty = friendLayout->getLayoutOffline()->count() == 0;
bool onlineEmpty = offlineEmpty && ((friendLayout->getLayoutOnline()->count() == 0 && groupsOnTop) || !groupsOnTop);
bool groupsEmpty = offlineEmpty && ((groupLayout.getLayout()->count() == 0 && !groupsOnTop) || groupsOnTop);
if ((currentLayout == friendLayout->getLayoutOffline())
|| (currentLayout == friendLayout->getLayoutOnline() && groupsEmpty)
|| (currentLayout == groupLayout.getLayout() && onlineEmpty))
{
forward = !forward;
}
}
index += forward ? 1 : -1;
for (;;)
{
// Bounds checking.
if (index < 0)
{
currentLayout = nextLayout(currentLayout, forward);
index = currentLayout->count() - 1;
continue;
}
else if (index >= currentLayout->count())
{
currentLayout = nextLayout(currentLayout, forward);
index = 0;
continue;
}
GenericChatroomWidget* chatWidget = dynamic_cast<GenericChatroomWidget*>(currentLayout->itemAt(index)->widget());
if (chatWidget != nullptr && chatWidget != activeChatroomWidget)
onChatroomWidgetClicked(chatWidget, false);
return;
}
}
ContentDialog* ContentDialog::current()
{
return currentDialog;
}
bool ContentDialog::existsFriendWidget(int friendId, bool focus)
{
return existsWidget(friendId, focus, friendList);
}
bool ContentDialog::existsGroupWidget(int groupId, bool focus)
{
return existsWidget(groupId, focus, groupList);
}
void ContentDialog::updateFriendStatus(int friendId)
{
updateStatus(friendId, friendList);
ContentDialog* contentDialog = getFriendDialog(friendId);
if (contentDialog != nullptr)
{
FriendWidget* friendWidget = static_cast<FriendWidget*>(std::get<1>(friendList.find(friendId).value()));
contentDialog->friendLayout->addFriendWidget(friendWidget, FriendList::findFriend(friendId)->getStatus());
}
}
void ContentDialog::updateFriendStatusMessage(int friendId, const QString &message)
{
auto iter = friendList.find(friendId);
if (iter == friendList.end())
return;
std::get<1>(iter.value())->setStatusMsg(message);
}
void ContentDialog::updateGroupStatus(int groupId)
{
updateStatus(groupId, groupList);
}
bool ContentDialog::isFriendWidgetActive(int friendId)
{
return isWidgetActive(friendId, friendList);
}
bool ContentDialog::isGroupWidgetActive(int groupId)
{
return isWidgetActive(groupId, groupList);
}
ContentDialog* ContentDialog::getFriendDialog(int friendId)
{
return getDialog(friendId, friendList);
}
ContentDialog* ContentDialog::getGroupDialog(int groupId)
{
return getDialog(groupId, groupList);
}
void ContentDialog::updateTitleUsername(const QString& username)
{
if (displayWidget != nullptr)
setWindowTitle(displayWidget->getTitle() + QStringLiteral(" - ") + username);
else
setWindowTitle(username);
}
void ContentDialog::updateTitle(GenericChatroomWidget* chatroomWidget)
{
displayWidget = chatroomWidget;
updateTitleUsername(Core::getInstance()->getUsername());
}
void ContentDialog::previousContact()
{
cycleContacts(false);
}
void ContentDialog::nextContact()
{
cycleContacts(true);
}
bool ContentDialog::event(QEvent* event)
{
switch (event->type())
{
case QEvent::WindowActivate:
if (activeChatroomWidget != nullptr)
{
activeChatroomWidget->resetEventFlags();
activeChatroomWidget->updateStatusLight();
updateTitle(activeChatroomWidget);
Friend* frnd = activeChatroomWidget->getFriend();
if (frnd)
{
frnd->getFriendWidget()->resetEventFlags();
frnd->getFriendWidget()->updateStatusLight();
}
else
{
Group* g = activeChatroomWidget->getGroup();
g->getGroupWidget()->resetEventFlags();
g->getGroupWidget()->updateStatusLight();
}
}
currentDialog = this;
#ifdef Q_OS_MAC
emit activated();
#endif
default:
break;
}
return ActivateDialog::event(event);
}
void ContentDialog::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("friend"))
{
int friendId = event->mimeData()->data("friend").toInt();
auto iter = friendList.find(friendId);
// If friend is already in a dialog then you can't drop friend where it already is.
if (iter == friendList.end() || (iter != friendList.end() && std::get<0>(iter.value()) != this))
event->acceptProposedAction();
}
else if (event->mimeData()->hasFormat("group"))
{
int groupId = event->mimeData()->data("group").toInt();
auto iter = groupList.find(groupId);
if (iter == groupList.end() || (iter != groupList.end() && std::get<0>(iter.value()) != this))
event->acceptProposedAction();
}
}
void ContentDialog::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("friend"))
{
int friendId = event->mimeData()->data("friend").toInt();
auto iter = friendList.find(friendId);
if (iter != friendList.end())
std::get<0>(iter.value())->removeFriend(friendId);
Friend* contact = FriendList::findFriend(friendId);
Widget::getInstance()->addFriendDialog(contact, this);
ensureSplitterVisible();
}
else if (event->mimeData()->hasFormat("group"))
{
int groupId = event->mimeData()->data("group").toInt();
auto iter = friendList.find(groupId);
if (iter != friendList.end())
std::get<0>(iter.value())->removeGroup(groupId);
Group* contact = GroupList::findGroup(groupId);
Widget::getInstance()->addGroupDialog(contact, this);
ensureSplitterVisible();
}
}
void ContentDialog::changeEvent(QEvent *event)
{
QWidget::changeEvent(event);
if (event->type() == QEvent::ActivationChange)
{
if (isActiveWindow())
currentDialog = this;
}
}
void ContentDialog::resizeEvent(QResizeEvent* event)
{
saveDialogGeometry();
QDialog::resizeEvent(event);
}
void ContentDialog::moveEvent(QMoveEvent* event)
{
saveDialogGeometry();
QDialog::moveEvent(event);
}
void ContentDialog::keyPressEvent(QKeyEvent* event)
{
if(event->key() != Qt::Key_Escape)
QDialog::keyPressEvent(event); // Ignore escape keyboard shortcut.
}
void ContentDialog::onChatroomWidgetClicked(GenericChatroomWidget *widget, bool group)
{
if (group)
{
ContentDialog* contentDialog = new ContentDialog(settingsWidget);
contentDialog->show();
if (widget->getFriend() != nullptr)
{
removeFriend(widget->getFriend()->getFriendID());
Widget::getInstance()->addFriendDialog(widget->getFriend(), contentDialog);
}
else
{
removeGroup(widget->getGroup()->getGroupId());
Widget::getInstance()->addGroupDialog(widget->getGroup(), contentDialog);
}
contentDialog->raise();
contentDialog->activateWindow();
return;
}
// If we clicked on the currently active widget, don't reload and relayout everything
if (activeChatroomWidget == widget)
return;
contentLayout->clear();
if (activeChatroomWidget != nullptr)
activeChatroomWidget->setAsInactiveChatroom();
activeChatroomWidget = widget;
widget->setChatForm(contentLayout);
widget->setAsActiveChatroom();
widget->resetEventFlags();
widget->updateStatusLight();
updateTitle(widget);
if (widget->getFriend())
widget->getFriend()->getFriendWidget()->updateStatusLight();
else
widget->getGroup()->getGroupWidget()->updateStatusLight();
}
void ContentDialog::updateFriendWidget(FriendWidget *w, Status s)
{
FriendWidget* friendWidget = static_cast<FriendWidget*>(std::get<1>(friendList.find(w->friendId).value()));
friendWidget->setName(w->getName());
friendLayout->addFriendWidget(friendWidget, s);
}
void ContentDialog::updateGroupWidget(GroupWidget *w)
{
std::get<1>(groupList.find(w->groupId).value())->setName(w->getName());
static_cast<GroupWidget*>(std::get<1>(groupList.find(w->groupId).value()))->onUserListChanged();
}
void ContentDialog::onGroupchatPositionChanged(bool top)
{
friendLayout->removeItem(groupLayout.getLayout());
if (top)
friendLayout->insertLayout(0, groupLayout.getLayout());
else
friendLayout->insertLayout(1, groupLayout.getLayout());
}
void ContentDialog::retranslateUi()
{
updateTitleUsername(Core::getInstance()->getUsername());
}
void ContentDialog::saveDialogGeometry()
{
Settings::getInstance().setDialogGeometry(saveGeometry());
}
void ContentDialog::saveSplitterState()
{
Settings::getInstance().setDialogSplitterState(splitter->saveState());
}
bool ContentDialog::hasWidget(int id, GenericChatroomWidget* chatroomWidget, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list)
{
auto iter = list.find(id);
if (iter == list.end() || std::get<0>(iter.value()) != this)
return false;
return chatroomWidget == std::get<1>(iter.value());
}
bool ContentDialog::existsWidget(int id, bool focus, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list)
{
auto iter = list.find(id);
if (iter == list.end())
return false;
if (focus)
{
if (std::get<0>(iter.value())->windowState() & Qt::WindowMinimized)
std::get<0>(iter.value())->showNormal();
std::get<0>(iter.value())->raise();
std::get<0>(iter.value())->activateWindow();
std::get<0>(iter.value())->onChatroomWidgetClicked(std::get<1>(iter.value()), false);
}
return true;
}
void ContentDialog::updateStatus(int id, const QHash<int, std::tuple<ContentDialog *, GenericChatroomWidget *> > &list)
{
auto iter = list.find(id);
if (iter == list.end())
return;
GenericChatroomWidget* chatroomWidget = std::get<1>(iter.value());
chatroomWidget->updateStatusLight();
if (chatroomWidget->isActive())
std::get<0>(iter.value())->updateTitle(chatroomWidget);
}
bool ContentDialog::isWidgetActive(int id, const QHash<int, std::tuple<ContentDialog *, GenericChatroomWidget *> > &list)
{
auto iter = list.find(id);
if (iter == list.end())
return false;
return std::get<0>(iter.value())->activeChatroomWidget == std::get<1>(iter.value());
}
ContentDialog* ContentDialog::getDialog(int id, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list)
{
auto iter = list.find(id);
if (iter == list.end())
return nullptr;
return std::get<0>(iter.value());
}
QLayout* ContentDialog::nextLayout(QLayout* layout, bool forward) const
{
if (layout == groupLayout.getLayout())
{
if (forward)
{
if (Settings::getInstance().getGroupchatPosition())
return friendLayout->getLayoutOnline();
return friendLayout->getLayoutOffline();
}
else
{
if (Settings::getInstance().getGroupchatPosition())
return friendLayout->getLayoutOffline();
return friendLayout->getLayoutOnline();
}
}
else if (layout == friendLayout->getLayoutOnline())
{
if (forward)
{
if (Settings::getInstance().getGroupchatPosition())
return friendLayout->getLayoutOffline();
return groupLayout.getLayout();
}
else
{
if (Settings::getInstance().getGroupchatPosition())
return groupLayout.getLayout();
return friendLayout->getLayoutOffline();
}
}
else if (layout == friendLayout->getLayoutOffline())
{
if (forward)
{
if (Settings::getInstance().getGroupchatPosition())
return groupLayout.getLayout();
return friendLayout->getLayoutOnline();
}
else
{
if (Settings::getInstance().getGroupchatPosition())
return friendLayout->getLayoutOnline();
return groupLayout.getLayout();
}
}
return nullptr;
}

119
src/widget/contentdialog.h Normal file
View File

@ -0,0 +1,119 @@
/*
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 CONTENTDIALOG_H
#define CONTENTDIALOG_H
#include "src/widget/tool/activatedialog.h"
#include <tuple>
#include "src/core/corestructs.h"
#include "src/widget/genericchatitemlayout.h"
template <typename K, typename V> class QHash;
template <typename T> class QSet;
class QSplitter;
class QVBoxLayout;
class ContentLayout;
class GenericChatroomWidget;
class FriendWidget;
class GroupWidget;
class FriendListLayout;
class SettingsWidget;
class ContentDialog : public ActivateDialog
{
Q_OBJECT
public:
ContentDialog(SettingsWidget* settingsWidget, QWidget* parent = 0);
~ContentDialog();
FriendWidget* addFriend(int friendId, QString id);
GroupWidget* addGroup(int groupId, const QString& name);
void removeFriend(int friendId);
void removeGroup(int groupId);
bool hasFriendWidget(int friendId, GenericChatroomWidget* chatroomWidget);
bool hasGroupWidget(int groupId, GenericChatroomWidget* chatroomWidget);
int chatroomWidgetCount() const;
void ensureSplitterVisible();
void cycleContacts(bool forward, bool loop = true);
static ContentDialog* current();
static bool existsFriendWidget(int friendId, bool focus);
static bool existsGroupWidget(int groupId, bool focus);
static void updateFriendStatus(int friendId);
static void updateFriendStatusMessage(int friendId, const QString &message);
static void updateGroupStatus(int groupId);
static bool isFriendWidgetActive(int friendId);
static bool isGroupWidgetActive(int groupId);
static ContentDialog* getFriendDialog(int friendId);
static ContentDialog* getGroupDialog(int groupId);
#ifdef Q_OS_MAC
signals:
void activated();
#endif
public slots:
void updateTitleUsername(const QString& username);
void updateTitle(GenericChatroomWidget* chatroomWidget);
void previousContact();
void nextContact();
protected:
bool event(QEvent* event) final override;
void dragEnterEvent(QDragEnterEvent* event) final override;
void dropEvent(QDropEvent* event) final override;
void changeEvent(QEvent* event) override;
void resizeEvent(QResizeEvent* event) override;
void moveEvent(QMoveEvent* event) override;
void keyPressEvent(QKeyEvent* event) override;
private slots:
void onChatroomWidgetClicked(GenericChatroomWidget* widget, bool group);
void updateFriendWidget(FriendWidget* w, Status s);
void updateGroupWidget(GroupWidget* w);
void onGroupchatPositionChanged(bool top);
private:
void retranslateUi();
void saveDialogGeometry();
void saveSplitterState();
QLayout* nextLayout(QLayout* layout, bool forward) const;
bool hasWidget(int id, GenericChatroomWidget* chatroomWidget, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list);
static bool existsWidget(int id, bool focus, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list);
static void updateStatus(int id, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list);
static bool isWidgetActive(int id, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list);
static ContentDialog* getDialog(int id, const QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>>& list);
QSplitter* splitter;
FriendListLayout* friendLayout;
GenericChatItemLayout groupLayout;
ContentLayout* contentLayout;
GenericChatroomWidget* activeChatroomWidget;
GenericChatroomWidget* displayWidget = nullptr;
SettingsWidget* settingsWidget;
static ContentDialog* currentDialog;
static QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>> friendList;
static QHash<int, std::tuple<ContentDialog*, GenericChatroomWidget*>> groupList;
};
#endif // CONTENTDIALOG_H

View File

@ -0,0 +1,124 @@
/*
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 "contentlayout.h"
#include "src/persistence/settings.h"
#include "style.h"
#include <QStyleFactory>
#include <QFrame>
ContentLayout::ContentLayout()
: QVBoxLayout()
{
init();
}
ContentLayout::ContentLayout(QWidget *parent)
: QVBoxLayout(parent)
{
init();
QPalette palette = parent->palette();
palette.setBrush(QPalette::WindowText, QColor(0, 0, 0));
palette.setBrush(QPalette::Button, QColor(255, 255, 255));
palette.setBrush(QPalette::Light, QColor(255, 255, 255));
palette.setBrush(QPalette::Midlight, QColor(255, 255, 255));
palette.setBrush(QPalette::Dark, QColor(127, 127, 127));
palette.setBrush(QPalette::Mid, QColor(170, 170, 170));
palette.setBrush(QPalette::Text, QColor(0, 0, 0));
palette.setBrush(QPalette::BrightText, QColor(255, 255, 255));
palette.setBrush(QPalette::ButtonText, QColor(0, 0, 0));
palette.setBrush(QPalette::Base, QColor(255, 255, 255));
palette.setBrush(QPalette::Window, QColor(255, 255, 255));
palette.setBrush(QPalette::Shadow, QColor(0, 0, 0));
palette.setBrush(QPalette::AlternateBase, QColor(255, 255, 255));
palette.setBrush(QPalette::ToolTipBase, QColor(255, 255, 220));
palette.setBrush(QPalette::ToolTipText, QColor(0, 0, 0));
palette.setBrush(QPalette::Disabled, QPalette::WindowText, QColor(127, 127, 127));
palette.setBrush(QPalette::Disabled, QPalette::Text, QColor(127, 127, 127));
palette.setBrush(QPalette::Disabled, QPalette::ButtonText, QColor(127, 127, 127));
parent->setPalette(palette);
}
ContentLayout::~ContentLayout()
{
clear();
mainHead->deleteLater();
mainContent->deleteLater();
}
void ContentLayout::clear()
{
QLayoutItem* item;
while ((item = mainHead->layout()->takeAt(0)) != 0)
{
item->widget()->hide();
item->widget()->setParent(nullptr);
}
while ((item = mainContent->layout()->takeAt(0)) != 0)
{
item->widget()->hide();
item->widget()->setParent(nullptr);
}
}
void ContentLayout::init()
{
setMargin(0);
setSpacing(0);
mainHead = new QWidget();
mainHead->setLayout(new QVBoxLayout);
mainHead->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::Fixed);
mainHead->layout()->setMargin(0);
mainHead->layout()->setSpacing(0);
mainHead->setMouseTracking(true);
mainHLine = new QFrame();
mainHLine->setFrameShape(QFrame::HLine);
mainHLine->setFrameShadow(QFrame::Plain);
QPalette palette = mainHLine->palette();
palette.setBrush(QPalette::WindowText, QBrush(QColor(193, 193, 193)));
palette.setBrush(QPalette::WindowText, QBrush(QColor(193, 193, 193)));
mainHLine->setPalette(palette);
mainContent = new QWidget();
mainContent->setLayout(new QVBoxLayout);
mainContent->setSizePolicy(QSizePolicy::MinimumExpanding, QSizePolicy::MinimumExpanding);
if (QStyleFactory::keys().contains(Settings::getInstance().getStyle())
&& Settings::getInstance().getStyle() != "None")
{
mainHead->setStyle(QStyleFactory::create(Settings::getInstance().getStyle()));
mainContent->setStyle(QStyleFactory::create(Settings::getInstance().getStyle()));
}
#ifndef Q_OS_MAC
mainHead->setStyleSheet(Style::getStylesheet(":ui/settings/mainHead.css"));
mainContent->setStyleSheet(Style::getStylesheet(":ui/settings/mainContent.css"));
#endif
addWidget(mainHead);
addWidget(mainHLine);
addWidget(mainContent);
}

View File

@ -0,0 +1,44 @@
/*
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 CONTENTLAYOUT_H
#define CONTENTLAYOUT_H
#include <QBoxLayout>
class QFrame;
class ContentLayout : public QVBoxLayout
{
public:
ContentLayout();
ContentLayout(QWidget* parent);
~ContentLayout();
void clear();
QWidget* mainContent;
QFrame* mainHLine;
QWidget* mainHead;
private:
void init();
};
#endif // CONTENTLAYOUT_H

View File

@ -22,9 +22,9 @@
#include <QFont>
#include <QMessageBox>
#include <QErrorMessage>
#include <QApplication>
#include <QClipboard>
#include <tox/tox.h>
#include "ui_mainwindow.h"
#include "src/nexus.h"
#include "src/core/core.h"
#include "src/core/cdata.h"
@ -32,6 +32,8 @@
#include "src/persistence/settings.h"
#include "src/widget/gui.h"
#include "src/widget/translator.h"
#include "src/widget/contentlayout.h"
#include <QWindow>
AddFriendForm::AddFriendForm()
{
@ -66,10 +68,21 @@ AddFriendForm::~AddFriendForm()
main->deleteLater();
}
void AddFriendForm::show(Ui::MainWindow &ui)
bool AddFriendForm::isShown() const
{
ui.mainContent->layout()->addWidget(main);
ui.mainHead->layout()->addWidget(head);
if (main->isVisible())
{
head->window()->windowHandle()->alert(0);
return true;
}
return false;
}
void AddFriendForm::show(ContentLayout* contentLayout)
{
contentLayout->mainContent->layout()->addWidget(main);
contentLayout->mainHead->layout()->addWidget(head);
main->show();
head->show();
setIdFromClipboard();

View File

@ -26,7 +26,7 @@
#include <QTextEdit>
#include <QPushButton>
namespace Ui {class MainWindow;}
class ContentLayout;
class AddFriendForm : public QObject
{
@ -37,7 +37,8 @@ public:
AddFriendForm& operator=(const AddFriendForm&) = delete;
~AddFriendForm();
void show(Ui::MainWindow &ui);
bool isShown() const;
void show(ContentLayout* contentLayout);
QString getMessage() const;
signals:

View File

@ -216,13 +216,7 @@ void ChatForm::onFileRecvRequest(ToxFile file)
if (file.friendId != f->getFriendID())
return;
Widget* w = Widget::getInstance();
if (!w->isFriendWidgetCurActiveWidget(f)|| w->isMinimized() || !w->isActiveWindow())
{
w->newMessageAlert(f->getFriendWidget());
f->setEventFlag(true);
f->getFriendWidget()->updateStatusLight();
}
Widget::getInstance()->newFriendMessageAlert(file.friendId);
QString name;
ToxId friendId = f->getToxId();
@ -265,7 +259,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video)
if (video)
{
callConfirm = new CallConfirmWidget(videoButton, *f);
if (Widget::getInstance()->isFriendWidgetCurActiveWidget(f))
if (f->getFriendWidget()->chatFormIsSet(false))
callConfirm->show();
connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered);
@ -280,7 +274,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video)
else
{
callConfirm = new CallConfirmWidget(callButton, *f);
if (Widget::getInstance()->isFriendWidgetCurActiveWidget(f))
if (f->getFriendWidget()->chatFormIsSet(false))
callConfirm->show();
connect(callConfirm, &CallConfirmWidget::accepted, this, &ChatForm::onAnswerCallTriggered);
@ -292,6 +286,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video)
videoButton->setToolTip("");
connect(callButton, &QPushButton::clicked, this, &ChatForm::onAnswerCallTriggered);
}
callButton->style()->polish(callButton);
videoButton->style()->polish(videoButton);
@ -299,13 +294,7 @@ void ChatForm::onAvInvite(uint32_t FriendId, int CallId, bool video)
ChatMessage::INFO,
QDateTime::currentDateTime()));
Widget* w = Widget::getInstance();
if (!w->isFriendWidgetCurActiveWidget(f)|| w->isMinimized() || !w->isActiveWindow())
{
w->newMessageAlert(f->getFriendWidget());
f->setEventFlag(true);
f->getFriendWidget()->updateStatusLight();
}
Widget::getInstance()->newFriendMessageAlert(FriendId);
}
void ChatForm::onAvStart(uint32_t FriendId, int CallId, bool video)
@ -1009,9 +998,9 @@ void ChatForm::setFriendTyping(bool isTyping)
text->setText("<div class=typing>" + QString("%1 is typing").arg(f->getDisplayedName()) + "</div>");
}
void ChatForm::show(Ui::MainWindow &ui)
void ChatForm::show(ContentLayout* contentLayout)
{
GenericChatForm::show(ui);
GenericChatForm::show(contentLayout);
if (callConfirm)
callConfirm->show();

View File

@ -27,7 +27,6 @@
#include <QTimer>
#include <QElapsedTimer>
class Friend;
class FileTransferInstance;
class NetCamView;
@ -50,7 +49,7 @@ public:
void setFriendTyping(bool isTyping);
OfflineMsgEngine* getOfflineMsgEngine();
virtual void show(Ui::MainWindow &ui) final override;
virtual void show(ContentLayout* contentLayout) final override;
signals:
void sendFile(uint32_t friendId, QString, QString, long long);

View File

@ -18,10 +18,11 @@
*/
#include "filesform.h"
#include "ui_mainwindow.h"
#include "src/widget/widget.h"
#include "src/widget/translator.h"
#include "src/widget/contentlayout.h"
#include <QFileInfo>
#include <QWindow>
FilesForm::FilesForm()
: QObject(), doneIcon(":/ui/fileTransferWidget/fileDone.svg")
@ -54,10 +55,21 @@ FilesForm::~FilesForm()
head->deleteLater();
}
void FilesForm::show(Ui::MainWindow& ui)
bool FilesForm::isShown() const
{
ui.mainContent->layout()->addWidget(&main);
ui.mainHead->layout()->addWidget(head);
if (main.isVisible())
{
head->window()->windowHandle()->alert(0);
return true;
}
return false;
}
void FilesForm::show(ContentLayout* contentLayout)
{
contentLayout->mainContent->layout()->addWidget(&main);
contentLayout->mainHead->layout()->addWidget(head);
main.show();
head->show();
}

View File

@ -26,7 +26,7 @@
#include <QLabel>
#include <QVBoxLayout>
namespace Ui {class MainWindow;}
class ContentLayout;
class QListWidget;
class FilesForm : public QObject
@ -37,7 +37,8 @@ public:
FilesForm();
~FilesForm();
void show(Ui::MainWindow &ui);
bool isShown() const;
void show(ContentLayout* contentLayout);
public slots:
void onFileDownloadComplete(const QString& path);

View File

@ -18,7 +18,6 @@
*/
#include "genericchatform.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QHBoxLayout>
@ -42,6 +41,9 @@
#include "src/chatlog/content/timestamp.h"
#include "src/widget/tool/flyoutoverlaywidget.h"
#include "src/widget/translator.h"
#include "src/widget/contentlayout.h"
#include "src/widget/tool/croppinglabel.h"
#include <QPushButton>
GenericChatForm::GenericChatForm(QWidget *parent)
: QWidget(parent)
@ -255,10 +257,10 @@ void GenericChatForm::setName(const QString &newName)
nameLabel->setToolTip(newName); // for overlength names
}
void GenericChatForm::show(Ui::MainWindow &ui)
void GenericChatForm::show(ContentLayout* contentLayout)
{
ui.mainContent->layout()->addWidget(this);
ui.mainHead->layout()->addWidget(headWidget);
contentLayout->mainContent->layout()->addWidget(this);
contentLayout->mainHead->layout()->addWidget(headWidget);
headWidget->show();
QWidget::show();
}

View File

@ -40,10 +40,7 @@ class ChatLog;
class MaskablePixmapWidget;
class Widget;
class FlyoutOverlayWidget;
namespace Ui {
class MainWindow;
}
class ContentLayout;
class GenericChatForm : public QWidget
{
@ -54,7 +51,7 @@ public:
void setName(const QString &newName);
virtual void show() final{}
virtual void show(Ui::MainWindow &ui);
virtual void show(ContentLayout* contentLayout);
ChatMessage::Ptr addMessage(const ToxId& author, const QString &message, bool isAction, const QDateTime &datetime, bool isSent);
ChatMessage::Ptr addSelfMessage(const QString &message, bool isAction, const QDateTime &datetime, bool isSent);

View File

@ -21,11 +21,11 @@
#include "src/nexus.h"
#include "ui_profileform.h"
#include "profileform.h"
#include "ui_mainwindow.h"
#include "src/widget/form/settingswidget.h"
#include "src/widget/maskablepixmapwidget.h"
#include "src/widget/form/setpassworddialog.h"
#include "src/persistence/settings.h"
#include "src/widget/contentlayout.h"
#include "src/widget/tool/croppinglabel.h"
#include "src/widget/widget.h"
#include "src/widget/gui.h"
@ -44,6 +44,7 @@
#include <QBuffer>
#include <QMessageBox>
#include <QComboBox>
#include <QWindow>
ProfileForm::ProfileForm(QWidget *parent) :
QWidget{parent}, qr{nullptr}
@ -134,10 +135,21 @@ ProfileForm::~ProfileForm()
head->deleteLater();
}
void ProfileForm::show(Ui::MainWindow &ui)
bool ProfileForm::isShown() const
{
ui.mainHead->layout()->addWidget(head);
ui.mainContent->layout()->addWidget(this);
if (head->isVisible())
{
window()->windowHandle()->alert(0);
return true;
}
return false;
}
void ProfileForm::show(ContentLayout* contentLayout)
{
contentLayout->mainHead->layout()->addWidget(head);
contentLayout->mainContent->layout()->addWidget(this);
head->show();
QWidget::show();
prFileLabelUpdate();

View File

@ -30,10 +30,10 @@
class CroppingLabel;
class Core;
class MaskablePixmapWidget;
class ContentLayout;
namespace Ui {
class IdentitySettings;
class MainWindow;
}
class ClickableTE : public QLineEdit
@ -54,7 +54,8 @@ public:
ProfileForm(QWidget *parent = nullptr);
~ProfileForm();
virtual void show() final{}
void show(Ui::MainWindow &ui);
void show(ContentLayout* contentLayout);
bool isShown() const;
signals:
void userNameChanged(QString);

View File

@ -87,6 +87,9 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
bodyUI->groupAlwaysNotify->setChecked(Settings::getInstance().getGroupAlwaysNotify());
bodyUI->cbFauxOfflineMessaging->setChecked(Settings::getInstance().getFauxOfflineMessaging());
bodyUI->cbCompactLayout->setChecked(Settings::getInstance().getCompactLayout());
bodyUI->cbSeparateWindow->setChecked(Settings::getInstance().getSeparateWindow());
bodyUI->cbDontGroupWindows->setChecked(Settings::getInstance().getDontGroupWindows());
bodyUI->cbDontGroupWindows->setEnabled(bodyUI->cbSeparateWindow->isChecked());
bodyUI->cbGroupchatPosition->setChecked(Settings::getInstance().getGroupchatPosition());
for (auto entry : SmileyPack::listSmileyPacks())
@ -179,6 +182,8 @@ GeneralForm::GeneralForm(SettingsWidget *myParent) :
connect(bodyUI->reconnectButton, &QPushButton::clicked, this, &GeneralForm::onReconnectClicked);
connect(bodyUI->cbFauxOfflineMessaging, &QCheckBox::stateChanged, this, &GeneralForm::onFauxOfflineMessaging);
connect(bodyUI->cbCompactLayout, &QCheckBox::stateChanged, this, &GeneralForm::onCompactLayout);
connect(bodyUI->cbSeparateWindow, &QCheckBox::stateChanged, this, &GeneralForm::onSeparateWindowChanged);
connect(bodyUI->cbDontGroupWindows, &QCheckBox::stateChanged, this, &GeneralForm::onDontGroupWindowsChanged);
connect(bodyUI->cbGroupchatPosition, &QCheckBox::stateChanged, this, &GeneralForm::onGroupchatPositionChanged);
// prevent stealing mouse whell scroll
@ -430,6 +435,18 @@ void GeneralForm::onCompactLayout()
emit parent->compactToggled(bodyUI->cbCompactLayout->isChecked());
}
void GeneralForm::onSeparateWindowChanged()
{
bodyUI->cbDontGroupWindows->setEnabled(bodyUI->cbSeparateWindow->isChecked());
Settings::getInstance().setSeparateWindow(bodyUI->cbSeparateWindow->isChecked());
emit parent->separateWindowToggled(bodyUI->cbSeparateWindow->isChecked());
}
void GeneralForm::onDontGroupWindowsChanged()
{
Settings::getInstance().setDontGroupWindows(bodyUI->cbDontGroupWindows->isChecked());
}
void GeneralForm::onGroupchatPositionChanged()
{
Settings::getInstance().setGroupchatPosition(bodyUI->cbGroupchatPosition->isChecked());

View File

@ -67,6 +67,8 @@ private slots:
void onSetGroupAlwaysNotify();
void onFauxOfflineMessaging();
void onCompactLayout();
void onSeparateWindowChanged();
void onDontGroupWindowsChanged();
void onGroupchatPositionChanged();
void onThemeColorChanged(int);

View File

@ -40,7 +40,7 @@
<x>0</x>
<y>0</y>
<width>639</width>
<height>1221</height>
<height>1388</height>
</rect>
</property>
<layout class="QVBoxLayout" name="verticalLayout_4" stretch="0,0,0,1">
@ -374,6 +374,23 @@ instead of system taskbar.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbSeparateWindow">
<property name="text">
<string>Open chats in separate window.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbDontGroupWindows">
<property name="enabled">
<bool>false</bool>
</property>
<property name="text">
<string>Don't group chat windows.</string>
</property>
</widget>
</item>
<item>
<widget class="QCheckBox" name="cbGroupchatPosition">
<property name="toolTip">

View File

@ -19,7 +19,6 @@
#include "settingswidget.h"
#include "src/widget/widget.h"
#include "ui_mainwindow.h"
#include "src/video/camerasource.h"
#include "src/widget/form/settings/generalform.h"
#include "src/widget/form/settings/privacyform.h"
@ -27,12 +26,15 @@
#include "src/widget/form/settings/advancedform.h"
#include "src/widget/form/settings/aboutform.h"
#include "src/widget/translator.h"
#include "src/widget/contentlayout.h"
#include <QTabWidget>
#include <QLabel>
#include <QWindow>
SettingsWidget::SettingsWidget(QWidget* parent)
: QWidget(parent)
{
body = new QWidget(this);
body = new QWidget();
QVBoxLayout* bodyLayout = new QVBoxLayout();
body->setLayout(bodyLayout);
@ -86,10 +88,21 @@ void SettingsWidget::showAbout()
onTabChanged(settingsWidgets->count() - 1);
}
void SettingsWidget::show(Ui::MainWindow& ui)
bool SettingsWidget::isShown() const
{
ui.mainContent->layout()->addWidget(body);
ui.mainHead->layout()->addWidget(head);
if (body->isVisible())
{
body->window()->windowHandle()->alert(0);
return true;
}
return false;
}
void SettingsWidget::show(ContentLayout* contentLayout)
{
contentLayout->mainContent->layout()->addWidget(body);
contentLayout->mainHead->layout()->addWidget(head);
body->show();
head->show();
onTabChanged(settingsWidgets->currentIndex());

View File

@ -32,8 +32,7 @@ class PrivacyForm;
class AVForm;
class QLabel;
class QTabWidget;
namespace Ui {class MainWindow;}
class ContentLayout;
class SettingsWidget : public QWidget
{
@ -42,7 +41,8 @@ public:
SettingsWidget(QWidget* parent = nullptr);
~SettingsWidget();
void show(Ui::MainWindow &ui);
bool isShown() const;
void show(ContentLayout* contentLayout);
void setBodyHeadStyle(QString style);
void showAbout();
@ -50,6 +50,7 @@ public:
signals:
void setShowSystemTray(bool newValue);
void compactToggled(bool compact);
void separateWindowToggled(bool separateWindow);
void groupchatPositionToggled(bool groupchatPosition);
private slots:

View File

@ -62,7 +62,7 @@ void FriendListLayout::removeFriendWidget(FriendWidget *widget, Status s)
friendOnlineLayout.removeSortedWidget(widget);
}
int FriendListLayout::indexOfFriendWidget(FriendWidget* widget, bool online) const
int FriendListLayout::indexOfFriendWidget(GenericChatItemWidget* widget, bool online) const
{
if (online)
return friendOnlineLayout.indexOfSortedWidget(widget);

View File

@ -31,7 +31,7 @@ public:
void addFriendWidget(FriendWidget* widget, Status s);
void removeFriendWidget(FriendWidget* widget, Status s);
int indexOfFriendWidget(FriendWidget* widget, bool online) const;
int indexOfFriendWidget(GenericChatItemWidget* widget, bool online) const;
void moveFriendWidgets(FriendListWidget* listWidget);
int friendOnlineCount() const;
int friendTotalCount() const;

View File

@ -389,8 +389,11 @@ void FriendListWidget::addCircleWidget(FriendWidget* friendWidget)
}
Widget::getInstance()->searchCircle(circleWidget);
circleWidget->editName();
if (window()->isActiveWindow())
circleWidget->editName();
}
reDraw();
}
void FriendListWidget::removeCircleWidget(CircleWidget* widget)
@ -596,17 +599,6 @@ void FriendListWidget::cycleContacts(GenericChatroomWidget* activeChatroomWidget
}
}
QVector<CircleWidget*> FriendListWidget::getAllCircles()
{
QVector<CircleWidget*> vec;
vec.reserve(circleLayout->getLayout()->count());
for (int i = 0; i < circleLayout->getLayout()->count(); ++i)
{
vec.push_back(dynamic_cast<CircleWidget*>(circleLayout->getLayout()->itemAt(i)->widget()));
}
return vec;
}
void FriendListWidget::dragEnterEvent(QDragEnterEvent* event)
{
if (event->mimeData()->hasFormat("friend"))

View File

@ -58,7 +58,6 @@ public:
void searchChatrooms(const QString &searchString, bool hideOnline = false, bool hideOffline = false, bool hideGroups = false);
void cycleContacts(GenericChatroomWidget* activeChatroomWidget, bool forward);
QVector<CircleWidget*> getAllCircles();
void updateActivityDate(const QDate& date);
void reDraw();

View File

@ -26,6 +26,7 @@
#include "src/core/core.h"
#include "form/chatform.h"
#include "maskablepixmapwidget.h"
#include "contentdialog.h"
#include "src/widget/tool/croppinglabel.h"
#include "src/widget/style.h"
#include "src/persistence/settings.h"
@ -67,6 +68,20 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
ToxId id = FriendList::findFriend(friendId)->getToxId();
QString dir = Settings::getInstance().getAutoAcceptDir(id);
QMenu menu;
QAction* openChat = menu.addAction(tr("Open chat"));
QAction* openChatWindow = nullptr;
QAction* removeChatWindow = nullptr;
ContentDialog* contentDialog = ContentDialog::getFriendDialog(friendId);
bool notAlone = contentDialog != nullptr && contentDialog->chatroomWidgetCount() > 1;
if (contentDialog == nullptr || notAlone)
openChatWindow = menu.addAction(tr("Open chat in new window"));
if (contentDialog->hasFriendWidget(friendId, this))
removeChatWindow = menu.addAction(tr("Remove chat from this window"));
menu.addSeparator();
QMenu* inviteMenu = menu.addMenu(tr("Invite to group","Menu to invite a friend to a groupchat"));
QMap<QAction*, Group*> groupActions;
@ -90,7 +105,7 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
FriendListWidget *friendList;
if (circleWidget == nullptr)
friendList = dynamic_cast<FriendListWidget*>(parentWidget());
friendList = dynamic_cast<FriendListWidget*>(FriendList::findFriend(friendId)->getFriendWidget()->parentWidget());
else
friendList = dynamic_cast<FriendListWidget*>(circleWidget->parentWidget());
@ -132,7 +147,10 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
autoAccept->setChecked(!dir.isEmpty());
menu.addSeparator();
QAction* removeFriendAction = menu.addAction(tr("Remove friend", "Menu to remove the friend from our friendlist"));
QAction* removeFriendAction = nullptr;
if (contentDialog == nullptr || !contentDialog->hasFriendWidget(friendId, this))
removeFriendAction = menu.addAction(tr("Remove friend", "Menu to remove the friend from our friendlist"));
QAction* selectedItem = menu.exec(pos);
@ -156,6 +174,22 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
emit removeFriend(friendId);
return;
}
else if (selectedItem == openChat)
{
emit chatroomWidgetClicked(this);
return;
}
else if (selectedItem == openChatWindow)
{
emit chatroomWidgetClicked(this, true);
return;
}
else if (selectedItem == removeChatWindow)
{
ContentDialog* contentDialog = ContentDialog::getFriendDialog(friendId);
contentDialog->removeFriend(friendId);
return;
}
else if (selectedItem == autoAccept)
{
if (!autoAccept->isChecked())
@ -180,7 +214,7 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
circleWidget->updateStatus();
if (friendList != nullptr)
friendList->addCircleWidget(this);
friendList->addCircleWidget(FriendList::findFriend(friendId)->getFriendWidget());
else
Settings::getInstance().setFriendCircleID(id, Settings::getInstance().addCircle());
}
@ -192,7 +226,7 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
else if (removeCircleAction != nullptr && selectedItem == removeCircleAction)
{
if (friendList != nullptr)
friendList->moveWidget(this, FriendList::findFriend(friendId)->getStatus(), true);
friendList->moveWidget(FriendList::findFriend(friendId)->getFriendWidget(), FriendList::findFriend(friendId)->getStatus(), true);
else
Settings::getInstance().setFriendCircleID(id, -1);
@ -208,7 +242,7 @@ void FriendWidget::contextMenuEvent(QContextMenuEvent * event)
if (circle != nullptr)
{
circle->addFriendWidget(this, FriendList::findFriend(friendId)->getStatus());
circle->addFriendWidget(FriendList::findFriend(friendId)->getFriendWidget(), FriendList::findFriend(friendId)->getStatus());
circle->setExpanded(true);
Widget::getInstance()->searchCircle(circle);
Settings::getInstance().savePersonal();
@ -278,7 +312,7 @@ void FriendWidget::updateStatusLight()
statusPic.setMargin(0);
}
QString FriendWidget::getStatusString()
QString FriendWidget::getStatusString() const
{
Friend* f = FriendList::findFriend(friendId);
Status status = f->getStatus();
@ -296,6 +330,11 @@ QString FriendWidget::getStatusString()
return QString::null;
}
Friend* FriendWidget::getFriend() const
{
return FriendList::findFriend(friendId);
}
void FriendWidget::search(const QString &searchString, bool hide)
{
searchName(searchString, hide);
@ -304,10 +343,16 @@ void FriendWidget::search(const QString &searchString, bool hide)
circleWidget->search(searchString);
}
void FriendWidget::setChatForm(Ui::MainWindow &ui)
bool FriendWidget::chatFormIsSet(bool focus) const
{
Friend* f = FriendList::findFriend(friendId);
f->getChatForm()->show(ui);
return ContentDialog::existsFriendWidget(friendId, focus) || f->getChatForm()->isVisible();
}
void FriendWidget::setChatForm(ContentLayout* contentLayout)
{
Friend* f = FriendList::findFriend(friendId);
f->getChatForm()->show(contentLayout);
}
void FriendWidget::resetEventFlags()

View File

@ -32,9 +32,11 @@ public:
virtual void setAsActiveChatroom() override;
virtual void setAsInactiveChatroom() override;
virtual void updateStatusLight() override;
virtual void setChatForm(Ui::MainWindow &) override;
virtual bool chatFormIsSet(bool focus) const override;
virtual void setChatForm(ContentLayout* contentLayout) override;
virtual void resetEventFlags() override;
virtual QString getStatusString() override;
virtual QString getStatusString() const override;
virtual Friend* getFriend() const override;
void search(const QString &searchString, bool hide = false);
signals:
@ -56,7 +58,6 @@ public:
int friendId;
bool isDefaultAvatar;
bool historyLoaded;
QPoint dragStartPos;
};
#endif // FRIENDWIDGET_H

View File

@ -144,6 +144,16 @@ QString GenericChatroomWidget::getStatusMsg() const
return statusMessageLabel->text();
}
QString GenericChatroomWidget::getTitle() const
{
QString title = getName();
if (!getStatusString().isNull())
title += QStringLiteral(" (") + getStatusString() + QStringLiteral(")");
return title;
}
void GenericChatroomWidget::reloadTheme()
{
QPalette p;

View File

@ -26,10 +26,9 @@ class CroppingLabel;
class MaskablePixmapWidget;
class QVBoxLayout;
class QHBoxLayout;
namespace Ui {
class MainWindow;
}
class ContentLayout;
class Friend;
class Group;
class GenericChatroomWidget : public GenericChatItemWidget
{
@ -40,9 +39,12 @@ public:
virtual void setAsActiveChatroom() = 0;
virtual void setAsInactiveChatroom() = 0;
virtual void updateStatusLight() = 0;
virtual void setChatForm(Ui::MainWindow &) = 0;
virtual bool chatFormIsSet(bool focus) const = 0;
virtual void setChatForm(ContentLayout* contentLayout) = 0;
virtual void resetEventFlags() = 0;
virtual QString getStatusString() = 0;
virtual QString getStatusString() const = 0;
virtual Friend* getFriend() const{return nullptr;}
virtual Group* getGroup() const{return nullptr;}
virtual bool eventFilter(QObject *, QEvent *) final override;
@ -52,6 +54,7 @@ public:
void setName(const QString& name);
void setStatusMsg(const QString& status);
QString getStatusMsg() const;
QString getTitle() const;
void reloadTheme();
@ -59,13 +62,15 @@ public slots:
void compactChange(bool compact);
signals:
void chatroomWidgetClicked(GenericChatroomWidget* widget);
void chatroomWidgetClicked(GenericChatroomWidget* widget, bool group = false);
protected:
virtual void mouseReleaseEvent(QMouseEvent* event) override;
virtual void enterEvent(QEvent* e) override;
virtual void leaveEvent(QEvent* e) override;
QPoint dragStartPos;
protected:
QColor lastColor;
QHBoxLayout* mainLayout = nullptr;

View File

@ -19,8 +19,10 @@
#include "groupwidget.h"
#include "maskablepixmapwidget.h"
#include "contentdialog.h"
#include "src/grouplist.h"
#include "src/group.h"
#include "src/persistence/settings.h"
#include "form/groupchatform.h"
#include "src/widget/style.h"
#include "src/core/core.h"
@ -30,6 +32,8 @@
#include <QContextMenuEvent>
#include <QDragEnterEvent>
#include <QMimeData>
#include <QApplication>
#include <QDrag>
GroupWidget::GroupWidget(int GroupId, QString Name)
: groupId{GroupId}
@ -62,6 +66,22 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent* event)
installEventFilter(this); // Disable leave event.
QMenu menu(this);
QAction* openChat = menu.addAction(tr("Open chat"));
QAction* openChatWindow = nullptr;
QAction* removeChatWindow = nullptr;
ContentDialog* contentDialog = ContentDialog::getGroupDialog(groupId);
bool notAlone = contentDialog != nullptr && contentDialog->chatroomWidgetCount() > 1;
if (contentDialog == nullptr || notAlone)
openChatWindow = menu.addAction(tr("Open chat in new window"));
if (contentDialog->hasGroupWidget(groupId, this))
removeChatWindow = menu.addAction(tr("Remove chat from this window"));
menu.addSeparator();
QAction* setTitle = menu.addAction(tr("Set title..."));
QAction* quitGroup = menu.addAction(tr("Quit group","Menu to quit a groupchat"));
@ -78,6 +98,22 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent* event)
{
emit removeGroup(groupId);
}
else if (selectedItem == openChat)
{
emit chatroomWidgetClicked(this);
return;
}
else if (selectedItem == openChatWindow)
{
emit chatroomWidgetClicked(this, true);
return;
}
else if (selectedItem == removeChatWindow)
{
ContentDialog* contentDialog = ContentDialog::getGroupDialog(groupId);
contentDialog->removeGroup(groupId);
return;
}
else if (selectedItem == setTitle)
{
editName();
@ -85,6 +121,32 @@ void GroupWidget::contextMenuEvent(QContextMenuEvent* event)
}
}
void GroupWidget::mousePressEvent(QMouseEvent *ev)
{
if (ev->button() == Qt::LeftButton)
dragStartPos = ev->pos();
GenericChatroomWidget::mousePressEvent(ev);
}
void GroupWidget::mouseMoveEvent(QMouseEvent *ev)
{
if (!(ev->buttons() & Qt::LeftButton))
return;
if ((dragStartPos - ev->pos()).manhattanLength() > QApplication::startDragDistance())
{
QDrag* drag = new QDrag(this);
QMimeData* mdata = new QMimeData;
mdata->setData("group", QString::number(groupId).toLatin1());
drag->setMimeData(mdata);
drag->setPixmap(avatar->getPixmap());
drag->exec(Qt::CopyAction | Qt::MoveAction);
}
}
void GroupWidget::onUserListChanged()
{
Group* g = GroupList::findGroup(groupId);
@ -122,7 +184,7 @@ void GroupWidget::updateStatusLight()
}
}
QString GroupWidget::getStatusString()
QString GroupWidget::getStatusString() const
{
Group *g = GroupList::findGroup(groupId);
@ -137,10 +199,22 @@ void GroupWidget::editName()
nameLabel->editBegin();
}
void GroupWidget::setChatForm(Ui::MainWindow &ui)
Group* GroupWidget::getGroup() const
{
return GroupList::findGroup(groupId);
}
bool GroupWidget::chatFormIsSet(bool focus) const
{
(void)focus;
Group* g = GroupList::findGroup(groupId);
return ContentDialog::existsGroupWidget(groupId, focus) || g->getChatForm()->isVisible();
}
void GroupWidget::setChatForm(ContentLayout* contentLayout)
{
Group* g = GroupList::findGroup(groupId);
g->getChatForm()->show(ui);
g->getChatForm()->show(contentLayout);
}
void GroupWidget::resetEventFlags()

View File

@ -30,9 +30,11 @@ public:
virtual void setAsInactiveChatroom() final override;
virtual void setAsActiveChatroom() final override;
virtual void updateStatusLight() final override;
virtual void setChatForm(Ui::MainWindow &) final override;
virtual bool chatFormIsSet(bool focus) const final override;
virtual void setChatForm(ContentLayout* contentLayout) override;
virtual void resetEventFlags() final override;
virtual QString getStatusString() final override;
virtual QString getStatusString() const final override;
virtual Group* getGroup() const override;
void setName(const QString& name);
void onUserListChanged();
void editName();
@ -44,6 +46,8 @@ signals:
protected:
virtual void contextMenuEvent(QContextMenuEvent * event) final override;
virtual void mousePressEvent(QMouseEvent* event) final override;
virtual void mouseMoveEvent(QMouseEvent* event) final override;
virtual void dragEnterEvent(QDragEnterEvent* ev) override;
virtual void dragLeaveEvent(QDragLeaveEvent* ev);
virtual void dropEvent(QDropEvent* ev) override;

View File

@ -97,6 +97,16 @@ void LoginScreen::reset()
ui->autoLoginCB->setChecked(Settings::getInstance().getAutoLogin());
}
#ifdef Q_OS_MAC
bool LoginScreen::event(QEvent* event)
{
if (event->type() == QEvent::WindowActivate || event->type() == QEvent::WindowStateChange)
emit windowStateChanged(windowState());
return QWidget::event(event);
}
#endif
void LoginScreen::onNewProfilePageClicked()
{
ui->stackedWidget->setCurrentIndex(0);

View File

@ -37,6 +37,13 @@ public:
~LoginScreen();
void reset(); ///< Resets the UI, clears all fields
#ifdef Q_OS_MAC
bool event(QEvent* event) final override;
signals:
void windowStateChanged(Qt::WindowStates states);
#endif
private slots:
void onAutoLoginToggled(int state);
void onLoginUsernameSelected(const QString& name);

View File

@ -0,0 +1,36 @@
/*
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 "activatedialog.h"
#include <QEvent>
ActivateDialog::ActivateDialog(QWidget *parent, Qt::WindowFlags f)
: QDialog(parent, f)
{
}
bool ActivateDialog::event(QEvent* event)
{
if (event->type() == QEvent::WindowActivate || event->type() == QEvent::WindowStateChange)
emit windowStateChanged(windowState());
return QDialog::event(event);
}

View File

@ -0,0 +1,36 @@
/*
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 ACTIVATEDIALOG_H
#define ACTIVATEDIALOG_H
#include <QDialog>
class ActivateDialog : public QDialog
{
Q_OBJECT
public:
ActivateDialog(QWidget* parent = 0, Qt::WindowFlags f = 0);
bool event(QEvent* event) override;
signals:
void windowStateChanged(Qt::WindowStates state);
};
#endif // ACTIVATEDIALOG_H

View File

@ -19,7 +19,6 @@
#include "callconfirmwidget.h"
#include "src/widget/gui.h"
#include "src/widget/widget.h"
#include <assert.h>
#include <QVBoxLayout>
@ -33,7 +32,7 @@
#include <QPalette>
CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor, const Friend& f) :
QWidget(GUI::getMainWidget()), anchor(Anchor), f(f),
QWidget(), anchor(Anchor), f(f),
rectW{120}, rectH{85},
spikeW{30}, spikeH{15},
roundedFactor{20},
@ -47,6 +46,7 @@ CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor, const Friend& f) :
QVBoxLayout *layout = new QVBoxLayout(this);
QLabel *callLabel = new QLabel(QObject::tr("Incoming call..."), this);
callLabel->setStyleSheet("color: white");
callLabel->setWordWrap(true);
callLabel->setAlignment(Qt::AlignHCenter);
QDialogButtonBox *buttonBox = new QDialogButtonBox(Qt::Horizontal, this);
@ -66,8 +66,6 @@ CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor, const Friend& f) :
connect(buttonBox, &QDialogButtonBox::accepted, this, &CallConfirmWidget::accepted);
connect(buttonBox, &QDialogButtonBox::rejected, this, &CallConfirmWidget::rejected);
connect(&GUI::getInstance(), &GUI::resized, this, &CallConfirmWidget::reposition);
layout->setMargin(12);
layout->addSpacing(spikeH);
layout->addWidget(callLabel);
@ -79,7 +77,13 @@ CallConfirmWidget::CallConfirmWidget(const QWidget *Anchor, const Friend& f) :
void CallConfirmWidget::reposition()
{
QWidget* w = GUI::getMainWidget();
if (parentWidget())
parentWidget()->removeEventFilter(this);
setParent(anchor->window());
parentWidget()->installEventFilter(this);
QWidget* w = anchor->window();
QPoint pos = anchor->mapToGlobal({(anchor->width()-rectW)/2,anchor->height()})-w->mapToGlobal({0,0});
// We don't want the widget to overflow past the right of the screen
@ -114,11 +118,27 @@ void CallConfirmWidget::showEvent(QShowEvent*)
// If someone does show() from Widget or lower, the event will reach us
// because it's our parent, and we could show up in the wrong form.
// So check here if our friend's form is actually the active one.
if (!Widget::getInstance()->isFriendWidgetCurActiveWidget(&f))
//if (!Widget::getInstance()->isFriendWidgetCurActiveWidget(&f))
{
QWidget::hide();
return;
//QWidget::hide();
//return;
}
reposition();
update();
}
void CallConfirmWidget::hideEvent(QHideEvent *)
{
if (parentWidget())
parentWidget()->removeEventFilter(this);
setParent(nullptr);
}
bool CallConfirmWidget::eventFilter(QObject*, QEvent* event)
{
if (event->type() == QEvent::Resize)
reposition();
return false;
}

View File

@ -43,12 +43,14 @@ signals:
void accepted();
void rejected();
public slots:
void reposition(); ///< Recalculate our positions to track the anchor
protected:
virtual void paintEvent(QPaintEvent* event) final override;
virtual void showEvent(QShowEvent* event) final override;
protected slots:
void reposition(); ///< Recalculate our positions to track the anchor
virtual void hideEvent(QHideEvent* event) final override;
virtual bool eventFilter(QObject *, QEvent* event) final override;
private:
const QWidget* anchor; ///< The widget we're going to be tracking

View File

@ -20,6 +20,7 @@
#include "croppinglabel.h"
#include <QResizeEvent>
#include <QLineEdit>
#include <QKeyEvent>
CroppingLabel::CroppingLabel(QWidget* parent)
: QLabel(parent)
@ -29,13 +30,31 @@ CroppingLabel::CroppingLabel(QWidget* parent)
{
setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Preferred);
textEdit = new QLineEdit(this);
class LineEdit : public QLineEdit
{
public:
LineEdit(QWidget* parent = 0) :
QLineEdit(parent)
{}
protected:
void keyPressEvent(QKeyEvent* event) override
{
if (event->key() == Qt::Key_Escape)
clearFocus();
QLineEdit::keyPressEvent(event);
}
};
textEdit = new LineEdit(this);
textEdit->hide();
textEdit->setInputMethodHints(Qt::ImhNoAutoUppercase
| Qt::ImhNoPredictiveText
| Qt::ImhPreferLatin);
connect(textEdit, &QLineEdit::editingFinished, this, &CroppingLabel::editingFinished);
connect(textEdit, &QLineEdit::returnPressed, this, &CroppingLabel::editingFinished);
connect(textEdit, &QLineEdit::editingFinished, this, &CroppingLabel::hideTextEdit);
}
void CroppingLabel::editBegin()
@ -114,6 +133,12 @@ void CroppingLabel::setElidedText()
QLabel::setText(elidedText);
}
void CroppingLabel::hideTextEdit()
{
textEdit->hide();
blockPaintEvents = false;
}
void CroppingLabel::showTextEdit()
{
blockPaintEvents = true;
@ -142,7 +167,5 @@ void CroppingLabel::editingFinished()
if (origText != newText)
emit editFinished(textEdit->text());
textEdit->hide();
blockPaintEvents = false;
emit editRemoved();
}

View File

@ -49,7 +49,7 @@ signals:
protected:
void paintEvent(QPaintEvent* paintEvent) override;
void setElidedText();
void hideTextEdit(bool acceptText);
void hideTextEdit();
void showTextEdit();
virtual void resizeEvent(QResizeEvent *ev) final override;
virtual QSize sizeHint() const final override;

File diff suppressed because it is too large Load Diff

View File

@ -51,6 +51,8 @@ class SettingsWidget;
class AddFriendForm;
class CircleWidget;
class QActionGroup;
class ContentLayout;
class ContentDialog;
class Widget final : public QMainWindow
{
@ -63,12 +65,26 @@ public:
QString getUsername();
Camera* getCamera();
static Widget* getInstance();
void newMessageAlert(GenericChatroomWidget* chat);
bool isFriendWidgetCurActiveWidget(const Friend* f) const;
void addFriendDialog(Friend* frnd, ContentDialog* dialog);
void addGroupDialog(Group* group, ContentDialog* dialog);
bool newFriendMessageAlert(int friendId);
bool newGroupMessageAlert(int groupId, bool notify);
bool getIsWindowMinimized();
void updateIcons();
void clearContactsList();
enum DialogType
{
AddDialog,
TransferDialog,
SettingDialog,
ProfileDialog
};
static QString fromDialogType(DialogType type);
ContentDialog* createContentDialog() const;
ContentLayout* createContentDialog(DialogType type);
static void confirmExecutableOpen(const QFileInfo file);
void clearAllReceipts();
@ -87,6 +103,8 @@ public:
public slots:
void onSettingsClicked();
void onSeparateWindowClicked(bool separate);
void onSeparateWindowChanged(bool separate, bool clicked);
void setWindowTitle(const QString& title);
void forceShow();
void onConnected();
@ -129,6 +147,9 @@ signals:
void usernameChanged(const QString& username);
void statusMessageChanged(const QString& statusMessage);
void resized();
#ifdef Q_OS_MAC
void windowStateChanged(Qt::WindowStates states);
#endif
protected:
virtual bool eventFilter(QObject *obj, QEvent *event) final override;
@ -143,8 +164,8 @@ private slots:
void onTransferClicked();
void showProfile();
void onUsernameChanged(const QString& newUsername, const QString& oldUsername);
void onChatroomWidgetClicked(GenericChatroomWidget *, bool group);
void onStatusMessageChanged(const QString& newStatusMessage);
void onChatroomWidgetClicked(GenericChatroomWidget *);
void removeFriend(int friendId);
void copyFriendIdToClipboard(int friendId);
void removeGroup(int groupId);
@ -160,11 +181,6 @@ private slots:
void processOfflineMsgs();
void friendListContextMenu(const QPoint &pos);
#ifdef Q_OS_MAC
void bringAllToFront();
void toggleFullscreen();
#endif
private:
enum ActiveToolMenuButton {
AddButton,
@ -184,8 +200,9 @@ private:
};
private:
bool newMessageAlert(QWidget* currentWindow, bool isActive, bool notify = true);
void setActiveToolMenuButton(ActiveToolMenuButton newActiveButton);
void hideMainForms();
void hideMainForms(GenericChatroomWidget* chatroomWidget);
Group *createGroup(int groupId);
void removeFriend(Friend* f, bool fake = false);
void removeGroup(Group* g, bool fake = false);
@ -225,6 +242,7 @@ private:
Ui::MainWindow *ui;
QSplitter *centralLayout;
QPoint dragPosition;
ContentLayout* contentLayout;
AddFriendForm *addFriendForm;
ProfileForm *profileForm;
SettingsWidget *settingsWidget;
@ -243,7 +261,15 @@ private:
bool wasMaximized = false;
#ifdef Q_OS_MAC
QAction* fullscreenAction;
QAction* fileMenu;
QAction* editMenu;
QAction* contactMenu;
QMenu* changeStatusMenu;
QAction* editProfileAction;
QAction* logoutAction;
QAction* addContactAction;
QAction* nextConversationAction;
QAction* previousConversationAction;
#endif
};