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:
parent
7963e5206f
commit
5b7696219e
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,7 +5,7 @@ LabeledSplitterDetachedWindow::LabeledSplitterDetachedWindow(QWidget* parent, La
|
|||
: QMainWindow(parent),
|
||||
index(0)
|
||||
{
|
||||
m_SplitterWidget = splitterwidget;
|
||||
mSplitterWidget = splitterwidget;
|
||||
}
|
||||
|
||||
LabeledSplitterDetachedWindow::~LabeledSplitterDetachedWindow()
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
||||
|
|
|
@ -60,7 +60,7 @@ private:
|
|||
CachedFontMetrics* mFontMetrics;
|
||||
dsint topVA;
|
||||
dsint selectedVA;
|
||||
QFont m_DefaultFont;
|
||||
QFont mDefaultFont;
|
||||
int fontWidth, fontHeight;
|
||||
int viewableRows;
|
||||
int mBulletRadius;
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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">
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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
|
|
@ -10,7 +10,7 @@ SelectFields::SelectFields(QWidget* parent) :
|
|||
setModal(true);
|
||||
}
|
||||
|
||||
QListWidget* SelectFields::GetList(void)
|
||||
QListWidget* SelectFields::GetList()
|
||||
{
|
||||
return ui->listWidget;
|
||||
}
|
||||
|
|
|
@ -16,7 +16,7 @@ class SelectFields : public QDialog
|
|||
|
||||
public:
|
||||
explicit SelectFields(QWidget* parent = 0);
|
||||
QListWidget* GetList(void);
|
||||
QListWidget* GetList();
|
||||
~SelectFields();
|
||||
|
||||
private:
|
||||
|
|
|
@ -30,7 +30,7 @@ MHTabBar::MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete) : QTabBa
|
|||
//////////////////////////////////////////////////////////////
|
||||
// Default Destructor
|
||||
//////////////////////////////////////////////////////////////
|
||||
MHTabBar::~MHTabBar(void)
|
||||
MHTabBar::~MHTabBar()
|
||||
{
|
||||
}
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ class MHTabBar: public QTabBar
|
|||
|
||||
public:
|
||||
MHTabBar(QWidget* parent, bool allowDetach, bool allowDelete);
|
||||
~MHTabBar(void);
|
||||
~MHTabBar();
|
||||
|
||||
protected:
|
||||
void contextMenuEvent(QContextMenuEvent* event);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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__
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 += \
|
||||
|
|
Loading…
Reference in New Issue