1
0
Fork 0
x64dbg/src/gui/Src/Gui/TabWidget.cpp

346 lines
9.3 KiB
C++

// Qt includes
#include "tabbar.h"
#include "tabwidget.h"
#include <QMoveEvent>
#include <QApplication>
#include <QDesktopWidget>
//////////////////////////////////////////////////////////////
// Default Constructor
//////////////////////////////////////////////////////////////
MHTabWidget::MHTabWidget(QWidget* parent, bool allowDetach, bool allowDelete) : QTabWidget(parent)
{
mHistoryPopup = new MultiItemsSelectWindow(this, parentWidget(), true);
mTabBar = new MHTabBar(this, allowDetach, allowDelete);
connect(mTabBar, SIGNAL(OnDetachTab(int, const QPoint &)), this, SLOT(DetachTab(int, const QPoint &)));
connect(mTabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int)));
connect(mTabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabMoved(int, int)));
connect(mTabBar, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));
setTabBar(mTabBar);
setMovable(true);
mWindows.clear();
}
//////////////////////////////////////////////////////////////
// Default Destructor
//////////////////////////////////////////////////////////////
MHTabWidget::~MHTabWidget()
{
disconnect(mTabBar, SIGNAL(OnDetachTab(int, const QPoint &)), this, SLOT(DetachTab(int, const QPoint &)));
disconnect(mTabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int)));
disconnect(mTabBar, SIGNAL(currentChanged(int)), this, SLOT(currentChanged(int)));
delete mTabBar;
}
QWidget* MHTabWidget::widget(int index) const
{
int baseCount = QTabWidget::count();
// Check if it's just a normal tab
if(index < baseCount)
return QTabWidget::widget(index);
// Otherwise it's going to be a window
return mWindows.at(index - baseCount);
}
int MHTabWidget::count() const
{
return QTabWidget::count() + mWindows.size();
}
QList<QWidget*> MHTabWidget::windows()
{
return mWindows;
}
// Add a tab
int MHTabWidget::addTabEx(QWidget* widget, const QIcon & icon, const QString & label, const QString & nativeName)
{
mNativeNames.append(nativeName);
mHistory.push_back((MIDPKey)widget);
return this->addTab(widget, icon, label);
}
// Convert an external window to a widget tab
void MHTabWidget::AttachTab(QWidget* parent)
{
// Retrieve widget
MHDetachedWindow* detachedWidget = reinterpret_cast<MHDetachedWindow*>(parent);
QWidget* tearOffWidget = detachedWidget->centralWidget();
// Reattach the tab
auto newIndex = addTabEx(tearOffWidget, detachedWidget->windowIcon(), detachedWidget->windowTitle(), detachedWidget->mNativeName);
// Remove it from the windows list
for(int i = 0; i < mWindows.size(); i++)
{
if(mWindows.at(i) == tearOffWidget)
{
mWindows.removeAt(i);
}
}
// Cleanup Window
disconnect(detachedWidget, SIGNAL(OnClose(QWidget*)), this, SLOT(AttachTab(QWidget*)));
disconnect(detachedWidget, SIGNAL(OnFocused(QWidget*)), this, SLOT(OnDetachFocused(QWidget*)));
detachedWidget->hide();
detachedWidget->close();
// Move the tab back to the previous index
if(detachedWidget->mPreviousIndex >= 0)
mTabBar->moveTab(newIndex, detachedWidget->mPreviousIndex);
}
// Convert a tab to an external window
void MHTabWidget::DetachTab(int index, const QPoint & dropPoint)
{
Q_UNUSED(dropPoint);
// Create the window
MHDetachedWindow* detachedWidget = new MHDetachedWindow(parentWidget());
detachedWidget->setWindowModality(Qt::NonModal);
// Find Widget and connect
connect(detachedWidget, SIGNAL(OnClose(QWidget*)), this, SLOT(AttachTab(QWidget*)));
connect(detachedWidget, SIGNAL(OnFocused(QWidget*)), this, SLOT(OnDetachFocused(QWidget*)));
detachedWidget->setWindowTitle(tabText(index));
detachedWidget->setWindowIcon(tabIcon(index));
detachedWidget->mNativeName = mNativeNames[index];
detachedWidget->mPreviousIndex = index;
mNativeNames.removeAt(index);
// Remove from tab bar
QWidget* tearOffWidget = widget(index);
tearOffWidget->setParent(detachedWidget);
// Add it to the windows list
mWindows.append(tearOffWidget);
// Make first active
if(count() > 0)
setCurrentIndex(0);
// Create and show
detachedWidget->setCentralWidget(tearOffWidget);
// Needs to be done explicitly
tearOffWidget->showNormal();
QRect screenGeometry = QApplication::desktop()->screenGeometry();
int w = 640;
int h = 480;
int x = (screenGeometry.width() - w) / 2;
int y = (screenGeometry.height() - h) / 2;
detachedWidget->showNormal();
detachedWidget->setGeometry(x, y, w, h);
detachedWidget->showNormal();
}
// Remove a tab, while still keeping the widget intact
void MHTabWidget::DeleteTab(int index)
{
QWidget* w = widget(index);
mHistory.removeAll((MIDPKey)w);
removeTab(index);
mNativeNames.removeAt(index);
}
void MHTabWidget::tabMoved(int from, int to)
{
std::swap(mNativeNames[from], mNativeNames[to]);
emit tabMovedTabWidget(from, to);
}
void MHTabWidget::OnDetachFocused(QWidget* parent)
{
MHDetachedWindow* detachedWidget = reinterpret_cast<MHDetachedWindow*>(parent);
QWidget* tearOffWidget = detachedWidget->centralWidget();
setLatestFocused(tearOffWidget);
}
void MHTabWidget::currentChanged(int index)
{
setLatestFocused(widget(index));
}
void MHTabWidget::setCurrentIndex(int index)
{
// Check if it's just a normal tab
if(index < QTabWidget::count())
{
QTabWidget::setCurrentIndex(index);
}
else
{
// Otherwise it's going to be a window (just bring it up)
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(widget(index)->parent());
window->activateWindow();
window->showNormal();
window->setFocus();
}
setLatestFocused(widget(index));
}
MHTabBar* MHTabWidget::tabBar() const
{
return mTabBar;
}
const QList<MIDPKey> & MHTabWidget::MIDP_getItems() const
{
return mHistory;
}
QString MHTabWidget::MIDP_getItemName(MIDPKey index)
{
return reinterpret_cast<QWidget*>(index)->windowTitle();
}
void MHTabWidget::MIDP_selected(MIDPKey index)
{
setLatestFocused((QWidget*)index);
// check in tabbar
for(auto i = 0; i < QTabWidget::count(); ++i)
{
if(reinterpret_cast<QWidget*>(index) == QTabWidget::widget(i))
{
QTabWidget::setCurrentIndex(i);
parentWidget()->activateWindow();
parentWidget()->setFocus();
return;
}
}
// should be a detached window
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(reinterpret_cast<QWidget*>(index)->parent());
window->activateWindow();
window->showNormal();
window->setFocus();
}
QIcon MHTabWidget::MIDP_getIcon(MIDPKey index)
{
// check in tabbar
for(auto i = 0; i < QTabWidget::count(); ++i)
{
if(reinterpret_cast<QWidget*>(index) == QTabWidget::widget(i))
{
return mTabBar->tabIcon(i);
}
}
// should be a detached window
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(reinterpret_cast<QWidget*>(index)->parent());
return window->windowIcon();
}
void MHTabWidget::setLatestFocused(QWidget* w)
{
mHistory.removeAll((MIDPKey)w);
mHistory.push_front((MIDPKey)w);
}
QString MHTabWidget::getNativeName(int index)
{
if(index < QTabWidget::count())
{
return mNativeNames.at(index);
}
else
{
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(mWindows.at(index - QTabWidget::count())->parent());
if(window)
return window->mNativeName;
else
return QString();
}
}
void MHTabWidget::showPreviousTab()
{
if(QTabWidget::count() <= 1)
{
return;
}
int previousTabIndex = QTabWidget::currentIndex();
if(previousTabIndex == 0)
{
previousTabIndex = QTabWidget::count() - 1;
}
else
{
previousTabIndex--;
}
QTabWidget::setCurrentIndex(previousTabIndex);
}
void MHTabWidget::showNextTab()
{
if(QTabWidget::count() <= 1)
{
return;
}
QTabWidget::setCurrentIndex((QTabWidget::currentIndex() + 1) % QTabWidget::count());
}
void MHTabWidget::showPreviousView()
{
mHistoryPopup->gotoPreviousItem();
}
void MHTabWidget::showNextView()
{
mHistoryPopup->gotoNextItem();
}
void MHTabWidget::deleteCurrentTab()
{
if(QTabWidget::count() == 0)
{
return;
}
int index = QTabWidget::currentIndex();
DeleteTab(index);
if(index < count())
{
// open the tab to the right of the deleted tab
setCurrentIndex(index);
}
}
//----------------------------------------------------------------------------
MHDetachedWindow::MHDetachedWindow(QWidget* parent) : QMainWindow(parent)
{
}
MHDetachedWindow::~MHDetachedWindow()
{
}
void MHDetachedWindow::closeEvent(QCloseEvent* event)
{
Q_UNUSED(event);
emit OnClose(this);
}
bool MHDetachedWindow::event(QEvent* event)
{
if(event->type() == QEvent::WindowActivate && this->isActiveWindow())
{
emit OnFocused(this);
}
return QMainWindow::event(event);
}