Qt Editor: Add viewport context menu

qteditor
Sven Eberhardt 2016-06-19 18:19:43 -04:00
parent 7d43d364d0
commit e7be7d6acd
9 changed files with 192 additions and 4 deletions

View File

@ -85,6 +85,8 @@ IDS_CNS_SCENARIOSAVED=Szenario gespeichert.
IDS_CNS_SCENARIOSETTINGS=Szenarieneinstellungen
IDS_CNS_SCRIPT=Script
IDS_CNS_SCRIPTCREATEDOBJECTS=Das Script dieses Szenarios hat beim Start der Runde Objekte erschaffen.
IDS_CNS_SELECTNEARBYOBJECTS=Objekt auswählen
IDS_CNS_SELECTCONTENTS=%s Inhalt...
IDS_CNS_TITLE=Titel
IDS_CNS_TRUE=Ja
IDS_CNS_TYPE=Typ: %s (%s)

View File

@ -85,6 +85,8 @@ IDS_CNS_SCENARIOSAVED=Scenario saved.
IDS_CNS_SCENARIOSETTINGS=Scenario settings
IDS_CNS_SCRIPT=Script
IDS_CNS_SCRIPTCREATEDOBJECTS=This scenario's script has created objects on initialization.
IDS_CNS_SELECTNEARBYOBJECTS=Select object
IDS_CNS_SELECTCONTENTS=%s contents...
IDS_CNS_TITLE=Title
IDS_CNS_TRUE=Yes
IDS_CNS_TYPE=Type: %s (%s)

View File

@ -975,6 +975,33 @@
<string>MAP_STATICFLAT_TIP</string>
</property>
</action>
<action name="actionDeleteObject">
<property name="text">
<string comment="res">IDS_MNU_DELETE</string>
</property>
<property name="toolTip">
<string comment="res">IDS_MNU_DELETE</string>
</property>
<property name="shortcut">
<string>Del</string>
</property>
</action>
<action name="actionDuplicateObject">
<property name="text">
<string comment="res">IDS_MNU_DUPLICATE</string>
</property>
<property name="toolTip">
<string comment="res">IDS_MNU_DUPLICATE</string>
</property>
</action>
<action name="actionEjectContents">
<property name="text">
<string comment="res">IDS_MNU_CONTENTS</string>
</property>
<property name="toolTip">
<string comment="res">IDS_MNU_CONTENTS</string>
</property>
</action>
</widget>
<resources>
<include location="resource.qrc"/>
@ -1540,6 +1567,54 @@
</hint>
</hints>
</connection>
<connection>
<sender>actionDeleteObject</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>SelectionDelete()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>312</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionDuplicateObject</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>SelectionDuplicate()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>312</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionEjectContents</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>SelectionEjectContents()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>312</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>PlayPressed(bool)</slot>
@ -1576,5 +1651,8 @@
<slot>AddArrayElement()</slot>
<slot>RemoveArrayElement()</slot>
<slot>StaticFlatLandscapePressed(bool)</slot>
<slot>SelectionDelete()</slot>
<slot>SelectionDuplicate()</slot>
<slot>SelectionEjectContents()</slot>
</slots>
</ui>

View File

@ -420,6 +420,21 @@ void C4ConsoleQtMainWindow::WelcomeLinkActivated(const QString &link)
}
}
void C4ConsoleQtMainWindow::SelectionDelete()
{
::Console.EditCursor.Delete();
}
void C4ConsoleQtMainWindow::SelectionDuplicate()
{
::Console.EditCursor.Duplicate();
}
void C4ConsoleQtMainWindow::SelectionEjectContents()
{
::Console.EditCursor.GrabContents();
}
/* Common C4ConsoleGUI interface */

View File

@ -141,6 +141,10 @@ public slots:
void BackgroundMaterialChanged(const QString &new_selection);
// Links on welcome page
void WelcomeLinkActivated(const QString &link);
// Object context menu
void SelectionDelete();
void SelectionDuplicate();
void SelectionEjectContents();
};

View File

