More menu work

This commit is contained in:
Brad Davis 2015-04-25 10:41:06 -07:00
parent fbdb9b143e
commit ee30588fd4
14 changed files with 1376 additions and 199 deletions

View file

@ -1,20 +0,0 @@
import QtQuick 2.4
import QtQuick.Controls 1.3
Action {
property string name
objectName: name + "HifiAction"
text: qsTr(name)
signal triggeredByName(string name);
signal toggledByName(string name);
onTriggered: {
triggeredByName(name);
}
onToggled: {
toggledByName(name, checked);
}
}

View file

@ -17,7 +17,7 @@ Hifi.HifiMenu {
onEnabledChanged: {
if (enabled && columns.length == 0) {
pushColumn(rootMenu.items);
pushColumn(rootMenu.menus);
}
opacity = enabled ? 1.0 : 0.0
if (enabled) {
@ -42,9 +42,95 @@ Hifi.HifiMenu {
}
property var menu: Menu {}
property var models: []
property var columns: []
property var menuBuilder: Component {
Border {
SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active }
x: root.models.length == 1 ?
(root.width / 2 - width / 2) :
root.columns[root.models.length - 2].x + 60;
anchors.verticalCenter: parent.verticalCenter
border.color: hifiPalette.hifiBlue
color: sysPalette.window
ListView {
spacing: 6
property int outerMargin: 8
property real minWidth: 0
anchors.fill: parent
anchors.margins: outerMargin
id: listView
height: root.height
currentIndex: -1
onCountChanged: {
recalculateSize()
}
function recalculateSize() {
var newHeight = 0
var newWidth = minWidth;
for (var i = 0; i < children.length; ++i) {
var item = children[i];
newHeight += item.height
}
parent.height = newHeight + outerMargin * 2;
parent.width = newWidth + outerMargin * 2
}
highlight: Rectangle {
width: listView.minWidth - 32;
height: 32
color: sysPalette.highlight
y: (listView.currentItem) ? listView.currentItem.y : 0;
x: 32
Behavior on y {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuint
}
}
}
property int columnIndex: root.models.length - 1
model: root.models[columnIndex]
delegate: Loader {
id: loader
sourceComponent: root.itemBuilder
Binding {
target: loader.item
property: "root"
value: root
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "source"
value: modelData
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listViewIndex"
value: index
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listView"
value: listView
when: loader.status == Loader.Ready
}
}
}
}
}
property var itemBuilder: Component {
Text {
SystemPalette { id: sp; colorGroup: SystemPalette.Active }
@ -93,6 +179,8 @@ Hifi.HifiMenu {
MouseArea {
id: mouseArea
acceptedButtons: Qt.LeftButton
anchors.left: parent.left
anchors.leftMargin: -32
anchors.bottom: parent.bottom
anchors.bottomMargin: 0
anchors.top: parent.top
@ -106,91 +194,6 @@ Hifi.HifiMenu {
}
}
property var menuBuilder: Component {
Border {
SystemPalette { id: sysPalette; colorGroup: SystemPalette.Active }
x: root.models.length == 1 ?
(root.width / 2 - width / 2) :
root.columns[root.models.length - 2].x + 60;
anchors.verticalCenter: parent.verticalCenter
border.color: hifiPalette.hifiBlue
color: sysPalette.window
ListView {
spacing: 6
property int outerMargin: 8
property real minWidth: 0
anchors.fill: parent
anchors.margins: outerMargin
id: listView
height: root.height
currentIndex: -1
onCountChanged: {
recalculateSize()
}
function recalculateSize() {
var newHeight = 0
var newWidth = minWidth;
for (var i = 0; i < children.length; ++i) {
var item = children[i];
newHeight += item.height
}
parent.height = newHeight + outerMargin * 2;
parent.width = newWidth + outerMargin * 2
}
highlight: Rectangle {
width: listView.minWidth; height: 32
color: sysPalette.highlight
y: (listView.currentItem) ? listView.currentItem.y : 0;
x: 32
Behavior on y {
NumberAnimation {
duration: 100
easing.type: Easing.InOutQuint
}
}
}
property int columnIndex: root.models.length - 1
model: root.models[columnIndex]
delegate: Loader {
id: loader
sourceComponent: root.itemBuilder
Binding {
target: loader.item
property: "root"
value: root
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "source"
value: modelData
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listViewIndex"
value: index
when: loader.status == Loader.Ready
}
Binding {
target: loader.item
property: "listView"
value: listView
when: loader.status == Loader.Ready
}
}
}
}
}
function lastColumn() {

File diff suppressed because it is too large Load diff

View file

@ -761,17 +761,6 @@ void Application::initializeGL() {
InfoView::showFirstTime(INFO_HELP_PATH);
}
class OAuthFactory : public QQmlNetworkAccessManagerFactory {
QThreadStorage<OAuthNetworkAccessManager*> oauthNetworkAccessManagers;
public:
virtual QNetworkAccessManager * create(QObject * parent) {
if (!oauthNetworkAccessManagers.hasLocalData()) {
oauthNetworkAccessManagers.setLocalData(OAuthNetworkAccessManager::getInstance());
}
return oauthNetworkAccessManagers.localData();
}
};
void Application::initializeUi() {
AddressBarDialog::registerType();
LoginDialog::registerType();

View file

@ -35,8 +35,8 @@ void LoginDialog::toggleAction() {
});
} else {
// change the menu item to login
loginAction->setText("Login");
connect(loginAction, &QAction::triggered, [] {
menu->setOptionText(MenuOption::Login, "Login");
menu->setOptionTriggerAction(MenuOption::Login, [] {
LoginDialog::show();
});
}

View file

@ -12,7 +12,7 @@
#include "MarketplaceDialog.h"
#include "DependencyManager.h"
QML_DIALOG_DEF(MarketplaceDialog)
HIFI_QML_DEF(MarketplaceDialog)
MarketplaceDialog::MarketplaceDialog(QQuickItem *parent) : OffscreenQmlDialog(parent) {

View file

@ -17,7 +17,7 @@
class MarketplaceDialog : public OffscreenQmlDialog
{
Q_OBJECT
QML_DIALOG_DECL
HIFI_QML_DECL
public:
MarketplaceDialog(QQuickItem *parent = 0);

View file

@ -1,19 +0,0 @@
//
// MenuQml.cpp
//
// Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#include "Application.h"
#include "MenuQml.h"
QML_DIALOG_DEF(MenuQml)
MenuQml::MenuQml(QQuickItem *parent) : QQuickItem(parent) {
auto menu = Menu::getInstance();
}

View file

@ -1,26 +0,0 @@
//
// MenuQml.h
//
// Created by Bradley Austin Davis on 2015/04/14
// Copyright 2015 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#pragma once
#ifndef hifi_MenuQml_h
#define hifi_MenuQml_h
#include <OffscreenQmlDialog.h>
class MenuQml : public QQuickItem
{
Q_OBJECT
QML_DIALOG_DECL
public:
MenuQml(QQuickItem *parent = 0);
};
#endif

View file

@ -277,3 +277,26 @@ void HifiMenu::connectItem(const QString& menuOption, QObject* receiver, const c
QObject* result = findMenuObject(menuOption);
connect(result, SIGNAL(triggered()), receiver, slot);
}
void HifiMenu::setExclusiveGroup(const QString& menuOption, const QString& groupName) {
static const QString GROUP_SUFFIX{ "__Group" };
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QObject* group = offscreenUi->getRootItem()->findChild<QObject*>(groupName + GROUP_SUFFIX);
if (!group) {
group = offscreenUi->load("ExclusiveGroup.qml");
Q_ASSERT(group);
}
QObject* menuItem = findMenuObject(menuOption);
bool result = menuItem->setProperty("text", QVariant::fromValue(group));
Q_ASSERT(result);
}
bool HifiMenu::connectAction(int action, QObject * receiver, const char * slot) {
auto offscreenUi = DependencyManager::get<OffscreenUi>();
QObject* rootMenu = offscreenUi->getRootItem()->findChild<QObject*>("AllActions");
QString name = "HifiAction_" + QVariant(action).toString();
QObject* quitAction = rootMenu->findChild<QObject*>(name);
connect(quitAction, SIGNAL(triggered()), qApp, SLOT(quit()));
return true;
}

View file

@ -23,6 +23,9 @@ class HifiMenu : public QQuickItem {
HIFI_QML_DECL_LAMBDA
public:
static bool connectAction(int action, QObject * receiver, const char * slot);
HifiMenu(QQuickItem* parent = nullptr);
void setToggleAction(const QString& name, std::function<void(bool)> f);

View file

@ -152,13 +152,12 @@ void OffscreenUi::setBaseUrl(const QUrl& baseUrl) {
}
QObject* OffscreenUi::load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f) {
qDebug() << "Loading QML from URL " << qmlSource;
_qmlComponent->loadUrl(qmlSource);
if (_qmlComponent->isLoading()) {
connect(_qmlComponent, &QQmlComponent::statusChanged, this,
[this, f](QQmlComponent::Status){
finishQmlLoad(f);
});
[this, f](QQmlComponent::Status){
finishQmlLoad(f);
});
return nullptr;
}

View file

@ -38,9 +38,9 @@ private: \
static const QUrl QML; \
public: \
static void registerType(); \
static void show(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
static void toggle(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
static void load(std::function<void(QQmlContext*, QQuickItem *)> f = [](QQmlContext*, QQuickItem*) {}); \
static void show(std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}); \
static void toggle(std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}); \
static void load(std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}); \
private:
#define HIFI_QML_DECL_LAMBDA \
@ -62,16 +62,16 @@ private:
qmlRegisterType<x>("Hifi", 1, 0, NAME.toLocal8Bit().constData()); \
} \
\
void x::show(std::function<void(QQmlContext*, QQuickItem *)> f) { \
void x::show(std::function<void(QQmlContext*, QObject*)> f) { \
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
offscreenUi->show(QML, NAME, f); \
} \
\
void x::toggle(std::function<void(QQmlContext*, QQuickItem *)> f) { \
void x::toggle(std::function<void(QQmlContext*, QObject*)> f) { \
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
offscreenUi->toggle(QML, NAME, f); \
} \
void x::load(std::function<void(QQmlContext*, QQuickItem *)> f) { \
void x::load(std::function<void(QQmlContext*, QObject*)> f) { \
auto offscreenUi = DependencyManager::get<OffscreenUi>(); \
offscreenUi->load(QML, f); \
}
@ -122,9 +122,9 @@ public:
virtual ~OffscreenUi();
void create(QOpenGLContext* context);
void resize(const QSize& size);
void load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
void load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
load(QUrl(qmlSourceFile), f);
QObject* load(const QUrl& qmlSource, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
QObject* load(const QString& qmlSourceFile, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {}) {
return load(QUrl(qmlSourceFile), f);
}
void show(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
void toggle(const QUrl& url, const QString& name, std::function<void(QQmlContext*, QObject*)> f = [](QQmlContext*, QObject*) {});
@ -169,11 +169,11 @@ public:
ButtonCallback callback = NO_OP_CALLBACK,
QMessageBox::StandardButtons buttons = QMessageBox::Ok);
protected:
private:
QObject* finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f);
private slots:
void updateQuick();
void finishQmlLoad(std::function<void(QQmlContext*, QObject*)> f);
public slots:
void requestUpdate();

View file

@ -74,6 +74,171 @@ public:
};
class MenuConstants : public QObject{
Q_OBJECT
Q_ENUMS(Item)
public:
enum Item {
AboutApp,
AddRemoveFriends,
AddressBar,
AlignForearmsWithWrists,
AlternateIK,
AmbientOcclusion,
Animations,
Atmosphere,
Attachments,
AudioNoiseReduction,
AudioScope,
AudioScopeFiftyFrames,
AudioScopeFiveFrames,
AudioScopeFrames,
AudioScopePause,
AudioScopeTwentyFrames,
AudioStats,
AudioStatsShowInjectedStreams,
BandwidthDetails,
BlueSpeechSphere,
BookmarkLocation,
Bookmarks,
CascadedShadows,
CachesSize,
Chat,
Collisions,
Console,
ControlWithSpeech,
CopyAddress,
CopyPath,
DecreaseAvatarSize,
DeleteBookmark,
DisableActivityLogger,
DisableLightEntities,
DisableNackPackets,
DiskCacheEditor,
DisplayHands,
DisplayHandTargets,
DisplayModelBounds,
DisplayModelTriangles,
DisplayModelElementChildProxies,
DisplayModelElementProxy,
DisplayDebugTimingDetails,
DontDoPrecisionPicking,
DontFadeOnOctreeServerChanges,
DontRenderEntitiesAsScene,
EchoLocalAudio,
EchoServerAudio,
EditEntitiesHelp,
Enable3DTVMode,
EnableCharacterController,
EnableGlowEffect,
EnableVRMode,
ExpandMyAvatarSimulateTiming,
ExpandMyAvatarTiming,
ExpandOtherAvatarTiming,
ExpandPaintGLTiming,
ExpandUpdateTiming,
Faceshift,
FilterSixense,
FirstPerson,
FrameTimer,
Fullscreen,
FullscreenMirror,
GlowWhenSpeaking,
NamesAboveHeads,
GoToUser,
HMDTools,
IncreaseAvatarSize,
KeyboardMotorControl,
LeapMotionOnHMD,
LoadScript,
LoadScriptURL,
LoadRSSDKFile,
LodTools,
Login,
Log,
LowVelocityFilter,
Mirror,
MuteAudio,
MuteEnvironment,
NoFaceTracking,
NoShadows,
OctreeStats,
OffAxisProjection,
OnlyDisplayTopTen,
PackageModel,
Pair,
PipelineWarnings,
Preferences,
Quit,
ReloadAllScripts,
RenderBoundingCollisionShapes,
RenderFocusIndicator,
RenderHeadCollisionShapes,
RenderLookAtVectors,
RenderSkeletonCollisionShapes,
RenderTargetFramerate,
RenderTargetFramerateUnlimited,
RenderTargetFramerate60,
RenderTargetFramerate50,
RenderTargetFramerate40,
RenderTargetFramerate30,
RenderTargetFramerateVSyncOn,
RenderResolution,
RenderResolutionOne,
RenderResolutionTwoThird,
RenderResolutionHalf,
RenderResolutionThird,
RenderResolutionQuarter,
RenderAmbientLight,
RenderAmbientLightGlobal,
RenderAmbientLight0,
RenderAmbientLight1,
RenderAmbientLight2,
RenderAmbientLight3,
RenderAmbientLight4,
RenderAmbientLight5,
RenderAmbientLight6,
RenderAmbientLight7,
RenderAmbientLight8,
RenderAmbientLight9,
ResetAvatarSize,
ResetSensors,
RunningScripts,
RunTimingTests,
ScriptEditor,
ScriptedMotorControl,
ShowBordersEntityNodes,
ShowIKConstraints,
SimpleShadows,
SixenseEnabled,
SixenseMouseInput,
SixenseLasers,
ShiftHipsForIdleAnimations,
Stars,
Stats,
StereoAudio,
StopAllScripts,
SuppressShortTimings,
TestPing,
ToolWindow,
TransmitterDrive,
TurnWithHead,
UseAudioForMouth,
UseCamera,
VelocityFilter,
VisibleToEveryone,
VisibleToFriends,
VisibleToNoOne,
Wireframe,
};
public:
MenuConstants(QObject * parent = nullptr) : QObject(parent) {
}
};
const QString & getQmlDir() {
static QString dir;
if (dir.isEmpty()) {
@ -156,6 +321,8 @@ public:
MessageDialog::registerType();
HifiMenu::registerType();
qmlRegisterType<MenuConstants>("Hifi", 1, 0, "MenuConstants");
auto offscreenUi = DependencyManager::get<OffscreenUi>();
offscreenUi->create(_context);
@ -181,24 +348,10 @@ public:
#else
offscreenUi->setBaseUrl(QUrl::fromLocalFile(getQmlDir()));
offscreenUi->load(QUrl("TestRoot.qml"));
offscreenUi->load(QUrl("RootMenu.qml"));
offscreenUi->load(QUrl("Menu.qml"));
// Requires a root menu to have been loaded before it can load
HifiMenu::load();
QObject* menuObject = offscreenUi->getRootItem()->findChild<QObject*>("HifiMenu");
HifiMenu* menu = offscreenUi->getRootItem()->findChild<HifiMenu*>();
menu->addMenu("", "File");
menu->addItem("File", "Quit", []{
QApplication::quit();
});
menu->addCheckableItem("File", "Toggle", false, [](bool toggled) {
qDebug() << "Toggle is " << toggled;
});
menu->addMenu("", "Edit");
menu->addItem("Edit", "Undo");
menu->addItem("Edit", "Redo");
menu->addItem("Edit", "Copy");
menu->addItem("Edit", "Cut");
menu->addItem("Edit", "Paste");
menu->addMenu("", "Long Menu Name...");
HifiMenu::connectAction(MenuConstants::Quit, qApp, SLOT(quit()));
#endif
installEventFilter(offscreenUi.data());
offscreenUi->resume();