mirror of
https://github.com/overte-org/overte.git
synced 2025-04-20 04:44:11 +02:00
Merge pull request #10046 from Triplelexx/21224
21224 - Allow people to save avatar bookmarks
This commit is contained in:
commit
7505b82189
15 changed files with 464 additions and 210 deletions
|
@ -542,7 +542,7 @@ ScrollingWindow {
|
|||
Item {
|
||||
height: parent.height
|
||||
width: parent.width
|
||||
HifiControls.Button {
|
||||
HifiControls.QueuedButton {
|
||||
id: uploadButton
|
||||
anchors.right: parent.right
|
||||
|
||||
|
@ -552,22 +552,7 @@ ScrollingWindow {
|
|||
height: 30
|
||||
width: 155
|
||||
|
||||
onClicked: uploadClickedTimer.running = true
|
||||
|
||||
// For some reason trigginer an API that enters
|
||||
// an internal event loop directly from the button clicked
|
||||
// trigger below causes the appliction to behave oddly.
|
||||
// Most likely because the button onClicked handling is never
|
||||
// completed until the function returns.
|
||||
// FIXME find a better way of handling the input dialogs that
|
||||
// doesn't trigger this.
|
||||
Timer {
|
||||
id: uploadClickedTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: uploadClicked();
|
||||
}
|
||||
onClickedQueued: uploadClicked()
|
||||
}
|
||||
|
||||
Item {
|
||||
|
|
43
interface/resources/qml/controls-uit/QueuedButton.qml
Normal file
43
interface/resources/qml/controls-uit/QueuedButton.qml
Normal file
|
@ -0,0 +1,43 @@
|
|||
//
|
||||
// QueuedButton.qml
|
||||
// -- original Button.qml + signal timer workaround --ht
|
||||
// Created by David Rowe on 16 Feb 2016
|
||||
// Copyright 2016 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
|
||||
//
|
||||
|
||||
import QtQuick 2.5
|
||||
import QtQuick.Controls 1.4 as Original
|
||||
import QtQuick.Controls.Styles 1.4
|
||||
|
||||
import "../styles-uit"
|
||||
import "." as HifiControls
|
||||
|
||||
HifiControls.Button {
|
||||
// FIXME: THIS WORKAROUND MIGRATED/CONSOLIDATED FROM RUNNINGSCRIPTS.QML
|
||||
|
||||
// For some reason trigginer an API that enters
|
||||
// an internal event loop directly from the button clicked
|
||||
// trigger below causes the appliction to behave oddly.
|
||||
// Most likely because the button onClicked handling is never
|
||||
// completed until the function returns.
|
||||
// FIXME find a better way of handling the input dialogs that
|
||||
// doesn't trigger this.
|
||||
|
||||
// NOTE: dialogs that need to use this workaround can connect via
|
||||
// onQueuedClicked: ...
|
||||
// instead of:
|
||||
// onClicked: ...
|
||||
|
||||
signal clickedQueued()
|
||||
Timer {
|
||||
id: fromTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: clickedQueued()
|
||||
}
|
||||
onClicked: fromTimer.running = true
|
||||
}
|
|
@ -16,7 +16,6 @@ import "../../hifi/tablet/tabletWindows/preferences"
|
|||
Preference {
|
||||
id: root
|
||||
property alias text: dataTextField.text
|
||||
property alias buttonText: button.text
|
||||
property alias placeholderText: dataTextField.placeholderText
|
||||
property var browser;
|
||||
height: control.height + hifi.dimensions.controlInterlineHeight
|
||||
|
@ -58,28 +57,46 @@ Preference {
|
|||
right: parent.right
|
||||
bottom: parent.bottom
|
||||
}
|
||||
height: Math.max(dataTextField.controlHeight, button.height)
|
||||
height: dataTextField.controlHeight + bookmarkAvatarButton.height + hifi.dimensions.contentSpacing.y
|
||||
|
||||
TextField {
|
||||
id: dataTextField
|
||||
label: root.label
|
||||
placeholderText: root.placeholderText
|
||||
text: preference.value
|
||||
label: root.label
|
||||
colorScheme: dataTextField.acceptableInput ? hifi.colorSchemes.dark : hifi.colorSchemes.light
|
||||
validator: RegExpValidator {
|
||||
regExp: /.*\.(?:fst).*\?*/ig
|
||||
}
|
||||
anchors {
|
||||
left: parent.left
|
||||
right: button.left
|
||||
rightMargin: hifi.dimensions.contentSpacing.x
|
||||
bottom: parent.bottom
|
||||
right: parent.right
|
||||
bottom: bookmarkAvatarButton.top
|
||||
bottomMargin: hifi.dimensions.contentSpacing.y
|
||||
}
|
||||
colorScheme: hifi.colorSchemes.dark
|
||||
}
|
||||
|
||||
QueuedButton {
|
||||
id: bookmarkAvatarButton
|
||||
text: "Bookmark Avatar"
|
||||
width: 140
|
||||
visible: dataTextField.acceptableInput
|
||||
anchors {
|
||||
left: parent.left
|
||||
bottom: parent.bottom
|
||||
rightMargin: hifi.dimensions.contentSpacing.x
|
||||
}
|
||||
onClickedQueued: ApplicationInterface.loadAddAvatarBookmarkDialog()
|
||||
}
|
||||
|
||||
Button {
|
||||
id: button
|
||||
text: "Browse"
|
||||
id: browseAvatarsButton
|
||||
text: "Browse Avatars"
|
||||
width: 140
|
||||
anchors {
|
||||
right: parent.right
|
||||
verticalCenter: dataTextField.verticalCenter
|
||||
left: dataTextField.acceptableInput ? bookmarkAvatarButton.right : parent.left
|
||||
bottom: parent.bottom
|
||||
leftMargin: dataTextField.acceptableInput ? hifi.dimensions.contentSpacing.x : 0
|
||||
}
|
||||
onClicked: {
|
||||
if (typeof desktop !== "undefined") {
|
||||
|
@ -103,5 +120,6 @@ Preference {
|
|||
eventBridge: tabletRoot.eventBridge
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -219,41 +219,18 @@ ScrollingWindow {
|
|||
Row {
|
||||
spacing: hifi.dimensions.contentSpacing.x
|
||||
|
||||
HifiControls.Button {
|
||||
HifiControls.QueuedButton {
|
||||
text: "from URL"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: fromUrlTimer.running = true
|
||||
|
||||
// For some reason trigginer an API that enters
|
||||
// an internal event loop directly from the button clicked
|
||||
// trigger below causes the appliction to behave oddly.
|
||||
// Most likely because the button onClicked handling is never
|
||||
// completed until the function returns.
|
||||
// FIXME find a better way of handling the input dialogs that
|
||||
// doesn't trigger this.
|
||||
Timer {
|
||||
id: fromUrlTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: ApplicationInterface.loadScriptURLDialog();
|
||||
}
|
||||
onClickedQueued: ApplicationInterface.loadScriptURLDialog()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
HifiControls.QueuedButton {
|
||||
text: "from Disk"
|
||||
color: hifi.buttons.black
|
||||
height: 26
|
||||
onClicked: fromDiskTimer.running = true
|
||||
|
||||
Timer {
|
||||
id: fromDiskTimer
|
||||
interval: 5
|
||||
repeat: false
|
||||
running: false
|
||||
onTriggered: ApplicationInterface.loadDialog();
|
||||
}
|
||||
onClickedQueued: ApplicationInterface.loadDialog()
|
||||
}
|
||||
|
||||
HifiControls.Button {
|
||||
|
|
|
@ -59,6 +59,7 @@
|
|||
#include <AssetUpload.h>
|
||||
#include <AutoUpdater.h>
|
||||
#include <AudioInjectorManager.h>
|
||||
#include <AvatarBookmarks.h>
|
||||
#include <CursorManager.h>
|
||||
#include <DebugDraw.h>
|
||||
#include <DeferredLightingEffect.h>
|
||||
|
@ -81,6 +82,7 @@
|
|||
#include <controllers/StateController.h>
|
||||
#include <UserActivityLoggerScriptingInterface.h>
|
||||
#include <LogHandler.h>
|
||||
#include "LocationBookmarks.h"
|
||||
#include <MainWindow.h>
|
||||
#include <MappingRequest.h>
|
||||
#include <MessagesClient.h>
|
||||
|
@ -530,6 +532,8 @@ bool setupEssentials(int& argc, char** argv) {
|
|||
DependencyManager::set<EntityScriptServerLogClient>();
|
||||
DependencyManager::set<LimitlessVoiceRecognitionScriptingInterface>();
|
||||
DependencyManager::set<OctreeStatsProvider>(nullptr, qApp->getOcteeSceneStats());
|
||||
DependencyManager::set<AvatarBookmarks>();
|
||||
DependencyManager::set<LocationBookmarks>();
|
||||
|
||||
return previousSessionCrashed;
|
||||
}
|
||||
|
@ -703,8 +707,6 @@ Application::Application(int& argc, char** argv, QElapsedTimer& startupTimer, bo
|
|||
usleep(USECS_PER_MSEC * 50); // 20hz
|
||||
}
|
||||
|
||||
_bookmarks = new Bookmarks(); // Before setting up the menu
|
||||
|
||||
// start the nodeThread so its event loop is running
|
||||
QThread* nodeThread = new QThread(this);
|
||||
nodeThread->setObjectName("NodeList Thread");
|
||||
|
@ -2009,6 +2011,8 @@ void Application::initializeUi() {
|
|||
rootContext->setContextProperty("Settings", SettingsScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("ScriptDiscoveryService", DependencyManager::get<ScriptEngines>().data());
|
||||
rootContext->setContextProperty("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
rootContext->setContextProperty("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||
rootContext->setContextProperty("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||
|
||||
// Caches
|
||||
rootContext->setContextProperty("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
|
@ -5494,6 +5498,8 @@ void Application::registerScriptEngineWithApplicationServices(ScriptEngine* scri
|
|||
scriptEngine->registerGlobalObject("AudioDevice", AudioDeviceScriptingInterface::getInstance());
|
||||
scriptEngine->registerGlobalObject("AudioStats", DependencyManager::get<AudioClient>()->getStats().data());
|
||||
scriptEngine->registerGlobalObject("AudioScope", DependencyManager::get<AudioScope>().data());
|
||||
scriptEngine->registerGlobalObject("AvatarBookmarks", DependencyManager::get<AvatarBookmarks>().data());
|
||||
scriptEngine->registerGlobalObject("LocationBookmarks", DependencyManager::get<LocationBookmarks>().data());
|
||||
|
||||
// Caches
|
||||
scriptEngine->registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
|
||||
|
@ -6359,7 +6365,6 @@ void Application::loadLODToolsDialog() {
|
|||
} else {
|
||||
tablet->pushOntoStack("../../hifi/dialogs/TabletLODTools.qml");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -6409,6 +6414,11 @@ void Application::toggleEntityScriptServerLogDialog() {
|
|||
}
|
||||
}
|
||||
|
||||
void Application::loadAddAvatarBookmarkDialog() const {
|
||||
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
|
||||
avatarBookmarks->addBookmark();
|
||||
}
|
||||
|
||||
void Application::takeSnapshot(bool notify, bool includeAnimated, float aspectRatio) {
|
||||
postLambdaEvent([notify, includeAnimated, aspectRatio, this] {
|
||||
QMediaPlayer* player = new QMediaPlayer();
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
|
||||
#include "avatar/MyAvatar.h"
|
||||
#include "BandwidthRecorder.h"
|
||||
#include "Bookmarks.h"
|
||||
#include "Camera.h"
|
||||
#include "ConnectionMonitor.h"
|
||||
#include "gpu/Context.h"
|
||||
|
@ -261,7 +260,6 @@ public:
|
|||
glm::mat4 getEyeProjection(int eye) const;
|
||||
|
||||
QRect getDesirableApplicationGeometry() const;
|
||||
Bookmarks* getBookmarks() const { return _bookmarks; }
|
||||
|
||||
virtual bool canAcceptURL(const QString& url) const override;
|
||||
virtual bool acceptURL(const QString& url, bool defaultUpload = false) override;
|
||||
|
@ -330,6 +328,7 @@ public slots:
|
|||
void toggleEntityScriptServerLogDialog();
|
||||
void toggleRunningScriptsWidget() const;
|
||||
Q_INVOKABLE void showAssetServerWidget(QString filePath = "");
|
||||
Q_INVOKABLE void loadAddAvatarBookmarkDialog() const;
|
||||
|
||||
void showDialog(const QString& desktopURL, const QString& tabletURL, const QString& name) const;
|
||||
|
||||
|
@ -599,8 +598,6 @@ private:
|
|||
|
||||
bool _aboutToQuit;
|
||||
|
||||
Bookmarks* _bookmarks;
|
||||
|
||||
bool _notifiedPacketVersionMismatchThisDomain;
|
||||
|
||||
QThread _settingsThread;
|
||||
|
|
81
interface/src/AvatarBookmarks.cpp
Normal file
81
interface/src/AvatarBookmarks.cpp
Normal file
|
@ -0,0 +1,81 @@
|
|||
//
|
||||
// AvatarBookmarks.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 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 <QAction>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
#include <QQmlContext>
|
||||
|
||||
#include <Application.h>
|
||||
#include <OffscreenUi.h>
|
||||
#include <avatar/AvatarManager.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "AvatarBookmarks.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
AvatarBookmarks::AvatarBookmarks() {
|
||||
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + AVATARBOOKMARKS_FILENAME;
|
||||
readFromFile();
|
||||
}
|
||||
|
||||
void AvatarBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||
// Add menus/actions
|
||||
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkAvatar);
|
||||
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection);
|
||||
_bookmarksMenu = menu->addMenu(MenuOption::AvatarBookmarks);
|
||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteAvatarBookmark);
|
||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
||||
|
||||
Bookmarks::setupMenus(menubar, menu);
|
||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||
}
|
||||
|
||||
void AvatarBookmarks::changeToBookmarkedAvatar() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
const QString& address = action->data().toString();
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
myAvatar->useFullAvatarURL(address);
|
||||
}
|
||||
|
||||
void AvatarBookmarks::addBookmark() {
|
||||
bool ok = false;
|
||||
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Avatar", "Name", QString(), &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto myAvatar = DependencyManager::get<AvatarManager>()->getMyAvatar();
|
||||
const QString& bookmarkAddress = myAvatar->getSkeletonModelURL().toString();
|
||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
|
||||
}
|
||||
|
||||
void AvatarBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
|
||||
QAction* changeAction = _bookmarksMenu->newAction();
|
||||
changeAction->setData(address);
|
||||
connect(changeAction, SIGNAL(triggered()), this, SLOT(changeToBookmarkedAvatar()));
|
||||
if (!_isMenuSorted) {
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
||||
} else {
|
||||
// TODO: this is aggressive but other alternatives have proved less fruitful so far.
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, changeAction, name, 0, QAction::NoRole);
|
||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||
}
|
||||
}
|
40
interface/src/AvatarBookmarks.h
Normal file
40
interface/src/AvatarBookmarks.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
//
|
||||
// AvatarBookmarks.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
#ifndef hifi_AvatarBookmarks_h
|
||||
#define hifi_AvatarBookmarks_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include "Bookmarks.h"
|
||||
|
||||
class AvatarBookmarks: public Bookmarks, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
AvatarBookmarks();
|
||||
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
||||
|
||||
public slots:
|
||||
void addBookmark();
|
||||
|
||||
protected:
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
||||
|
||||
private:
|
||||
const QString AVATARBOOKMARKS_FILENAME = "avatarbookmarks.json";
|
||||
|
||||
private slots:
|
||||
void changeToBookmarkedAvatar();
|
||||
};
|
||||
|
||||
#endif // hifi_AvatarBookmarks_h
|
|
@ -11,14 +11,10 @@
|
|||
|
||||
#include <QAction>
|
||||
#include <QDebug>
|
||||
#include <QJsonObject>
|
||||
#include <QFile>
|
||||
#include <QInputDialog>
|
||||
#include <QJsonDocument>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <Application.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
|
@ -27,15 +23,69 @@
|
|||
#include "InterfaceLogging.h"
|
||||
|
||||
#include "Bookmarks.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
Bookmarks::Bookmarks() :
|
||||
_isMenuSorted(false)
|
||||
{
|
||||
}
|
||||
|
||||
const QString Bookmarks::HOME_BOOKMARK = "Home";
|
||||
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||
// Enable/Disable menus as needed
|
||||
enableMenuItems(_bookmarks.count() > 0);
|
||||
|
||||
// Load Bookmarks
|
||||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it) {
|
||||
QString bookmarkName = it.key();
|
||||
QString bookmarkAddress = it.value().toString();
|
||||
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
}
|
||||
}
|
||||
|
||||
Bookmarks::Bookmarks() {
|
||||
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + BOOKMARKS_FILENAME;
|
||||
readFromFile();
|
||||
void Bookmarks::deleteBookmark() {
|
||||
QStringList bookmarkList;
|
||||
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
||||
for (int i = 0; i < menuItems.count(); ++i) {
|
||||
bookmarkList.append(menuItems[i]->text());
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bookmarkName = bookmarkName.trimmed();
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeBookmarkFromMenu(Menu::getInstance(), bookmarkName);
|
||||
remove(bookmarkName);
|
||||
|
||||
if (_bookmarksMenu->actions().count() == 0) {
|
||||
enableMenuItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress) {
|
||||
Menu* menubar = Menu::getInstance();
|
||||
if (contains(bookmarkName)) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
|
||||
"The bookmark name you entered already exists in your list.",
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
||||
|
||||
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
||||
if (result != QMessageBox::Yes) {
|
||||
return;
|
||||
}
|
||||
removeBookmarkFromMenu(menubar, bookmarkName);
|
||||
}
|
||||
|
||||
addBookmarkToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::insert(const QString& name, const QString& address) {
|
||||
|
@ -64,6 +114,33 @@ bool Bookmarks::contains(const QString& name) const {
|
|||
return _bookmarks.contains(name);
|
||||
}
|
||||
|
||||
bool Bookmarks::sortOrder(QAction* a, QAction* b) {
|
||||
return a->text().toLower().localeAwareCompare(b->text().toLower()) < 0;
|
||||
}
|
||||
|
||||
void Bookmarks::sortActions(Menu* menubar, MenuWrapper* menu) {
|
||||
QList<QAction*> actions = menu->actions();
|
||||
qSort(actions.begin(), actions.end(), sortOrder);
|
||||
for (QAction* action : menu->actions()) {
|
||||
menu->removeAction(action);
|
||||
}
|
||||
for (QAction* action : actions) {
|
||||
menu->addAction(action);
|
||||
}
|
||||
_isMenuSorted = true;
|
||||
}
|
||||
|
||||
int Bookmarks::getMenuItemLocation(QList<QAction*> actions, const QString& name) const {
|
||||
int menuItemLocation = 0;
|
||||
for (QAction* action : actions) {
|
||||
if (name.toLower().localeAwareCompare(action->text().toLower()) < 0) {
|
||||
menuItemLocation = actions.indexOf(action);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return menuItemLocation;
|
||||
}
|
||||
|
||||
QString Bookmarks::addressForBookmark(const QString& name) const {
|
||||
return _bookmarks.value(name).toString();
|
||||
}
|
||||
|
@ -99,108 +176,6 @@ void Bookmarks::persistToFile() {
|
|||
saveFile.write(data);
|
||||
}
|
||||
|
||||
void Bookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||
// Add menus/actions
|
||||
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation);
|
||||
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(bookmarkLocation()), Qt::QueuedConnection);
|
||||
auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation);
|
||||
QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection);
|
||||
_bookmarksMenu = menu->addMenu(MenuOption::Bookmarks);
|
||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
|
||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
||||
|
||||
// Enable/Disable menus as needed
|
||||
enableMenuItems(_bookmarks.count() > 0);
|
||||
|
||||
// Load bookmarks
|
||||
for (auto it = _bookmarks.begin(); it != _bookmarks.end(); ++it ) {
|
||||
QString bookmarkName = it.key();
|
||||
QString bookmarkAddress = it.value().toString();
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::bookmarkLocation() {
|
||||
bool ok = false;
|
||||
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
|
||||
Menu* menubar = Menu::getInstance();
|
||||
if (contains(bookmarkName)) {
|
||||
auto offscreenUi = DependencyManager::get<OffscreenUi>();
|
||||
auto duplicateBookmarkMessage = offscreenUi->createMessageBox(OffscreenUi::ICON_WARNING, "Duplicate Bookmark",
|
||||
"The bookmark name you entered already exists in your list.",
|
||||
QMessageBox::Yes | QMessageBox::No, QMessageBox::Yes);
|
||||
duplicateBookmarkMessage->setProperty("informativeText", "Would you like to overwrite it?");
|
||||
|
||||
auto result = offscreenUi->waitForMessageBoxResult(duplicateBookmarkMessage);
|
||||
if (result != QMessageBox::Yes) {
|
||||
return;
|
||||
}
|
||||
removeLocationFromMenu(menubar, bookmarkName);
|
||||
}
|
||||
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::setHomeLocation() {
|
||||
Menu* menubar = Menu::getInstance();
|
||||
QString bookmarkName = HOME_BOOKMARK;
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
|
||||
addLocationToMenu(menubar, bookmarkName, bookmarkAddress);
|
||||
insert(bookmarkName, bookmarkAddress); // Overwrites any item with the same bookmarkName.
|
||||
|
||||
enableMenuItems(true);
|
||||
}
|
||||
|
||||
void Bookmarks::teleportToBookmark() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
QString address = action->data().toString();
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(address);
|
||||
}
|
||||
|
||||
void Bookmarks::deleteBookmark() {
|
||||
|
||||
QStringList bookmarkList;
|
||||
QList<QAction*> menuItems = _bookmarksMenu->actions();
|
||||
for (int i = 0; i < menuItems.count(); i += 1) {
|
||||
bookmarkList.append(menuItems[i]->text());
|
||||
}
|
||||
|
||||
bool ok = false;
|
||||
auto bookmarkName = OffscreenUi::getItem(OffscreenUi::ICON_PLACEMARK, "Delete Bookmark", "Select the bookmark to delete", bookmarkList, 0, false, &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bookmarkName = bookmarkName.trimmed();
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
removeLocationFromMenu(Menu::getInstance(), bookmarkName);
|
||||
remove(bookmarkName);
|
||||
|
||||
if (_bookmarksMenu->actions().count() == 0) {
|
||||
enableMenuItems(false);
|
||||
}
|
||||
}
|
||||
|
||||
void Bookmarks::enableMenuItems(bool enabled) {
|
||||
if (_bookmarksMenu) {
|
||||
_bookmarksMenu->setEnabled(enabled);
|
||||
|
@ -210,17 +185,6 @@ void Bookmarks::enableMenuItems(bool enabled) {
|
|||
}
|
||||
}
|
||||
|
||||
void Bookmarks::addLocationToMenu(Menu* menubar, QString& name, QString& address) {
|
||||
QAction* teleportAction = _bookmarksMenu->newAction();
|
||||
teleportAction->setData(address);
|
||||
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
||||
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction,
|
||||
name, 0, QAction::NoRole);
|
||||
}
|
||||
|
||||
void Bookmarks::removeLocationFromMenu(Menu* menubar, QString& name) {
|
||||
void Bookmarks::removeBookmarkFromMenu(Menu* menubar, const QString& name) {
|
||||
menubar->removeAction(_bookmarksMenu, name);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -27,37 +27,35 @@ class Bookmarks: public QObject {
|
|||
public:
|
||||
Bookmarks();
|
||||
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu);
|
||||
|
||||
virtual void setupMenus(Menu* menubar, MenuWrapper* menu);
|
||||
QString addressForBookmark(const QString& name) const;
|
||||
|
||||
static const QString HOME_BOOKMARK;
|
||||
protected:
|
||||
virtual void addBookmarkToFile(const QString& bookmarkName, const QString& bookmarkAddress);
|
||||
virtual void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) = 0;
|
||||
void enableMenuItems(bool enabled);
|
||||
void readFromFile();
|
||||
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
|
||||
void sortActions(Menu* menubar, MenuWrapper* menu);
|
||||
int getMenuItemLocation(QList<QAction*> actions, const QString& name) const;
|
||||
|
||||
private slots:
|
||||
void bookmarkLocation();
|
||||
void setHomeLocation();
|
||||
void teleportToBookmark();
|
||||
void deleteBookmark();
|
||||
|
||||
private:
|
||||
QVariantMap _bookmarks; // { name: address, ... }
|
||||
|
||||
QVariantMap _bookmarks; // { name: url, ... }
|
||||
QPointer<MenuWrapper> _bookmarksMenu;
|
||||
QPointer<QAction> _deleteBookmarksAction;
|
||||
|
||||
const QString BOOKMARKS_FILENAME = "bookmarks.json";
|
||||
QString _bookmarksFilename;
|
||||
|
||||
void insert(const QString& name, const QString& address); // Overwrites any existing entry with same name.
|
||||
bool _isMenuSorted;
|
||||
|
||||
protected slots:
|
||||
void deleteBookmark();
|
||||
|
||||
private:
|
||||
void remove(const QString& name);
|
||||
bool contains(const QString& name) const;
|
||||
static bool sortOrder(QAction* a, QAction* b);
|
||||
|
||||
void readFromFile();
|
||||
void persistToFile();
|
||||
|
||||
void enableMenuItems(bool enabled);
|
||||
void addLocationToMenu(Menu* menubar, QString& name, QString& address);
|
||||
void removeLocationFromMenu(Menu* menubar, QString& name);
|
||||
void removeBookmarkFromMenu(Menu* menubar, const QString& name);
|
||||
};
|
||||
|
||||
#endif // hifi_Bookmarks_h
|
||||
#endif // hifi_Bookmarks_h
|
||||
|
|
88
interface/src/LocationBookmarks.cpp
Normal file
88
interface/src/LocationBookmarks.cpp
Normal file
|
@ -0,0 +1,88 @@
|
|||
//
|
||||
// LocationBookmarks.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 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 <QAction>
|
||||
#include <QInputDialog>
|
||||
#include <QMessageBox>
|
||||
#include <QStandardPaths>
|
||||
|
||||
#include <AddressManager.h>
|
||||
#include <Application.h>
|
||||
#include <OffscreenUi.h>
|
||||
|
||||
#include "MainWindow.h"
|
||||
#include "Menu.h"
|
||||
|
||||
#include "LocationBookmarks.h"
|
||||
#include <QtQuick/QQuickWindow>
|
||||
|
||||
const QString LocationBookmarks::HOME_BOOKMARK = "Home";
|
||||
|
||||
LocationBookmarks::LocationBookmarks() {
|
||||
_bookmarksFilename = QStandardPaths::writableLocation(QStandardPaths::DataLocation) + "/" + LOCATIONBOOKMARKS_FILENAME;
|
||||
readFromFile();
|
||||
}
|
||||
|
||||
void LocationBookmarks::setupMenus(Menu* menubar, MenuWrapper* menu) {
|
||||
// Add menus/actions
|
||||
auto bookmarkAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::BookmarkLocation);
|
||||
QObject::connect(bookmarkAction, SIGNAL(triggered()), this, SLOT(addBookmark()), Qt::QueuedConnection);
|
||||
auto setHomeAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::SetHomeLocation);
|
||||
QObject::connect(setHomeAction, SIGNAL(triggered()), this, SLOT(setHomeLocation()), Qt::QueuedConnection);
|
||||
_bookmarksMenu = menu->addMenu(MenuOption::LocationBookmarks);
|
||||
_deleteBookmarksAction = menubar->addActionToQMenuAndActionHash(menu, MenuOption::DeleteBookmark);
|
||||
QObject::connect(_deleteBookmarksAction, SIGNAL(triggered()), this, SLOT(deleteBookmark()), Qt::QueuedConnection);
|
||||
|
||||
Bookmarks::setupMenus(menubar, menu);
|
||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||
}
|
||||
|
||||
void LocationBookmarks::setHomeLocation() {
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
Bookmarks::addBookmarkToFile(HOME_BOOKMARK, bookmarkAddress);
|
||||
}
|
||||
|
||||
void LocationBookmarks::teleportToBookmark() {
|
||||
QAction* action = qobject_cast<QAction*>(sender());
|
||||
QString address = action->data().toString();
|
||||
DependencyManager::get<AddressManager>()->handleLookupString(address);
|
||||
}
|
||||
|
||||
void LocationBookmarks::addBookmark() {
|
||||
bool ok = false;
|
||||
auto bookmarkName = OffscreenUi::getText(OffscreenUi::ICON_PLACEMARK, "Bookmark Location", "Name", QString(), &ok);
|
||||
if (!ok) {
|
||||
return;
|
||||
}
|
||||
|
||||
bookmarkName = bookmarkName.trimmed().replace(QRegExp("(\r\n|[\r\n\t\v ])+"), " ");
|
||||
if (bookmarkName.length() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
QString bookmarkAddress = addressManager->currentAddress().toString();
|
||||
Bookmarks::addBookmarkToFile(bookmarkName, bookmarkAddress);
|
||||
}
|
||||
|
||||
void LocationBookmarks::addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) {
|
||||
QAction* teleportAction = _bookmarksMenu->newAction();
|
||||
teleportAction->setData(address);
|
||||
connect(teleportAction, SIGNAL(triggered()), this, SLOT(teleportToBookmark()));
|
||||
if (!_isMenuSorted) {
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
|
||||
} else {
|
||||
// TODO: this is aggressive but other alternatives have proved less fruitful so far.
|
||||
menubar->addActionToQMenuAndActionHash(_bookmarksMenu, teleportAction, name, 0, QAction::NoRole);
|
||||
Bookmarks::sortActions(menubar, _bookmarksMenu);
|
||||
}
|
||||
}
|
42
interface/src/LocationBookmarks.h
Normal file
42
interface/src/LocationBookmarks.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// LocationBookmarks.h
|
||||
// interface/src
|
||||
//
|
||||
// Created by Triplelexx on 23/03/17.
|
||||
// Copyright 2017 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
|
||||
//
|
||||
|
||||
#ifndef hifi_LocationBookmarks_h
|
||||
#define hifi_LocationBookmarks_h
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include "Bookmarks.h"
|
||||
|
||||
class LocationBookmarks : public Bookmarks, public Dependency {
|
||||
Q_OBJECT
|
||||
SINGLETON_DEPENDENCY
|
||||
|
||||
public:
|
||||
LocationBookmarks();
|
||||
|
||||
void setupMenus(Menu* menubar, MenuWrapper* menu) override;
|
||||
static const QString HOME_BOOKMARK;
|
||||
|
||||
public slots:
|
||||
void addBookmark();
|
||||
|
||||
protected:
|
||||
void addBookmarkToMenu(Menu* menubar, const QString& name, const QString& address) override;
|
||||
|
||||
private:
|
||||
const QString LOCATIONBOOKMARKS_FILENAME = "bookmarks.json";
|
||||
|
||||
private slots:
|
||||
void setHomeLocation();
|
||||
void teleportToBookmark();
|
||||
};
|
||||
|
||||
#endif // hifi_LocationBookmarks_h
|
|
@ -32,6 +32,7 @@
|
|||
#include "assets/ATPAssetMigrator.h"
|
||||
#include "audio/AudioScope.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "AvatarBookmarks.h"
|
||||
#include "devices/DdeFaceTracker.h"
|
||||
#include "devices/Faceshift.h"
|
||||
#include "MainWindow.h"
|
||||
|
@ -40,6 +41,7 @@
|
|||
#include "ui/DialogsManager.h"
|
||||
#include "ui/StandAloneJSConsole.h"
|
||||
#include "InterfaceLogging.h"
|
||||
#include "LocationBookmarks.h"
|
||||
|
||||
#if defined(Q_OS_MAC) || defined(Q_OS_WIN)
|
||||
#include "SpeechRecognizer.h"
|
||||
|
@ -194,6 +196,9 @@ Menu::Menu() {
|
|||
0, // QML Qt::Key_Apostrophe,
|
||||
qApp, SLOT(resetSensors()));
|
||||
|
||||
// Avatar > AvatarBookmarks related menus -- Note: the AvatarBookmarks class adds its own submenus here.
|
||||
auto avatarBookmarks = DependencyManager::get<AvatarBookmarks>();
|
||||
avatarBookmarks->setupMenus(this, avatarMenu);
|
||||
|
||||
// Display menu ----------------------------------
|
||||
// FIXME - this is not yet matching Alan's spec because it doesn't have
|
||||
|
@ -256,8 +261,9 @@ Menu::Menu() {
|
|||
addActionToQMenuAndActionHash(navigateMenu, MenuOption::AddressBar, Qt::CTRL | Qt::Key_L,
|
||||
dialogsManager.data(), SLOT(showAddressBar()));
|
||||
|
||||
// Navigate > Bookmark related menus -- Note: the Bookmark class adds its own submenus here.
|
||||
qApp->getBookmarks()->setupMenus(this, navigateMenu);
|
||||
// Navigate > LocationBookmarks related menus -- Note: the LocationBookmarks class adds its own submenus here.
|
||||
auto locationBookmarks = DependencyManager::get<LocationBookmarks>();
|
||||
locationBookmarks->setupMenus(this, navigateMenu);
|
||||
|
||||
// Navigate > Copy Address [advanced]
|
||||
auto addressManager = DependencyManager::get<AddressManager>();
|
||||
|
|
|
@ -47,10 +47,11 @@ namespace MenuOption {
|
|||
const QString AudioTools = "Show Level Meter";
|
||||
const QString AutoMuteAudio = "Auto Mute Microphone";
|
||||
const QString AvatarReceiveStats = "Show Receive Stats";
|
||||
const QString AvatarBookmarks = "Avatar Bookmarks";
|
||||
const QString Back = "Back";
|
||||
const QString BinaryEyelidControl = "Binary Eyelid Control";
|
||||
const QString BookmarkAvatar = "Bookmark Avatar";
|
||||
const QString BookmarkLocation = "Bookmark Location";
|
||||
const QString Bookmarks = "Bookmarks";
|
||||
const QString CalibrateCamera = "Calibrate Camera";
|
||||
const QString CameraEntityMode = "Entity Mode";
|
||||
const QString CenterPlayerInView = "Center Player In View";
|
||||
|
@ -78,6 +79,7 @@ namespace MenuOption {
|
|||
const QString DeadlockInterface = "Deadlock Interface";
|
||||
const QString DecreaseAvatarSize = "Decrease Avatar Size";
|
||||
const QString DefaultSkybox = "Default Skybox";
|
||||
const QString DeleteAvatarBookmark = "Delete Avatar Bookmark...";
|
||||
const QString DeleteBookmark = "Delete Bookmark...";
|
||||
const QString DisableActivityLogger = "Disable Activity Logger";
|
||||
const QString DisableEyelidAdjustment = "Disable Eyelid Adjustment";
|
||||
|
@ -89,6 +91,7 @@ namespace MenuOption {
|
|||
const QString DisplayModelElementChildProxies = "Display Model Element Children";
|
||||
const QString DisplayModelElementProxy = "Display Model Element Bounds";
|
||||
const QString DisplayDebugTimingDetails = "Display Timing Details";
|
||||
const QString LocationBookmarks = "Bookmarks";
|
||||
const QString DontDoPrecisionPicking = "Don't Do Precision Picking";
|
||||
const QString DontRenderEntitiesAsScene = "Don't Render Entities as Scene";
|
||||
const QString EchoLocalAudio = "Echo Local Audio";
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include "DependencyManager.h"
|
||||
#include "AddressManager.h"
|
||||
#include "DialogsManager.h"
|
||||
#include "LocationBookmarks.h"
|
||||
|
||||
HIFI_QML_DEF(AddressBarDialog)
|
||||
|
||||
|
@ -52,7 +53,8 @@ void AddressBarDialog::loadAddress(const QString& address, bool fromSuggestions)
|
|||
|
||||
void AddressBarDialog::loadHome() {
|
||||
qDebug() << "Called LoadHome";
|
||||
QString homeLocation = qApp->getBookmarks()->addressForBookmark(Bookmarks::HOME_BOOKMARK);
|
||||
auto locationBookmarks = DependencyManager::get<LocationBookmarks>();
|
||||
QString homeLocation = locationBookmarks->addressForBookmark(LocationBookmarks::HOME_BOOKMARK);
|
||||
const QString DEFAULT_HOME_LOCATION = "localhost";
|
||||
if (homeLocation == "") {
|
||||
homeLocation = DEFAULT_HOME_LOCATION;
|
||||
|
|
Loading…
Reference in a new issue