New editor (Qt-based)

Work in progress. So far only for Windows.
qteditor
Sven Eberhardt 2016-02-11 23:37:13 -05:00
parent ba3160c4c3
commit 2af22ee824
22 changed files with 2484 additions and 14 deletions

7
.gitignore vendored
View File

@ -131,3 +131,10 @@ tests/openclonk_unittest.sln
# Packed groups created directly in root path
/*.oc*
# QMake stuff
*_automoc.cpp
moc_*.cpp
qrc_resource.cpp
ui_C4ConsoleQtMainWindow.h
resource.qrc.depends

View File

@ -309,6 +309,22 @@ endif()
set(HAVE_SDL ${SDL2_FOUND})
include_directories(SYSTEM ${SDL2_INCLUDE_DIRS})
# Qt5 for editor
find_path(Qt5DIR qt.pro PATHS ${CMAKE_ADDITIONAL_DEPS_PATH}/qt-5.5.0)
find_package(Qt5Widgets PATHS ${Qt5DIR}/qtbase/lib/cmake/Qt5Widgets)
if(Qt5Widgets_FOUND)
SET(WITH_QT_EDITOR ${Qt5Widgets_FOUND} "Qt editor dialogues available")
add_definitions(-DWITH_QT_EDITOR)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTOUIC ON)
# As moc files are generated in the binary dir, tell CMake
# to always look for includes there:
set(CMAKE_INCLUDE_CURRENT_DIR ON)
else()
message("Qt5Widgets not found. Building openclonk without editor.")
UNSET(WITH_QT_EDITOR)
endif()
############################################################################
# generated source files
############################################################################
@ -905,8 +921,25 @@ elseif(USE_SDL_MAINLOOP)
src/platform/C4WindowSDL.cpp
)
elseif(USE_WIN32_WINDOWS)
if(WITH_QT_EDITOR)
qt5_add_resources(qt_editor_resources "src/editor/resource.qrc")
list(APPEND OC_GUI_SOURCES
src/editor/C4ConsoleQt.cpp
src/editor/C4ConsoleQt.h
src/editor/C4ConsoleQtState.cpp
src/editor/C4ConsoleQtState.h
src/editor/C4ConsoleQtPropListViewer.cpp
src/editor/C4ConsoleQtPropListViewer.h
src/editor/C4ConsoleQtMainWindow.ui
src/editor/resource.qrc
${qt_editor_resources}
)
else()
list(APPEND OC_GUI_SOURCES
src/editor/C4ConsoleWin32.cpp
)
endif()
list(APPEND OC_GUI_SOURCES
src/editor/C4ConsoleWin32.cpp
src/platform/C4WindowWin32.cpp
src/platform/StdJoystick.cpp
src/platform/StdJoystick.h
@ -1116,6 +1149,10 @@ if(USE_COCOA)
target_link_libraries(openclonk "-framework Cocoa -framework AppKit -framework Quartz -framework OpenAL -framework AudioToolbox")
endif()
if(WITH_QT_EDITOR)
qt5_use_modules(openclonk Widgets)
endif()
add_executable(openclonk-server
${OC_SYSTEM_SOURCES}
${OC_CLONK_SOURCES}
@ -1225,9 +1262,10 @@ if(HAVE_PRECOMPILED_HEADERS)
foreach(FILE ${OC_SOURCES})
get_filename_component(FILE_EXT ${FILE} EXT)
get_filename_component(FILE_NAME_WE ${FILE} NAME_WE)
if(FILE_EXT STREQUAL ".cpp")
# This check is necessary since gzio.c gets compiled as C
# code, which can't use C++ PCH.
if(FILE_EXT STREQUAL ".cpp" AND NOT FILE STREQUAL qt_editor_resources)
# The check for .cpp is necessary since gzio.c gets compiled as C
# code, which can't use C++ PCH. Also, the auto-generated file
# qt_editor_resources does not include the PCH.
set_property(SOURCE ${FILE} PROPERTY COMPILE_FLAGS /YuC4Include.h)
endif()
endforeach()

View File

@ -371,6 +371,7 @@ void C4Console::HelpAbout()
void C4Console::ViewportNew()
{
if (!fGameOpen) return;
::Viewports.CreateViewport(NO_OWNER);
}
@ -492,6 +493,7 @@ void C4Console::SetCaptionToFilename(const char* szFilename)
void C4Console::Execute()
{
C4ConsoleGUI::Execute();
EditCursor.Execute();
ObjectListDlg.Execute();
UpdateStatusBars();
@ -590,7 +592,7 @@ bool C4ConsoleGUI::Message(char const*, bool) {return 0;}
void C4ConsoleGUI::Out(char const*) {}
bool C4ConsoleGUI::PropertyDlgOpen() {return 0;}
void C4ConsoleGUI::PropertyDlgClose() {}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &, bool) {}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &, bool, class C4PropList *) {}
void C4ConsoleGUI::RecordingEnabled() {}
void C4ConsoleGUI::SetCaptionToFileName(char const*) {}
void C4ConsoleGUI::SetCursor(C4ConsoleGUI::Cursor) {}

View File

@ -171,7 +171,7 @@ void C4ConsoleGUI::PropertyDlgClose()
[ctrler(this).objectsPanel orderOut:nil];
}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update)
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *)
{
if (![ctrler(this).objectsPanel isVisible])
return;

View File

@ -994,7 +994,7 @@ void C4ConsoleGUI::PropertyDlgClose()
{
}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update)
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *)
{
if (!state->propertydlg) return;
if (!C4DevmodeDlg::GetWindow()) return;

View File

@ -79,6 +79,16 @@ public:
C4ConsoleGUI();
~C4ConsoleGUI();
#ifdef WITH_QT_EDITOR
void Execute();
void AddViewport(C4ViewportWindow *cvp);
void OnViewportActiveChanged(C4ViewportWindow *cvp, bool is_active);
#else
void Execute() { }
void AddViewport(C4ViewportWindow *cvp) { }
void OnViewportActiveChanged(C4ViewportWindow *cvp, bool is_active) { }
#endif
void SetCursor(Cursor cursor);
void RecordingEnabled();
void ShowAboutWithCopyright(StdStrBuf &copyright);
@ -120,7 +130,7 @@ public:
bool PropertyDlgOpen();
void PropertyDlgClose();
void PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update);
void PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *);
C4Object * PropertyDlgObject;
bool ToolsDlgOpen(class C4ToolsDlg *dlg);
@ -138,6 +148,7 @@ public:
friend INT_PTR CALLBACK PropertyDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
friend INT_PTR CALLBACK ConsoleDlgProc(HWND hDlg, UINT Msg, WPARAM wParam, LPARAM lParam);
friend class C4ToolsDlg;
#endif
};

View File

@ -0,0 +1,387 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Editor windows using Qt*/
#include <C4Include.h>
#include <C4ConsoleQtState.h>
#include <C4Console.h>
#include <C4ConsoleGUI.h>
#include <C4Texture.h>
#include <C4Landscape.h>
#include <C4Version.h>
#include <C4ConsoleQt.h>
// todo:
// * viewport subwindow hack causes alt+tab entry to disappear
// * script window inputs
// * object properties
// * object creator
// * missing translation strings
// * missing tooltips
// * mattex pictures in dropdown
// * mat drawing cursor size preview in active viewports
// * proper viewport focus when clicked
// -----------------------------------------------
void C4ConsoleGUI::Execute() { state->Execute(); }
void C4ConsoleGUI::SetCursor(C4ConsoleGUI::Cursor cursor)
{
}
void C4ConsoleGUI::RecordingEnabled()
{
if (Active) state->SetRecording(true); // TODO this is never reset. Noone uses it anyway...
}
void C4ConsoleGUI::ShowAboutWithCopyright(StdStrBuf &copyright)
{
QMessageBox::about(state->window.get(), QString(LoadResStr("IDS_MENU_ABOUT")), QString(copyright.getData()));
}
bool C4ConsoleGUI::UpdateModeCtrls(int iMode)
{
if (!Active) return false;
state->SetEditCursorMode(iMode);
return true;
}
void C4ConsoleGUI::AddNetMenu()
{
if (Active) state->SetNetEnabled(true);
}
void C4ConsoleGUI::ClearNetMenu()
{
if (Active) state->ClearNetMenu();
}
void C4ConsoleGUI::AddNetMenuItemForPlayer(int32_t index, StdStrBuf &text)
{
if (Active) state->AddNetMenuItem(index, text.getData());
}
void C4ConsoleGUI::ClearPlayerMenu()
{
if (Active) state->ClearPlayerMenu();
}
void C4ConsoleGUI::SetInputFunctions(std::list<const char*> &functions)
{
if (Active) state->SetInputFunctions(functions);
}
C4Window* C4ConsoleGUI::CreateConsoleWindow(C4AbstractApp *application)
{
if (!state->CreateConsoleWindow(application)) return NULL;
#ifdef USE_WIN32_WINDOWS
hWindow = reinterpret_cast<HWND>(state->window->winId());
renderwnd = hWindow;
#else
TODO
#endif
Active = true;
EnableControls(fGameOpen);
return this;
}
void C4ConsoleGUI::Out(const char* message)
{
// Log text: Add to log window
if (state->window.get())
{
// Append text
state->ui.logView->insertPlainText(QString(message) + "\n");
// Scroll to end to display it
QScrollBar *sb = state->ui.logView->verticalScrollBar();
if (sb) sb->setValue(sb->maximum());
state->Redraw();
}
}
bool C4ConsoleGUI::ClearLog()
{
// Empty log window
if (!Active) return false;
state->ui.logView->clear();
return true;
}
void C4ConsoleGUI::DisplayInfoText(InfoTextType type, StdStrBuf& text)
{
QLabel *target = NULL;
switch (type)
{
case CONSOLE_Cursor: target = state->status_cursor; break;
case CONSOLE_FrameCounter: target = state->status_framecounter; break;
case CONSOLE_TimeFPS: target = state->status_timefps; break;
}
if (!target) return;
target->setText(text.getData());
}
void C4ConsoleGUI::SetCaptionToFileName(const char* file_name) { /* This is never even called? */ }
bool C4ConsoleGUI::FileSelect(StdStrBuf *sFilename, const char * szFilter, DWORD dwFlags, bool fSave)
{
// Prepare filters from double-zero-terminated list to ";;"-separated list in Qt format
QString filter="", selected_filter, filename;
QStringList filenames; bool has_multi = (dwFlags & OpenFileFlags::OFN_ALLOWMULTISELECT);
if (szFilter)
{
while (*szFilter)
{
if (filter.length() > 0) filter.append(";;");
filter.append(szFilter);
szFilter += strlen(szFilter) + 1;
if (*szFilter)
{
filter.append(" (");
filter.append(szFilter);
filter.append(")");
szFilter += strlen(szFilter) + 1;
}
if (selected_filter.length() <= 0) selected_filter = filter;
}
}
#ifdef USE_WIN32_WINDOWS
// cwd backup
size_t l = GetCurrentDirectoryW(0, 0);
std::unique_ptr<wchar_t []> wd(new wchar_t[l]);
GetCurrentDirectoryW(l, wd.get());
#endif
// Show dialogue
if (fSave)
filename = QFileDialog::getSaveFileName(state->window.get(), LoadResStr("IDS_DLG_SAVE"), QString(), filter, &selected_filter);
else if (!has_multi)
filename = QFileDialog::getOpenFileName(state->window.get(), LoadResStr("IDS_DLG_OPEN"), QString(), filter, &selected_filter);
else
filenames = QFileDialog::getOpenFileNames(state->window.get(), LoadResStr("IDS_DLG_OPEN"), QString(), filter, &selected_filter);
#ifdef USE_WIN32_WINDOWS
// Restore cwd; may have been changed in open/save dialogue
SetCurrentDirectoryW(wd.get());
#endif
// Process multi vs single file select
if (has_multi)
{
// Multi-select: Return double-zero-terminated string list
if (!filenames.length()) return false;
for (auto fn : filenames)
{
sFilename->Append(fn.toStdString().c_str());
sFilename->AppendChar('\0');
}
return true;
}
// Cancelled?
if (filename.length() <= 0) return false;
// File selected!
sFilename->Copy(filename.toStdString().c_str());
sFilename->AppendChar('\0');
return true;
}
void C4ConsoleGUI::AddMenuItemForPlayer(C4Player *player, StdStrBuf& player_text)
{
// Add "new viewport for X" to window menu
if (Active) state->AddPlayerViewportMenuItem(player->Number, player_text.getData());
}
void C4ConsoleGUI::AddKickPlayerMenuItem(C4Player *player, StdStrBuf& player_text, bool enabled)
{
// Add "kick X" to player menu
if (Active) state->AddKickPlayerMenuItem(player->Number, player_text.getData(), enabled);
}
void C4ConsoleGUI::ClearViewportMenu()
{
// Remove all "new viewport for X" entries from window menu
if (Active) state->ClearViewportMenu();
}
bool C4ConsoleGUI::Message(const char *message, bool query)
{
// Show a message through Qt
if (query)
{
auto result = QMessageBox::question(state->window.get(), C4ENGINECAPTION, message, QMessageBox::StandardButton::Ok | QMessageBox::StandardButton::Cancel);
return (result == QMessageBox::StandardButton::Ok);
}
else
{
QMessageBox::information(state->window.get(), C4ENGINECAPTION, message, QMessageBox::StandardButton::Ok);
return true;
}
}
void C4ConsoleGUI::DoEnableControls(bool fEnable)
{
if (!Active) return;
state->SetEnabled(fEnable);
state->SetLandscapeMode(::Landscape.Mode); // initial setting
}
bool C4ConsoleGUI::DoUpdateHaltCtrls(bool fHalt)
{
// Reflect halt state in play/pause buttons
if (!Active) return false;
state->ui.actionPlay->setChecked(!fHalt);
state->ui.actionPause->setChecked(fHalt);
return true;
}
bool C4ConsoleGUI::PropertyDlgOpen() { /* Always open */ return true; }
void C4ConsoleGUI::PropertyDlgClose() { /* Always open */ }
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *proplist_selection)
{
if (Active) state->PropertyDlgUpdate(rSelection, force_function_update, proplist_selection);
}
bool C4ConsoleGUI::ToolsDlgOpen(class C4ToolsDlg *dlg) { /* Always open */ return true; }
void C4ConsoleGUI::ToolsDlgClose() { /* Always open */ }
void C4ConsoleGUI::ToolsDlgInitMaterialCtrls(class C4ToolsDlg *dlg)
{
// All foreground materials
assert(Active);
if (!Active) return;
state->ui.foregroundMatTexComboBox->addItem(QString(C4TLS_MatSky));
const C4TexMapEntry *entry; int32_t i = 0;
while ((entry = ::TextureMap.GetEntry(i++)))
{
if (!entry->isNull())
{
const char *material_name = entry->GetMaterialName();
if (strcmp(material_name, "Vehicle") && strcmp(material_name, "HalfVehicle"))
{
state->ui.foregroundMatTexComboBox->addItem(QString(FormatString("%s-%s", material_name, entry->GetTextureName()).getData()));
}
}
}
auto width = 130; /* The ToolBar randomly resizes the control */
state->ui.foregroundMatTexComboBox->view()->setMinimumWidth(width);
state->ui.foregroundMatTexComboBox->setFixedWidth(width);
// Background materials: True background materials first; then the "funny" stuff
state->ui.backgroundMatTexComboBox->addItem(QString(C4TLS_MatSky));
i = 0;
while ((entry = ::TextureMap.GetEntry(i++)))
{
if (!entry->isNull())
{
const char *material_name = entry->GetMaterialName();
C4Material *mat = entry->GetMaterial();
if (strcmp(material_name, "Vehicle") && strcmp(material_name, "HalfVehicle") && mat->Density == C4M_Background)
{
state->ui.backgroundMatTexComboBox->addItem(QString(FormatString("%s-%s", material_name, entry->GetTextureName()).getData()));
}
}
}
state->ui.backgroundMatTexComboBox->addItem(QString("----------"));
i = 0;
while ((entry = ::TextureMap.GetEntry(i++)))
{
if (!entry->isNull())
{
const char *material_name = entry->GetMaterialName();
C4Material *mat = entry->GetMaterial();
if (strcmp(material_name, "Vehicle") && strcmp(material_name, "HalfVehicle") && mat->Density != C4M_Background)
{
state->ui.backgroundMatTexComboBox->addItem(QString(FormatString("%s-%s", material_name, entry->GetTextureName()).getData()));
}
}
}
state->ui.backgroundMatTexComboBox->view()->setMinimumWidth(width);
state->ui.backgroundMatTexComboBox->setFixedWidth(width);
// Select current materials
state->SetMaterial(dlg->Material);
state->SetTexture(dlg->Texture);
state->SetBackMaterial(dlg->BackMaterial);
state->SetBackTexture(dlg->BackTexture);
state->UpdateMatTex();
state->UpdateBackMatTex();
}
void C4ConsoleGUI::ToolsDlgSelectTexture(C4ToolsDlg *dlg, const char *texture) { if (!Active) return; state->SetTexture(texture); }
void C4ConsoleGUI::ToolsDlgSelectMaterial(C4ToolsDlg *dlg, const char *material) { if (!Active) return; state->SetMaterial(material); }
void C4ConsoleGUI::ToolsDlgSelectBackTexture(C4ToolsDlg *dlg, const char *texture) { if (!Active) return; state->SetBackTexture(texture); }
void C4ConsoleGUI::ToolsDlgSelectBackMaterial(C4ToolsDlg *dlg, const char *material) { if (!Active) return; state->SetBackMaterial(material); }
void C4ConsoleGUI::Win32KeepDialogsFloating(HWND hwnd) { /* Dialogues float nicely */ }
bool C4ConsoleGUI::Win32DialogMessageHandling(MSG *msg) { return false; /* message handling done through Qt (somehow?) */ }
void C4ConsoleGUI::UpdateMenuText(HMENU hMenu) { /* Translation done through QTranslator */ }
void C4ConsoleGUI::AddViewport(C4ViewportWindow *cvp)
{
// Add surrounding widget for viewport
state->AddViewport(cvp);
}
void C4ConsoleGUI::OnViewportActiveChanged(C4ViewportWindow *cvp, bool is_active)
{
// Reflect viewport activation in GUI
state->OnViewportActiveChanged(cvp, is_active);
}
void C4ToolsDlg::UpdateToolCtrls()
{
// Set selected drawing tool
if (::Console.Active) ::Console.state->SetDrawingTool(Tool);
}
void C4ToolsDlg::UpdateTextures() { /* Textures are done with materials */ }
void C4ToolsDlg::NeedPreviewUpdate() { /* No preview */}
void C4ToolsDlg::InitGradeCtrl()
{
// Update current grade
if (::Console.Active) ::Console.state->ui.drawSizeSlider->setValue(Grade);
}
bool C4ToolsDlg::PopMaterial()
{
// Show material selection
if (!::Console.Active) return false;
::Console.state->ui.foregroundMatTexComboBox->setFocus();
::Console.state->ui.foregroundMatTexComboBox->showPopup();
return true;
}
bool C4ToolsDlg::PopTextures()
{
// Show texture selection
if (!::Console.Active) return false;
::Console.state->ui.foregroundMatTexComboBox->setFocus();
::Console.state->ui.foregroundMatTexComboBox->showPopup();
return true;
}
void C4ToolsDlg::UpdateIFTControls() { /* not using IFT */ }
void C4ToolsDlg::UpdateLandscapeModeCtrls()
{
// Update button down states for landscape mode
if (::Console.Active) ::Console.state->SetLandscapeMode(::Landscape.Mode);
}
void C4ToolsDlg::EnableControls() { /* Handled internally by tool selection */ }
#include "C4ConsoleGUICommon.h"

