1
0
Fork 0

Tab switch using history stack (#1807)

* add OpenViewsWindow
* almost done for history view switch
* rename the class
* add icon in history popup window
* astyle format
* add config TabSwitchUseHistory, default disable history tab switch
* remove no used code
* add shortcuts for the stuff
* rename HistoryViewsPopupWindow to MultiItemsSelectWindow, for further common use
* GUI: some small style adjustments
* GUI: change default hotkeys for ViewNextTab
This commit is contained in:
lynnux 2017-11-17 21:40:08 +08:00 committed by Duncan Ogilvie
parent 7963e5206f
commit 5b7696219e
19 changed files with 567 additions and 69 deletions

View File

@ -88,14 +88,14 @@ void LabeledSplitter::detachSlot()
// Find Widget and connect
connect(detachedWidget, SIGNAL(OnClose(LabeledSplitterDetachedWindow*)), this, SLOT(attachSlot(LabeledSplitterDetachedWindow*)));
detachedWidget->setWindowTitle(names.at(currentIndex));
detachedWidget->setWindowTitle(mNames.at(currentIndex));
detachedWidget->index = currentIndex;
// Remove from splitter
QWidget* tearOffWidget = widget(currentIndex);
tearOffWidget->setParent(detachedWidget);
// Add it to the windows list
m_Windows.append(tearOffWidget);
mWindows.append(tearOffWidget);
// Create and show
detachedWidget->setCentralWidget(tearOffWidget);
@ -110,7 +110,7 @@ void LabeledSplitter::detachSlot()
detachedWidget->showNormal();
detachedWidget->setGeometry(x, y, w, h);
detachedWidget->showNormal();
names.removeAt(currentIndex);
mNames.removeAt(currentIndex);
}
void LabeledSplitter::attachSlot(LabeledSplitterDetachedWindow* widget)
@ -119,11 +119,11 @@ void LabeledSplitter::attachSlot(LabeledSplitterDetachedWindow* widget)
QWidget* tearOffWidget = widget->centralWidget();
// Remove it from the windows list
for(int i = 0; i < m_Windows.size(); i++)
for(int i = 0; i < mWindows.size(); i++)
{
if(m_Windows.at(i) == tearOffWidget)
if(mWindows.at(i) == tearOffWidget)
{
m_Windows.removeAt(i);
mWindows.removeAt(i);
}
}
@ -161,7 +161,7 @@ void LabeledSplitterHandle::paintEvent(QPaintEvent* event)
painter.drawLine(rect.left(), rect.height() - 1, rect.right(), rect.height() - 1);
}
QRect textRect(rect.left() + charHeight, rect.top(), rect.width() - charHeight, rect.height());
painter.drawText(textRect, 0, parent->names.at(index));
painter.drawText(textRect, 0, parent->mNames.at(index));
}
void LabeledSplitterHandle::mouseMoveEvent(QMouseEvent* event)
@ -221,7 +221,7 @@ QSplitterHandle* LabeledSplitter::createHandle()
void LabeledSplitter::addWidget(QWidget* widget, const QString & name)
{
names.push_back(name);
mNames.push_back(name);
addWidget(widget);
}
@ -246,7 +246,7 @@ void LabeledSplitter::collapseLowerTabs()
void LabeledSplitter::insertWidget(int index, QWidget* widget, const QString & name)
{
names.insert(index, name);
mNames.insert(index, name);
insertWidget(index, widget);
}

View File

@ -17,15 +17,16 @@ public:
void insertWidget(int index, QWidget* widget, const QString & name);
void collapseLowerTabs();
void loadFromConfig(const QString & configName);
QList<QString> names;
QList<QWidget*> m_Windows;
public slots:
void attachSlot(LabeledSplitterDetachedWindow* widget);
void contextMenuEvent(QContextMenuEvent* event);
protected slots:
void detachSlot();
void collapseSlot();
void closeSlot();
protected:
QMenu* mMenu;
QAction* mExpandCollapseAction;
@ -38,6 +39,10 @@ protected:
void setupContextMenu();
friend class LabeledSplitterHandle;
private:
QList<QString> mNames;
QList<QWidget*> mWindows;
};
#endif //LABELEDSPLITTER_H