@ -23,10 +23,12 @@
#include "editor/C4Console.h"
#include "editor/C4ConsoleQtShapes.h"
#include "game/C4Viewport.h"
#include "object/C4Object.h"
#include "editor/C4ViewportWindow.h"
#include "editor/C4Console.h"
#include "gui/C4MouseControl.h"
#include "landscape/C4Landscape.h"
#include "object/C4GameObjects.h"
/* Console viewports */
@ -36,9 +38,12 @@ C4ConsoleQtViewportView::C4ConsoleQtViewportView(class C4ConsoleQtViewportScroll
setAttribute(Qt::WA_ShowWithoutActivating, true);
setFocusPolicy(Qt::WheelFocus);
setMouseTracking(true);
setContextMenuPolicy(Qt::CustomContextMenu);
// Register for viewport
C4ViewportWindow *window = dock->cvp;
window->glwidget = this;
// Enable context menu
connect(this, &QWidget::customContextMenuRequested, this, &C4ConsoleQtViewportView::ShowContextMenu);
}
bool C4ConsoleQtViewportView::IsPlayViewport() const
@ -61,6 +66,82 @@ qreal C4ConsoleQtViewportView::GetDevicePixelRatio()
return screen->devicePixelRatio();
}
void C4ConsoleQtViewportView::AddSelectObjectContextEntry(C4Object *obj, QMenu *menu)
{
// Add select object item for object and for all contents
if (!obj || !obj->Status) return;
int32_t object_number = obj->Number;
QAction *select_object_action = new QAction(QString("%1 #%2 (%3/%4)").arg(obj->GetName()).arg(object_number).arg(obj->GetX()).arg(obj->GetY()), menu);
connect(select_object_action, &QAction::triggered, menu, [object_number]() {
bool add = !!(QGuiApplication::keyboardModifiers() & Qt::ShiftModifier);
C4Object *obj = ::Objects.SafeObjectPointer(object_number);
if (obj) ::Console.EditCursor.DoContextObjsel(obj, !add);
});
menu->addAction(select_object_action);
if (obj->Contents.ObjectCount())
{
QMenu *submenu = menu->addMenu(FormatString(LoadResStr("IDS_CNS_SELECTCONTENTS"), obj->GetName()).getData());
for (C4Object *cobj : obj->Contents)
{
AddSelectObjectContextEntry(cobj, submenu);
}
}
}
void C4ConsoleQtViewportView::ShowContextMenu(const QPoint &pos)
{
// Coordinates are in viewport (not adjusted by parent scroll window)
if (!IsPlayViewport())
{
// Show context menu in editor viewport
QMenu *menu = new QMenu(this);
// Show current object(s) as unselectable item
auto &ui = dock->main_window->GetConsoleState()->ui;
menu->addSection(ui.selectionInfoLabel->text());
// Object actions. Always shown but grayed out if no object is selected.
bool has_object = false;
int32_t contents_count = 0;
for (const C4Value &sel : ::Console.EditCursor.GetSelection())
{
C4Object *obj = sel.getObj();
if (obj)
{
has_object = true;
contents_count += obj->Contents.ObjectCount();
}
}
for (QAction *act : { ui.actionDeleteObject, ui.actionDuplicateObject, ui.actionEjectContents })
{
act->setEnabled(has_object);
menu->addAction(act);
}
if (!contents_count)
{
ui.actionEjectContents->setEnabled(false);
}
ui.actionEjectContents->setText(QString("%1 (%2)").arg(LoadResStr("IDS_MNU_CONTENTS")).arg((int)contents_count));
// Object selection section for overlapping objects
auto pr = GetDevicePixelRatio();
int32_t x = cvp->WindowToGameX(pr * pos.x()),
y = cvp->WindowToGameY(pr * pos.y());
auto pFOl = new C4FindObjectAtPoint(x, y); // freed by ~C4FindObjectAnd
auto pFOc = new C4FindObjectContainer(nullptr); // freed by ~C4FindObjectAnd
C4FindObject *pFO_conds[] = { pFOl , pFOc };
C4FindObjectAnd pFO(2, pFO_conds, false);
std::unique_ptr<C4ValueArray> atcursor(pFO.FindMany(::Objects, ::Objects.Sectors)); // needs freeing (single object ptr)
int itemcount = atcursor->GetSize();
if (itemcount)
{
menu->addSection(LoadResStr("IDS_CNS_SELECTNEARBYOBJECTS"));
for (int32_t i = 0; i < itemcount; ++i)
{
AddSelectObjectContextEntry(atcursor->GetItem(i).getObj(), menu);
}
}
menu->popup(mapToGlobal(pos));
}
}
// Get Shift state as Win32 wParam
uint32_t GetShiftWParam()
{

View File

@ -34,6 +34,8 @@ class C4ConsoleQtViewportView : public QOpenGLWidget
private:
bool IsPlayViewport() const;
qreal GetDevicePixelRatio();
void ShowContextMenu(const QPoint &pos);
void AddSelectObjectContextEntry(C4Object *obj, QMenu *menu);
protected:
void focusInEvent(QFocusEvent * event) override;

View File

@ -615,11 +615,12 @@ bool SetMenuItemText(HMENU hMenu, WORD id, const char *szText)
bool C4EditCursor::RightButtonUp(DWORD dwKeyState)
{
Target=NULL;
#ifndef WITH_QT_EDITOR
DoContextMenu(dwKeyState);
#endif
// Update
UpdateStatusBar();
return true;
}

View File

@ -130,8 +130,8 @@ protected:
void ToolFailure();
void PutContents();
void UpdateDropTarget(DWORD dwKeyState);
void AppendMenuItem(int num, const StdStrBuf & label);
bool DoContextMenu(DWORD dwKeyState);
void AppendMenuItem(int num, const StdStrBuf & label);
void ApplyToolFill();
void ApplyToolRect();
void ApplyToolLine();
@ -142,10 +142,13 @@ protected:
void FrameSelection();
void MoveSelection(C4Real iXOff, C4Real iYOff);
void EMMoveObject(enum C4ControlEMObjectAction eAction, C4Real tx, C4Real ty, C4Object *pTargetObj, const C4EditCursorSelection *pObjs = NULL, const char *szScript = NULL);
void DoContextObjsel(C4Object *, bool clear);
void DoContextObjCommand(C4Object *, const char *cmd);
void ObjselectDelItems();
public:
void DoContextObjsel(C4Object *, bool clear);
protected:
#ifdef USE_GTK
static void OnDelete(GtkWidget* widget, gpointer data);
static void OnDuplicate(GtkWidget* widget, gpointer data);