View File

@ -0,0 +1,42 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Console forward from C4ConsoleGUI to C4ConsoleGUI::State */
#ifndef INC_C4ConsoleQt
#define INC_C4ConsoleQt
#ifdef WITH_QT_EDITOR
// Avoid some name conflicts
#undef LineFeed
#undef new
// disable OPENGL_ES
// (not necessery if Qt is compiled with -opengl desktop)
//#define QT_OPENGL_ES_2
//#define QT_NO_OPENGL_ES_2
//#define QT_OPENGL_ES
//#define QT_NO_OPENGL_ES
#include <QtWidgets>
#include <memory>
// TODO: If we remove the other editors, state and consolegui can be merged and the relevant header go into this file
// For now, just use this to include Qt
#endif // WITH_QT_EDITOR
#endif //INC_C4ConsoleQt

View File

@ -0,0 +1,990 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>MainWindow</class>
<widget class="QMainWindow" name="MainWindow">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>955</width>
<height>578</height>
</rect>
</property>
<property name="windowTitle">
<string>EDITOR</string>
</property>
<widget class="QWidget" name="centralwidget">
<widget class="QComboBox" name="foregroundMatTexComboBox">
<property name="geometry">
<rect>
<x>10</x>
<y>10</y>
<width>131</width>
<height>20</height>
</rect>
</property>
<property name="editable">
<bool>false</bool>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
<widget class="QComboBox" name="backgroundMatTexComboBox">
<property name="geometry">
<rect>
<x>10</x>
<y>30</y>
<width>131</width>
<height>20</height>
</rect>
</property>
<property name="sizeAdjustPolicy">
<enum>QComboBox::AdjustToContents</enum>
</property>
</widget>
<widget class="QSlider" name="drawSizeSlider">
<property name="geometry">
<rect>
<x>200</x>
<y>10</y>
<width>100</width>
<height>16</height>
</rect>
</property>
<property name="maximumSize">
<size>
<width>100</width>
<height>16777215</height>
</size>
</property>
<property name="minimum">
<number>1</number>
</property>
<property name="value">
<number>10</number>
</property>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
<widget class="QLabel" name="drawSizeLabel">
<property name="geometry">
<rect>
<x>150</x>
<y>10</y>
<width>47</width>
<height>13</height>
</rect>
</property>
<property name="text">
<string comment="res">IDS_CTL_SIZE</string>
</property>
</widget>
</widget>
<widget class="QMenuBar" name="menubar">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>955</width>
<height>18</height>
</rect>
</property>
<widget class="QMenu" name="menuFile">
<property name="title">
<string comment="res">IDS_MNU_FILE</string>
</property>
<addaction name="actionFileOpen"/>
<addaction name="actionFileOpenWithPlayers"/>
<addaction name="separator"/>
<addaction name="actionFileRecord"/>
<addaction name="actionFileSaveScenario"/>
<addaction name="actionFileSaveScenarioAs"/>
<addaction name="actionFileSaveGameAs"/>
<addaction name="separator"/>
<addaction name="actionFileClose"/>
<addaction name="actionFileQuit"/>
</widget>
<widget class="QMenu" name="menuPlayers">
<property name="title">
<string comment="res">IDS_MNU_PLAYER</string>
</property>
<addaction name="actionPlayerJoin"/>
</widget>
<widget class="QMenu" name="menuHelp">
<property name="title">
<string comment="res">?</string>
</property>
<addaction name="actionHelpAbout"/>
</widget>
<widget class="QMenu" name="menuWindows">
<property name="title">
<string comment="res">IDS_MNU_WINDOWS</string>
</property>
<addaction name="actionViewportNew"/>
</widget>
<widget class="QMenu" name="menuNet">
<property name="title">
<string comment="res">IDS_MNU_NET</string>
</property>
</widget>
<addaction name="menuFile"/>
<addaction name="menuPlayers"/>
<addaction name="menuWindows"/>
<addaction name="menuNet"/>
<addaction name="menuHelp"/>
</widget>
<widget class="QStatusBar" name="statusbar"/>
<widget class="QDockWidget" name="propertyDockWidget">
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>PROPERTIES</string>
</property>
<attribute name="dockWidgetArea">
<number>2</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_2">
<layout class="QVBoxLayout" name="verticalLayout_4">
<property name="spacing">
<number>2</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="QFrame" name="userPropertyFrame">
<property name="frameShape">
<enum>QFrame::HLine</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Plain</enum>
</property>
<property name="lineWidth">
<number>1</number>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="multiSelInfoLabel">
<property name="text">
<string>SELECTION</string>
</property>
</widget>
</item>
<item>
<widget class="QTableView" name="propertyTable"/>
</item>
<item>
<widget class="QComboBox" name="propertyInputBox">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="logDockWidget">
<property name="windowTitle">
<string>LOG</string>
</property>
<attribute name="dockWidgetArea">
<number>8</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_3">
<layout class="QVBoxLayout" name="verticalLayout_3">
<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="QTextEdit" name="logView"/>
</item>
<item>
<widget class="QComboBox" name="consoleInputBox">
<property name="editable">
<bool>true</bool>
</property>
</widget>
</item>
</layout>
</widget>
</widget>
<widget class="QDockWidget" name="creatorDockWidget">
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>CREATOR</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_4">
<layout class="QVBoxLayout" name="verticalLayout_2">
<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="QTreeView" name="creatorTreeView"/>
</item>
<item>
<widget class="QComboBox" name="creatorModeComboBox"/>
</item>
</layout>
<zorder>creatorModeComboBox</zorder>
<zorder>creatorTreeView</zorder>
</widget>
</widget>
<widget class="QToolBar" name="toolBar">
<property name="windowTitle">
<string>toolBar</string>
</property>
<attribute name="toolBarArea">
<enum>TopToolBarArea</enum>
</attribute>
<attribute name="toolBarBreak">
<bool>false</bool>
</attribute>
<addaction name="actionPlay"/>
<addaction name="actionPause"/>
<addaction name="separator"/>
<addaction name="actionCursorGame"/>
<addaction name="actionCursorSelect"/>
<addaction name="separator"/>
<addaction name="actionCursorDrawPen"/>
<addaction name="actionCursorDrawLine"/>
<addaction name="actionCursorDrawRect"/>
<addaction name="actionCursorFill"/>
<addaction name="actionCursorPicker"/>
<addaction name="separator"/>
<addaction name="actionDynamicLandscape"/>
<addaction name="actionStaticLandscape"/>
<addaction name="actionExactLandscape"/>
<addaction name="separator"/>
</widget>
<widget class="QDockWidget" name="objectListDockWidget">
<property name="allowedAreas">
<set>Qt::LeftDockWidgetArea|Qt::RightDockWidgetArea</set>
</property>
<property name="windowTitle">
<string>OBJECTS</string>
</property>
<attribute name="dockWidgetArea">
<number>1</number>
</attribute>
<widget class="QWidget" name="dockWidgetContents_5">
<layout class="QVBoxLayout" name="verticalLayout_5">
<property name="spacing">
<number>2</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="QTreeView" name="objectListView"/>
</item>
</layout>
</widget>
</widget>
<action name="actionPlay">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Play_Trans.png</normaloff>
<normalon>:/editor/res/Play_Trans.png</normalon>:/editor/res/Play_Trans.png</iconset>
</property>
<property name="text">
<string>PLAY</string>
</property>
<property name="toolTip">
<string comment="res">IDS_TEXT_UNPAUSETHEGAME</string>
</property>
</action>
<action name="actionPause">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Halt_Trans.png</normaloff>:/editor/res/Halt_Trans.png</iconset>
</property>
<property name="text">
<string>PAUSE</string>
</property>
<property name="toolTip">
<string comment="res">IDS_TEXT_PAUSETHEGAME</string>
</property>
</action>
<action name="actionCursorGame">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Mouse_Trans.png</normaloff>:/editor/res/Mouse_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_GAME</string>
</property>
<property name="toolTip">
<string>CURSOR_GAME_TIP</string>
</property>
</action>
<action name="actionCursorSelect">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Cursor_Trans.png</normaloff>:/editor/res/Cursor_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_SELECT</string>
</property>
<property name="toolTip">
<string>CURSOR_SELECT_TIP</string>
</property>
</action>
<action name="actionCursorDrawPen">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Brush_Trans.png</normaloff>:/editor/res/Brush_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_DRAWPEN</string>
</property>
<property name="toolTip">
<string>CURSOR_DRAWPEN_TIP</string>
</property>
</action>
<action name="actionCursorDrawLine">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Line_Trans.png</normaloff>:/editor/res/Line_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_DRAWLINE</string>
</property>
<property name="toolTip">
<string>CURSOR_DRAWLINETIP</string>
</property>
</action>
<action name="actionCursorDrawRect">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Rect_Trans.png</normaloff>:/editor/res/Rect_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_DRAWRECT</string>
</property>
<property name="toolTip">
<string>CURSOR_DRAWRECT_TIP</string>
</property>
</action>
<action name="actionCursorPicker">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Picker_Trans.png</normaloff>:/editor/res/Picker_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_DRAWPICKER</string>
</property>
<property name="toolTip">
<string>CURSOR_DRAWPICKER_TIP</string>
</property>
</action>
<action name="actionDynamicLandscape">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Dynamic_Trans.png</normaloff>:/editor/res/Dynamic_Trans.png</iconset>
</property>
<property name="text">
<string>MAP_DYNAMIC</string>
</property>
<property name="toolTip">
<string>MAP_DYNAMIC_TIP</string>
</property>
</action>
<action name="actionStaticLandscape">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Static_Trans.png</normaloff>:/editor/res/Static_Trans.png</iconset>
</property>
<property name="text">
<string>MAP_STATIC</string>
</property>
<property name="toolTip">
<string>MAP_STATIC_TIP</string>
</property>
</action>
<action name="actionExactLandscape">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Exact_Trans.png</normaloff>:/editor/res/Exact_Trans.png</iconset>
</property>
<property name="text">
<string>MAP_EXACT</string>
</property>
<property name="toolTip">
<string>MAP_EXACT_TIP</string>
</property>
</action>
<action name="actionCursorFill">
<property name="checkable">
<bool>true</bool>
</property>
<property name="icon">
<iconset resource="resource.qrc">
<normaloff>:/editor/res/Fill_Trans.png</normaloff>:/editor/res/Fill_Trans.png</iconset>
</property>
<property name="text">
<string>CURSOR_DRAWFILL</string>
</property>
<property name="toolTip">
<string>CURSOR_DRAWFILL_TIP</string>
</property>
</action>
<action name="actionViewportNew">
<property name="text">
<string comment="res">IDS_MNU_NEWVIEWPORT</string>
</property>
</action>
<action name="actionFileOpen">
<property name="text">
<string comment="res">IDS_MNU_OPEN</string>
</property>
<property name="toolTip">
<string>IDS_MNU_OPEN</string>
</property>
</action>
<action name="actionFileOpenWithPlayers">
<property name="text">
<string comment="res">IDS_MNU_OPENWPLRS</string>
</property>
</action>
<action name="actionFileRecord">
<property name="checkable">
<bool>true</bool>
</property>
<property name="text">
<string comment="res">IDS_MNU_RECORD</string>
</property>
</action>
<action name="actionFileSaveScenario">
<property name="text">
<string comment="res">IDS_MNU_SAVESCENARIO</string>
</property>
</action>
<action name="actionFileSaveScenarioAs">
<property name="text">
<string comment="res">IDS_MNU_SAVESCENARIOAS</string>
</property>
</action>
<action name="actionFileSaveGameAs">
<property name="text">
<string comment="res">IDS_MNU_SAVEGAMEAS</string>
</property>
</action>
<action name="actionFileClose">
<property name="text">
<string comment="res">IDS_MNU_CLOSE</string>
</property>
</action>
<action name="actionFileQuit">
<property name="text">
<string comment="res">IDS_MNU_QUIT</string>
</property>
</action>
<action name="actionPlayerJoin">
<property name="text">
<string comment="res">IDS_MNU_JOIN</string>
</property>
</action>
<action name="actionHelpAbout">
<property name="text">
<string comment="res">IDS_MENU_ABOUT</string>
</property>
</action>
</widget>
<resources>
<include location="resource.qrc"/>
</resources>
<connections>
<connection>
<sender>actionPlay</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>PlayPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>523</x>
<y>299</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionPause</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>PausePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorGame</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorGamePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorSelect</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorSelectPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorDrawPen</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorDrawPenPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorDrawLine</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorDrawLinePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorDrawRect</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorDrawRectPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorPicker</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorPickerPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionDynamicLandscape</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>DynamicLandscapePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionStaticLandscape</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>StaticLandscapePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionExactLandscape</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>ExactLandscapePressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionCursorFill</sender>
<signal>triggered(bool)</signal>
<receiver>MainWindow</receiver>
<slot>CursorFillPressed(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>523</x>
<y>299</y>
</hint>
</hints>
</connection>
<connection>
<sender>drawSizeSlider</sender>
<signal>sliderMoved(int)</signal>
<receiver>MainWindow</receiver>
<slot>DrawSizeChanged(int)</slot>
<hints>
<hint type="sourcelabel">
<x>499</x>
<y>69</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionViewportNew</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>ViewportNew()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionPlayerJoin</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>PlayerJoin()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileSaveScenarioAs</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileSaveAs()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileSaveScenario</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileSave()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileSaveGameAs</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileSaveGameAs()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileRecord</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileRecord()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileQuit</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileQuit()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileClose</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileClose()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileOpenWithPlayers</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileOpenWithPlayers()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionFileOpen</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>FileOpen()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
<connection>
<sender>actionHelpAbout</sender>
<signal>triggered()</signal>
<receiver>MainWindow</receiver>
<slot>HelpAbout()</slot>
<hints>
<hint type="sourcelabel">
<x>-1</x>
<y>-1</y>
</hint>
<hint type="destinationlabel">
<x>477</x>
<y>288</y>
</hint>
</hints>
</connection>
</connections>
<slots>
<slot>PlayPressed(bool)</slot>
<slot>PausePressed(bool)</slot>
<slot>CursorGamePressed(bool)</slot>
<slot>CursorSelectPressed(bool)</slot>
<slot>CursorDrawPenPressed(bool)</slot>
<slot>CursorDrawLinePressed(bool)</slot>
<slot>CursorDrawRectPressed(bool)</slot>
<slot>CursorPickerPressed(bool)</slot>
<slot>DynamicLandscapePressed(bool)</slot>
<slot>StaticLandscapePressed(bool)</slot>
<slot>ExactLandscapePressed(bool)</slot>
<slot>CursorFillPressed(bool)</slot>
<slot>DrawSizeChanged(int)</slot>
<slot>FileOpen()</slot>
<slot>FileOpenWithPlayers()</slot>
<slot>FileRecord()</slot>
<slot>FileSave()</slot>
<slot>FileSaveAs()</slot>
<slot>FileSaveGameAs()</slot>
<slot>FileClose()</slot>
<slot>FileQuit()</slot>
<slot>PlayerJoin()</slot>
<slot>ViewportNew()</slot>
<slot>HelpAbout()</slot>
<slot>ConsoleEnter(QString)</slot>
</slots>
</ui>

View File

@ -0,0 +1,88 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Proplist table view */
#include <C4Include.h>
#include <C4Value.h>
#include <C4ConsoleQtPropListViewer.h>
C4ConsoleQtPropListModel::C4ConsoleQtPropListModel()
{
proplist.reset(new C4Value());
}
C4ConsoleQtPropListModel::~C4ConsoleQtPropListModel()
{
}
void C4ConsoleQtPropListModel::SetPropList(class C4PropList *new_proplist)
{
// Update properties
proplist->SetPropList(new_proplist);
if (new_proplist) properties = new_proplist->GetSortedLocalProperties();
QModelIndex topLeft = index(0, 0);
QModelIndex bottomRight = index(rowCount() - 1, columnCount() - 1);
emit dataChanged(topLeft, bottomRight);
emit layoutChanged();
}
int C4ConsoleQtPropListModel::rowCount(const QModelIndex & parent) const
{
return properties.size();
}
int C4ConsoleQtPropListModel::columnCount(const QModelIndex & parent) const
{
return 2; // Name + Data
}
QVariant C4ConsoleQtPropListModel::headerData(int section, Qt::Orientation orientation, int role) const
{
// Table headers
if (role == Qt::DisplayRole && orientation == Qt::Orientation::Horizontal)
{
if (section == 0) return QVariant(LoadResStr("IDS_CTL_NAME"));
if (section == 1) return QVariant(LoadResStr("IDS_CTL_VALUE"));
}
return QVariant();
}
QVariant C4ConsoleQtPropListModel::data(const QModelIndex & index, int role) const
{
// Query latest data from prop list
C4PropList *props = proplist->getPropList();
if (role == Qt::DisplayRole && props)
{
int row = index.row();
if (row < 0 || row >= properties.size()) return QVariant();
C4String *prop_name = properties[row].Get();
if (!prop_name) return QVariant();
switch (index.column())
{
case 0: // First col: Property Name
return QVariant(prop_name->GetCStr());
case 1: // Second col: Property value
{
C4Value v;
if (!props->GetPropertyByS(prop_name, &v)) return QVariant("???"); /* Property got removed between update calls */
return QVariant(v.GetDataString().getData());
}
}
}
// Nothing to show
return QVariant();
}

View File

@ -0,0 +1,49 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Proplist table view */
#ifndef INC_C4ConsoleQtPropListViewer
#define INC_C4ConsoleQtPropListViewer
#ifdef WITH_QT_EDITOR
#include <C4Include.h> // needed for automoc
#include <C4ConsoleGUI.h> // for glew.h
#include <C4ConsoleQt.h>
#include <QAbstractTableModel>
// Prop list view implemented as a model view
class C4ConsoleQtPropListModel : public QAbstractTableModel
{
Q_OBJECT
std::unique_ptr<class C4Value> proplist;
std::vector< C4RefCntPointer<C4String> > properties;
public:
C4ConsoleQtPropListModel();
~C4ConsoleQtPropListModel();
void SetPropList(class C4PropList *new_proplist);
protected:
virtual int rowCount(const QModelIndex & parent = QModelIndex()) const;
virtual int columnCount(const QModelIndex & parent = QModelIndex()) const;
virtual QVariant headerData(int section, Qt::Orientation orientation, int role = Qt::DisplayRole) const;
virtual QVariant data(const QModelIndex & index, int role = Qt::DisplayRole) const;
};
#endif // WITH_QT_EDITOR
#endif // INC_C4ConsoleQtPropListViewer

View File

@ -0,0 +1,576 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Editor windows using Qt*/
#include <C4Include.h>
#include <C4ConsoleQtState.h>
#include <C4ConsoleQtPropListViewer.h>
#include <C4Console.h>
#include <StdRegistry.h>
#include <C4ViewportWindow.h>
#include <C4Landscape.h>
#include <C4PlayerList.h>
#include <C4Viewport.h>
#include <C4Object.h>
/* String translation */
QString C4ConsoleQtTranslator::translate(const char * context, const char * sourceText, const char * disambiguation, int n) const
{
// Map to LoadResStr for all QStrings marked as res
if (disambiguation && !strcmp(disambiguation, "res"))
return QString(LoadResStr(sourceText));
else
return QString(sourceText);
}
C4ConsoleQtTranslator qt_translator;
/* Kick client action */
C4ConsoleClientAction::C4ConsoleClientAction(int32_t client_id, const char *text, QObject *parent)
: QAction(text, parent), client_id(client_id)
{
connect(this, SIGNAL(triggered()), this, SLOT(Execute()));
}
void C4ConsoleClientAction::Execute()
{
if (!::Control.isCtrlHost()) return;
::Game.Clients.CtrlRemove(Game.Clients.getClientByID(client_id), LoadResStr("IDS_MSG_KICKBYMENU"));
}
/* Remove player action */
C4ConsoleRemovePlayerAction::C4ConsoleRemovePlayerAction(int32_t player_num, const char *text, QObject *parent)
: QAction(text, parent), player_num(player_num)
{
connect(this, SIGNAL(triggered()), this, SLOT(Execute()));
}
void C4ConsoleRemovePlayerAction::Execute()
{
C4Player *plr = ::Players.Get(player_num);
if (!plr) return;
::Control.Input.Add(CID_PlrAction, C4ControlPlayerAction::Eliminate(plr));
}
/* Add viewport for player action */
C4ConsoleOpenViewportAction::C4ConsoleOpenViewportAction(int32_t player_num, const char *text, QObject *parent)
: QAction(text, parent), player_num(player_num)
{
connect(this, SIGNAL(triggered()), this, SLOT(Execute()));
}
void C4ConsoleOpenViewportAction::Execute()
{
::Viewports.CreateViewport(player_num);
}
/* Console viewports */
C4ConsoleViewportWidget::C4ConsoleViewportWidget(QMainWindow *parent, C4ViewportWindow *cvp)
: QDockWidget("VIEWPORT", parent), cvp(cvp)
{
#ifdef USE_WIN32_WINDOWS
// hack
window = QWindow::fromWinId(reinterpret_cast<WId>(cvp->hWindow));
QWidget *window_container = QWidget::createWindowContainer(window, parent, Qt::Widget);
window_container->setFocusPolicy(Qt::TabFocus);
setWidget(window_container);
#else
TODO
#endif
connect(this, SIGNAL(dockLocationChanged(bool)), this, SLOT(DockLocationChanged(bool)));
OnActiveChanged(true);
}
void C4ConsoleViewportWidget::OnActiveChanged(bool active)
{
// set color schemes for inactive / active viewport headers
QColor bgclr = QApplication::palette(this).color(QPalette::Highlight);
QColor fontclr = QApplication::palette(this).color(QPalette::HighlightedText);
if (active)
setStyleSheet(FormatString("QDockWidget::title { background: %s; padding: 5px; } QDockWidget { color: %s; font-weight: bold; }",
bgclr.name().toStdString().c_str(),
fontclr.name().toStdString().c_str()).getData());
else
setStyleSheet("");
}
void C4ConsoleViewportWidget::focusInEvent(QFocusEvent * event)
{
OnActiveChanged(true);
QDockWidget::focusInEvent(event);
}
void C4ConsoleViewportWidget::focusOutEvent(QFocusEvent * event)
{
OnActiveChanged(false);
QDockWidget::focusOutEvent(event);
}
void C4ConsoleViewportWidget::DockLocationChanged(Qt::DockWidgetArea new_area)
{
// Re-docked:
}
void C4ConsoleViewportWidget::closeEvent(QCloseEvent * event)
{
QDockWidget::closeEvent(event);
if (event->isAccepted())
{
if (cvp) cvp->Close();
cvp = NULL;
deleteLater();
}
}
/* Console main window */
C4ConsoleQtMainWindow::C4ConsoleQtMainWindow(C4AbstractApp *app, C4ConsoleGUIState *state)
: QMainWindow(NULL), state(state)
{
#ifdef USE_WIN32_WINDOWS
HWND hWindow = reinterpret_cast<HWND>(winId());
// Set icon
SendMessage(hWindow, WM_SETICON, ICON_BIG, (LPARAM)LoadIcon(app->GetInstance(), MAKEINTRESOURCE(IDI_00_C4X)));
SendMessage(hWindow, WM_SETICON, ICON_SMALL, (LPARAM)LoadIcon(app->GetInstance(), MAKEINTRESOURCE(IDI_00_C4X)));
#endif
}
void C4ConsoleQtMainWindow::closeEvent(QCloseEvent *event)
{
QMainWindow::closeEvent(event);
::Console.Close();
}
void C4ConsoleQtMainWindow::PlayPressed(bool down)
{
if (down)
::Console.DoPlay();
else // cannot un-check by pressing again
state->ui.actionPlay->setChecked(true);
}
void C4ConsoleQtMainWindow::PausePressed(bool down)
{
if (down)
::Console.DoHalt();
else // cannot un-check by pressing again
state->ui.actionPause->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorGamePressed(bool down)
{
if (down)
::Console.EditCursor.SetMode(C4CNS_ModePlay);
else // cannot un-check by pressing again
state->ui.actionCursorGame->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorSelectPressed(bool down)
{
if (down)
::Console.EditCursor.SetMode(C4CNS_ModeEdit);
else // cannot un-check by pressing again
state->ui.actionCursorSelect->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorDrawPenPressed(bool down)
{
if (down)
{
::Console.EditCursor.SetMode(C4CNS_ModeDraw);
::Console.ToolsDlg.SetTool(C4TLS_Brush, false);
}
else // cannot un-check by pressing again
state->ui.actionCursorDrawPen->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorDrawLinePressed(bool down)
{
if (down)
{
::Console.EditCursor.SetMode(C4CNS_ModeDraw);
::Console.ToolsDlg.SetTool(C4TLS_Line, false);
}
else // cannot un-check by pressing again
state->ui.actionCursorDrawLine->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorDrawRectPressed(bool down)
{
if (down)
{
::Console.EditCursor.SetMode(C4CNS_ModeDraw);
::Console.ToolsDlg.SetTool(C4TLS_Rect, false);
}
else // cannot un-check by pressing again
state->ui.actionCursorDrawRect->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorFillPressed(bool down)
{
if (down)
{
::Console.EditCursor.SetMode(C4CNS_ModeDraw);
::Console.ToolsDlg.SetTool(C4TLS_Fill, false);
}
else // cannot un-check by pressing again
state->ui.actionCursorFill->setChecked(true);
}
void C4ConsoleQtMainWindow::CursorPickerPressed(bool down)
{
if (down)
{
::Console.EditCursor.SetMode(C4CNS_ModeDraw);
::Console.ToolsDlg.SetTool(C4TLS_Picker, false);
}
else // cannot un-check by pressing again
state->ui.actionCursorPicker->setChecked(true);
}
void C4ConsoleQtMainWindow::DynamicLandscapePressed(bool down)
{
if (down)
::Console.ToolsDlg.SetLandscapeMode(C4LSC_Dynamic);
else // cannot un-check by pressing again
state->ui.actionDynamicLandscape->setChecked(true);
}
void C4ConsoleQtMainWindow::StaticLandscapePressed(bool down)
{
if (down)
::Console.ToolsDlg.SetLandscapeMode(C4LSC_Static);
else // cannot un-check by pressing again
state->ui.actionStaticLandscape->setChecked(true);
}
void C4ConsoleQtMainWindow::ExactLandscapePressed(bool down)
{
if (down)
::Console.ToolsDlg.SetLandscapeMode(C4LSC_Exact);
else // cannot un-check by pressing again
state->ui.actionExactLandscape->setChecked(true);
}
void C4ConsoleQtMainWindow::DrawSizeChanged(int newval)
{
::Console.ToolsDlg.SetGrade(newval);
}
// File menu
void C4ConsoleQtMainWindow::FileOpen() { ::Console.FileOpen(); }
void C4ConsoleQtMainWindow::FileOpenWithPlayers() { Console.FileOpenWPlrs(); }
void C4ConsoleQtMainWindow::FileRecord() { ::Console.FileRecord(); }
void C4ConsoleQtMainWindow::FileSave() { ::Console.FileSave(); }
void C4ConsoleQtMainWindow::FileSaveAs() { ::Console.FileSaveAs(false); }
void C4ConsoleQtMainWindow::FileSaveGameAs() { ::Console.FileSaveAs(true); }
void C4ConsoleQtMainWindow::FileClose() { ::Console.FileClose(); }
void C4ConsoleQtMainWindow::FileQuit() { ::Console.FileQuit(); }
// Player menu
void C4ConsoleQtMainWindow::PlayerJoin() { ::Console.PlayerJoin(); }
// Window menu
void C4ConsoleQtMainWindow::ViewportNew() { ::Console.ViewportNew(); }
// Help menu
void C4ConsoleQtMainWindow::HelpAbout() { ::Console.HelpAbout(); }
// Script enter
void C4ConsoleQtMainWindow::MainConsoleEditEnter()
{
QLineEdit *main_console_edit = state->ui.consoleInputBox->lineEdit();
std::string script = main_console_edit->text().toStdString();
::Console.RegisterRecentInput(script.c_str(), C4Console::MRU_Scenario);
::Console.In(script.c_str());
}
void C4ConsoleQtMainWindow::PropertyConsoleEditEnter()
{
QLineEdit *property_console_edit = state->ui.propertyInputBox->lineEdit();
std::string script = property_console_edit->text().toStdString();
//::Console.RegisterRecentInput(script.c_str(), C4Console::MRU_Object); - done by EditCursor
::Console.EditCursor.In(script.c_str());
}
/* Common C4ConsoleGUI interface */
C4ConsoleGUIState::C4ConsoleGUIState(C4ConsoleGUI *console) : viewport_area(NULL),
enabled(false), recording(false), net_enabled(false), landscape_mode(C4LSC_Dynamic),
editcursor_mode(C4CNS_ModePlay), drawing_tool(C4TLS_Brush)
{
}
C4ConsoleGUIState::~C4ConsoleGUIState()
{
}
void C4ConsoleGUIState::AddToolbarSpacer(int space)
{
auto spacer = new QWidget();
spacer->setFixedWidth(space);
ui.toolBar->addWidget(spacer);
}
bool C4ConsoleGUIState::CreateConsoleWindow(C4AbstractApp *app)
{
// Basic Qt+Main window setup from .ui file
int fake_argc = 0;
application.reset(new QApplication(fake_argc, NULL));
application->installTranslator(&qt_translator);
window.reset(new C4ConsoleQtMainWindow(app, this));
ui.setupUi(window.get());
// Setup some extra stuff that cannot be done easily in the designer
// Divide status bar
status_cursor = new QLabel("", window.get());
status_framecounter = new QLabel("", window.get());
status_timefps = new QLabel("", window.get());
ui.statusbar->addPermanentWidget(status_cursor, 3);
ui.statusbar->addPermanentWidget(status_framecounter, 1);
ui.statusbar->addPermanentWidget(status_timefps, 1);
// Move drawing tools into toolbar
ui.toolBar->addWidget(ui.foregroundMatTexComboBox);
ui.toolBar->addWidget(ui.backgroundMatTexComboBox);
AddToolbarSpacer(5);
ui.toolBar->addWidget(ui.drawSizeLabel);
AddToolbarSpacer(5);
ui.toolBar->addWidget(ui.drawSizeSlider);
ui.drawSizeSlider->setMaximum(C4TLS_GradeMax);
ui.drawSizeSlider->setMinimum(C4TLS_GradeMin);
ui.drawSizeSlider->setValue(C4TLS_GradeDefault);
// Console input box signal
QLineEdit *main_console_edit = ui.consoleInputBox->lineEdit();
main_console_edit->connect(main_console_edit, SIGNAL(returnPressed()), window.get(), SLOT(MainConsoleEditEnter()));
QLineEdit *property_console_edit = ui.propertyInputBox->lineEdit();
property_console_edit->connect(property_console_edit, SIGNAL(returnPressed()), window.get(), SLOT(PropertyConsoleEditEnter()));
// Add window menu actions
window_menu_separator = ui.menuWindows->addSeparator();
ui.menuWindows->addAction(ui.creatorDockWidget->toggleViewAction());
ui.menuWindows->addAction(ui.objectListDockWidget->toggleViewAction());
ui.menuWindows->addAction(ui.propertyDockWidget->toggleViewAction());
ui.menuWindows->addAction(ui.logDockWidget->toggleViewAction());
// Viewport area setup
viewport_area = new QMainWindow();
viewport_area->setWindowFlags(Qt::Widget);
window->setCentralWidget(viewport_area);
window->setDockNestingEnabled(true);
viewport_area->setDockNestingEnabled(true);
// Property view model
property_model.reset(new C4ConsoleQtPropListModel());
ui.propertyTable->setModel(property_model.get());
window->showNormal();
#ifdef USE_WIN32_WINDOWS
// Restore window position
HWND hWindow = reinterpret_cast<HWND>(window->winId());
RestoreWindowPosition(hWindow, "Main", Config.GetSubkeyPath("Console"));
#endif
return true;
}
void C4ConsoleGUIState::Execute()
{
// Qt window message handling and object cleanup
if (application)
{
application->processEvents();
application->sendPostedEvents(0, QEvent::DeferredDelete);
}
}
void C4ConsoleGUIState::Redraw()
{
// process only non-critical events
if (application) application->processEvents(QEventLoop::ExcludeUserInputEvents);
}
// Set action pressed/checked and enabled states
void C4ConsoleGUIState::UpdateActionStates()
{
// Enabled states
bool has_draw_tools = enabled && landscape_mode != C4LSC_Dynamic;
bool has_exact_draw_tools = enabled && landscape_mode == C4LSC_Exact;
bool is_drawing = has_draw_tools && editcursor_mode == C4CNS_ModeDraw;
ui.actionPlay->setEnabled(enabled);
ui.actionPause->setEnabled(enabled);
ui.actionCursorGame->setEnabled(enabled);
ui.actionCursorSelect->setEnabled(enabled);
ui.actionCursorDrawPen->setEnabled(has_draw_tools);
ui.actionCursorDrawLine->setEnabled(has_draw_tools);
ui.actionCursorDrawRect->setEnabled(has_draw_tools);
ui.actionCursorPicker->setEnabled(has_draw_tools);
ui.actionCursorFill->setEnabled(has_exact_draw_tools);
ui.actionDynamicLandscape->setEnabled(enabled);
ui.actionStaticLandscape->setEnabled(enabled);
ui.actionExactLandscape->setEnabled(enabled);
ui.foregroundMatTexComboBox->setEnabled(is_drawing);
ui.backgroundMatTexComboBox->setEnabled(is_drawing);
ui.drawSizeSlider->setEnabled(is_drawing);
ui.actionFileClose->setEnabled(enabled);
ui.actionFileRecord->setEnabled(enabled && !recording);
ui.actionFileSaveGameAs->setEnabled(enabled);
ui.actionFileSaveScenario->setEnabled(enabled);
ui.actionFileSaveScenarioAs->setEnabled(enabled);
ui.actionViewportNew->setEnabled(enabled);
ui.actionPlayerJoin->setEnabled(enabled);
ui.menuNet->setVisible(net_enabled);
ui.menuNet->setHidden(!net_enabled);
ui.menuNet->setEnabled(net_enabled);
// Checked states
ui.actionCursorGame->setChecked(editcursor_mode == C4CNS_ModePlay);
ui.actionCursorSelect->setChecked(editcursor_mode == C4CNS_ModeEdit);
ui.actionCursorDrawPen->setChecked((editcursor_mode == C4CNS_ModeDraw) && (drawing_tool == C4TLS_Brush));
ui.actionCursorDrawLine->setChecked((editcursor_mode == C4CNS_ModeDraw) && (drawing_tool == C4TLS_Line));
ui.actionCursorDrawRect->setChecked((editcursor_mode == C4CNS_ModeDraw) && (drawing_tool == C4TLS_Rect));
ui.actionCursorFill->setChecked((editcursor_mode == C4CNS_ModeDraw) && (drawing_tool == C4TLS_Fill));
ui.actionCursorPicker->setChecked((editcursor_mode == C4CNS_ModeDraw) && (drawing_tool == C4TLS_Picker));
ui.actionDynamicLandscape->setChecked(landscape_mode == C4LSC_Dynamic);
ui.actionStaticLandscape->setChecked(landscape_mode == C4LSC_Static);
ui.actionExactLandscape->setChecked(landscape_mode == C4LSC_Exact);
ui.actionFileRecord->setChecked(recording);
}
// Put function list into combo box selectable items
static void SetComboItems(QComboBox *box, std::list<const char*> &items)
{
QString text = box->lineEdit()->text(); // remember and restore current text
box->clear();
for (std::list<const char*>::iterator it = items.begin(); it != items.end(); it++)
{
if (!*it)
box->addItem("----------");
else
box->addItem(*it);
}
box->lineEdit()->setText(text);
}
void C4ConsoleGUIState::UpdateMatTex()
{
// Update selection of mattex in combo box
int new_index = 0;
if (material != C4TLS_MatSky) new_index = ui.foregroundMatTexComboBox->findText(QString(FormatString("%s-%s", material.getData(), texture.getData()).getData()));
if (new_index >= 0) ui.foregroundMatTexComboBox->setCurrentIndex(new_index);
}
void C4ConsoleGUIState::UpdateBackMatTex()
{
// Update selection of mattex in combo box
int new_index = 0;
if (back_material != C4TLS_MatSky) new_index = ui.backgroundMatTexComboBox->findText(QString(FormatString("%s-%s", back_material.getData(), back_texture.getData()).getData()));
if (new_index >= 0) ui.backgroundMatTexComboBox->setCurrentIndex(new_index);
}
void C4ConsoleGUIState::AddNetMenuItem(int32_t index, const char *text)
{
auto *kick_action = new C4ConsoleClientAction(index, text, ui.menuNet);
client_actions.emplace_back(kick_action);
ui.menuNet->addAction(kick_action);
}
void C4ConsoleGUIState::ClearNetMenu()
{
for (auto &action : client_actions) ui.menuNet->removeAction(action.get());
client_actions.clear();
}
void C4ConsoleGUIState::AddKickPlayerMenuItem(int32_t plr, const char *text, bool item_enabled)
{
auto *kick_action = new C4ConsoleRemovePlayerAction(plr, text, ui.menuPlayers);
kick_action->setEnabled(item_enabled);
player_actions.emplace_back(kick_action);
ui.menuPlayers->addAction(kick_action);
}
void C4ConsoleGUIState::ClearPlayerMenu()
{
for (auto &action : player_actions) ui.menuPlayers->removeAction(action.get());
player_actions.clear();
}
void C4ConsoleGUIState::AddPlayerViewportMenuItem(int32_t plr, const char *text)
{
auto *action = new C4ConsoleOpenViewportAction(plr, text, ui.menuWindows);
viewport_actions.emplace_back(action);
ui.menuWindows->insertAction(window_menu_separator, action);
}
void C4ConsoleGUIState::ClearViewportMenu()
{
for (auto &action : viewport_actions) ui.menuWindows->removeAction(action.get());
viewport_actions.clear();
}
void C4ConsoleGUIState::AddViewport(C4ViewportWindow *cvp)
{
if (!viewport_area) return;
C4ConsoleViewportWidget *new_viewport = new C4ConsoleViewportWidget(viewport_area, cvp);
viewport_area->addDockWidget(Qt::BottomDockWidgetArea, new_viewport);
viewports.push_back(new_viewport);
new_viewport->setFocus();
}
void C4ConsoleGUIState::OnViewportActiveChanged(C4ViewportWindow *cvp, bool is_active)
{
// Viewport active state changed: Forward to appropriate viewport window
for (auto vp : viewports)
if (vp->GetViewportWindow() == cvp)
{
vp->OnActiveChanged(is_active);
}
}
void C4ConsoleGUIState::SetInputFunctions(std::list<const char*> &functions)
{
SetComboItems(ui.consoleInputBox, functions);
}
void C4ConsoleGUIState::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *proplist_selection)
{
int sel_count = rSelection.ObjectCount();
if (sel_count != 1)
{
// Multi object selection: Hide property view; show info label
ui.propertyTable->setVisible(false);
ui.multiSelInfoLabel->setText(rSelection.GetDataString().getData());
ui.multiSelInfoLabel->setVisible(true);
}
else
{
// Single object selection: Show property view
property_model->SetPropList(proplist_selection);
ui.multiSelInfoLabel->setVisible(false);
ui.propertyTable->setVisible(true);
}
// Function update in script combo box
if (force_function_update)
SetComboItems(ui.propertyInputBox, ::Console.GetScriptSuggestions(::Console.PropertyDlgObject, C4Console::MRU_Object));
}

View File

@ -0,0 +1,230 @@
/*
* OpenClonk, http://www.openclonk.org
*
* Copyright (c) 2001-2009, RedWolf Design GmbH, http://www.clonk.de/
* Copyright (c) 2013, The OpenClonk Team and contributors
*
* Distributed under the terms of the ISC license; see accompanying file
* "COPYING" for details.
*
* "Clonk" is a registered trademark of Matthes Bender, used with permission.
* See accompanying file "TRADEMARK" for details.
*
* To redistribute this file separately, substitute the full license texts
* for the above references.
*/
/* Editor windows using Qt - internal state */
#ifndef INC_C4ConsoleQtState
#define INC_C4ConsoleQtState
#ifdef WITH_QT_EDITOR
#include <C4Include.h> // needed for automoc
#include <C4ConsoleGUI.h>
#include <C4ToolsDlg.h>
#include <C4ConsoleQt.h>
#include <ui_C4ConsoleQtMainWindow.h>
#ifdef USE_WIN32_WINDOWS
#include <WinUser.h>
#include <resource.h>
#endif
/* Forward string translation to GetResStr */
class C4ConsoleQtTranslator : public QTranslator
{
Q_OBJECT
public:
bool isEmpty() { return false; }
QString translate(const char * context, const char * sourceText, const char * disambiguation = 0, int n = -1) const;
};
extern C4ConsoleQtTranslator qt_translator;
class C4ConsoleClientAction : public QAction
{
Q_OBJECT
int32_t client_id;
public:
C4ConsoleClientAction(int32_t client_id, const char *text, QObject *parent);
int32_t GetClientID() const { return client_id; }
private slots:
void Execute();
};
class C4ConsoleRemovePlayerAction : public QAction
{
Q_OBJECT
int32_t player_num;
public:
C4ConsoleRemovePlayerAction(int32_t player_num, const char *text, QObject *parent);
int32_t GetPlayerNum() const { return player_num; }
private slots:
void Execute();
};
class C4ConsoleOpenViewportAction : public QAction
{
Q_OBJECT
int32_t player_num;
public:
C4ConsoleOpenViewportAction(int32_t player_num, const char *text, QObject *parent);
int32_t GetPlayerNum() const { return player_num; }
private slots:
void Execute();
};
class C4ConsoleViewportWidget : public QDockWidget
{
Q_OBJECT
class C4ViewportWindow *cvp;
QWindow *window;
QPalette pal_inactive, pal_active;
protected:
virtual void focusInEvent(QFocusEvent * event);
virtual void focusOutEvent(QFocusEvent * event);
virtual QObject *focusObject() const { return window; }
public:
C4ConsoleViewportWidget(class QMainWindow *parent, class C4ViewportWindow *window);
virtual void closeEvent(QCloseEvent * event);
void OnActiveChanged(bool active);
class C4ViewportWindow *GetViewportWindow() const { return cvp; }
private slots:
void DockLocationChanged(Qt::DockWidgetArea new_area);
};
class C4ConsoleQtMainWindow : public QMainWindow
{
Q_OBJECT
class C4ConsoleGUIState *state;
public:
C4ConsoleQtMainWindow(class C4AbstractApp *app, class C4ConsoleGUIState *state);
void closeEvent(class QCloseEvent *event);
public slots:
// Toolbar items
void PlayPressed(bool down);
void PausePressed(bool down);
void CursorGamePressed(bool down);
void CursorSelectPressed(bool down);
void CursorDrawPenPressed(bool down);
void CursorDrawLinePressed(bool down);
void CursorDrawRectPressed(bool down);
void CursorFillPressed(bool down);
void CursorPickerPressed(bool down);
void DynamicLandscapePressed(bool down);
void StaticLandscapePressed(bool down);
void ExactLandscapePressed(bool down);
void DrawSizeChanged(int newval);
// File menu
void FileOpen();
void FileOpenWithPlayers();
void FileRecord();
void FileSave();
void FileSaveAs();
void FileSaveGameAs();
void FileClose();
void FileQuit();
// Player menu
void PlayerJoin();
// Window menu
void ViewportNew();
// Help menu
void HelpAbout();
// Console edits enter pressed events
void MainConsoleEditEnter(); // console edit below log
void PropertyConsoleEditEnter(); // console edit of property window
};
/* Main Qt editor class controlled through ControlGUI */
class C4ConsoleGUIState // Avoid direct declaration of C4ConsoleGUI::State because qmake doesn't like some declarations in the nested class
{
public:
std::unique_ptr<QApplication> application;
std::unique_ptr<C4ConsoleQtMainWindow> window;
std::unique_ptr<class C4ConsoleQtPropListModel> property_model;
std::list<C4ConsoleViewportWidget *> viewports;
std::list<std::unique_ptr<C4ConsoleClientAction> > client_actions;
std::list<std::unique_ptr<C4ConsoleRemovePlayerAction> > player_actions;
std::list<std::unique_ptr<C4ConsoleOpenViewportAction> > viewport_actions;
Ui::MainWindow ui;
// ptrs owned by window
QMainWindow *viewport_area;
QLabel *status_cursor, *status_framecounter, *status_timefps;
QAction *window_menu_separator;
// Current editor/tool states
// Cannot use direct members in C4EditorCursor because callbacks into the GUI happen before the values change.
// If other C4Console implementations are removed, the state could be merged and these members removed.
bool enabled, recording, net_enabled;
int32_t landscape_mode, editcursor_mode, drawing_tool;
StdCopyStrBuf material, texture, back_material, back_texture;
C4ConsoleGUIState(C4ConsoleGUI *console);
~C4ConsoleGUIState();
void AddToolbarSpacer(int space);
bool CreateConsoleWindow(C4AbstractApp *app);
void Execute();
void Redraw();
void UpdateActionStates();
void UpdateMatTex();
void UpdateBackMatTex();
// Set modes and tools
void SetEnabled(bool to_enabled) { enabled = to_enabled; UpdateActionStates(); }
void SetLandscapeMode(int32_t to_landscape_mode) { landscape_mode = to_landscape_mode; UpdateActionStates(); }
void SetEditCursorMode(int32_t to_editcursor_mode) { editcursor_mode = to_editcursor_mode; UpdateActionStates(); }
void SetDrawingTool(int32_t to_drawing_tool) { drawing_tool = to_drawing_tool; UpdateActionStates(); }
void SetMaterial(const char *new_material) { material.Copy(new_material); UpdateMatTex(); }
void SetTexture(const char *new_texture) { texture.Copy(new_texture); UpdateMatTex(); }
void SetBackMaterial(const char *new_material) { back_material.Copy(new_material); UpdateBackMatTex(); }
void SetBackTexture(const char *new_texture) { back_texture.Copy(new_texture); UpdateBackMatTex(); }
void SetRecording(bool to_recording) { recording = to_recording; UpdateActionStates(); }
void SetNetEnabled(bool enabled) { net_enabled = enabled; UpdateActionStates(); }
void AddNetMenuItem(int32_t index, const char *text);
void ClearNetMenu();
void AddKickPlayerMenuItem(int32_t plr, const char *text, bool item_enabled);
void ClearPlayerMenu();
void AddPlayerViewportMenuItem(int32_t plr, const char *text);
void ClearViewportMenu();
void AddViewport(class C4ViewportWindow *cvp);
void OnViewportActiveChanged(C4ViewportWindow *cvp, bool is_active);
void SetInputFunctions(std::list<const char*> &functions);
void PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *proplist_selection);
};
class C4ConsoleGUI::State : public C4ConsoleGUIState
{
public:
State(C4ConsoleGUI *console) : C4ConsoleGUIState(console) {}
};
class C4ToolsDlg::State : C4ConsoleGUI::InternalState<class C4ToolsDlg>
{
public:
State(C4ToolsDlg *toolsDlg) : C4ConsoleGUI::InternalState<class C4ToolsDlg>(toolsDlg) {}
~State() {}
void Clear() {}
void Default() {}
};
#endif // WITH_QT_EDITOR
#endif // INC_C4ConsoleQtState

View File

@ -1074,7 +1074,7 @@ static void SetComboItems(HWND hCombo, std::list<const char*> &items)
}
}
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update)
void C4ConsoleGUI::PropertyDlgUpdate(C4ObjectList &rSelection, bool force_function_update, class C4PropList *proplist_selection)
{
HWND hDialog = state->hPropertyDlg;
if (!hDialog) return;

View File

@ -73,7 +73,7 @@ void C4EditCursor::Execute()
// - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}
if (!::Game.iTick35)
Console.PropertyDlgUpdate(Selection, false);
Console.PropertyDlgUpdate(Selection, false, proplist_selection.getPropList());
}
bool C4EditCursor::Init()
@ -106,6 +106,7 @@ bool C4EditCursor::Init()
void C4EditCursor::ClearPointers(C4Object *pObj)
{
if (proplist_selection.getObj() == pObj) proplist_selection.Set0(); // update immediately to ensure it's cleared before update
if (Target==pObj) Target=NULL;
if (Selection.ClearPointers(pObj))
OnSelectionChanged();
@ -200,7 +201,7 @@ void C4EditCursor::UpdateStatusBar()
void C4EditCursor::OnSelectionChanged()
{
Console.PropertyDlgUpdate(Selection, false);
Console.PropertyDlgUpdate(Selection, false, proplist_selection.getPropList());
Console.ObjectListDlg.Update(Selection);
}
@ -208,6 +209,7 @@ void C4EditCursor::AddToSelection(C4Object *add_obj)
{
if (!add_obj || !add_obj->Status) return;
// add object to selection and do script callback
if (!proplist_selection) proplist_selection.SetPropList(add_obj);
Selection.Add(add_obj, C4ObjectList::stNone);
::Control.DoInput(CID_EMMoveObj, new C4ControlEMMoveObject(EMMO_Select, Fix0, Fix0, add_obj), CDT_Decide);
}
@ -217,6 +219,11 @@ bool C4EditCursor::RemoveFromSelection(C4Object *remove_obj)
if (!remove_obj || !remove_obj->Status) return false;
// remove object from selection and do script callback
if (!Selection.Remove(remove_obj)) return false;
if (proplist_selection.getObj() == remove_obj)
if (Selection.First && Selection.First->Obj && Selection.First->Obj->Status)
proplist_selection.SetPropList(Selection.First->Obj);
else
proplist_selection.Set0();
::Control.DoInput(CID_EMMoveObj, new C4ControlEMMoveObject(EMMO_Deselect, Fix0, Fix0, remove_obj), CDT_Decide);
return true;
}
@ -243,6 +250,7 @@ void C4EditCursor::ClearSelection(C4Object *next_selection)
}
}
Selection.Clear();
proplist_selection.Set0();
}
bool C4EditCursor::LeftButtonDown(DWORD dwKeyState)
@ -476,7 +484,7 @@ bool C4EditCursor::OpenPropTools()
{
case C4CNS_ModeEdit: case C4CNS_ModePlay:
Console.PropertyDlgOpen();
Console.PropertyDlgUpdate(Selection, false);
Console.PropertyDlgUpdate(Selection, false, proplist_selection.getPropList());
break;
case C4CNS_ModeDraw:
Console.ToolsDlg.Open();
@ -607,7 +615,7 @@ bool C4EditCursor::In(const char *szText)
{
::Console.RegisterRecentInput(szText, C4Console::MRU_Object);
EMMoveObject(EMMO_Script, Fix0, Fix0, NULL, &Selection, szText);
::Console.PropertyDlgUpdate(Selection, true);
::Console.PropertyDlgUpdate(Selection, true, proplist_selection.getPropList());
return true;
}

View File

@ -23,6 +23,7 @@
#include "C4ObjectList.h"
#include "C4Control.h"
#include "C4Rect.h"
#include "C4Value.h"
#include <vector>
#ifdef USE_GTK
@ -61,7 +62,9 @@ protected:
GtkWidget* itemGrabContents;
GtkWidget* itemProperties;
#endif
// Selection may either be any number of objects or a single non-object prop list
C4ObjectList Selection;
C4Value proplist_selection;
public:
void Default();
void Clear();

View File

@ -181,8 +181,13 @@ C4Window * C4ViewportWindow::Init(int32_t Player)
if (!result) return result;
pSurface = new C4Surface(&Application, this);
#ifdef WITH_QT_EDITOR
// embed into editor
::Console.AddViewport(this);
#else
// Position and size
RestorePosition(FormatString("Viewport%i", Player+1).getData(), Config.GetSubkeyPath("Console"));
#endif
return result;
}