View File

@ -5,7 +5,7 @@ LabeledSplitterDetachedWindow::LabeledSplitterDetachedWindow(QWidget* parent, La
: QMainWindow(parent),
index(0)
{
m_SplitterWidget = splitterwidget;
mSplitterWidget = splitterwidget;
}
LabeledSplitterDetachedWindow::~LabeledSplitterDetachedWindow()

View File

@ -12,6 +12,7 @@ class LabeledSplitterHandle : public QSplitterHandle
public:
LabeledSplitterHandle(Qt::Orientation o, LabeledSplitter* parent);
int originalSize;
protected slots:
QSize sizeHint() const override;
QSize minimumSizeHint() const override;
@ -19,10 +20,12 @@ protected slots:
void mousePressEvent(QMouseEvent* event) override;
void paintEvent(QPaintEvent* event) override;
void contextMenuEvent(QContextMenuEvent* event) override;
protected:
int getIndex();
int charHeight;
LabeledSplitter* getParent() const;
int charHeight;
};
class LabeledSplitterDetachedWindow : public QMainWindow
@ -31,16 +34,17 @@ class LabeledSplitterDetachedWindow : public QMainWindow
public:
LabeledSplitterDetachedWindow(QWidget* parent = 0, LabeledSplitter* splitterwidget = 0);
~LabeledSplitterDetachedWindow(void);
~LabeledSplitterDetachedWindow();
int index;
protected:
LabeledSplitter* m_SplitterWidget;
void closeEvent(QCloseEvent* event);
signals:
void OnClose(LabeledSplitterDetachedWindow* widget);
protected:
void closeEvent(QCloseEvent* event);
LabeledSplitter* mSplitterWidget;
};

View File

@ -67,11 +67,11 @@ void CPUSideBar::updateColors()
void CPUSideBar::updateFonts()
{
m_DefaultFont = mDisas->font();
this->setFont(m_DefaultFont);
mDefaultFont = mDisas->font();
this->setFont(mDefaultFont);
delete mFontMetrics;
mFontMetrics = new CachedFontMetrics(this, m_DefaultFont);
mFontMetrics = new CachedFontMetrics(this, mDefaultFont);
fontWidth = mFontMetrics->width(' ');
fontHeight = mFontMetrics->height();

View File

@ -60,7 +60,7 @@ private:
CachedFontMetrics* mFontMetrics;
dsint topVA;
dsint selectedVA;
QFont m_DefaultFont;
QFont mDefaultFont;
int fontWidth, fontHeight;
int viewableRows;
int mBulletRadius;

View File

@ -211,7 +211,6 @@ MainWindow::MainWindow(QWidget* parent)
mTraceBrowser->setWindowIcon(DIcon("trace.png"));
connect(mTraceBrowser, SIGNAL(displayReferencesWidget()), this, SLOT(displayReferencesWidget()));
// Create the tab widget and enable detaching and hiding
mTabWidget = new MHTabWidget(this, true, true);
// Add all widgets to the list
@ -321,6 +320,8 @@ MainWindow::MainWindow(QWidget* parent)
connect(ui->actionGraph, SIGNAL(triggered()), this, SLOT(displayGraphWidget()));
connect(ui->actionPreviousTab, SIGNAL(triggered()), this, SLOT(displayPreviousTab()));
connect(ui->actionNextTab, SIGNAL(triggered()), this, SLOT(displayNextTab()));
connect(ui->actionPreviousView, SIGNAL(triggered()), this, SLOT(displayPreviousView()));
connect(ui->actionNextView, SIGNAL(triggered()), this, SLOT(displayNextView()));
connect(ui->actionHideTab, SIGNAL(triggered()), this, SLOT(hideTab()));
makeCommandAction(ui->actionStepIntoSource, "TraceIntoConditional src.line(cip) && !src.disp(cip)");
makeCommandAction(ui->actionStepOverSource, "TraceOverConditional src.line(cip) && !src.disp(cip)");
@ -690,6 +691,8 @@ void MainWindow::refreshShortcuts()
setGlobalShortcut(ui->actionGraph, ConfigShortcut("ViewGraph"));
setGlobalShortcut(ui->actionPreviousTab, ConfigShortcut("ViewPreviousTab"));
setGlobalShortcut(ui->actionNextTab, ConfigShortcut("ViewNextTab"));
setGlobalShortcut(ui->actionPreviousView, ConfigShortcut("ViewPreviousHistory"));
setGlobalShortcut(ui->actionNextView, ConfigShortcut("ViewNextHistory"));
setGlobalShortcut(ui->actionHideTab, ConfigShortcut("ViewHideTab"));
setGlobalShortcut(ui->actionRun, ConfigShortcut("DebugRun"));
@ -904,6 +907,17 @@ void MainWindow::dropEvent(QDropEvent* pEvent)
}
}
bool MainWindow::event(QEvent* event)
{
// just make sure mTabWidget take current view as the latest
if(event->type() == QEvent::WindowActivate && this->isActiveWindow())
{
mTabWidget->setCurrentIndex(mTabWidget->currentIndex());
}
return QMainWindow::event(event);
}
void MainWindow::updateWindowTitleSlot(QString filename)
{
if(filename.length())
@ -963,6 +977,16 @@ void MainWindow::displayNextTab()
mTabWidget->showNextTab();
}
void MainWindow::displayPreviousView()
{
mTabWidget->showPreviousView();
}
void MainWindow::displayNextView()
{
mTabWidget->showNextView();
}
void MainWindow::hideTab()
{
mTabWidget->deleteCurrentTab();

View File

@ -92,6 +92,8 @@ public slots:
void displayRunTrace();
void displayPreviousTab();
void displayNextTab();
void displayPreviousView();
void displayNextView();
void hideTab();
void openSettings();
void openAppearance();
@ -265,6 +267,7 @@ private:
protected:
void dragEnterEvent(QDragEnterEvent* pEvent);
void dropEvent(QDropEvent* pEvent);
bool event(QEvent* event);
public:
static QString windowTitle;

View File

@ -81,6 +81,8 @@
<addaction name="separator"/>
<addaction name="actionPreviousTab"/>
<addaction name="actionNextTab"/>
<addaction name="actionPreviousView"/>
<addaction name="actionNextView"/>
<addaction name="actionHideTab"/>
</widget>
<widget class="QMenu" name="menuDebug">
@ -1107,6 +1109,24 @@
<string>Next Tab</string>
</property>
</action>
<action name="actionPreviousView">
<property name="icon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/previous.png</normaloff>:/icons/images/previous.png</iconset>
</property>
<property name="text">
<string>Previous View</string>
</property>
</action>
<action name="actionNextView">
<property name="icon">
<iconset resource="../../resource.qrc">
<normaloff>:/icons/images/next.png</normaloff>:/icons/images/next.png</iconset>
</property>
<property name="text">
<string>Next View</string>
</property>
</action>
<action name="actionHideTab">
<property name="icon">
<iconset resource="../../resource.qrc">

View File

@ -0,0 +1,245 @@
#include "MultiItemsSelectWindow.h"
#define QTC_ASSERT(cond, action) if (cond) {} else { action; } do {} while (0)
#include <QFocusEvent>
#include <QHeaderView>
#include <QVBoxLayout>
#include <QScrollBar>
#include <QApplication>
enum class Role
{
ItemData = Qt::UserRole
};
MultiItemsSelectWindow::MultiItemsSelectWindow(MultiItemsDataProvider* hp, QWidget* parent, bool showIcon) :
QFrame(parent, Qt::Popup),
mDataProvider(hp),
mShowIcon(showIcon),
mEditorList(new OpenViewsTreeWidget(this))
{
setMinimumSize(300, 200);
mEditorList->setColumnCount(1);
mEditorList->header()->hide();
mEditorList->setIndentation(0);
mEditorList->setSelectionMode(QAbstractItemView::SingleSelection);
mEditorList->setTextElideMode(Qt::ElideMiddle);
mEditorList->installEventFilter(this);
setFrameStyle(mEditorList->frameStyle());
mEditorList->setFrameStyle(QFrame::NoFrame);
QVBoxLayout* layout = new QVBoxLayout(this);
layout->setMargin(0);
layout->addWidget(mEditorList);
connect(mEditorList, &QTreeWidget::itemClicked,
this, &MultiItemsSelectWindow::editorClicked);
setVisible(false);
}
void MultiItemsSelectWindow::gotoNextItem()
{
if(isVisible())
{
selectPreviousEditor();
}
else
{
addItems();
selectPreviousEditor();
showPopupOrSelectDocument();
}
}
void MultiItemsSelectWindow::gotoPreviousItem()
{
if(isVisible())
{
selectNextEditor();
}
else
{
addItems();
selectNextEditor();
showPopupOrSelectDocument();
}
}
void MultiItemsSelectWindow::showPopupOrSelectDocument()
{
if(QApplication::keyboardModifiers() == Qt::NoModifier)
{
selectAndHide();
}
else
{
QWidget* activeWindow = QApplication::activeWindow();
if(!activeWindow)
return;
QWidget* referenceWidget = activeWindow;
const QPoint p = referenceWidget->mapToGlobal(QPoint(0, 0));
this->setMaximumSize(qMax(this->minimumWidth(), referenceWidget->width() / 2),
qMax(this->minimumHeight(), referenceWidget->height() / 2));
this->adjustSize();
this->move((referenceWidget->width() - this->width()) / 2 + p.x(),
(referenceWidget->height() - this->height()) / 2 + p.y());
this->setVisible(true);
}
}
void MultiItemsSelectWindow::selectAndHide()
{
setVisible(false);
selectEditor(mEditorList->currentItem());
}
void MultiItemsSelectWindow::setVisible(bool visible)
{
QWidget::setVisible(visible);
if(visible)
setFocus();
}
bool MultiItemsSelectWindow::eventFilter(QObject* obj, QEvent* e)
{
if(obj == mEditorList)
{
if(e->type() == QEvent::KeyPress)
{
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
if(ke->key() == Qt::Key_Escape)
{
setVisible(false);
return true;
}
if(ke->key() == Qt::Key_Return
|| ke->key() == Qt::Key_Enter)
{
selectEditor(mEditorList->currentItem());
return true;
}
}
else if(e->type() == QEvent::KeyRelease)
{
QKeyEvent* ke = static_cast<QKeyEvent*>(e);
if(ke->modifiers() == 0
/*HACK this is to overcome some event inconsistencies between platforms*/
|| (ke->modifiers() == Qt::AltModifier
&& (ke->key() == Qt::Key_Alt || ke->key() == -1)))
{
selectAndHide();
}
}
}
return QWidget::eventFilter(obj, e);
}
void MultiItemsSelectWindow::focusInEvent(QFocusEvent*)
{
mEditorList->setFocus();
}
void MultiItemsSelectWindow::selectUpDown(bool up)
{
int itemCount = mEditorList->topLevelItemCount();
if(itemCount < 2)
return;
int index = mEditorList->indexOfTopLevelItem(mEditorList->currentItem());
if(index < 0)
return;
QTreeWidgetItem* editor = 0;
int count = 0;
while(!editor && count < itemCount)
{
if(up)
{
index--;
if(index < 0)
index = itemCount - 1;
}
else
{
index++;
if(index >= itemCount)
index = 0;
}
editor = mEditorList->topLevelItem(index);
count++;
}
if(editor)
{
mEditorList->setCurrentItem(editor);
ensureCurrentVisible();
}
}
void MultiItemsSelectWindow::selectPreviousEditor()
{
selectUpDown(false);
}
QSize MultiItemsSelectWindow::OpenViewsTreeWidget::sizeHint() const
{
return QSize(sizeHintForColumn(0) + verticalScrollBar()->width() + frameWidth() * 2,
viewportSizeHint().height() + frameWidth() * 2);
}
QSize MultiItemsSelectWindow::sizeHint() const
{
return mEditorList->sizeHint() + QSize(frameWidth() * 2, frameWidth() * 2);
}
void MultiItemsSelectWindow::selectNextEditor()
{
selectUpDown(true);
}
void MultiItemsSelectWindow::addItems()
{
mEditorList->clear();
auto & history = mDataProvider->MIDP_getItems();
for(auto & i : history)
{
addItem(i);
}
}
void MultiItemsSelectWindow::selectEditor(QTreeWidgetItem* item)
{
if(!item)
return;
auto index = item->data(0, int(Role::ItemData)).value<MIDPKey>();
mDataProvider->MIDP_selected(index);
}
void MultiItemsSelectWindow::editorClicked(QTreeWidgetItem* item)
{
selectEditor(item);
setFocus();
}
void MultiItemsSelectWindow::ensureCurrentVisible()
{
mEditorList->scrollTo(mEditorList->currentIndex(), QAbstractItemView::PositionAtCenter);
}
void MultiItemsSelectWindow::addItem(MIDPKey index)
{
QTreeWidgetItem* item = new QTreeWidgetItem();
if(mShowIcon)
item->setIcon(0, mDataProvider->MIDP_getIcon(index));
item->setText(0, mDataProvider->MIDP_getItemName(index));
item->setData(0, int(Role::ItemData), QVariant::fromValue(index));
item->setTextAlignment(0, Qt::AlignLeft);
mEditorList->addTopLevelItem(item);
if(mEditorList->topLevelItemCount() == 1)
mEditorList->setCurrentItem(item);
}

View File

@ -0,0 +1,71 @@
#ifndef OPENVIEWSWINDOW_H
#define OPENVIEWSWINDOW_H
// stolen from http://code.qt.io/cgit/qt-creator/qt-creator.git/tree/src/plugins/coreplugin/editormanager/openeditorswindow.h
#include <QFrame>
#include <QIcon>
#include <QList>
#include <QTreeWidget>
QT_BEGIN_NAMESPACE
class QTreeWidgetItem;
class QWidget;
QT_END_NAMESPACE
typedef void* MIDPKey;
class MultiItemsDataProvider
{
public:
virtual const QList<MIDPKey> & MIDP_getItems() const = 0;
virtual QString MIDP_getItemName(MIDPKey index) = 0;
virtual QIcon MIDP_getIcon(MIDPKey index) = 0;
virtual void MIDP_selected(MIDPKey index) = 0;
};
class MultiItemsSelectWindow : public QFrame
{
Q_OBJECT
public:
MultiItemsSelectWindow(MultiItemsDataProvider* hp, QWidget* parent, bool showIcon);
void gotoNextItem();
void gotoPreviousItem();
private slots:
void selectAndHide();
private:
void addItems();
bool eventFilter(QObject* src, QEvent* e);
void focusInEvent(QFocusEvent*);
void setVisible(bool visible);
void selectNextEditor();
void selectPreviousEditor();
QSize sizeHint() const;
void showPopupOrSelectDocument();
void editorClicked(QTreeWidgetItem* item);
void selectEditor(QTreeWidgetItem* item);
void addItem(MIDPKey index);
void ensureCurrentVisible();
void selectUpDown(bool up);
class OpenViewsTreeWidget : public QTreeWidget
{
public:
explicit OpenViewsTreeWidget(QWidget* parent = 0) : QTreeWidget(parent) {}
~OpenViewsTreeWidget() {}
QSize sizeHint() const;
};
OpenViewsTreeWidget* mEditorList;
MultiItemsDataProvider* mDataProvider = nullptr;
bool mShowIcon;
};
#endif

View File

@ -10,7 +10,7 @@ SelectFields::SelectFields(QWidget* parent) :
setModal(true);
}
QListWidget* SelectFields::GetList(void)
QListWidget* SelectFields::GetList()
{
return ui->listWidget;
}