View File

@ -0,0 +1,17 @@
<RCC>
<qresource prefix="/editor">
<file>../res/Brush_Trans.png</file>
<file>../res/Cursor_Trans.png</file>
<file>../res/Dynamic_Trans.png</file>
<file>../res/Exact_Trans.png</file>
<file>../res/Fill_Trans.png</file>
<file>../res/Halt_Trans.png</file>
<file>../res/Line_Trans.png</file>
<file>../res/Mouse_Trans.png</file>
<file>../res/oc64.png</file>
<file>../res/Picker_Trans.png</file>
<file>../res/Play_Trans.png</file>
<file>../res/Rect_Trans.png</file>
<file>../res/Static_Trans.png</file>
</qresource>
</RCC>

View File

@ -354,6 +354,10 @@ LRESULT APIENTRY ViewportWinProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lPa
return 0;
//----------------------------------------------------------------------------------------------------------------------------------
case WM_ACTIVATE:
#ifdef WITH_QT_EDITOR
// Notify editor that viewport needs to be drawn in activated state
::Console.OnViewportActiveChanged(cvp->GetWindow(), LOWORD(wParam) != WA_INACTIVE);
#endif
// Keep editing dialogs on top of the current viewport, but don't make them
// float on other windows (i.e., no HWND_TOPMOST).
// Also, don't use SetParent, since that activates the window, which in turn