View File

@ -16,7 +16,7 @@ class SelectFields : public QDialog
public:
explicit SelectFields(QWidget* parent = 0);
QListWidget* GetList(void);
QListWidget* GetList();
~SelectFields();
private:

View File

@ -30,7 +30,7 @@ MHTabBar::MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete) : QTabBa
//////////////////////////////////////////////////////////////
// Default Destructor
//////////////////////////////////////////////////////////////
MHTabBar::~MHTabBar(void)
MHTabBar::~MHTabBar()
{
}

View File

@ -14,7 +14,7 @@ class MHTabBar: public QTabBar
public:
MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete);
~MHTabBar(void);
~MHTabBar();
protected:
void contextMenuEvent(QContextMenuEvent* event);

View File

@ -10,28 +10,32 @@
//////////////////////////////////////////////////////////////
MHTabWidget::MHTabWidget(QWidget* parent, bool allowDetach, bool allowDelete) : QTabWidget(parent)
{
m_tabBar = new MHTabBar(this, allowDetach, allowDelete);
connect(m_tabBar, SIGNAL(OnDetachTab(int, const QPoint &)), this, SLOT(DetachTab(int, const QPoint &)));
connect(m_tabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int)));
connect(m_tabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int)));
connect(m_tabBar, SIGNAL(tabMoved(int, int)), this, SLOT(tabMoved(int, int)));
mHistoryPopup = new MultiItemsSelectWindow(this, parentWidget(), true);
setTabBar(m_tabBar);
mTabBar = new MHTabBar(this, allowDetach, allowDelete);
connect(mTabBar, SIGNAL(OnDetachTab(int, const QPoint &)), this, SLOT(DetachTab(int, const QPoint &)));
connect(mTabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int)));
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);
setStyleSheet("QTabWidget::pane { border: 0px; }");
m_Windows.clear();
mWindows.clear();
}
//////////////////////////////////////////////////////////////
// Default Destructor
//////////////////////////////////////////////////////////////
MHTabWidget::~MHTabWidget(void)
MHTabWidget::~MHTabWidget()
{
disconnect(m_tabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int)));
disconnect(m_tabBar, SIGNAL(OnDetachTab(int, const QPoint &)), this, SLOT(DetachTab(int, const QPoint &)));
disconnect(m_tabBar, SIGNAL(OnDeleteTab(int)), this, SLOT(DeleteTab(int)));
delete m_tabBar;
disconnect(mTabBar, SIGNAL(OnMoveTab(int, int)), this, SLOT(MoveTab(int, int)));
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
@ -43,23 +47,24 @@ QWidget* MHTabWidget::widget(int index) const
return QTabWidget::widget(index);
// Otherwise it's going to be a window
return m_Windows.at(index - baseCount);
return mWindows.at(index - baseCount);
}
int MHTabWidget::count() const
{
return QTabWidget::count() + m_Windows.size();
return QTabWidget::count() + mWindows.size();
}
QList<QWidget*> MHTabWidget::windows()
{
return m_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);
}
@ -74,16 +79,17 @@ void MHTabWidget::AttachTab(QWidget* parent)
addTabEx(tearOffWidget, detachedWidget->windowIcon(), detachedWidget->windowTitle(), detachedWidget->mNativeName);
// Remove it from the windows list
for(int i = 0; i < m_Windows.size(); i++)
for(int i = 0; i < mWindows.size(); i++)
{
if(m_Windows.at(i) == tearOffWidget)
if(mWindows.at(i) == tearOffWidget)
{
m_Windows.removeAt(i);
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();
}
@ -98,6 +104,7 @@ void MHTabWidget::DetachTab(int index, const QPoint & dropPoint)
// 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));
@ -109,7 +116,7 @@ void MHTabWidget::DetachTab(int index, const QPoint & dropPoint)
tearOffWidget->setParent(detachedWidget);
// Add it to the windows list
m_Windows.append(tearOffWidget);
mWindows.append(tearOffWidget);
// Make first active
if(count() > 0)
@ -145,6 +152,8 @@ void MHTabWidget::MoveTab(int fromIndex, int toIndex)
// 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);
}
@ -158,6 +167,18 @@ void MHTabWidget::tabMoved(int from, int 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
@ -173,11 +194,68 @@ void MHTabWidget::setCurrentIndex(int index)
window->showNormal();
window->setFocus();
}
setLatestFocused(widget(index));
}
MHTabBar* MHTabWidget::tabBar() const
{
return m_tabBar;
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)
@ -188,7 +266,7 @@ QString MHTabWidget::getNativeName(int index)
}
else
{
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(m_Windows.at(index - QTabWidget::count())->parent());
MHDetachedWindow* window = dynamic_cast<MHDetachedWindow*>(mWindows.at(index - QTabWidget::count())->parent());
if(window)
return window->mNativeName;
else
@ -226,6 +304,16 @@ void MHTabWidget::showNextTab()
QTabWidget::setCurrentIndex((QTabWidget::currentIndex() + 1) % QTabWidget::count());
}
void MHTabWidget::showPreviousView()
{
mHistoryPopup->gotoPreviousItem();
}
void MHTabWidget::showNextView()
{
mHistoryPopup->gotoNextItem();
}
void MHTabWidget::deleteCurrentTab()
{
if(QTabWidget::count() == 0)
@ -246,10 +334,10 @@ void MHTabWidget::deleteCurrentTab()
MHDetachedWindow::MHDetachedWindow(QWidget* parent, MHTabWidget* tabwidget) : QMainWindow(parent)
{
m_TabWidget = tabwidget;
mTabWidget = tabwidget;
}
MHDetachedWindow::~MHDetachedWindow(void)
MHDetachedWindow::~MHDetachedWindow()
{
}
@ -259,3 +347,12 @@ void MHDetachedWindow::closeEvent(QCloseEvent* event)
emit OnClose(this);
}
bool MHDetachedWindow::event(QEvent* event)
{
if(event->type() == QEvent::WindowActivate && this->isActiveWindow())
{
emit OnFocused(this);
}
return QMainWindow::event(event);
}

View File

@ -6,6 +6,7 @@
#include <QTabWidget>
#include <QMainWindow>
#include "TabBar.h"
#include "MultiItemsSelectWindow.h"
// Qt forward class definitions
class MHTabBar;
@ -15,13 +16,13 @@ class MHTabBar;
// MHTabWidget implements the a Tab Widget with detach and attach
// functionality for MHTabBar.
//////////////////////////////////////////////////////////////////////////////
class MHTabWidget: public QTabWidget
class MHTabWidget: public QTabWidget, public MultiItemsDataProvider
{
Q_OBJECT
public:
MHTabWidget(QWidget* parent = nullptr, bool allowDetach = true, bool allowDelete = false);
virtual ~MHTabWidget(void);
virtual ~MHTabWidget();
QWidget* widget(int index) const;
int count() const;
@ -31,7 +32,10 @@ public:
QString getNativeName(int index);
void showPreviousTab();
void showNextTab();
void showPreviousView();
void showNextView();
void deleteCurrentTab();
signals:
void tabMovedTabWidget(int from, int to);
@ -41,18 +45,24 @@ public slots:
void MoveTab(int fromIndex, int toIndex);
void DeleteTab(int index);
void tabMoved(int from, int to);
public Q_SLOTS:
void OnDetachFocused(QWidget* parent);
void currentChanged(int index);
void setCurrentIndex(int index);
protected:
MHTabBar* tabBar() const;
const QList<MIDPKey> & MIDP_getItems() const override;
QString MIDP_getItemName(MIDPKey index) override;
void MIDP_selected(MIDPKey index) override;
QIcon MIDP_getIcon(MIDPKey index) override;
void setLatestFocused(QWidget* w);
private:
MHTabBar* m_tabBar;
QList<QWidget*> m_Windows;
MHTabBar* mTabBar;
QList<QWidget*> mWindows;
QList<QString> mNativeNames;
MultiItemsSelectWindow* mHistoryPopup;
QList<MIDPKey> mHistory;
};
//////////////////////////////////////////////////////////////////////////////
@ -68,16 +78,19 @@ class MHDetachedWindow : public QMainWindow
public:
MHDetachedWindow(QWidget* parent = 0, MHTabWidget* tabwidget = 0);
~MHDetachedWindow(void);
~MHDetachedWindow();
QString mNativeName;
protected:
MHTabWidget* m_TabWidget;
void closeEvent(QCloseEvent* event);
signals:
void OnClose(QWidget* widget);
void OnFocused(QWidget* widget);
protected:
void closeEvent(QCloseEvent* event);
bool event(QEvent* event);
MHTabWidget* mTabWidget;
};
#endif // __MHTABWIDGET_H__