View File

@ -459,6 +459,17 @@ void C4PropList::AppendDataString(StdStrBuf * out, const char * delim, int depth
}
}
std::vector< C4RefCntPointer<C4String> > C4PropList::GetSortedLocalProperties() const
{
// return property list without descending into prototype
std::list<const C4Property *> sorted_props = Properties.GetSortedListOfElementPointers();
std::vector< C4RefCntPointer<C4String> > result;
result.reserve(sorted_props.size() + 1);
result.push_back(&::Strings.P[P_Prototype]); // implicit prototype for every prop list
for (auto p : sorted_props) result.push_back(p->Key);
return result;
}
const char * C4PropList::GetName() const
{
C4String * s = GetPropertyStr(P_Name);

View File

@ -133,6 +133,7 @@ public:
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
void AppendDataString(StdStrBuf * out, const char * delim, int depth = 3) const;
std::vector< C4RefCntPointer<C4String> > GetSortedLocalProperties() const;
bool operator==(const C4PropList &b) const;
#ifdef _DEBUG

View File

@ -92,6 +92,7 @@ public:
const T* operator -> () const { return p; }
operator T * () { return p; }
operator const T * () const { return p; }
T *Get() const { return p; }
private:
void IncRef() { if (p) p->IncRef(); }
void DecRef() { if (p) p->DecRef(); }
@ -173,7 +174,7 @@ public:
Table[i] = b.Table[i];
return *this;
}
void CompileFunc(StdCompiler *pComp, C4ValueNumbers *);
void CompileFunc(class StdCompiler *pComp, class C4ValueNumbers *);
void Clear()
{
ClearTable();