View File

@ -398,8 +398,10 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
defaultShortcuts.insert("ViewSnowman", Shortcut({tr("View"), tr("Snowman")}, "", true));
defaultShortcuts.insert("ViewHandles", Shortcut({tr("View"), tr("Handles")}, "", true));
defaultShortcuts.insert("ViewGraph", Shortcut({tr("View"), tr("Graph")}, "Alt+G", true));
defaultShortcuts.insert("ViewPreviousTab", Shortcut({tr("View"), tr("Previous Tab")}, "Ctrl+Shift+Tab"));
defaultShortcuts.insert("ViewNextTab", Shortcut({tr("View"), tr("Next Tab")}, "Ctrl+Tab"));
defaultShortcuts.insert("ViewPreviousTab", Shortcut({tr("View"), tr("Previous Tab")}, "Alt+Left"));
defaultShortcuts.insert("ViewNextTab", Shortcut({tr("View"), tr("Next Tab")}, "Alt+Right"));
defaultShortcuts.insert("ViewPreviousHistory", Shortcut({tr("View"), tr("Previous View")}, "Ctrl+Shift+Tab"));
defaultShortcuts.insert("ViewNextHistory", Shortcut({tr("View"), tr("Next View")}, "Ctrl+Tab"));
defaultShortcuts.insert("ViewHideTab", Shortcut({tr("View"), tr("Hide Tab")}, "Ctrl+W"));
defaultShortcuts.insert("DebugRun", Shortcut({tr("Debug"), tr("Run")}, "F9", true));
@ -610,9 +612,21 @@ Configuration::Configuration() : QObject(), noMoreMsgbox(false)
Shortcuts = defaultShortcuts;
load();
//because we changed the default this needs special handling for old configurations
if(Shortcuts["ViewPreviousTab"].Hotkey.toString() == Shortcuts["ViewPreviousHistory"].Hotkey.toString())
{
Shortcuts["ViewPreviousTab"].Hotkey = defaultShortcuts["ViewPreviousTab"].Hotkey;
save();
}
if(Shortcuts["ViewNextTab"].Hotkey.toString() == Shortcuts["ViewNextHistory"].Hotkey.toString())
{
Shortcuts["ViewNextTab"].Hotkey = defaultShortcuts["ViewNextTab"].Hotkey;
save();
}
}
Configuration* Config()
Configuration* Configuration::instance()
{
return mPtr;
}

View File

@ -188,7 +188,8 @@ SOURCES += \
Src/Utils/SymbolAutoCompleteModel.cpp \
Src/Tracer/TraceBrowser.cpp \
Src/Tracer/TraceFileReader.cpp \
Src/Tracer/TraceFileSearch.cpp
Src/Tracer/TraceFileSearch.cpp \
Src/Gui/MultiItemsSelectWindow.cpp
HEADERS += \
@ -311,7 +312,8 @@ HEADERS += \
Src/Tracer/TraceBrowser.h \
Src/Tracer/TraceFileReader.h \
Src/Tracer/TraceFileReaderInternal.h \
Src/Tracer/TraceFileSearch.h
Src/Tracer/TraceFileSearch.h \
Src/Gui/MultiItemsSelectWindow.h
FORMS += \